Editing Loggifier.unkrig.de

Jump to navigation Jump to search
Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.

Latest revision Your text
Line 1: Line 1:
<meta name="keywords" content="java, logging, inject, automated"></meta>
<meta name="description" content="A tool for automated injection of logging code into Java class files"></meta>
== Motivation ==
== Motivation ==


Line 40: Line 38:
** The LOGGIFIER [[Loggifier.unkrig.de / Tools / Command line tool|command line tool]]
** The LOGGIFIER [[Loggifier.unkrig.de / Tools / Command line tool|command line tool]]
** The LOGGIFIER [[Loggifier.unkrig.de / Tools / Eclipse plug-in|ECLIPSE plug-in]]
** The LOGGIFIER [[Loggifier.unkrig.de / Tools / Eclipse plug-in|ECLIPSE plug-in]]
** The <code><de.unkrig.loggifier></code> [[Loggifier.unkrig.de / Tools / Ant task|ANT task]]
** The &lt;de.unkrig.loggifier> [[Loggifier.unkrig.de / Tools / Ant task|ANT task]]
* At runtime:
* At runtime:
** The [[Loggifier.unkrig.de / Tools / LoggifyingClassLoader|LoggifyingClassLoader]]
** The [[Loggifier.unkrig.de / Tools / LoggifyingClassLoader|LoggifyingClassLoader]]
** The LOGGIFIER [[Loggifier.unkrig.de / Tools / Java agent|Java agent]]
** The LOGGIFIER [[Loggifier.unkrig.de / Tools / Java agent|Java agent]]


== Loggification ==
=== Java Agent ===


The LOGGIFIER loads a class file and analyzes the bytecode of the class's constructors and methods. Looking at the code, it identifies "interesting" points where logging code could be inserted. Each of the logging points is characterized by an [[#Logging actions|action]]. For each logging point, the relevant [[#Loggification rules|loggification rules]] are executed, and the first that matches determines at what level the logging event is to be logged (or if no logging code is injected for this logging point). Loggification rules optionally have a [[#Discriminator expression|discriminator expression]], which has a set of [[#Discriminator expression parameters|parameters]].
Probably the most convenient way to loggify classes at runtime is to start the JVM with the following command line option:


=== Logging actions ===
  $ java -javaagent:path/to/de.unkrig.loggifier.jar ...


