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 <[email protected]> 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 <[email protected]
>> <mailto:[email protected]>> wrote:
>>
>> On Sun, Sep 11, 2016 at 12:47 PM, Ralph Goers <[email protected]
>> <mailto:[email protected]>> 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 <[email protected]
>>> <mailto:[email protected]>> wrote:
>>>
>>> Are the <Appenders> tags really meant to be nested?
>>>
>>> Gary
>>>
>>> On Sat, Sep 10, 2016 at 11:48 AM, Ralph Goers <[email protected]
>>> <mailto:[email protected]>> wrote:
>>> Oops. I forgot the closing CDATA tag in the script.
>>>
>>> Ralph
>>>
>>>> On Sep 10, 2016, at 11:43 AM, Ralph Goers <[email protected]
>>>> <mailto:[email protected]>> 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 <[email protected]
>>>>> <mailto:[email protected]>> 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 <[email protected]
>>>>> <mailto:[email protected]>> 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 <[email protected]
>>>>> <mailto:[email protected]>> 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: [email protected] <mailto:[email protected]> |
>>>>> [email protected] <mailto:[email protected]>
>>>>> 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: [email protected] <mailto:[email protected]> |
>>>>> [email protected] <mailto:[email protected]>
>>>>> 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: [email protected] <mailto:[email protected]> |
>>>>> [email protected] <mailto:[email protected]>
>>>>> 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: [email protected] <mailto:[email protected]> |
>>> [email protected] <mailto:[email protected]>
>>> 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: [email protected] <mailto:[email protected]> |
>> [email protected] <mailto:[email protected]>
>> 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>