P6log
Platform 6 logging Consumer receives and filters log4j events.
log4j is the logging framework used by platform6. Other logging frameworks such as jdk, slf4j and commons are also redirected to log4j as are stdout and stderr streams. This means that nearly everything logged or written to an output stream by core p6 code, third-party libraries or Groovy scripts is captured.
For more information about log4j 1.2 see this: http://logging.apache.org/log4j/1.2/manual.html
A custom log4j appender called ‘platform6’ is defined in the log4j.properties file:
log4j.appender.platform6 = com.amalto.b2box.core.impl.logging.B2boxAppender
This appender will generate events via the p6log component and allows low level filtering by logger Level and Logger Name
Common Usage Scenarios¶
Email Errors to an Operator
All ERROR level logs are captured, stored and sent as xml to an route endpoint where they are filtered and used to generate an Active Routing Order by the p6route component.
The routing order is typically configured to transform the xml to an html document that is sent as an email body to an operator via the SMTP service
Send log messages to an ELK server
All ERROR and WARN logs are captured in JSON format and posted as strings to the ELASTICSEARCH audit provider
Configuration Attributes¶
Event Queue
There is an internal queue used to store log events awaiting processing. The size of this queue can be controlled by the following conf attribute:
- com.amalto.b2box.core.impl.application.camel.p6log.LogConsumer.QueueSize default: “2048”
Limiter
It is very easy to introduce recursion to your p6log routes especially if the scripts called as a result of an event generate ERRORs! To protect against an out of control recursion a limiter is used. By default, this ensures no more than ten matching log events can be processed within any five second period (additional events will be discarded).
The following conf attributes can be modified to change this default behaviour:
- com.amalto.b2box.core.impl.application.camel.p6log.LogConsumer.limiter.capacity default:”10”
- com.amalto.b2box.core.impl.application.camel.p6log.LogConsumer.limiter.resetValue default:”10”
- com.amalto.b2box.core.impl.application.camel.p6log.LogConsumer.limiter.resetMillis default:”5000”
URI Format¶
p6log://[?options]
Options¶
The P6log component supports three options which are described below.
Name | Description | Default | Type |
---|---|---|---|
level | log4j logger Level >= | ERROR | string |
nameRegex | Match required on ‘Logger Name’ | string | |
format | Log formatting, either: json, xml or map | xml | string |
persistXml | true to store xml in LOG partition | false | string |
Example of an xml formatted log event
This format is historical in design and mirrors the logging events generated by the B2BOX product.
<logging_event> <id>93a64239b5d811e8a1120c4de9a356bc</id> <time>2018-09-11 17:37:22.950 CEST</time> <level>ERROR</level> <logger>GROOVYSCRIPT: Simons_MacBook_Pro_local_ScriptModule__GENERATE_ERROR</logger> <message>this is an error!</message> <ndc></ndc> <thread>P6JobRunner_Pool-Thread-3</thread> </logging_event>
Example¶
Template: BaseRoute.groovy
${addRoutes}
:=
from("p6log://?level=ERROR&format=json") .description('JSON ERROR Log Listener') .to( "p6cmb://scripts?platform6.request.action=execute&id=ErrorLogger" ) .routeId('JSONlLogListener')
Template: BaseRoute.groovy
${addRoutes}
:=
from('p6log://?persistXml=true') .description('Xml ERROR Log Listener') .to("direct:p6router.1") .routeId('ClassicXmlLog_Listener') from('direct:p6router.1') .description('Xml ERROR Log Routing Rule') .choice() .when(xpath("/logging_event/level='ERROR'")) .setHeader( 'platform6.request.action').constant('execute') .setHeader('id').constant('XMLErrorTest') .setProperty('execute.async').constant(true) .to( 'p6route://scripts') .otherwise() .throwException(com.amalto.b2box.core.api.B2boxException,'No matching rule found for item!') .end() .routeId('ClassicXmlLog_Router')
Script ErrorLogger:
def jsonLogError = p6.pipeline.get('body') p6.audit.post('myerrorindex', jsonLogError)
Script XmlErrorTest:
def htmlToEmail = p6.xslt.process( "LoggingEvent", resource.get('LoggingEvent'), p6.transaction.getUsingPipelineRequest() ) if( p6.email.sendHtmlEmail( 'dev.platform6.io@amalto.com', 'simon.temple@amalto.com', htmlToEmail, ['subject': '[DEV P6] localhost - Logging Event'], null ) ){ // Remove the stored logging_event after you processed it def item = p6.transaction.remove( p6.transaction.getPKUsingPipelineRequest() ) assert item != null }