Gary, I have no problem with components that can be dumbed down to do simple things. I do have a problem with components that only do simple things because people will constantly asked to have them be enhanced.
As for what you are proposing here, can I just say “No”? Having the Appenders element deferred just smells to me and having an arbitrary script there just seems weird to me. Does it even have a contract or is it a free-for-all? How does it cause multiple appenders to be initialized? I think the RoutingAppender is a more appropriate solution. However, if you want to dumb it down a bit and turn it into an AppenderSelector I’d be ok with that. However, it would still be fairly similar to the RoutingAppender. Ralph > On Sep 16, 2016, at 11:43 AM, Gary Gregory <garydgreg...@gmail.com> wrote: > > Now I've dived into this part of the code and consider what this > configuration means for my use case, I see that it works and that the new > feature has merit on its own but... It feels to me like my specific use case > is an edge case of this new routing appender feature: I will only ever have > one route and that route is determined at start up time and will never > change. So it feels rather a heavy hammer for my fly. > > What I think would be nicer is this: > > <Configuration status="WARN" name="RoutingTest"> > <Appenders> > <Script name="AddAppender" language="JavaScript"><![CDATA[ > "OSNameFoo".search("Foo") > -1 ? "List2" : "List1";]]> > </Script> > <List name="List1" /> > <List name="List2" /> > </Appenders> > <Loggers> > <Root level="error"> > <AppenderRef ref="Routing" /> > </Root> > </Loggers> > </Configuration> > > The script AddAppender runs when Appenders is instantiated and picks which > appender to add. > > I think this means that the Appenders plugin must have deferChildren=true. > When created the Appender checks the name of the script, right now there is > only "AddAppender" but you could imagine other names like "AddAppenders" > (plural). If there is no script, the Appenders plugin converts the nodes into > configurations, which gives us the same result as before this change, it's > just that the convertion from nodes to configured items happens a little > later. If there is a script, then it is run and the semantics are applied, in > my case, pick the one Appender node and convert it to a configured appender. > > Thoughts? > > Gary > > On Tue, Sep 13, 2016 at 4:53 PM, Gary Gregory <garydgreg...@gmail.com > <mailto:garydgreg...@gmail.com>> wrote: > I committed a first cut, see comments in > https://issues.apache.org/jira/browse/LOG4J2-1578 > <https://issues.apache.org/jira/browse/LOG4J2-1578> > > Gary > > On Mon, Sep 12, 2016 at 11:40 PM, Ralph Goers <ralph.go...@dslextreme.com > <mailto:ralph.go...@dslextreme.com>> wrote: > Yes, it returns the key. Remember, a Route can dynamically create an Appender > so it isn’t required to be a reference. At the same time we can (and > probably should) pass variables and/or a Map to the script that it can update > in any way it wants for later usage by the Routing script. As is shown, it > can also return null which leaves the default route in place. So it need not > be strictly for returning the default route. > > Ralph > >> On Sep 12, 2016, at 10:30 PM, Gary Gregory <garydgreg...@gmail.com >> <mailto:garydgreg...@gmail.com>> wrote: >> >> Wait a sec, the DefaultRouteScript should return the Route key, not the >> Route ref. Right? >> >> Gary >> >> On Mon, Sep 12, 2016 at 9:53 PM, Gary Gregory <garydgreg...@gmail.com >> <mailto:garydgreg...@gmail.com>> wrote: >> "First, the init script changes the default route based on the OS." >> >> Maybe the tag should be called "DefaultRouteScript" since it's job is to >> return the default route name? >> >> Gary >> >> On Mon, Sep 12, 2016 at 8:05 PM, Ralph Goers <ralph.go...@dslextreme.com >> <mailto:ralph.go...@dslextreme.com>> wrote: >> 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 >> <http://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 >>> <mailto: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> >> >> >> >> >> -- >> 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>