private LogstashLayout(Builder builder) { super(builder.config, StandardCharsets.UTF_8, null, null); String template = readTemplate(builder); FastDateFormat timestampFormat = readDateFormat(builder); ObjectMapper objectMapper = new ObjectMapper(); StrSubstitutor substitutor = builder.config.getStrSubstitutor(); TemplateResolverContext resolverContext = TemplateResolverContext .newBuilder() .setObjectMapper(objectMapper) .setTimestampFormat(timestampFormat) .setLocationInfoEnabled(builder.locationInfoEnabled) .setStackTraceEnabled(builder.stackTraceEnabled) .setMdcKeyPattern(builder.mdcKeyPattern) .setNdcPattern(builder.ndcPattern) .build(); this.renderer = TemplateRenderer .newBuilder() .setSubstitutor(substitutor) .setResolverContext(resolverContext) .setPrettyPrintEnabled(builder.prettyPrintEnabled) .setTemplate(template) .setResolvers(RESOLVERS) .build(); }
/** * Merges the contents of the specified map into the contextMap, after * replacing any variables in the property values with the * StrSubstitutor-supplied actual values. * * @param properties configured properties * @param strSubstitutor used to lookup values of variables in properties */ public void mergePropertiesIntoContextMap( final Map<Property, Boolean> properties, final StrSubstitutor strSubstitutor) { if (properties == null) { return; // nothing to do } final Map<String, String> map = (contextMap == null) ? new HashMap<String, String>() : new HashMap<String, String>(contextMap); for (final Map.Entry<Property, Boolean> entry : properties.entrySet()) { final Property prop = entry.getKey(); if (map.containsKey(prop.getName())) { continue; // contextMap overrides config properties } final String value = entry.getValue() ? strSubstitutor.replace(prop .getValue()) : prop.getValue(); map.put(prop.getName(), value); } contextMap = map; }
private Map<String, String> resolveAdditionalFields(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 (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; }
public static boolean isUsingGemFireDefaultConfig() { final Configuration config = ((org.apache.logging.log4j.core.Logger) LogManager.getLogger(ROOT_LOGGER_NAME, GemFireParameterizedMessageFactory.INSTANCE)).getContext().getConfiguration(); final StrSubstitutor sub = config.getStrSubstitutor(); final StrLookup resolver = sub.getVariableResolver(); final String value = resolver.lookup(GEMFIRE_DEFAULT_PROPERTY); return "true".equals(value); }
/** * 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; }
/** * Format 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 Object obj) { final long time = prevFileTime == 0 ? System.currentTimeMillis() : prevFileTime; formatFileName(buf, new Date(time), obj); LogEvent event = new Log4jLogEvent(time); String fileName = subst.replace(event, buf); buf.setLength(0); buf.append(fileName); }
/** * Constructs a new instance. * @param minIndex The minimum index. * @param maxIndex The maximum index. */ protected DefaultRolloverStrategy(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; }
@Test public void testLookup() throws Exception { ServletContext servletContext = new MockServletContext(); servletContext.setAttribute("TestAttr", "AttrValue"); servletContext.setInitParameter("TestParam", "ParamValue"); servletContext.setAttribute("Name1", "Ben"); servletContext.setInitParameter("Name2", "Jerry"); Log4jWebInitializer initializer = Log4jWebInitializerImpl.getLog4jWebInitializer(servletContext); try { initializer.initialize(); initializer.setLoggerContext(); LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get(); assertNotNull("No LoggerContext", ctx); Configuration config = ctx.getConfiguration(); assertNotNull("No Configuration", config); StrSubstitutor substitutor = config.getStrSubstitutor(); assertNotNull("No Interpolator", substitutor); String value = substitutor.replace("${web:initParam.TestParam}"); assertNotNull("No value for TestParam", value); assertTrue("Incorrect value for TestParam: " + value, "ParamValue".equals(value)); value = substitutor.replace("${web:attr.TestAttr}"); assertNotNull("No value for TestAttr", value); assertTrue("Incorrect value for TestAttr: " + value, "AttrValue".equals(value)); value = substitutor.replace("${web:Name1}"); assertNotNull("No value for Name1", value); assertTrue("Incorrect value for Name1: " + value, "Ben".equals(value)); value = substitutor.replace("${web:Name2}"); assertNotNull("No value for Name2", value); assertTrue("Incorrect value for Name2: " + value, "Jerry".equals(value)); } catch (final UnavailableException e) { fail("Failed to initialize Log4j properly." + e.getMessage()); } }
/** * 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); } }
@Test public void testLookup() throws Exception { ContextAnchor.THREAD_CONTEXT.remove(); final ServletContext servletContext = new MockServletContext(); 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); } catch (final IllegalStateException e) { fail("Failed to initialize Log4j properly." + e.getMessage()); } 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. final long time = useCurrentTime && currentFileTime != 0 ? currentFileTime : 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; }
/** * 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 StrSubstitutor getSubstitutor() { return substitutor; }
public Builder setSubstitutor(StrSubstitutor substitutor) { this.substitutor = substitutor; return this; }
@Override public StrSubstitutor getStrSubstitutor() { return subst; }
@Override public PluginVisitor<A> setStrSubstitutor(final StrSubstitutor aSubstitutor) { this.substitutor = Objects.requireNonNull(aSubstitutor, "No StrSubstitutor was provided"); return this; }
protected AbstractRolloverStrategy(final StrSubstitutor strSubstitutor) { this.strSubstitutor = strSubstitutor; }
public StrSubstitutor getStrSubstitutor() { return strSubstitutor; }
public StrSubstitutor getStrSubstitutor() { return subst; }
private StringBuilder toText(final LogEvent event, final StringBuilder builder, final boolean gcFree) { builder.append('{'); builder.append("\"version\":\"1.1\","); builder.append("\"host\":\""); JsonUtils.quoteAsString(toNullSafeString(host), builder); builder.append(QC); builder.append("\"timestamp\":").append(formatTimestamp(event.getTimeMillis())).append(C); builder.append("\"level\":").append(formatLevel(event.getLevel())).append(C); if (event.getThreadName() != null) { builder.append("\"_thread\":\""); JsonUtils.quoteAsString(event.getThreadName(), builder); builder.append(QC); } if (event.getLoggerName() != null) { builder.append("\"_logger\":\""); JsonUtils.quoteAsString(event.getLoggerName(), builder); builder.append(QC); } if (additionalFields.length > 0) { final StrSubstitutor strSubstitutor = getConfiguration().getStrSubstitutor(); for (final KeyValuePair additionalField : additionalFields) { builder.append(QU); JsonUtils.quoteAsString(additionalField.getKey(), builder); builder.append("\":\""); final String value = valueNeedsLookup(additionalField.getValue()) ? strSubstitutor.replace(event, additionalField.getValue()) : additionalField.getValue(); JsonUtils.quoteAsString(toNullSafeString(value), builder); builder.append(QC); } } if (includeThreadContext) { event.getContextData().forEach(WRITE_KEY_VALUES_INTO, builder); } if (event.getThrown() != null) { builder.append("\"full_message\":\""); if (includeStacktrace) { JsonUtils.quoteAsString(formatThrowable(event.getThrown()), builder); } else { JsonUtils.quoteAsString(event.getThrown().toString(), builder); } builder.append(QC); } builder.append("\"short_message\":\""); final Message message = event.getMessage(); if (message instanceof CharSequence) { JsonUtils.quoteAsString(((CharSequence)message), builder); } else if (gcFree && message instanceof StringBuilderFormattable) { final StringBuilder messageBuffer = getMessageStringBuilder(); try { ((StringBuilderFormattable) message).formatTo(messageBuffer); JsonUtils.quoteAsString(messageBuffer, builder); } finally { trimToMaxSize(messageBuffer); } } else { JsonUtils.quoteAsString(toNullSafeString(message.getFormattedMessage()), builder); } builder.append(Q); builder.append('}'); if (includeNullDelimiter) { builder.append('\0'); } return builder; }
/** * 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 * @deprecated Since 2.9 Added tempCompressedFilePatternString parameter */ @Deprecated protected DirectWriteRolloverStrategy(final int maxFiles, final int compressionLevel, final StrSubstitutor strSubstitutor, final Action[] customActions, final boolean stopCustomActionsOnError) { this(maxFiles, compressionLevel, strSubstitutor, customActions, stopCustomActionsOnError, null); }
/** * Creates a new AbstractPathAction that starts scanning for files to process from the specified base path. * * @param basePath base path from where to start scanning for files to process. * @param followSymbolicLinks whether to follow symbolic links. Default is false. * @param maxDepth The maxDepth parameter is the maximum number of levels of directories to visit. A value of 0 * means that only the starting file is visited, unless denied by the security manager. A value of * MAX_VALUE may be used to indicate that all levels should be visited. * @param pathFilters an array of path filters (if more than one, they all need to accept a path before it is * processed). */ protected AbstractPathAction(final String basePath, final boolean followSymbolicLinks, final int maxDepth, final PathCondition[] pathFilters, final StrSubstitutor subst) { this.basePathString = basePath; this.options = followSymbolicLinks ? EnumSet.of(FileVisitOption.FOLLOW_LINKS) : Collections.<FileVisitOption> emptySet(); this.maxDepth = maxDepth; this.pathConditions = Arrays.asList(Arrays.copyOf(pathFilters, pathFilters.length)); this.subst = subst; }
/** * Creates a new DeleteAction that starts scanning for files to delete from the specified base path. * * @param basePath base path from where to start scanning for files to delete. * @param followSymbolicLinks whether to follow symbolic links. Default is false. * @param maxDepth The maxDepth parameter is the maximum number of levels of directories to visit. A value of 0 * means that only the starting file is visited, unless denied by the security manager. A value of * MAX_VALUE may be used to indicate that all levels should be visited. * @param testMode if true, files are not deleted but instead a message is printed to the <a * href="http://logging.apache.org/log4j/2.x/manual/configuration.html#StatusMessages">status logger</a> * at INFO level. Users can use this to do a dry run to test if their configuration works as expected. * @param sorter sorts * @param pathConditions an array of path filters (if more than one, they all need to accept a path before it is * deleted). * @param scriptCondition */ DeleteAction(final String basePath, final boolean followSymbolicLinks, final int maxDepth, final boolean testMode, final PathSorter sorter, final PathCondition[] pathConditions, final ScriptCondition scriptCondition, final StrSubstitutor subst) { super(basePath, followSymbolicLinks, maxDepth, pathConditions, subst); this.testMode = testMode; this.pathSorter = Objects.requireNonNull(sorter, "sorter"); this.scriptCondition = scriptCondition; if (scriptCondition == null && (pathConditions == null || pathConditions.length == 0)) { LOGGER.error("Missing Delete conditions: unconditional Delete not supported"); throw new IllegalArgumentException("Unconditional Delete not supported"); } }
/** * 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 * @deprecated Since 2.9 Added tempCompressedFilePatternString parameter */ @Deprecated protected DefaultRolloverStrategy(final int minIndex, final int maxIndex, final boolean useMax, final int compressionLevel, final StrSubstitutor strSubstitutor, final Action[] customActions, final boolean stopCustomActionsOnError) { this(minIndex, maxIndex, useMax, compressionLevel, strSubstitutor, customActions, stopCustomActionsOnError, null); }
/** * Sets the StrSubstitutor to use for converting raw strings before type conversion. Generally obtained from a * {@link org.apache.logging.log4j.core.config.Configuration}. * * @param substitutor the StrSubstitutor to use on plugin values. * @return {@code this}. * @throws NullPointerException if the argument is {@code null}. */ PluginVisitor<A> setStrSubstitutor(StrSubstitutor substitutor);
/** * 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 Object obj) { formatFileName(subst, buf, false, obj); }
/** * Define string substituter. * * @param subst {@link AbstractPathAction#getStrSubstitutor()} * @return This builder */ public Builder withSubst(final StrSubstitutor subst) { this.subst = subst; return this; }
StrSubstitutor getStrSubstitutor();