[ https://issues.apache.org/jira/browse/LOG4J2-1578?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Gary Gregory updated LOG4J2-1578: --------------------------------- Description: RoutingAppender can be configured with scripts. h2. Use Case What I need to do is only add a specific appender when running on a specific OS (USS on OS/390 if you must know). Then only add a different appender when not running on that OS. h2. Final Solution Example configuration: {code:xml} <Appenders> <Console name="STDOUT" target="SYSTEM_OUT"> <PatternLayout pattern="%m%n"/> </Console> <Flume name="AuditLogger" compress="true"> <Agent host="192.168.10.101" port="8800"/> <Agent host="192.168.10.102" port="8800"/> <RFC5424Layout enterpriseNumber="18060" includeMDC="true" appName="MyApp"/> </Flume> <Routing name="Routing"> <Script name="RoutingInit" language="groovy"><![CDATA[ if (System.getProperty(?os.name?).contains(?OS/390") { return "OS390"; } return null;]]> </Script> <Routes> <Script name="Router" language="groovy"><![CDATA[ if (logEvent.getMarker() != null && logEvent.getMarker().isInstanceOf("AUDIT")) { return "AUDIT"; } else if (logEvent.getContextMap().containsKey("UserId")) { return logEvent.getContextMap().get("UserId"); } return "STDOUT"; ]]> </Script> <Route> <OS390Appender name="OS390-${mdc:UserId"/> <RollingFile name="Rolling-${mdc:UserId}" fileName="${mdc:UserId}.log" filePattern="${mdc:UserId}.%i.log.gz"> <PatternLayout> <pattern>%d %p %c{1.} [%t] %m%n</pattern> </PatternLayout> <SizeBasedTriggeringPolicy size="500" /> </RollingFile> </Route> <Route ref="AuditLogger" key="Audit"/> <Route ref="STDOUT" key="STDOUT"/> </Routes> <IdlePurgePolicy timeToLive="15" timeUnit="minutes"/> </Routing> </Appenders> {code} As part of this the {{Routes}} class' factory method is deprecated in favor of a builder. h2. Initial Solution Posted by [~ralphgoers] on the dev ML: After reviewing what I wrote below and looking at the Routing Appender I think the best thing to do is just to add script support to it. It already has support for a default Route. The init script, if present, could override which Route to use as I described below. Then we could add a script attribute to the Routes plugin which could be used to select the Route instead of only matching on the ThreadContext key. With that I think you would have everything you want, plus it could be used as a more intelligent way to route to existing appenders. The configuration would then look like: {code:xml} <Appenders> <Console name="STDOUT" target="SYSTEM_OUT"> <PatternLayout pattern="%m%n"/> </Console> <Flume name="AuditLogger" compress="true"> <Agent host="192.168.10.101" port="8800"/> <Agent host="192.168.10.102" port="8800"/> <RFC5424Layout enterpriseNumber="18060" includeMDC="true" appName="MyApp"/> </Flume> <Routing name="Routing"> <InitScript name="RoutingInit" language="groovy"><![CDATA[ if (System.getProperty(?os.name?).contains(?OS/390") { return "OS390"; } return null;]]> </InitScript> <Routes> <Script name="Router" language="groovy"><![CDATA[ if (logEvent.getMarker() != null && logEvent.getMarker().isInstanceOf("AUDIT")) { return "AUDIT"; } else if (logEvent.getContextMap().containsKey("UserId")) { return logEvent.getContextMap().get("UserId"); } return "STDOUT"; ]]> </Script> <Route> <OS390Appender name="OS390-${mdc:UserId"/> <RollingFile name="Rolling-${mdc:UserId}" fileName="${mdc:UserId}.log" filePattern="${mdc:UserId}.%i.log.gz"> <PatternLayout> <pattern>%d %p %c{1.} [%t] %m%n</pattern> </PatternLayout> <SizeBasedTriggeringPolicy size="500" /> </RollingFile> </Route> <Route ref="AuditLogger" key="Audit"/> <Route ref="STDOUT" key="STDOUT"/> </Routes> <IdlePurgePolicy timeToLive="15" timeUnit="minutes"/> </Routing> </Appenders> {code} First, the init script changes the default route based on the OS. Second, notice that "Routes" has a new Script element and does not have a pattern specified, so the script is determining the key instead of the pattern. Third, the real default route is now "STDOUT" since the actual default Route is only referenced when a UserId is present in the thread context map. What would also be nice is if there was a way to have the returned value be usable as a Lookup value in the default Appender definition, instead of relying on the MDC as the code above does. I should be able to pick something out of the message itself and use that as the key. That should be doable but I am still pondering how I would implement that. was: RoutingAppender can be configured with scripts. h2. Use Case What I need to do is only add a specific appender when running on a specific OS (USS on OS/390 if you must know). Then only add a different appender when not running on that OS. h2. Solution Posted by [~ralphgoers] on the dev ML: After reviewing what I wrote below and looking at the Routing Appender I think the best thing to do is just to add script support to it. It already has support for a default Route. The init script, if present, could override which Route to use as I described below. Then we could add a script attribute to the Routes plugin which could be used to select the Route instead of only matching on the ThreadContext key. With that I think you would have everything you want, plus it could be used as a more intelligent way to route to existing appenders. The configuration would then look like: {code:xml} <Appenders> <Console name="STDOUT" target="SYSTEM_OUT"> <PatternLayout pattern="%m%n"/> </Console> <Flume name="AuditLogger" compress="true"> <Agent host="192.168.10.101" port="8800"/> <Agent host="192.168.10.102" port="8800"/> <RFC5424Layout enterpriseNumber="18060" includeMDC="true" appName="MyApp"/> </Flume> <Routing name="Routing"> <InitScript name="RoutingInit" language="groovy"><![CDATA[ if (System.getProperty(?os.name?).contains(?OS/390") { return "OS390"; } return null;]]> </InitScript> <Routes> <Script name="Router" language="groovy"><![CDATA[ if (logEvent.getMarker() != null && logEvent.getMarker().isInstanceOf("AUDIT")) { return "AUDIT"; } else if (logEvent.getContextMap().containsKey("UserId")) { return logEvent.getContextMap().get("UserId"); } return "STDOUT"; ]]> </Script> <Route> <OS390Appender name="OS390-${mdc:UserId"/> <RollingFile name="Rolling-${mdc:UserId}" fileName="${mdc:UserId}.log" filePattern="${mdc:UserId}.%i.log.gz"> <PatternLayout> <pattern>%d %p %c{1.} [%t] %m%n</pattern> </PatternLayout> <SizeBasedTriggeringPolicy size="500" /> </RollingFile> </Route> <Route ref="AuditLogger" key="Audit"/> <Route ref="STDOUT" key="STDOUT"/> </Routes> <IdlePurgePolicy timeToLive="15" timeUnit="minutes"/> </Routing> </Appenders> {code} First, the init script changes the default route based on the OS. Second, notice that "Routes" has a new Script element and does not have a pattern specified, so the script is determining the key instead of the pattern. Third, the real default route is now "STDOUT" since the actual default Route is only referenced when a UserId is present in the thread context map. What would also be nice is if there was a way to have the returned value be usable as a Lookup value in the default Appender definition, instead of relying on the MDC as the code above does. I should be able to pick something out of the message itself and use that as the key. That should be doable but I am still pondering how I would implement that. > RoutingAppender can be configured with scripts > ---------------------------------------------- > > Key: LOG4J2-1578 > URL: https://issues.apache.org/jira/browse/LOG4J2-1578 > Project: Log4j 2 > Issue Type: New Feature > Reporter: Gary Gregory > Assignee: Gary Gregory > > RoutingAppender can be configured with scripts. > h2. Use Case > What I need to do is only add a specific appender when running on a specific > OS (USS on OS/390 if you must know). Then only add a different appender when > not running on that OS. > h2. Final Solution > Example configuration: > {code:xml} > <Appenders> > <Console name="STDOUT" target="SYSTEM_OUT"> > <PatternLayout pattern="%m%n"/> > </Console> > <Flume name="AuditLogger" compress="true"> > <Agent host="192.168.10.101" port="8800"/> > <Agent host="192.168.10.102" port="8800"/> > <RFC5424Layout enterpriseNumber="18060" includeMDC="true" > appName="MyApp"/> > </Flume> > <Routing name="Routing"> > <Script name="RoutingInit" language="groovy"><![CDATA[ > if (System.getProperty(?os.name?).contains(?OS/390") { > return "OS390"; > } > return null;]]> > </Script> > <Routes> > <Script name="Router" language="groovy"><![CDATA[ > if (logEvent.getMarker() != null && > logEvent.getMarker().isInstanceOf("AUDIT")) { > return "AUDIT"; > } else if (logEvent.getContextMap().containsKey("UserId")) { > return logEvent.getContextMap().get("UserId"); > } > return "STDOUT"; > ]]> > </Script> > <Route> > <OS390Appender name="OS390-${mdc:UserId"/> > <RollingFile name="Rolling-${mdc:UserId}" > fileName="${mdc:UserId}.log" > filePattern="${mdc:UserId}.%i.log.gz"> > <PatternLayout> > <pattern>%d %p %c{1.} [%t] %m%n</pattern> > </PatternLayout> > <SizeBasedTriggeringPolicy size="500" /> > </RollingFile> > </Route> > <Route ref="AuditLogger" key="Audit"/> > <Route ref="STDOUT" key="STDOUT"/> > </Routes> > <IdlePurgePolicy timeToLive="15" timeUnit="minutes"/> > </Routing> > </Appenders> > {code} > As part of this the {{Routes}} class' factory method is deprecated in favor > of a builder. > h2. Initial Solution > Posted by [~ralphgoers] on the dev ML: > After reviewing what I wrote below and looking at the Routing Appender I > think the best thing to do is just to add script support to it. It already > has support for a default Route. The init script, if present, could override > which Route to use as I described below. Then we could add a script attribute > to the Routes plugin which could be used to select the Route instead of only > matching on the ThreadContext key. > With that I think you would have everything you want, plus it could be used > as a more intelligent way to route to existing appenders. > The configuration would then look like: > {code:xml} > <Appenders> > <Console name="STDOUT" target="SYSTEM_OUT"> > <PatternLayout pattern="%m%n"/> > </Console> > <Flume name="AuditLogger" compress="true"> > <Agent host="192.168.10.101" port="8800"/> > <Agent host="192.168.10.102" port="8800"/> > <RFC5424Layout enterpriseNumber="18060" includeMDC="true" > appName="MyApp"/> > </Flume> > <Routing name="Routing"> > <InitScript name="RoutingInit" language="groovy"><![CDATA[ > if (System.getProperty(?os.name?).contains(?OS/390") { > return "OS390"; > } > return null;]]> > </InitScript> > <Routes> > <Script name="Router" language="groovy"><![CDATA[ > if (logEvent.getMarker() != null && > logEvent.getMarker().isInstanceOf("AUDIT")) { > return "AUDIT"; > } else if (logEvent.getContextMap().containsKey("UserId")) { > return logEvent.getContextMap().get("UserId"); > } > return "STDOUT"; > ]]> > </Script> > <Route> > <OS390Appender name="OS390-${mdc:UserId"/> > <RollingFile name="Rolling-${mdc:UserId}" > fileName="${mdc:UserId}.log" > filePattern="${mdc:UserId}.%i.log.gz"> > <PatternLayout> > <pattern>%d %p %c{1.} [%t] %m%n</pattern> > </PatternLayout> > <SizeBasedTriggeringPolicy size="500" /> > </RollingFile> > </Route> > <Route ref="AuditLogger" key="Audit"/> > <Route ref="STDOUT" key="STDOUT"/> > </Routes> > <IdlePurgePolicy timeToLive="15" timeUnit="minutes"/> > </Routing> > </Appenders> > {code} > First, the init script changes the default route based on the OS. > Second, notice that "Routes" has a new Script element and does not have a > pattern specified, so the script is determining the key instead of the > pattern. > Third, the real default route is now "STDOUT" since the actual default Route > is only referenced when a UserId is present in the thread context map. > What would also be nice is if there was a way to have the returned value be > usable as a Lookup value in the default Appender definition, instead of > relying on the MDC as the code above does. I should be able to pick something > out of the message itself and use that as the key. That should be doable but > I am still pondering how I would implement that. -- This message was sent by Atlassian JIRA (v6.3.4#6332) --------------------------------------------------------------------- To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org For additional commands, e-mail: log4j-dev-h...@logging.apache.org