1. 程式人生 > >《Log4j 2 官方文件》Scripts

《Log4j 2 官方文件》Scripts

scriptFile包含了指令碼的名稱,和這個指令碼所在的位置,語言,字符集,是否對指令碼的變化進行監視。

scriptRef包含了在script元素定義的指令碼名稱。

指令碼的名稱通常用來儲存指令碼,並且和他的指令碼引擎在一起,因此每次指令碼需要執行的時候都可以被快速定位。然而指令碼的名字不是必須的,提供名字方便在執行的時候有助於除錯。在script元素中必須指定指令碼語言(language屬性),而且這些語言必須是在配置列表中的語言。如果指令碼語言沒有在scriptFile元素上指定,那麼通過指令碼的副檔名來識別指令碼語言。如果指令碼檔案監控需要執行,那麼必須在configuration元素中設定monitorInterval

為非0的值。間隔interval時長,系統將會檢測指令碼檔案的變化。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug" name="RoutingTest">
  <Scripts>
    <Script name="selector" language="javascript"><![CDATA[
            var result;
            if (logEvent.getLoggerName().equals("JavascriptNoLocation"
)) { result = "NoLocation"; } else if (logEvent.getMarker() != null && logEvent.getMarker().isInstanceOf("FLOW")) { result = "Flow"; } result; ]]>
</Script> <ScriptFile name="groovy.filter" path
="scripts/filter.groovy"/>
</Scripts> <Appenders> <Console name="STDOUT"> <ScriptPatternSelector defaultPattern="%d %p %m%n"> <ScriptRef ref="selector"/> <PatternMatch key="NoLocation" pattern="[%-5level] %c{1.} %msg%n"/> <PatternMatch key="Flow" pattern="[%-5level] %c{1.} ====== %C{1.}.%M:%L %msg ======%n"/> </ScriptPatternSelector> <PatternLayout pattern="%m%n"/> </Console> </Appenders> <Loggers> <Logger name="EventLogger" level="info" additivity="false"> <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY"> <Script name="GroovyFilter" language="groovy"><![CDATA[ if (logEvent.getMarker() != null && logEvent.getMarker().isInstanceOf("FLOW")) { return true; } else if (logEvent.getContextMap().containsKey("UserId")) { return true; } return false; ]]> </Script> </ScriptFilter> <AppenderRef ref="STDOUT"/> </Logger> <Root level="error"> <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY"> <ScriptRef ref="groovy.filter"/> </ScriptFilter> <AppenderRef ref="STDOUT"/> </Root> </Loggers> </Configuration>

如果Configuration元素設定statusDEBUG,那麼啟動的時候當前安裝的指令碼引擎以及指令碼的資訊,將會在輸出日誌中逐條顯示出來。

儘管有些引擎不是執行緒安全的,但是Log4j會確保他們線上程安全的模式下執行。

2015-09-27 16:13:22,925 main DEBUG Installed script engines
2015-09-27 16:13:22,963 main DEBUG AppleScriptEngine Version: 1.1, Language: AppleScript, Threading: Not Thread Safe,
            Compile: false, Names: {AppleScriptEngine, AppleScript, OSA}
2015-09-27 16:13:22,983 main DEBUG Groovy Scripting Engine Version: 2.0, Language: Groovy, Threading: MULTITHREADED,
            Compile: true, Names: {groovy, Groovy}
2015-09-27 16:13:23,030 main DEBUG BeanShell Engine Version: 1.0, Language: BeanShell, Threading: MULTITHREADED,
            Compile: true, Names: {beanshell, bsh, java}
2015-09-27 16:13:23,039 main DEBUG Mozilla Rhino Version: 1.7 release 3 PRERELEASE, Language: ECMAScript, Threading: MULTITHREADED,
            Compile: true, Names: {js, rhino, JavaScript, javascript, ECMAScript, ecmascript}

當指令碼被執行,他們會提供一系列的變數,這些變數保證完成 各種他們期望執行的各種任務。指令碼可用變數的列表,可以檢視每個元件的相關文件。

元件期望指令碼的返回值傳遞給Java程式碼。對於大多數指令碼語言都不是問題,但是JavaScript不允許返回,除非是在一個fuction裡。

然後JavaScript將指令碼中的最後一個表示式返回。

如下的程式碼就是我們期望的結果(result被返回)。

var result;
            if (logEvent.getLoggerName().equals("JavascriptNoLocation")) {
                result = "NoLocation";
            } else if (logEvent.getMarker() != null && logEvent.getMarker().isInstanceOf("FLOW")) {
                result = "Flow";
            }
            result;

Beanshell 備註

JSR 223 指令碼引擎規定如果引擎支援編譯他們的指令碼,需要識別他們支援的編譯介面。Beanshell就有這樣的特點。

然後無論什麼情況編譯方法只要被呼叫就會報一個錯誤(不是異常)

Log4j捕獲了這個錯誤,並且將這個錯誤列印了出來。所有的BeanShell指令碼在每次執行的時候才進行解釋(解釋執行)。

2015-09-27 16:13:23,095 main DEBUG Script BeanShellSelector is compilable
2015-09-27 16:13:23,096 main WARN Error compiling script java.lang.Error: unimplemented
            at bsh.engine.BshScriptEngine.compile(BshScriptEngine.java:175)
            at bsh.engine.BshScriptEngine.compile(BshScriptEngine.java:154)
            at org.apache.logging.log4j.core.script.ScriptManager$MainScriptRunner.<init>(ScriptManager.java:125)
            at org.apache.logging.log4j.core.script.ScriptManager.addScript(ScriptManager.java:94)