Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions docs/guides/src/main/server/logging.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,17 @@ Be aware that you need to escape characters when invoking commands containing sp
<@kc.start parameters="\"\'%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] (%t) %s%e%n\'\""/>
The example above abbreviates the category name, which could get rather long in some cases, to three characters by setting `[%c{3.}]` in the template instead of the default `[%c]`.

== Logging in JSON format
To use structured JSON log output, run the following command:

<@kc.start parameters="--log-json-enabled=true"/>

.Example Log Message
[source, json]
----
{"timestamp":"2022-02-25T10:31:32.452+01:00","sequence":8442,"loggerClassName":"org.jboss.logging.Logger","loggerName":"io.quarkus","level":"INFO","message":"Keycloak 18.0.0-SNAPSHOT on JVM (powered by Quarkus 2.7.2.Final) started in 3.253s. Listening on: http://0.0.0.0:8080","threadName":"main","threadId":1,"mdc":{},"ndc":"","hostName":"host-name","processName":"QuarkusEntryPoint","processId":36946}
----

== Configuring raw quarkus logging properties
At the time of writing, the logging features of the quarkus based Keycloak are basic, yet powerful. Nevertheless, expect more to come and feel free to join the https://github.com/keycloak/keycloak/discussions/8870[discussion] at GitHub.

Expand Down
4 changes: 4 additions & 0 deletions quarkus/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-metrics-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-logging-json-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkiverse.vault</groupId>
<artifactId>quarkus-vault-deployment</artifactId>
Expand Down
4 changes: 4 additions & 0 deletions quarkus/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-metrics</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-logging-json</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static org.keycloak.quarkus.runtime.integration.QuarkusPlatform.addInitializationException;

import java.util.Arrays;
import java.util.Locale;
import java.util.function.BiFunction;
import java.util.logging.Level;
Expand Down Expand Up @@ -69,6 +70,13 @@ public String apply(String value, ConfigSourceInterceptorContext configSourceInt
.defaultValue("%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n")
.description("The format of log entries. If the format has spaces in it, you need to escape the value such as \"<format>\".")
.paramLabel("format")
.build(),
builder().from("log-json-enabled")
.to("quarkus.log.console.json")
.defaultValue(Boolean.FALSE.toString())
.description("Enable or disable logging to console using structured JSON.")
.paramLabel(Boolean.TRUE + "|" + Boolean.FALSE)
.expectedValues(Arrays.asList(Boolean.TRUE.toString(), Boolean.FALSE.toString()))
.build()
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ metrics-enabled=false

# Default, and insecure, and non-production grade configuration for the development profile
%dev.http-enabled=true
%dev.log-json-enabled=false
%dev.hostname-strict=false
%dev.hostname-strict-https=false
%dev.cache=local
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,17 @@
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.List;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.approvaltests.Approvals;
import io.quarkus.test.junit.main.LaunchResult;

public interface CLIResult extends LaunchResult {

static ObjectMapper objectMapper = new ObjectMapper();

static Object create(List<String> outputStream, List<String> errStream, int exitCode) {
return new CLIResult() {
@Override
Expand Down Expand Up @@ -97,4 +103,19 @@ default void assertLocalCache() {
default void assertClusteredCache() {
assertTrue(isClustered());
}

default void assertJsonLogDefaultsApplied() throws JsonProcessingException {
String[] split = getOutput().split(System.lineSeparator());
for (String l: split) {
if (!l.trim().startsWith("{")) {
//we ignore non-json output for now. Problem is the build does not know about the runtime configuration,
// so when invoking start-dev and a build is done, the output is not json but unstructured console output
continue;
}
JsonNode json = objectMapper.readTree(l);
assertTrue(json.has("timestamp"));
assertTrue(json.has("message"));
assertTrue(json.has("level"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.keycloak.it.junit5.extension.CLIResult;
import org.keycloak.it.junit5.extension.DistributionTest;
import org.keycloak.it.junit5.extension.RawDistOnly;
Expand All @@ -32,7 +31,6 @@

@DistributionTest(reInstall = DistributionTest.ReInstall.NEVER)
@RawDistOnly(reason = "Too verbose for docker and enough to check raw dist")
@TestMethodOrder(OrderAnnotation.class)
public class LoggingDistTest {

@Test
Expand Down Expand Up @@ -77,4 +75,21 @@ void testSetLogFormat(LaunchResult result) {
assertFalse(cliResult.getOutput().contains("(keycloak-cache-init)"));
cliResult.assertStartedDevMode();
}

@Test
@Launch({ "start-dev", "--log-json-enabled=true" })
void testJsonFormatApplied(LaunchResult result) throws JsonProcessingException {
CLIResult cliResult = (CLIResult) result;
cliResult.assertJsonLogDefaultsApplied();
cliResult.assertStartedDevMode();
}

@Test
@Launch({ "start-dev", "--log-level=off,org.keycloak:debug,org.infinispan:info", "--log-json-enabled=true" })
void testLogLevelSettingsAppliedWhenJsonEnabled(LaunchResult result) {
CLIResult cliResult = (CLIResult) result;
assertFalse(cliResult.getOutput().contains("\"loggerName\":\"io.quarkus\",\"level\":\"INFO\")"));
assertTrue(cliResult.getOutput().contains("\"loggerName\":\"org.keycloak.quarkus.runtime.storage.database.jpa.QuarkusJpaConnectionProviderFactory\",\"level\":\"DEBUG\""));
assertTrue(cliResult.getOutput().contains("\"loggerName\":\"org.infinispan.CONTAINER\",\"level\":\"INFO\""));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ Logging:
The format of log entries. If the format has spaces in it, you need to escape
the value such as "<format>". Default: %d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c]
(%t) %s%e%n.
--log-json-enabled <true|false>
Enable or disable logging to console using structured JSON. Default: false.
--log-level <category:level>
The log level of the root category or a comma-separated list of individual
categories and their levels. For the root category, you don't need to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ Logging:
The format of log entries. If the format has spaces in it, you need to escape
the value such as "<format>". Default: %d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c]
(%t) %s%e%n.
--log-json-enabled <true|false>
Enable or disable logging to console using structured JSON. Default: false.
--log-level <category:level>
The log level of the root category or a comma-separated list of individual
categories and their levels. For the root category, you don't need to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ Logging:
The format of log entries. If the format has spaces in it, you need to escape
the value such as "<format>". Default: %d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c]
(%t) %s%e%n.
--log-json-enabled <true|false>
Enable or disable logging to console using structured JSON. Default: false.
--log-level <category:level>
The log level of the root category or a comma-separated list of individual
categories and their levels. For the root category, you don't need to
Expand Down