Configuring Logs
Karnak offers the possibility of injecting your own log configuration.
The logging system used by Karnak is logback. For more details on logback, it provides a manual
Variables
Some variables are available and can be used in the logback file.
issuerOfPatientIDare the issuer of patient ID before the deidentificationPatientIDare the patient ID before the deidentificationSOPInstanceUIDare the SOPInstanceUID before the deidentificationDeidentifySOPInstanceUIDare the SOPInstanceUID after the deidentificationSeriesInstanceUIDare the SeriesInstanceUID before the deidentificationDeidentifySeriesInstanceUIDare the SeriesInstanceUID after the deidentificationProjectNameare the project name used for the deidentificationProfileNameare the profile name used for the deidentificationProfileCodenamesare a list of concatenated profile items that has been used for the deidentification
Inject the logback configuration file
By using docker
You must set the environment variable LOGBACK_CONFIGURATION_FILE with the path of Logback file configuration, it will override the default log file.
For example, if you create your own configuration with the file name my-logback.xml at the root of the docker-compose.yml.
You must create a volume that will copy the file in the Karnak docker and define the environment variable LOGBACK_CONFIGURATION_FILE with the path of the file in the docker container.
services:
karnak:
container_name: karnak
image: osirixfoundation/karnak:v0.9.7
volumes:
- ./my-logback.yml:/logs/my-logback.xml
environment:
LOGBACK_CONFIGURATION_FILE: /logs/my-logback.xmlBy using JAVA
If you use directly the Karnak jar, you must add the following parameter at the startup:
-Dlogging.config=my-logback.xml
Default logback file
The default logback file (see below) has two modes.
Dev Mode
- The variable
ENVIRONMENTmust be set toDEVto be activate. - Log everything at the
INFOlevel except for the packageorg.karnakandorg.weasis, they are at theDEBUGlevel.
Production Mode
- Always activate, except if the variable
ENVIRONMENTis set toDEV. - Logs everything at the
WARNlevel - Writes all.log file, it contains:
- Every
WARNlevel log org.weasisINFOlevel logorg.karnakINFOlevel log, excepted clinical log
- Every
- Writes clinical.log, it contains:
- Every log with the marker
CLINICALwhich concerns the deidentification
- Every log with the marker
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="LOGS" value="logs" />
<!--
DEV LOGS
Condition to verify if "ENVIRONMENT" is "DEV"
-->
<if condition='property("ENVIRONMENT").contains("DEV")'>
<then>
<!--
How the logs will be displayed in the standard output (console)
SOPInstanceUID, issuerOfPatientID and PatientID are variables to associate the current DICOM with the log
-->
<appender name="DEV_OUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%black(%d{ISO8601}) %highlight(%-5level) %marker %highlight(%X{SOPInstanceUID}) %highlight(%X{issuerOfPatientID}) %highlight(%X{PatientID}) [%yellow(%t)] %yellow(%C{1.}): %msg%n%throwable</Pattern>
</encoder>
</appender>
<!--
Log everything at the INFO level except for the package org.karnak and org.weasis, they are at the DEBUG level.
-->
<root level="info">
<appender-ref ref="DEV_OUT" />
</root>
<logger name="org.weasis" level="debug" />
<logger name="org.karnak" level="debug" />
</then>
<!--
PRODUCTION LOGS
-->
<else>
<!--
How the warning logs will be displayed in the standard output (console)
SOPInstanceUID, issuerOfPatientID and PatientID are variables to associate the current DICOM with the log
-->
<appender name="WARNING_OUT" class="ch.qos.logback.core.ConsoleAppender">
<!--
Log only at WARN level
-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>WARN</level>
</filter>
<encoder>
<Pattern>%black(%d{ISO8601}) %highlight(%-5level) %marker %highlight(%X{SOPInstanceUID}) %highlight(%X{issuerOfPatientID}) %highlight(%X{PatientID}) [%yellow(%t)] %yellow(%C{1.}): %msg%n%throwable </Pattern>
</encoder>
</appender>
<!--
Write all.log file in the file system.
-->
<appender name="ALL_LOGS" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOGS}/all/all.log</file>
<!--
Window rolling policy defined by the variable KARNAK_LOGS_MIN_INDEX or KARNAK_LOGS_MAX_INDEX
By default the min is 1 and the max is 10
-->
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>${LOGS}/all/all_%i.log</fileNamePattern>
<minIndex>${KARNAK_LOGS_MIN_INDEX:-1}</minIndex>
<maxIndex>${KARNAK_LOGS_MAX_INDEX:-10}</maxIndex>
</rollingPolicy>
<!--
Size rolling policy defined by the variable KARNAK_LOGS_MAX_FILE_SIZE
By default the max file size is 50MB
-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>${KARNAK_LOGS_MAX_FILE_SIZE:-50MB}</maxFileSize>
</triggeringPolicy>
<!--
Filter not to write logs with the clinical marker
-->
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator class="ch.qos.logback.classic.boolex.OnMarkerEvaluator">
<marker>CLINICAL</marker>
</evaluator>
<onMismatch>NEUTRAL</onMismatch>
<onMatch>DENY</onMatch>
</filter>
<encoder>
<pattern>%d %-5level %m%n</pattern>
</encoder>
</appender>
<!--
Write clinical.log file in the file system.
Will contains only the logs with the CLINICAL marker. The logs with CLINICAL marker concerns the information about the deidentification.
Variables used for the CLINICAL log:
SOPInstanceUID, DeidentifySOPInstanceUID, SeriesInstanceUID, DeidentifySeriesInstanceUID, ProjectName, ProfileName, ProfileCodenames
-->
<appender name="CLINICAL_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOGS}/Clinical/clinical.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>${LOGS}/Clinical/clinical_%i.log</fileNamePattern>
<minIndex>${KARNAK_CLINICAL_LOGS_MIN_INDEX:-1}</minIndex>
<maxIndex>${KARNAK_CLINICAL_LOGS_MAX_INDEX:-10}</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>${KARNAK_CLINICAL_LOGS_MAX_FILE_SIZE:-50MB}</maxFileSize>
</triggeringPolicy>
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator class="ch.qos.logback.classic.boolex.OnMarkerEvaluator">
<marker>CLINICAL</marker>
</evaluator>
<onMismatch>DENY</onMismatch>
<onMatch>NEUTRAL</onMatch>
</filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%d SOPInstanceUID_OLD=%X{SOPInstanceUID} SOPInstanceUID_NEW=%X{DeidentifySOPInstanceUID} SeriesInstanceUID_OLD=%X{SeriesInstanceUID} SeriesInstanceUID_NEW=%X{DeidentifySeriesInstanceUID} ProjectName=%X{ProjectName} ProfileName=%X{ProfileName} ProfileCodenames=%X{ProfileCodenames}</Pattern>
</encoder>
</appender>
<!--
Log everything at the WARN level except for the package org.karnak and org.weasis, they are at the INFO level.
The INFO logs won't appear in the standard output, because they will be filtered by the WARNING_OUT appender
-->
<root level="warn">
<appender-ref ref="ALL_LOGS" />
<appender-ref ref="CLINICAL_FILE" />
<appender-ref ref="WARNING_OUT" />
</root>
<logger name="org.weasis" level="info" />
<logger name="org.karnak" level="info" />
</else>
</if>
</configuration>