Replace the “?” characters with double quotes. Ralph
> On Sep 12, 2016, at 8:05 PM, Ralph Goers <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") { > 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> >