Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Routing engine Logging #2

Open
dixitdeepak opened this issue Feb 6, 2024 · 1 comment
Open

Routing engine Logging #2

dixitdeepak opened this issue Feb 6, 2024 · 1 comment

Comments

@dixitdeepak
Copy link
Contributor

Moqui Framework provides a versatile logging system that can be adapted for various use cases.
The Moqui logging system leverages SLF4J (Simple Logging Facade for Java) as its logging facade, with Log4J2 as the default logging implementation. This setup allows for flexible logging configuration, including file, console, and external systems logging, with support for different log levels (e.g., DEBUG, INFO, WARN, ERROR).

@AyanF
Copy link

AyanF commented Feb 7, 2024

Configuring Log4j2

Overview

The logger configuration has 3 main components

  1. Properties
  2. Loggers
  3. Appenders

Each log in the code goes through these.

Properties

In the < Properties > < /Properties > we can define key value pairs and refer to these in other components of the configuration.

Logger

Logger help in filtering which files and levels should be logged. The job of logger is to extract specific logs from all incoming logs based on the properties. We can set the following properties -

  1. Name - Name of package or class to scan
  2. Level - Level of log which should be passed further.
  3. Appender ref - Specifies the appender to be used for these filtered logs
  4. Additivity (Boolean) - Whether to pass this log to parent loggers

If a logger1 is configured for

name= apache. org
level=error

and logger2 is configured for

name = apache.org.xyz
level =info

by default the logger2 logs will go to logger1 also, unless additivity is set to false.

Root Logger
This logger is utilised if the event does not match any other specified condition or log filters, this is ancestor of all other loggers.

<Root level="info"><AppenderRef ref="AsyncLog"/></Root>

We can specify AppenderRef to configure any particular appender we want to use.
By default all other loggers pass log events to the Root Logger, unless additivity is set to false.

Appender

The filtered logs are sent to specified appender. Appender are responsible for delivering log events to their destination.

This answer specifically addressed how to log event of a specific class or package, write them to a separate file and how to configure whether the logs should be sent out to the console.

Logging specific class or package

In this file a custom logger is created to filter log event of test3.groovy file -

        <Logger name="org.moqui.example.test3" level="info" additivity="false">  
            <AppenderRef ref="RoutingAppender"/>  
        </Logger>  

This filters log events in the test3 file, since additivity is set to false these events are not passed to the "org.moqui" logger or the root logger.

Appender ref specifies which Appender will consume this log event.

Logging specfic events based on conditions

Thread Context Map

Log4j provides a ThreadContextMap, in which we can store key value pairs associated with a specific thread, these values are accessible in the log4j configurable file.

To use it we need to import in our java/groovy file-

import org.apache.logging.log4j.ThreadContext

ThreadContext.put("identifier","type-1")

We can later access this value and use it to route the log events.

Appending filtered log to files

We can can define Routes in RoutingAppender and redirect LogEvents based on the values we put in Thread Context Map.

<Routing name="RoutingAppender">  
    <Routes pattern="$${ctx:identifier}">  
        <Route if="$${ctx:identifier} != ''">  
            <RollingFile name="DmLogger" fileName="runtime/datamanager/${ctx:identifier	}.log" filePattern="runtime/datamanager/log-%d{yyyy-MM-dd}-%i-${ctx:identifier}-%i.log">  
                <PatternLayout>`  
                    <pattern>&lt;div class=&quot;%p&quot;&gt;%d |%-5level| %msg%n%rEx&lt;/div&gt;</pattern>  
                </PatternLayout>  
                <Policies>  
                    <TimeBasedTriggeringPolicy/>  
                    <SizeBasedTriggeringPolicy size="5 MB"/>  
                </Policies>  
                <DefaultRolloverStrategy max="10"/>  
            </RollingFile>  
        </Route>  
    </Routes>  
</Routing>

Here we are checking if "identifier" we put earlier in Thread Context Map is null, if not we use it as a property in the pattern to create log file name.

Logging to console

Currently this log is sent to RoutingAppender only which saves it into a log file.

To send any Log Event to console it should be passed to < Console > Element which is present inside
< Appenders >

<Console name="STDOUT" target="SYSTEM_OUT">  
    <PatternLayout pattern="%highlight{%d{HH:mm:ss.SSS} %5p %12.12t %38.38c{1.9.1.}} %m%n"/>  
</Console>

Logging to multiple Appenders and Console

To send LogEvents to multiple Appenders, we can utilise the Async Appender.

Async Appender
AsyncAppender accepts references to other Appenders and causes LogEvents to be written to them on a separate Thread. The AsyncAppender should be configured after the appenders it references to allow it to shut down properly.

<Async name="AsyncLog">  
    <AppenderRef ref="STDOUT"/>  
    <AppenderRef ref="RoutingAppender"/>  
</Async>  
<Console name="STDOUT" target="SYSTEM_OUT">  
    <PatternLayout pattern="%highlight{%d{HH:mm:ss.SSS} %5p %12.12t %38.38c{1.9.1.}} %m%n"/>  
</Console>

This will send the log events to Routing Appender as well as to the Console.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants