Camunda JSON Logging for shared engine: solved!

Hey everyone!

A new contribution for the community!

JSON logging / using logback has been discussed quite a bit:

But there has never been a clear way to implement this using the Shared engine approach or using the official camunda docker containers.

So i have put something together that does this:

Specifically my use case is adding JSON logging capabilities so the logs can be picked up by third-party json logging systems such as Elastic search or graylog.

I currently have implemented a pattern that works with Camunda Tomcat 7.9.0.

Detailed usage instructions have been provided: camunda-json-logging/tomcat/7.9.0/docker at master · DigitalState/camunda-json-logging · GitHub

and a docker hub image has been provided as well. The base of the image is the official camunda tomcat 7.9.0 image with modifications to the image for logging capabilities.

To get started really quickly you can just start using the following:

docker run --name camunda -p 8080:8080 digitalstate/camunda-bpm-platform:tomcat-7.9.0-json-logging

By default JSON is run in “production mode” meaning it wont be Pretty-Print. This is not so great when you are debugging and want human readable logs. So you can turn on pretty print with a ENV var on the container:

docker run --name camunda -p 8080:8080 -e PRETTY_JSON_LOG=true digitalstate/camunda-bpm-platform:tomcat-7.9.0-json-logging

See the Readme for further instructions and capabilities.

All logs from camunda, and Tomcat have been routed into logback.xml.

Enjoy.

@menski

4 Likes

@StephenOTT Thanks for this . I am looking for similar configuration for Camunda 7.20 . Is this possible to update the example.
I tries myself but can’t figure out the correct jar combination to make it work.
I will also share if I am able to make it work.

I tried following combination that can start Json logging in Camunda 7.20 but now Camunda webapp fail to start with error

jul-to-slf4j: 1.7.26
logback-classic:1.2.11
logstash-logback-encoder:7.3
janino:3.1.11

