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: <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> 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. Ralph > On Sep 12, 2016, at 6:06 PM, Ralph Goers <ralph.go...@dslextreme.com> wrote: > > I’ll try to describe it better but I’m not sure how good a job I’ll do if the > dots aren’t clicking yet. Also, even though I might say to do it one way if I > was coding I could very well change my mind as I implement it. That said: > Create an Appender plugin named ScriptSelector or ScriptAppenderSelector. It > needs the following parameters > name, a String PluginAttribute > default, a String PluginAttribute > initScript or startupScript, an AbstractScript PluginElement > script, an AbstractScript PluginElement > appenderList, an AppenderList PluginElement. > As always, the builder (or factory) creates an instance of the > ScriptAppenderSelector. > If there is an init script then the builder (or factory) executes it. > If the returned value is not null then instantiate the Appender with that > name using the configuration in the AppenderList. > Whatever Appender the init script names should become the default Appender. > If no init script is present or the init script returns null use the value of > the default setting as the name of the default Appender to use. > Create the default Appender and save it in the Map of created appenders > wrapped by an AppenderControl. > When the append method is called check for a script setting. > If a script is found, run it. > If it returns a value see if that appender is saved in the AppenderMap. > If it is, call the appender and return. > If it is not, locate the configuration for the appender, create it and add it > to the AppenderMap. Then call it and return. > If it returns null or no script is defined then call the default Appender and > return. > When the stop method is called call the stop method on each of the Appenders > in the AppenderMap. > > Note that signatures for scripts are defined by the components that use them. > In this case both the init script and script return the name of the appender > to execute. > > Ralph > > >> On Sep 12, 2016, at 12:54 PM, Gary Gregory <garydgreg...@gmail.com >> <mailto:garydgreg...@gmail.com>> wrote: >> >> On Sun, Sep 11, 2016 at 12:47 PM, Ralph Goers <ralph.go...@dslextreme.com >> <mailto:ralph.go...@dslextreme.com>> wrote: >> Yes. The Appenders tag inside the ScriptSelector are the Appenders that are >> to be created. But now that I think about it, we can’t use “Appenders” for >> this. If you look at the RoutingAppender you will notice that Appenders >> there are declared under a Route element. The Route plugin is defined with >> deferChildren=true. This means that whatever is configured under the Route >> will not be created during initial configuration. Instead the Route keeps a >> reference to the Node and then configures the Appender when it is required. >> So we would need a new plugin to wrap the Appenders that are to be created. >> >> Can you please describe in more detail how this new plug fits in and what it >> does? I can't quite connect the dots with the parallel of the routing >> appender. I'm willing to implement this as I need the feature ASAP. >> >> Gary >> >> >> Ralph >> >>> On Sep 11, 2016, at 11:10 AM, Gary Gregory <garydgreg...@gmail.com >>> <mailto:garydgreg...@gmail.com>> wrote: >>> >>> Are the <Appenders> tags really meant to be nested? >>> >>> Gary >>> >>> On Sat, Sep 10, 2016 at 11:48 AM, Ralph Goers <ralph.go...@dslextreme.com >>> <mailto:ralph.go...@dslextreme.com>> wrote: >>> Oops. I forgot the closing CDATA tag in the script. >>> >>> Ralph >>> >>>> On Sep 10, 2016, at 11:43 AM, Ralph Goers <ralph.go...@dslextreme.com >>>> <mailto:ralph.go...@dslextreme.com>> wrote: >>>> >>>> Interesting. OS/390. I worked on MVS, OS/370, z/OS, etc many moons ago >>>> but haven’t worked on a mainframe since 2001. >>>> >>>> This sort of sounds like you want an Appender Selector, which would be an >>>> Appender that uses a Selector to figure out which Appender to delegate to. >>>> This is a bit like the PatternSelector. I would imagine it would make >>>> sense to implement AppenderSelectors and LayoutSelectors. You probably >>>> would want to dynamically initialize the Appenders much like the >>>> RoutingAppender does. >>>> >>>> Maybe it would look like: >>>> >>>> <Appenders> >>>> <ScriptSelector name=“" default=“”> >>>> <Script language=“groovy”><![CDATA[ >>>> if (System.getProperty”os.name >>>> <http://os.name/>”).contains(“OS/390”)) then { >>>> return “Socket”; >>>> } else { >>>> return “File”; >>>> } >>>> </Script> >>>> <Appenders> >>>> <SocketAppender name=“Socket” …/> >>>> <FileAppender name=“File” …/> >>>> </Appenders> >>>> </ScriptSelector> >>>> </Appenders> >>>> >>>> The thing is that this script would run every time the Selector was >>>> accessed while it sounds like you would only want the script to run when >>>> the Selector is initialized. We could do that too but the script would >>>> need to be declared in a property that would only be used when the >>>> selector is initialized. I would want to support being able to do both. >>>> >>>> Ralph >>>> >>>>> On Sep 10, 2016, at 11:04 AM, Gary Gregory <garydgreg...@gmail.com >>>>> <mailto:garydgreg...@gmail.com>> wrote: >>>>> >>>>> <Appenders> >>>>> <ScriptTest language="JavaScript"> >>>>> <If>System.getProperty("os.name >>>>> <http://os.name/>").contains("OS/390")</If> >>>>> <True> >>>>> <SocketAppender ...> >>>>> </True> >>>>> <False> >>>>> <FileAppender ...> >>>>> </False> >>>>> </ScriptTest> >>>>> </Appenders> >>>>> >>>>> ? >>>>> >>>>> >>>>> On Sat, Sep 10, 2016 at 10:40 AM, Gary Gregory <garydgreg...@gmail.com >>>>> <mailto:garydgreg...@gmail.com>> wrote: >>>>> OK, I found >>>>> https://logging.apache.org/log4j/2.x/manual/configuration.html#Scripts >>>>> <https://logging.apache.org/log4j/2.x/manual/configuration.html#Scripts> >>>>> and I think I could use either: >>>>> >>>>> - Use composite configurations: One file for OS/390, one for all other >>>>> OSs; or >>>>> - Do it all in one configuration file (that seems simpler) >>>>> >>>>> It seems like there are some pieces missing to do what I want >>>>> conveniently. >>>>> >>>>> Should I define all appenders in <Appenders> and later use a script to >>>>> only add the one(s) I want in the <Root> section? >>>>> >>>>> Or, should the <Appenders> section itself be scripted to only add the >>>>> appenders I want? >>>>> >>>>> Since I expect the OS/390 appender will likely blow up running on a >>>>> different OK I do not want to create it unless I know it can run OK. >>>>> >>>>> I guess then I have a conditional section in both the Appenders and in >>>>> the Root section so that when I say <AppenderRef =...> we do not go look >>>>> for an appender that is not defined. >>>>> >>>>> Thoughts? >>>>> >>>>> A narrow solution would be to add an "os" attribute to all appenders but >>>>> that seems lame. os="OS/390" and os="!OS/390" means also knowing about >>>>> "not", yikes. >>>>> >>>>> Gary >>>>> >>>>> On Sat, Sep 10, 2016 at 10:05 AM, Gary Gregory <garydgreg...@gmail.com >>>>> <mailto:garydgreg...@gmail.com>> wrote: >>>>> Hi, >>>>> >>>>> I can't seem to find on our site the scripting support that was recently >>>>> added (or is that only in master?). >>>>> >>>>> 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. >>>>> >>>>> I'd rather not have to hard-code this and make thing more complicated. >>>>> >>>>> Thoughts? >>>>> >>>>> Gary >>>>> >>>>> -- >>>>> E-Mail: garydgreg...@gmail.com <mailto:garydgreg...@gmail.com> | >>>>> ggreg...@apache.org <mailto:ggreg...@apache.org> >>>>> Java Persistence with Hibernate, Second Edition >>>>> <http://www.manning.com/bauer3/> >>>>> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> >>>>> Spring Batch in Action <http://www.manning.com/templier/> >>>>> Blog: http://garygregory.wordpress.com >>>>> <http://garygregory.wordpress.com/> >>>>> Home: http://garygregory.com/ <http://garygregory.com/> >>>>> Tweet! http://twitter.com/GaryGregory <http://twitter.com/GaryGregory> >>>>> >>>>> >>>>> -- >>>>> E-Mail: garydgreg...@gmail.com <mailto:garydgreg...@gmail.com> | >>>>> ggreg...@apache.org <mailto:ggreg...@apache.org> >>>>> Java Persistence with Hibernate, Second Edition >>>>> <http://www.manning.com/bauer3/> >>>>> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> >>>>> Spring Batch in Action <http://www.manning.com/templier/> >>>>> Blog: http://garygregory.wordpress.com >>>>> <http://garygregory.wordpress.com/> >>>>> Home: http://garygregory.com/ <http://garygregory.com/> >>>>> Tweet! http://twitter.com/GaryGregory <http://twitter.com/GaryGregory> >>>>> >>>>> >>>>> -- >>>>> E-Mail: garydgreg...@gmail.com <mailto:garydgreg...@gmail.com> | >>>>> ggreg...@apache.org <mailto:ggreg...@apache.org> >>>>> Java Persistence with Hibernate, Second Edition >>>>> <http://www.manning.com/bauer3/> >>>>> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> >>>>> Spring Batch in Action <http://www.manning.com/templier/> >>>>> Blog: http://garygregory.wordpress.com >>>>> <http://garygregory.wordpress.com/> >>>>> Home: http://garygregory.com/ <http://garygregory.com/> >>>>> Tweet! http://twitter.com/GaryGregory <http://twitter.com/GaryGregory> >>> >>> >>> >>> >>> -- >>> E-Mail: garydgreg...@gmail.com <mailto:garydgreg...@gmail.com> | >>> ggreg...@apache.org <mailto:ggreg...@apache.org> >>> Java Persistence with Hibernate, Second Edition >>> <http://www.manning.com/bauer3/> >>> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> >>> Spring Batch in Action <http://www.manning.com/templier/> >>> Blog: http://garygregory.wordpress.com <http://garygregory.wordpress.com/> >>> Home: http://garygregory.com/ <http://garygregory.com/> >>> Tweet! http://twitter.com/GaryGregory <http://twitter.com/GaryGregory> >> >> >> >> -- >> E-Mail: garydgreg...@gmail.com <mailto:garydgreg...@gmail.com> | >> ggreg...@apache.org <mailto:ggreg...@apache.org> >> Java Persistence with Hibernate, Second Edition >> <http://www.manning.com/bauer3/> >> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> >> Spring Batch in Action <http://www.manning.com/templier/> >> Blog: http://garygregory.wordpress.com <http://garygregory.wordpress.com/> >> Home: http://garygregory.com/ <http://garygregory.com/> >> Tweet! http://twitter.com/GaryGregory <http://twitter.com/GaryGregory>