下面列出了怎么用org.apache.logging.log4j.core.lookup.StrSubstitutor的API类实例代码及写法,或者点击链接到github查看源代码。
private Map<String, String> resolveAdditionalFields(final LogEvent logEvent) {
// Note: LinkedHashMap retains order
final Map<String, String> additionalFieldsMap = new LinkedHashMap<>(additionalFields.length);
final StrSubstitutor strSubstitutor = configuration.getStrSubstitutor();
// Go over each field
for (final ResolvableKeyValuePair pair : additionalFields) {
if (pair.valueNeedsLookup) {
// Resolve value
additionalFieldsMap.put(pair.key, strSubstitutor.replace(logEvent, pair.value));
} else {
// Plain text value
additionalFieldsMap.put(pair.key, pair.value);
}
}
return additionalFieldsMap;
}
@Test
public void resolvesDynamicPropertyOnEachCall() {
// given
String expectedValue = UUID.randomUUID().toString();
VirtualProperty virtualProperty = VirtualPropertyTest.createDefaultVirtualPropertyBuilder()
.withValue(expectedValue)
.withDynamic(true)
.build();
StrSubstitutor strSubstitutor = spy(createDefaultTestStrSubstitutor());
Log4j2Lookup lookup = createDefaultTestLog4j2Lookup(strSubstitutor);
// when
lookup.resolve(virtualProperty);
lookup.resolve(virtualProperty);
// then
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
verify(strSubstitutor, times(2)).replace(captor.capture());
Assert.assertEquals(expectedValue, captor.getAllValues().get(0));
Assert.assertEquals(expectedValue, captor.getAllValues().get(1));
}
@Test
public void doesNotResolveNonDynamicVirtualProperties() {
// given
VirtualProperty virtualProperty = VirtualPropertyTest.createDefaultVirtualPropertyBuilder()
.withDynamic(false)
.build();
StrSubstitutor strSubstitutor = spy(createDefaultTestStrSubstitutor());
Log4j2Lookup lookup = createDefaultTestLog4j2Lookup(strSubstitutor);
// when
lookup.resolve(virtualProperty);
// then
verify(strSubstitutor, never()).replace(anyString());
}
private JsonTemplateLayout(final Builder builder) {
this.charset = builder.charset;
this.contentType = "application/json; charset=" + charset;
this.eventDelimiter = builder.eventDelimiter;
final Configuration configuration = builder.configuration;
final StrSubstitutor substitutor = configuration.getStrSubstitutor();
final JsonWriter jsonWriter = JsonWriter
.newBuilder()
.setMaxStringLength(builder.maxStringLength)
.setTruncatedStringSuffix(builder.truncatedStringSuffix)
.build();
final TemplateResolver<StackTraceElement> stackTraceElementObjectResolver =
builder.stackTraceEnabled
? createStackTraceElementResolver(builder, substitutor, jsonWriter)
: null;
this.eventResolver = createEventResolver(
builder,
configuration,
substitutor,
charset,
jsonWriter,
stackTraceElementObjectResolver);
this.contextRecycler = createContextRecycler(builder, jsonWriter);
}
private Map<String, String> resolveAdditionalFields(final LogEvent logEvent) {
// Note: LinkedHashMap retains order
final Map<String, String> additionalFieldsMap = new LinkedHashMap<>(additionalFields.length);
final StrSubstitutor strSubstitutor = configuration.getStrSubstitutor();
// Go over each field
for (final ResolvableKeyValuePair pair : additionalFields) {
if (pair.valueNeedsLookup) {
// Resolve value
additionalFieldsMap.put(pair.key, strSubstitutor.replace(logEvent, pair.value));
} else {
// Plain text value
additionalFieldsMap.put(pair.key, pair.value);
}
}
return additionalFieldsMap;
}
private Map<String, String> resolveAdditionalFields(final LogEvent logEvent) {
// Note: LinkedHashMap retains order
final Map<String, String> additionalFieldsMap = new LinkedHashMap<>(additionalFields.length);
final StrSubstitutor strSubstitutor = configuration.getStrSubstitutor();
// Go over each field
for (final ResolvableKeyValuePair pair : additionalFields) {
if (pair.valueNeedsLookup) {
// Resolve value
additionalFieldsMap.put(pair.key, strSubstitutor.replace(logEvent, pair.value));
} else {
// Plain text value
additionalFieldsMap.put(pair.key, pair.value);
}
}
return additionalFieldsMap;
}
private void serializeAdditionalFieldsAndMDC(LogEvent event, StringBuilder builder) {
final int length = additionalFields.length;
if (!event.getContextData().isEmpty() || length > 0) {
if (length > 0) {
final StrSubstitutor strSubstitutor = getConfiguration().getStrSubstitutor();
for (int i = 0; i < length; i++) {
KeyValuePair additionalField = additionalFields[i];
PatternFormatter[] formatters = fieldValuePatternFormatter[i];
CharSequence value = null;
if (formatters != null) {
StringBuilder buffer = EcsJsonSerializer.getMessageStringBuilder();
formatPattern(event, formatters, buffer);
if (buffer.length() > 0) {
value = buffer;
}
} else if (valueNeedsLookup(additionalField.getValue())) {
StringBuilder lookupValue = EcsJsonSerializer.getMessageStringBuilder();
lookupValue.append(additionalField.getValue());
if (strSubstitutor.replaceIn(event, lookupValue)) {
value = lookupValue;
}
} else {
value = additionalField.getValue();
}
if (value != null) {
builder.append('\"');
JsonUtils.quoteAsString(additionalField.getKey(), builder);
builder.append("\":\"");
JsonUtils.quoteAsString(EcsJsonSerializer.toNullSafeString(value), builder);
builder.append("\",");
}
}
}
event.getContextData().forEach(WRITE_MDC, builder);
}
}
/**
* Constructs a new instance.
* @param minIndex The minimum index.
* @param maxIndex The maximum index.
*/
protected ZebraRolloverStrategy(final int minIndex, final int maxIndex, final boolean useMax, final int compressionLevel, final StrSubstitutor subst) {
this.minIndex = minIndex;
this.maxIndex = maxIndex;
this.useMax = useMax;
this.compressionLevel = compressionLevel;
this.subst = subst;
}
/**
* Parses a Log4j 1.2 properties configuration file in ISO 8859-1 encoding into a ConfigurationBuilder.
*
* @param input
* InputStream to read from is assumed to be ISO 8859-1, and will not be closed.
* @return the populated ConfigurationBuilder, never {@literal null}
* @throws IOException
* if unable to read the input
* @throws ConfigurationException
* if the input does not contain a valid configuration
*/
public ConfigurationBuilder<BuiltConfiguration> buildConfigurationBuilder(final InputStream input)
throws IOException {
try {
properties.load(input);
strSubstitutorProperties = new StrSubstitutor(properties);
strSubstitutorSystem = new StrSubstitutor(System.getProperties());
final String rootCategoryValue = getLog4jValue(ROOTCATEGORY);
final String rootLoggerValue = getLog4jValue(ROOTLOGGER);
if (rootCategoryValue == null && rootLoggerValue == null) {
// This is not a Log4j 1 properties configuration file.
warn("Missing " + ROOTCATEGORY + " or " + ROOTLOGGER + " in " + input);
// throw new ConfigurationException(
// "Missing " + ROOTCATEGORY + " or " + ROOTLOGGER + " in " + input);
}
builder.setConfigurationName("Log4j1");
// DEBUG
final String debugValue = getLog4jValue("debug");
if (Boolean.valueOf(debugValue)) {
builder.setStatusLevel(Level.DEBUG);
}
// Root
buildRootLogger(getLog4jValue(ROOTCATEGORY));
buildRootLogger(getLog4jValue(ROOTLOGGER));
// Appenders
final Map<String, String> appenderNameToClassName = buildClassToPropertyPrefixMap();
for (final Map.Entry<String, String> entry : appenderNameToClassName.entrySet()) {
final String appenderName = entry.getKey();
final String appenderClass = entry.getValue();
buildAppender(appenderName, appenderClass);
}
// Loggers
buildLoggers("log4j.category.");
buildLoggers("log4j.logger.");
buildProperties();
return builder;
} catch (final IllegalArgumentException e) {
throw new ConfigurationException(e);
}
}
/**
* Parses a Log4j 1.2 properties configuration file in ISO 8859-1 encoding into a ConfigurationBuilder.
*
* @param input
* InputStream to read from is assumed to be ISO 8859-1, and will not be closed.
* @return the populated ConfigurationBuilder, never {@literal null}
* @throws IOException
* if unable to read the input
* @throws ConfigurationException
* if the input does not contain a valid configuration
*/
public ConfigurationBuilder<BuiltConfiguration> buildConfigurationBuilder(final InputStream input)
throws IOException {
try {
properties.load(input);
strSubstitutorProperties = new StrSubstitutor(properties);
strSubstitutorSystem = new StrSubstitutor(System.getProperties());
final String rootCategoryValue = getLog4jValue(ROOTCATEGORY);
final String rootLoggerValue = getLog4jValue(ROOTLOGGER);
if (rootCategoryValue == null && rootLoggerValue == null) {
// This is not a Log4j 1 properties configuration file.
warn("Missing " + ROOTCATEGORY + " or " + ROOTLOGGER + " in " + input);
// throw new ConfigurationException(
// "Missing " + ROOTCATEGORY + " or " + ROOTLOGGER + " in " + input);
}
builder.setConfigurationName("Log4j1");
// DEBUG
final String debugValue = getLog4jValue("debug");
if (Boolean.valueOf(debugValue)) {
builder.setStatusLevel(Level.DEBUG);
}
// Root
buildRootLogger(getLog4jValue(ROOTCATEGORY));
buildRootLogger(getLog4jValue(ROOTLOGGER));
// Appenders
final Map<String, String> appenderNameToClassName = buildClassToPropertyPrefixMap();
for (final Map.Entry<String, String> entry : appenderNameToClassName.entrySet()) {
final String appenderName = entry.getKey();
final String appenderClass = entry.getValue();
buildAppender(appenderName, appenderClass);
}
// Loggers
buildLoggers("log4j.category.");
buildLoggers("log4j.logger.");
buildProperties();
return builder;
} catch (final IllegalArgumentException e) {
throw new ConfigurationException(e);
}
}
private static TemplateResolver<StackTraceElement> createStackTraceElementResolver(
final Builder builder,
final StrSubstitutor substitutor,
final JsonWriter jsonWriter) {
final StackTraceElementObjectResolverContext stackTraceElementObjectResolverContext =
StackTraceElementObjectResolverContext
.newBuilder()
.setSubstitutor(substitutor)
.setJsonWriter(jsonWriter)
.build();
final String stackTraceElementTemplate = readStackTraceElementTemplate(builder);
return TemplateResolvers.ofTemplate(stackTraceElementObjectResolverContext, stackTraceElementTemplate);
}
private TemplateResolver<LogEvent> createEventResolver(
final Builder builder,
final Configuration configuration,
final StrSubstitutor substitutor,
final Charset charset,
final JsonWriter jsonWriter,
final TemplateResolver<StackTraceElement> stackTraceElementObjectResolver) {
final String eventTemplate = readEventTemplate(builder);
final float maxByteCountPerChar = builder.charset.newEncoder().maxBytesPerChar();
final int maxStringByteCount =
Math.toIntExact(Math.round(
maxByteCountPerChar * builder.maxStringLength));
final EventResolverContext resolverContext = EventResolverContext
.newBuilder()
.setConfiguration(configuration)
.setSubstitutor(substitutor)
.setCharset(charset)
.setJsonWriter(jsonWriter)
.setRecyclerFactory(builder.recyclerFactory)
.setMaxStringByteCount(maxStringByteCount)
.setLocationInfoEnabled(builder.locationInfoEnabled)
.setStackTraceEnabled(builder.stackTraceEnabled)
.setStackTraceElementObjectResolver(stackTraceElementObjectResolver)
.setEventTemplateAdditionalFields(builder.eventTemplateAdditionalFields.additionalFields)
.build();
return TemplateResolvers.ofTemplate(resolverContext, eventTemplate);
}
@Test
public void testLookup2() throws Exception {
ContextAnchor.THREAD_CONTEXT.remove();
final ServletContext servletContext = new MockServletContext();
((MockServletContext) servletContext).setContextPath("/");
servletContext.setAttribute("TestAttr", "AttrValue");
servletContext.setInitParameter("myapp.logdir", "target");
servletContext.setAttribute("Name1", "Ben");
servletContext.setInitParameter("Name2", "Jerry");
servletContext.setInitParameter("log4jConfiguration", "WEB-INF/classes/log4j-webvar.xml");
final Log4jWebLifeCycle initializer = WebLoggerContextUtils.getWebLifeCycle(servletContext);
initializer.start();
initializer.setLoggerContext();
final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
assertNotNull("No LoggerContext", ctx);
assertNotNull("No ServletContext", ctx.getExternalContext());
final Configuration config = ctx.getConfiguration();
assertNotNull("No Configuration", config);
final Map<String, Appender> appenders = config.getAppenders();
for (final Map.Entry<String, Appender> entry : appenders.entrySet()) {
if (entry.getKey().equals("file")) {
final FileAppender fa = (FileAppender) entry.getValue();
assertEquals("target/myapp.log", fa.getFileName());
}
}
final StrSubstitutor substitutor = config.getStrSubstitutor();
String value = substitutor.replace("${web:contextPathName:-default}");
assertNotNull("No value for context name", value);
assertEquals("Incorrect value for context name", "default", value);
initializer.stop();
ContextAnchor.THREAD_CONTEXT.remove();
}
/**
* Constructs a new instance.
*
* @param maxFiles The maximum number of files that match the date portion of the pattern to keep.
* @param customActions custom actions to perform asynchronously after rollover
* @param stopCustomActionsOnError whether to stop executing asynchronous actions if an error occurs
* @param tempCompressedFilePatternString File pattern of the working file
* used during compression, if null no temporary file are used
*/
protected DirectWriteRolloverStrategy(final int maxFiles, final int compressionLevel,
final StrSubstitutor strSubstitutor, final Action[] customActions,
final boolean stopCustomActionsOnError, final String tempCompressedFilePatternString) {
super(strSubstitutor);
this.maxFiles = maxFiles;
this.compressionLevel = compressionLevel;
this.stopCustomActionsOnError = stopCustomActionsOnError;
this.customActions = customActions == null ? Collections.<Action> emptyList() : Arrays.asList(customActions);
this.tempCompressedFilePattern =
tempCompressedFilePatternString != null ? new PatternProcessor(tempCompressedFilePatternString) : null;
}
/**
* Formats file name.
* @param subst The StrSubstitutor.
* @param buf string buffer to which formatted file name is appended, may not be null.
* @param obj object to be evaluated in formatting, may not be null.
*/
public final void formatFileName(final StrSubstitutor subst, final StringBuilder buf, final boolean useCurrentTime,
final Object obj) {
// LOG4J2-628: we deliberately use System time, not the log4j.Clock time
// for creating the file name of rolled-over files.
LOGGER.debug("Formatting file name. useCurrentTime={}, currentFileTime={}, prevFileTime={}",
useCurrentTime, currentFileTime, prevFileTime);
final long time = useCurrentTime ? currentFileTime != 0 ? currentFileTime : System.currentTimeMillis() :
prevFileTime != 0 ? prevFileTime : System.currentTimeMillis();
formatFileName(buf, new Date(time), obj);
final LogEvent event = new Log4jLogEvent.Builder().setTimeMillis(time).build();
final String fileName = subst.replace(event, buf);
buf.setLength(0);
buf.append(fileName);
}
private PosixViewAttributeAction(final String basePath, final boolean followSymbolicLinks,
final int maxDepth, final PathCondition[] pathConditions, final StrSubstitutor subst,
final Set<PosixFilePermission> filePermissions,
final String fileOwner, final String fileGroup) {
super(basePath, followSymbolicLinks, maxDepth, pathConditions, subst);
this.filePermissions = filePermissions;
this.fileOwner = fileOwner;
this.fileGroup = fileGroup;
}
@Override
public DefaultRolloverStrategy build() {
int minIndex;
int maxIndex;
boolean useMax;
if (fileIndex != null && fileIndex.equalsIgnoreCase("nomax")) {
minIndex = Integer.MIN_VALUE;
maxIndex = Integer.MAX_VALUE;
useMax = false;
} else {
useMax = fileIndex == null ? true : fileIndex.equalsIgnoreCase("max");
minIndex = MIN_WINDOW_SIZE;
if (min != null) {
minIndex = Integer.parseInt(min);
if (minIndex < 1) {
LOGGER.error("Minimum window size too small. Limited to " + MIN_WINDOW_SIZE);
minIndex = MIN_WINDOW_SIZE;
}
}
maxIndex = DEFAULT_WINDOW_SIZE;
if (max != null) {
maxIndex = Integer.parseInt(max);
if (maxIndex < minIndex) {
maxIndex = minIndex < DEFAULT_WINDOW_SIZE ? DEFAULT_WINDOW_SIZE : minIndex;
LOGGER.error("Maximum window size must be greater than the minimum windows size. Set to " + maxIndex);
}
}
}
final int compressionLevel = Integers.parseInt(compressionLevelStr, Deflater.DEFAULT_COMPRESSION);
// The config object can be null when this object is built programmatically.
StrSubstitutor nonNullStrSubstitutor = config != null ? config.getStrSubstitutor() : new StrSubstitutor();
return new DefaultRolloverStrategy(minIndex, maxIndex, useMax, compressionLevel, nonNullStrSubstitutor,
customActions, stopCustomActionsOnError, tempCompressedFilePattern);
}
/**
* Constructs a new instance.
*
* @param minIndex The minimum index.
* @param maxIndex The maximum index.
* @param customActions custom actions to perform asynchronously after rollover
* @param stopCustomActionsOnError whether to stop executing asynchronous actions if an error occurs
* @param tempCompressedFilePatternString File pattern of the working file
* used during compression, if null no temporary file are used
*/
protected DefaultRolloverStrategy(final int minIndex, final int maxIndex, final boolean useMax,
final int compressionLevel, final StrSubstitutor strSubstitutor, final Action[] customActions,
final boolean stopCustomActionsOnError, final String tempCompressedFilePatternString) {
super(strSubstitutor);
this.minIndex = minIndex;
this.maxIndex = maxIndex;
this.useMax = useMax;
this.compressionLevel = compressionLevel;
this.stopCustomActionsOnError = stopCustomActionsOnError;
this.customActions = customActions == null ? Collections.<Action> emptyList() : Arrays.asList(customActions);
this.tempCompressedFilePattern =
tempCompressedFilePatternString != null ? new PatternProcessor(tempCompressedFilePatternString) : null;
}
public Log4j2Lookup(StrSubstitutor strSubstitutor) {
this.strSubstitutor = strSubstitutor;
}
private Log4j2Lookup createDefaultTestLog4j2Lookup(StrSubstitutor strSubstitutor) {
return new Log4j2Lookup(strSubstitutor);
}
private StrSubstitutor createDefaultTestStrSubstitutor() {
return LoggerContext.getContext(false).getConfiguration().getStrSubstitutor();
}
@NotNull
public Log4j2Lookup defaultTestValueResolver() {
return new Log4j2Lookup(new StrSubstitutor(new Interpolator()));
}
@Override
public StrSubstitutor getSubstitutor() {
return substitutor;
}
public Builder setSubstitutor(final StrSubstitutor substitutor) {
this.substitutor = substitutor;
return this;
}
@Override
public StrSubstitutor getSubstitutor() {
return substitutor;
}
public Builder setSubstitutor(final StrSubstitutor substitutor) {
this.substitutor = substitutor;
return this;
}
@Test
public void testLookup() throws Exception {
ContextAnchor.THREAD_CONTEXT.remove();
final ServletContext servletContext = new MockServletContext();
((MockServletContext) servletContext).setContextPath("/WebApp");
servletContext.setAttribute("TestAttr", "AttrValue");
servletContext.setInitParameter("TestParam", "ParamValue");
servletContext.setAttribute("Name1", "Ben");
servletContext.setInitParameter("Name2", "Jerry");
final Log4jWebLifeCycle initializer = WebLoggerContextUtils.getWebLifeCycle(servletContext);
try {
initializer.start();
initializer.setLoggerContext();
final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
assertNotNull("No LoggerContext", ctx);
assertNotNull("No ServletContext", ctx.getExternalContext());
final Configuration config = ctx.getConfiguration();
assertNotNull("No Configuration", config);
final StrSubstitutor substitutor = config.getStrSubstitutor();
assertNotNull("No Interpolator", substitutor);
String value = substitutor.replace("${web:initParam.TestParam}");
assertNotNull("No value for TestParam", value);
assertEquals("Incorrect value for TestParam: " + value, "ParamValue", value);
value = substitutor.replace("${web:attr.TestAttr}");
assertNotNull("No value for TestAttr", value);
assertEquals("Incorrect value for TestAttr: " + value, "AttrValue", value);
value = substitutor.replace("${web:Name1}");
assertNotNull("No value for Name1", value);
assertEquals("Incorrect value for Name1: " + value, "Ben", value);
value = substitutor.replace("${web:Name2}");
assertNotNull("No value for Name2", value);
assertEquals("Incorrect value for Name2: " + value, "Jerry", value);
value = substitutor.replace("${web:contextPathName}");
assertNotNull("No value for context name", value);
assertEquals("Incorrect value for context name", "WebApp", value);
} catch (final IllegalStateException e) {
fail("Failed to initialize Log4j properly." + e.getMessage());
}
initializer.stop();
ContextAnchor.THREAD_CONTEXT.remove();
}
@Override
public StrSubstitutor getStrSubstitutor() {
return subst;
}
protected AbstractRolloverStrategy(final StrSubstitutor strSubstitutor) {
this.strSubstitutor = strSubstitutor;
}
public StrSubstitutor getStrSubstitutor() {
return strSubstitutor;
}