{
  "@timestamp" : "2024-01-10T09:27:16.919Z",
  "@version" : "1",
  "message" : "Error deploying web application directory [/camunda/webapps/camunda]",
  "logger_name" : "org.apache.catalina.startup.HostConfig",
  "thread_name" : "main",
  "level" : "ERROR",
  "level_value" : 40000,
  "stack_trace" : "java.lang.IllegalStateException: Error starting child\n\tat org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase
.java:686)\n\tat org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:658)\n\tat org.apache.catalina.core.StandardHost.addChild(Standa
rdHost.java:662)\n\tat org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1184)\n\tat org.apache.catalina.startup.HostConfig$Dep
loyDirectory.run(HostConfig.java:1932)\n\tat java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)\n\tat java.base/java.
util.concurrent.FutureTask.run(FutureTask.java:264)\n\tat org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75
)\n\tat java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:123)\n\tat org.apache.catalina.startup.HostConfig
.deployDirectories(HostConfig.java:1094)\n\tat org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:476)\n\tat org.apache.catalina.star
tup.HostConfig.start(HostConfig.java:1617)\n\tat org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:318)\n\tat org.apache.catalin
a.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123)\n\tat org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:423
)\n\tat org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:366)\n\tat org.apache.catalina.core.ContainerBase.startInternal(Container
Base.java:898)\n\tat org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:795)\n\tat org.apache.catalina.util.LifecycleBase.start(L
ifecycleBase.java:183)\n\tat org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1332)\n\tat org.apache.catalina.core.Containe
rBase$StartChild.call(ContainerBase.java:1322)\n\tat java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)\n\tat org.apache.tomcat.util
.threads.InlineExecutorService.execute(InlineExecutorService.java:75)\n\tat java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractEx
ecutorService.java:145)\n\tat org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:871)\n\tat org.apache.catalina.core.StandardEn
gine.startInternal(StandardEngine.java:249)\n\tat org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)\n\tat org.apache.catalina.cor
e.StandardService.startInternal(StandardService.java:428)\n\tat org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)\n\tat org.apach
e.catalina.core.StandardServer.startInternal(StandardServer.java:914)\n\tat org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)\n\t
at org.apache.catalina.startup.Catalina.start(Catalina.java:772)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method
)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)\n\tat java.base/jdk.internal.reflect.Delega
tingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n\tat java.base/java.lang.reflect.Method.invoke(Method.java:568)\n\tat org.apach
e.catalina.startup.Bootstrap.start(Bootstrap.java:347)\n\tat org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:478)\nCaused by: org.apache.c
atalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/camunda]]\n\tat org.apache.
catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:440)\n\tat org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:19
8)\n\tat org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:683)\n\t... 37 common frames omitted\nCaused by: java.lang.NoCla
ssDefFoundError: javax/servlet/ServletContainerInitializer\n\tat java.base/java.lang.ClassLoader.defineClass1(Native Method)\n\tat java.base/java.la
ng.ClassLoader.defineClass(ClassLoader.java:1017)\n\tat java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)\n\tat java
.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:862)\n\tat java.base/jdk.internal.loader.BuiltinClassLoader.findCla
ssOnClassPathOrNull(BuiltinClassLoader.java:760)\n\tat java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681)
\n\tat java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639)\n\tat java.base/jdk.internal.loader.ClassLoaders$AppC
lassLoader.loadClass(ClassLoaders.java:188)\n\tat java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:579)\n\tat java.base/java.lang.ClassLoa
der.loadClass(ClassLoader.java:525)\n\tat java.base/java.lang.Class.forName0(Native Method)\n\tat java.base/java.lang.Class.forName(Class.java:467)\
n\tat org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1396)\n\tat org.apache.catalina.loader.WebappClassLoader
Base.loadClass(WebappClassLoaderBase.java:1220)\n\tat java.base/java.lang.Class.forName0(Native Method)\n\tat java.base/java.lang.Class.forName(Clas
s.java:467)\n\tat org.apache.catalina.startup.WebappServiceLoader.loadServices(WebappServiceLoader.java:235)\n\tat org.apache.catalina.startup.Webap
pServiceLoader.load(WebappServiceLoader.java:206)\n\tat org.apache.catalina.startup.ContextConfig.processServletContainerInitializers(ContextConfig.
java:1842)\n\tat org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1299)\n\tat org.apache.catalina.startup.ContextConfig.config
ureStart(ContextConfig.java:987)\n\tat org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:304)\n\tat org.apache.catalina.ut
il.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123)\n\tat org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:4852)\
n\tat org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)\n\t... 38 common frames omitted\nCaused by: java.lang.ClassNotFoundExcept
ion: javax.servlet.ServletContainerInitializer\n\tat java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)\n\tat j
ava.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)\n\tat java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)\n\t... 63 common frames omitted\n"
}

Update: I was able to find the working combination.

Working combination is as below for Camunda 7.20

jul-to-slf4j: 2.0.11
slf4j-api:2.0.11
logback-classic:1.4.14
logstash-logback-encoder:7.4
janino:3.1.11

It can be referred here amardeep2006/camunda-json-logging at feat/upgrade-camunda-7.20 (github.com)

I have raised PR to original project as well.
feat(7.20): upgrade to camunda 7.20.0 by amardeep2006 · Pull Request #7 · DigitalState/camunda-json-logging (github.com)

Changes I had to make for Camunda 7.20:

  • I had to delete both slf4j-jdk14-1.7.26.jar and slf4j-api-1.7.26.jar from original image, modified Dockerfile for the same.
  • jul-to-slf4j is no more part of Camunda BOM so Version had to be added directly.
  • jackson jars and camunda spin are already part of Camunda image so no more needed.
  • -XX:MaxPermSize=256m -XX:PermSize=256m are no more supported in Java 17 . Deleted them from setenv.sh
  • Bumped up every maven plugin and wrapper to latest version as on today Jan 10 2024 .

The original repo seems inactive hence I have created a fork as well.

  • I have made it easy to build the docker image using multi stage builds.
  • Now the Jar file is not checked in repo but build during docker build itself.
  • I have not intentionally not published the Docker Image to Dockerhub for security reasons. In 2024 you simply should not trust on Images published by untrusted sources but rather build yourself if possible.
  • Refactored the folder structure for easy camunda upgrades in future.

amardeep2006/camunda-tomcat-json-logging-docker (github.com)