Logging is done on a per-category basis in Keycloak. You can configure logging for the root log level, or for more specific categories like `org.hibernate` or `org.keycloak`. In this guide, you will learn how to configure logging.
using one of the levels mentioned in the table above. When no log level configuration exists for a more specific category logger (see below), the enclosing category is used instead. When there is no enclosing category, the root logger level is used.
Setting the log level is case-insensitive, so you could either use for example `DEBUG` or `debug`.
When you accidentally set the log level twice, for example when you invoke `--log-level=info,...,debug,...` the last occurence in the list will be used as the log level, so for the example the root logger would be set to `DEBUG`.
=== Configuring category-specific log levels
It is possible to set a different log level for specific areas in Keycloak. To enable category-specific logging, provide a comma-separated list containing the categories you want another log level than for the root category to the `--log-level` configuration:
A configuration that applies to a category also applies to all sub-categories of that category, unless a more specific matching sub-category configuration is provided in the list.
The example above sets the root log level for all loggers to INFO, and the hibernate log level in general to debug. But as we don't want SQL abstract syntax trees to make the log output verbose, we set the more specific sub category `org.hibernate.hql.internal.ast` to info, so the SQL abstract syntax trees, which would be shown at `debug` level, don't show up anymore.
The available handlers are `console`, `file` and `gelf`. The more specific handler configuration mentioned below will only take effect when the handler is added to this comma-separated list.
Be aware that you need to escape characters when invoking commands containing special shell characters such as `;` using the CLI, so you might want to set it in the configuration file instead.
{"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}
----
When using JSON output, colors are disabled and the format settings set by `--log-console-format` will not apply.
To use unstructured logging, run the following command:
2022-03-02 10:36:50,603 INFO [io.quarkus] (main) Keycloak 18.0.0-SNAPSHOT on JVM (powered by Quarkus 2.7.2.Final) started in 3.615s. Listening on: http://0.0.0.0:8080
----
=== Colors
Colored console log output for unstructured logs is disabled by default. It may lead to better readability, but can cause problems when shipping logs to external log aggregation systems. If you want to enable or disable color-coded console log output, run following command:
Please make sure the location for the logfile is writeable. If not, an error will be thrown at start-up. Keycloak will start correctly, but no file containing logs will be created.
=== Configuring the file handler format
You can configure a different logging format for the file log handler by running the following command:
Keycloak is able to send logs to a centralized log management system like Graylog, Logstash (inside the Elastic Stack or ELK - Elasticsearch, Logstash, Kibana) or Fluentd (inside EFK - Elasticsearch, Fluentd, Kibana). Keycloak leverages the features of the https://quarkus.io/guides/centralized-log-management[Quarkus Logging GELF] extension to provide support for these environments.
By default, when the GELF handler is enabled, the host is using `localhost` as host value and UDP for communication. If you want to use TCP instead of UDP, prefix the host value with `tcp:`. The Default port is `12201`.
By default, Keycloak includes the complete Stacktrace inside the field `StackTrace`. If you do not want to include this field, run the following command:
You may consider to use the config file instead to avoid escaping:
[source, conf]
----
log-gelf-timestamp-format=yyyy-MM-dd HH:mm:ss
----
The default timestamp format is `yyyy-MM-dd HH:mm:ss,SSS`. You can use the https://docs.oracle.com/javase/10/docs/api/java/text/SimpleDateFormat.html[available SimpleDateFormat patterns] to define your needed timestamp.
.Configure the facility
To set the field `facility` - an indicator of the process or program that is the source of the log messages - to your preferred identifier (Default: keycloak), run the following command:
The maximum size of one GELF log message has to be set in Bytes. The example above increases the size to 16kb. When messages exceed the maximum size, GELF will submit the message in multiple chunks.
By default, Keycloak includes message parameters of the occured log event. These fields are shown in the output as `MessageParam0`, `MessageParam1`, and so on, depending on the parameter length.
To switch off this behaviour, run the following command:
By default, Keycloak includes the fields `SourceClassName`, `SourceMethodName` and `SourceSimpleClassName` in the GELF log messages to make it for example easier to see the location of an occured exception. To stop sending these fields, run the following command:
The following example shows how to send Keycloak logs to the Graylog centralized logging stack. It assumes you have a container tool like https://www.docker.com/[docker] installed to spin up the `compose.yml`.
Copy and save the example locally into a `compose.yml` file and run:
[source,bash]
----
docker compose up -d
----
After a few seconds the Stack should be ready to serve requests.
==== Create a Graylog UDP Input
After the stack is up and running, you need to create a UDP Input Graylog listens to. You can do it from the Graylog web UI (System → Input → Select GELF UDP) available at http://localhost:9000 or using the API:
This `curl` example creates a new GELF UDP Input using the API and the default Graylog login credentials (admin/admin).
If the stack is still in the bootstrap phase, you receive a response containing `* Empty reply from server`. A successfull response includes `HTTP/1.1 201 Created` to indicate that the UDP input is created.
Note that for this example to work, it is not really necessary to add the `log-gelf-host` and `log-gelf-port` values to your configuration, as these are the defaults and only shown for illustrational purposes.
Open your web browser, navigate to `http://localhost:9000`, login to the Graylog web UI using the admin credentials (admin/admin) and navigate to Streams → All Messages. Start updating the stream by pressing the play button in the up right corner. Then start Keycloak using `start` or `start-dev` and your GELF config. After a few seconds, Keycloaks messages will appear in the Graylog dashboard.
The following example shows how to send Keycloak logs to the ELK centralized logging stack. It assumes you have a container tool like https://www.docker.com/[docker] installed to spin up the `compose.yml`.
Logstash uses an input plugin that can understand and parse the GELF format. To activate it when spinning up the ELK stack later on, create a directory `pipelines` and a file `gelf.conf` located in this directory. Then create an empty `compose.yml` in the parent directory.
.File Structure:
[source]
----
/ELK
- compose.yml
- pipelines/
- gelf.conf
----
Add the following contents to `pipelines/gelf.conf` and save it:
Note that for this example to work, it is not really necessary to add the `log-gelf-host` and `log-gelf-port` values to your configuration, as these are the defaults and only shown for illustrational purposes.
With this configuration applied, start keycloak using `start-dev` or `start`.
==== Kibana: See the results
Open http://localhost:5601 to reach the Kibana dashboard. The exact configuration of a good monitoring dashboard is out of scope for this guide. The easiest way to find out if logs sent by Keycloak are delivered to Kibana is to open the http://localhost:5601/app/kibana#/dev_tools/console?_g=()[Dev Tools] and execute the default `match_all` query. The logs should appear in the result field.
=== Configure a different log level for the GELF logger
To keep log storage costs and verbosity low, it is often wanted to only store a subset of the verbose application logs inside a centralized log management system. To configure Keycloak to use a different log level for the logs you want to ingest, use the following configuration:
[source, conf]
----
log=console,gelf
log-gelf-level=<desired-log-level>
...
----
.Example
To only see occurred log levels of warn and above in your centralized logging stack, but still see INFO level logs on the applications console logs, use the following configuration:
[source, conf]
----
log=console,gelf
log-level=INFO
log-gelf-level=warn
...
----
Looking at your ingested logs, you will see only messages of level warn or above will appear.
Keep in mind that `--log-level` is setting the leading log level, so for example when you invoke the following command:
nothing below the error level will be sent to your logging stack. That means that even GELF in this example will receive only error level log messages.
Currently, the Keycloak configuration does not support partly dynamic configuration keys, as they are used in quarkus properties, e.g. when defining `quarkus.log.handler.gelf.additional-field.<my-name>.value`.
In order to add additional user-defined fields, you can provide them directly through a quarkus.properties file. Please refer to the <@links.server id="configuration"/> guide at section _Using unsupported server options_.