Each section of code is characterized by an 'Action'. For example, the JVM bytecodes <code>PUTFIELD</code> and <code>PUTSTATIC</code> are characterized by action '''PUT'''.
The LOGGIFIER plugs into the [http://docs.oracle.com/javase/7/docs/api/java/lang/instrument/package-summary.html "Java programming language agents" API] (available since Java 5) and implements loggification at class-loading time.


{| class="wikitable"
The agent interprets its argument as newline-separated loggification rules:
|-
|'''ALOAD'''    ||Log array type, array value, index and element value read from an array
|-
|'''ARITH'''    ||Log operands, operator (+, -, ...) and result of an arithmetic operation
|-
|'''ASTORE'''    ||Log the array, the index and the value being stored in an array
|-
|'''CAST'''      ||Log the type to which the operand is casted
|-
|'''CATCH'''    ||Log the declared catch type and the actually caught exception
|-
|'''CLINIT'''    ||Log the name of a class that is initialized
|-
|'''CONST'''    ||Log the value of a constant being pushed on the operand stack
|-
|'''CONVERT'''  ||Log a value that is arithmetically converted and the conversion result
|-
|'''ENTRY'''    ||Log the target object (if non-static) and the arguments as a method begins execution
|-
|'''GET'''      ||Log declaring class of, name of, source instance of (if non-static) and value read from a field
|-
|'''INVOKE'''    ||Log signature, target object (if non-static) and arguments right before a method is invoked
|-
|'''INSTANCEOF'''||Log the type to which the operand type is compared
|-
|'''LENGTH'''    ||Log the array who's length is determined
|-
|'''LOAD'''      ||Log type of, name of and value read from a local variable
|-
|'''NEW'''      ||Log the type of a new object being instantiated
|-
|'''PUT'''      ||Log declaring class of, name of, target instance of (if non-static) and value assigned to field
|-
|'''RESULT'''    ||Log method signature and invocation result (if not 'void')
|-
|'''RETURN'''    ||Log the value that is being returned by a method (if not 'void')
|-
|'''STORE'''    ||Log value assigned to, type of and name of a local variable
|-
|'''SWITCH'''    ||Log the integer value that a switch is being executed on
|-
|'''THROW'''    ||Log an exception right before it is thrown
|}


=== Loggification rule syntax ===
  $ java '-javaagent:path/to/de.unkrig.loggifier.jar<span style="color:blue">=CLINIT=INFO
  ALL=FINER</span>' ...


A rule triggers if and only if
== Loggification ==
* It applies to the action of the loggification point (ENTRY, EXIT, THROW, ...)
* Its discriminator expression (if any) evaluates to TRUE for the actual point (who's properties are availables as variables in the discriminator expression, see above)


The syntax of all loggification rules is:
The LOGGIFIER loads a class file and analyzes the bytecode of the class's constructors and methods. Looking at the code, it identifies "interesting" points where logging code could be inserted. Each of the logging points is characterized by an [[#Logging actions|action]]. For each logging point, the relevant [[#Loggification rules|loggification rules]] are executed, and the first that matches determines at what level the logging event is to be logged (or if no logging code is injected for this logging point). Loggification rules optionally have a "discriminator expression", which has a set of [[#Loggification rule parameters|parameters]].


loggification-rule :=
=== Logging actions ===
    ( action { ',' action } | 'ALL' ) '=' level [ ':' discriminator-expression ]
action :=
    (One of the actions documented above)
level :=
    'SEVERE' | 'WARNING' | 'INFO' | 'CONFIG' | 'FINE' | 'FINER' | 'FINEST'
discriminator-expression :=
    (Syntax defined below)


Examples of valid loggification rules are:
;ALOAD    :Log array type, array value, index and element value read from an array
;ARITH    :Log operands, operator (+, -, ...) and result of an arithmetic operation
;ASTORE    :Log the array, the index and the value being stored in an array
;CAST      :Log the type to which the operand is casted
;CATCH    :Log the declared catch type and the actually caught exception
;CLINIT    :Log the name of a class that is initialized
;CONST    :Log the value of a constant being pushed on the operand stack
;CONVERT  :Log a value that is arithmetically converted and the conversion result
;ENTRY    :Log the target object (if non-static) and the arguments as a method begins execution
;GET      :Log declaring class of, name of, source instance of (if non-static) and value read from a field
;INVOKE    :Log signature, target object (if non-static) and arguments right before a method is invoked
;INSTANCEOF:Log the type to which the operand type is compared
;LENGTH    :Log the array who's length is determined
;LOAD      :Log type of, name of and value read from a local variable
;NEW      :Log the type of a new object being instantiated
;PUT      :Log declaring class of, name of, target instance of (if non-static) and value assigned to field
;RESULT    :Log method signature and invocation result (if not 'void')
;RETURN    :Log the value that is being returned by a method (if not 'void')
;STORE    :Log value assigned to, type of and name of a local variable
;SWITCH    :Log the integer value that a switch is being executed on
;THROW    :Log an exception right before it is thrown


ALL=FINE
=== Loggification rules ===
ENTRY=FINE
ARITH=FINE
LOAD,CONVERT,ARITH,STORE=FINE
ALL=FINE:class =* "de.*"


(<code>=*</code> is the 'glob matching operator', e.g. "hello" matches "he*".)
A rule triggers if and only if
 
* It applies to the action of the loggification point (ENTRY, EXIT, THROW, ...)
=== Loggification rule precedence ===
* Its discriminator expression (if any) evaluates to TRUE for the actual point (who's properties are availables as variables in the discriminator expression, see above)


The sequence of checked rules for each logging point is as follows:
The sequence of checked rules for each logging point is as follows:
Line 141: Line 101:
:Its values of in reverse order (i.e. the last value/rule takes the highest precedence).
:Its values of in reverse order (i.e. the last value/rule takes the highest precedence).


;If using the four-parameter [[Loggifier.unkrig.de / Tools / LoggifyingClassLoader|LoggifyingClassLoader]] constructor
;If using the four-parameter [[#LoggifyingClassLoader|LoggifyingClassLoader]] constructor
:The 'logLevelCalculator' argument.
:The 'logLevelCalculator' argument.


;If using the [[Loggifier.unkrig.de / Tools / Ant task|ANT task]]
;If using the [[#ANT task|ANT task]]
:<code><rule></code> subelements, in reverse order (i.e. the last <code><rule></code> takes the highest precedence).
:'<rule>' subelements, in reverse order (i.e. the last <rule> takes the highest precedence).


;If using the [[Loggifier.unkrig.de / Tools / Command line tool|LOGGIFIER command line tool]]
;If using the [[#Command line tool|LOGGIFIER command line tool]]
:The '-rule' options, in reverse order (i.e. the last '-rule' option takes the highest precedence).
:The '-rule' options, in reverse order (i.e. the last '-rule' option takes the highest precedence).


;If using the [[Loggifier.unkrig.de / Tools / Eclipse plug-in|ECLIPSE plug-in]]
;If using the [[#ECLIPSE Plugin|ECLIPSE builder]]
:The levels on the "Loggifier" property page of each project. (This rule ALWAYS applies, hence the following rules are never executed).
:The levels on the "Loggifier" property page of each project. (This rule ALWAYS applies, hence the following rules are never executed).


;If using the [[Loggifier.unkrig.de / Tools / Java agent|Java agent]]
;If using the [[#Java Agent|Java agent]]
:Its argument string passed to the agent, split at '\n', in reverse order (i.e. the last fragment/rule takes the highest precedence).
:Its argument string passed to the agent, split at '\n', in reverse order (i.e. the last fragment/rule takes the highest precedence).


;If the action is LOAD or STORE, and the local variable's name ends with '__'
;Accesses to local variable who's name ends with '__'
:FINER
:FINER


;If the action is GET or PUT, and the field's name ends with '__'
;Accesses to fields who's name ends with '__'
:FINER
:FINER


;If the action is NEW, CAST or INSTANCEOF, and the target class's name ends with '__'
;Instantiations of a class who's name ends with '__'
:FINER
:FINER


Line 171: Line 131:
:OFF
:OFF


Notice that non-static fields (a.k.a. 'instance variables') are initialized by the class's constructors. Static fields ('class variables') are initialized by the synthetic <code><clinit>()</code> method, which cannot be annotated in source code.
Notice that non-static fields (a.k.a. 'instance variables) are initialized by the class's constructors. Static fields ('class variables') are initialized by the synthetic '<clinit>()' method, which cannot be annotated in source code.
 
=== Discriminator expression ===
 
Discriminator expressions are implemented by means of <code>de.unkrig.commons.text.expression.ExpressionEvaluator</code>; find the expression syntax documented [http://commons.unkrig.de/javadoc/de/unkrig/commons/text/expression/Parser.html here].


=== Discriminator expression parameters ===
=== Loggification rule parameters ===


To provide fine-grained control over loggification, the properties of each loggification point are provided as parameters to the discriminator expression:
Generally the LOGGIFER considers various points in the code that could be subject to loggification. Each of these
points is identified by


;action
;action
:One of the [[#Logging actions|documented logging actions]]
:E.g. 'method entry', 'local variable assignment', 'arithmetic operation' (see [[#Logging actions|logging actions]])
;source
;source
:The name of the Java source file that JAVAC stores in each <code>.class</code> file if enabled by <code>-g:source</code>.
:The name of the Java source file that JAVAC stores in each .class file if enabled by '-g:source'.
;classAccess
;classAccess
:The accessibility of the class being instrumented (<code>public</code>, <code>protected</code> or <code>private</code>)
:The accessibility of the class being instrumented ('public', 'protected' or 'private')
;class
;class
:The fully qualified name of the class being instrumented, e.g. <code>pkg.MyClass</code>
:The fully qualified name of the class being instrumented, e.g. '{@code pkg.MyClass}'
;methodAccess
;methodAccess
:The accessibility of the method being instrumented (<code>public</code>, <code>protected</code> or <code>private</code>)
:The accessibility of the method being instrumented ('public', 'protected' or 'private')
;method
;method
:The enhanced, dequalified name of the method being instrumented, e.g. <code>meth(String, MyClass)</code> or <code><T extends IOException>meth(T, MyClass, List<T>)</code>
:The enhanced, dequalified name of the method being instrumented, e.g. 'meth(String, MyClass)' or '<T extends IOException>meth(T, MyClass, List<T>)'
;line
;line
:The line number related to the code point being instrumented that JAVAC stores in each .class file if enabled by <code>-g:lines</code>
:The line number related to the code point being instrumented that JAVAC stores in each .class file if enabled by '-g:lines'.
;type
;type (only for actions CAST, INSTANCEOF and NEW)
:The relevant type for the operation, e.g. <code>pkg.Class</code>, <code>pkg.Class[][]</code>, <code>int[][]</code> (only for actions '''CAST''', '''INSTANCEOF''' and '''NEW''')
:The relevant type for the operation, e.g. 'pkg.Class', 'pkg.Class[][]', 'int[][]'
;classAndField
;classAndField (only for actions GET and PUT)
:The subject class and field, e.g. <code>pkg.Class.field</code> (only for actions '''GET''' and '''PUT''')
:The subject class and field, e.g. 'pkg.Class.field'
;variable
;variable (only for actions LOAD and STORE)
:The name of the subject local variable (only for actions '''LOAD''' and '''STORE''')
:The name of the subject local variable


At each loggification point, the LOGGIFIER determines if logging code is to be inserted or not ('discrimination') and
At each loggification point, the LOGGIFIER determines if logging code is to be inserted or not ('discrimination') and
Please note that all contributions to unkrig.de may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see Unkrig.de:Copyrights for details). Do not submit copyrighted work without permission!
Cancel Editing help (opens in new window)