Giter VIP home page Giter VIP logo

keycloak-metrics-spi's Introduction

License

Keycloak Metrics SPI

A Service Provider that adds a metrics endpoint to Keycloak. The endpoint returns metrics data ready to be scraped by Prometheus.

Two distinct providers are defined:

  • MetricsEventListener to record the internal Keycloak events
  • MetricsEndpoint to expose the data through a custom endpoint

The endpoint is available under <base url>/realms/<realm>/metrics (Quarkus) or <base url>/auth/realms/<realm>/metrics (Wildfly). It will return data for all realms, no matter which realm you use in the URL.

License

See LICENSE file

Running the tests

$ ./gradlew test

Build

There are two ways to build the project using:

You can choose between the tools the most convenient for you. Read further how to use each of them.

Gradle

The project is packaged as a jar file and bundles the prometheus client libraries.

$ ./gradlew jar

builds the jar and writes it to build/libs.

Maven

To build the jar file using maven run the following command (will bundle the prometheus client libraries as well):

mvn package

It will build the project and write jar to the ./target.

Configurable versions for some packages

You can build the project using a different version of Keycloak or Prometheus, running the command:

For Gradle

$ ./gradlew -PkeycloakVersion="15.0.2.Final" -PprometheusVersion="0.12.0" jar

or by changing the gradle.properties file in the root of the project.

For Maven

mvn clean package -Dkeycloak.version=15.0.0 -Dprometheus.version=0.9.0

Install and setup

On Keycloak Widfly Distribution

This section assumes /opt/jboss as the Keycloak home directory, which is used on the jboss/keycloak reference container on Docker Hub.

  • Drop the jar into the /opt/jboss/keycloak/standalone/deployments/ subdirectory of your Keycloak installation.

  • Touch a dodeploy file into the /opt/jboss/keycloak/standalone/deployments/ subdirectory of your Keycloak installation.

# If your jar file is `keycloak-metrics-spi-2.0.2.jar`
cd /opt/jboss/keycloak/standalone/deployments/
touch keycloak-metrics-spi-2.0.2.jar.dodeploy
  • Restart the keycloak service.

On Keycloak Quarkus Distribution

We assume the home of keycloak is on the default /opt/keycloak

You will need to either copy the jar into the build step and run step, or copy it from the build stage. Following the example docker instructions No need to add .dodeploy.

# On build stage
COPY keycloak-metrics-spi.jar /opt/keycloak/providers/

# On run stage
COPY keycloak-metrics-spi.jar /opt/keycloak/providers/

If not copied to both stages keycloak will complain

ERROR: Failed to start quarkus
ERROR: Failed to open /opt/keycloak/lib/../providers/keycloak-metrics-spi.jar

The endpoint for the metrics is <url>/<http_relative_path>/realms/<realm>/metrics

Enable metrics-listener event

  • To enable the event listener via the GUI interface, go to Manage -> Events -> Config. The Event Listeners configuration should have an entry named metrics-listener.

  • To enable the event listener via the Keycloak CLI, such as when building a Docker container, use these commands.

$ /opt/jboss/keycloak/bin/kcadm.sh config credentials --server http://localhost:8080/auth --realm master --user $KEYCLOAK_USER --password $KEYCLOAK_PASSWORD
$ /opt/jboss/keycloak/bin/kcadm.sh update events/config -s "eventsEnabled=true" -s "adminEventsEnabled=true" -s "eventsListeners+=metrics-listener"
$ /usr/bin/rm -f /opt/jboss/.keycloak/kcadm.config

PushGateway

If you are running keycloak in a cluster or if you are running behind a load balancer, you might have problems scraping the metrics endpoint of each node. To fix this, you can push your metrics to a PushGateway.

Prometheus PushGateway

You can enable pushing to PushGateway by setting the environment variable PROMETHEUS_PUSHGATEWAY_ADDRESS in the keycloak instance. The format is host:port or ip:port of the Pushgateway.

If you need basic authentication you must set PROMETHEUS_PUSHGATEWAY_BASIC_AUTH_USERNAME and PROMETHEUS_PUSHGATEWAY_BASIC_AUTH_PASSWORD.

Grouping instances

The default value for the grouping key "instance" is the IP. This can be changed setting the environment variable PROMETHEUS_GROUPING_KEY_INSTANCE to a fixed value. Additionaly, if the value provided starts with the prefix ENVVALUE:, the string after the : will be used to get the value from the environment variable with that name. For example, with the next setting:

PROMETHEUS_GROUPING_KEY_INSTANCE=ENVVALUE:HOSTNAME

instance will have the value of the environment variable HOSTNAME

Grouping instances by cluster

if you have multiple KeyCloak clusters on the same runtime then you might like to groups instances by cluster's name.

That's the purpose of the environment variable PROMETHEUS_PUSHGATEWAY_JOB. The default job value is keycloak for all the instances.

For example for all the instances of a KeyCloak cluster #1 you can set:

PROMETHEUS_PUSHGATEWAY_JOB="keycloak-cluster1"

Metrics

For each metric, the endpoint returns 2 or more lines of information:

  • # HELP: A small description provided by the SPI.
  • # TYPE: The type of metric, namely counter and gauge. More info about types at prometheus.io/docs.
  • Provided there were any values, the last one recorded. If no value has been recorded yet, no more lines will be given.
  • In case the same metric have different labels, there is a different line for each one. By default all metrics are labeled by realm. More info about labels at prometheus.io/docs.

Example:

# HELP jvm_memory_bytes_committed Committed (bytes) of a given JVM memory area.
# TYPE jvm_memory_bytes_committed gauge
jvm_memory_bytes_committed{area="heap",} 2.00802304E8
jvm_memory_bytes_committed{area="nonheap",} 2.0217856E8

JVM performance

A variety of JVM metrics are provided

Generic events

Every single internal Keycloak event is being shared through the endpoint, with the descriptions Generic Keycloak User event or Generic Keycloak Admin event. Most of these events are not likely useful for the majority users but are provided for good measure. A complete list of the events can be found at Keycloak documentation.

Featured events

There are however a few events that are particularly more useful from a mobile app perspective. These events have been overriden by the SPI and are described more thoroughly below.

keycloak_login_attempts

This counter counts every login attempt performed by a non-admin user. It also distinguishes logins by the utilised identity provider by means of the label provider and by client with the label client_id..

# HELP keycloak_login_attempts Total number of login attempts
# TYPE keycloak_login_attempts counter
keycloak_login_attempts{realm="test",provider="keycloak",client_id="account"} 3.0
keycloak_login_attempts{realm="test",provider="github",client_id="application1"} 2.0
keycloak_logins_total

This counter counts every login performed by a non-admin user. It also distinguishes logins by the utilised identity provider by means of the label provider and by client with the label client_id..

# HELP keycloak_logins_total Total successful logins
# TYPE keycloak_logins_total counter
keycloak_logins_total{realm="test",provider="keycloak",client_id="account"} 3.0
keycloak_logins_total{realm="test",provider="github",client_id="application1"} 2.0
keycloak_failed_login_attempts

This counter counts every login performed by a non-admin user that fails, being the error described by the label error. It also distinguishes logins by the identity provider used by means of the label provider and by client with the label client_id.

# HELP keycloak_failed_login_attempts Total failed login attempts
# TYPE keycloak_failed_login_attempts counter
keycloak_failed_login_attempts{realm="test",provider="keycloak",error="invalid_user_credentials",client_id="application1"} 6.0
keycloak_failed_login_attempts{realm="test",provider="keycloak",error="user_not_found",client_id="application1"} 2.0
keycloak_client_logins

This counter counts every client login.

# HELP keycloak_client_logins Total successful client logins
# TYPE keycloak_client_logins counter
keycloak_client_logins{realm="test",provider="keycloak",client_id="account"} 4.0
keycloak_client_logins{realm="test",provider="github",client_id="application2"} 7.0
keycloak_failed_client_login_attempts

This counter counts every client login performed that fails, being the error described by the label error.

# HELP keycloak_failed_client_login_attempts Total failed client login attempts
# TYPE keycloak_failed_client_login_attempts counter
keycloak_failed_client_login_attempts{realm="test2",provider="keycloak",error="invalid_client_credentials",client_id="application2"} 5.0
keycloak_failed_client_login_attempts{realm="test2",provider="keycloak",error="client_not_found",client_id="application2"} 3.0
keycloak_refresh_tokens

This counter counts every refresh token.

# HELP keycloak_refresh_tokens Total number of successful token refreshes
# TYPE keycloak_refresh_tokens counter
keycloak_refresh_tokens{realm="test3",provider="keycloak",client_id="account"} 1.0
keycloak_refresh_tokens{realm="test3",provider="github",client_id="application3"} 2.0
keycloak_refresh_tokens_errors

This counter counts every refresh token that fails.

# HELP keycloak_refresh_tokens_errors Total number of failed token refreshes
# TYPE keycloak_refresh_tokens_errors counter
keycloak_refresh_tokens_errors{realm="test3",provider="keycloak",error="invalid_token",client_id="application3"} 3.0
keycloak_registrations

This counter counts every new user registration. It also distinguishes registrations by the identity provider used by means of the label provider and by client with the label client_id..

# HELP keycloak_registrations Total registered users
# TYPE keycloak_registrations counter
keycloak_registrations{realm="test",provider="keycloak",client_id="application1"} 1.0
keycloak_registrations{realm="test",provider="github",client_id="application1"} 1.0
keycloak_registrations_errors

This counter counts every new user registration that fails, being the error described by the label error. It also distinguishes registrations by the identity provider used by means of the label provider and by client with the label client_id..

# HELP keycloak_registrations_errors Total errors on registrations
# TYPE keycloak_registrations_errors counter
keycloak_registrations_errors{realm="test",provider="keycloak",error="invalid_registration",client_id="application1",} 2.0
keycloak_registrations_errors{realm="test",provider="keycloak",error="email_in_use",client_id="application1",} 3.0
keycloak_code_to_tokens

This counter counts every code to token.

# HELP keycloak_code_to_tokens Total number of successful code to token
# TYPE keycloak_code_to_tokens counter
keycloak_code_to_tokens{realm="test4",provider="keycloak",client_id="account"} 3.0
keycloak_code_to_tokens{realm="test4",provider="github",client_id="application4"} 1.0
keycloak_code_to_tokens_errors

This counter counts every code to token performed that fails, being the error described by the label error.

# HELP keycloak_code_to_tokens_errors Total number of failed code to token
# TYPE keycloak_code_to_tokens_errors counter
keycloak_code_to_tokens_errors{realm="test4",provider="keycloak",error="invalid_client_credentials",client_id="application4"} 7.0
keycloak_request_duration

This histogram records the response times per http method and puts them in one of nine buckets:

  • Requests that take 50ms or less
  • Requests that take 100ms or less
  • Requests that take 250ms or less
  • Requests that take 500ms or less
  • Requests that take 1s or less
  • Requests that take 2s or less
  • Requests that take 10s or less
  • Requests that take 30s or less
  • Any request that takes longer than 30s

The response from this type of metrics has the following format:

# HELP keycloak_request_duration Request duration
# TYPE keycloak_request_duration histogram
keycloak_request_duration_bucket{method="PUT",le="50.0",} 0.0
keycloak_request_duration_bucket{method="PUT",le="100.0",} 0.0
keycloak_request_duration_bucket{method="PUT",le="250.0",} 0.0
keycloak_request_duration_bucket{method="PUT",le="500.0",} 0.0
keycloak_request_duration_bucket{method="PUT",le="1000.0",} 1.0
keycloak_request_duration_bucket{method="PUT",le="2000.0",} 2.0
keycloak_request_duration_bucket{method="PUT",le="10000.0",} 2.0
keycloak_request_duration_bucket{method="PUT",le="30000.0",} 2.0
keycloak_request_duration_bucket{method="PUT",le="+Inf",} 2.0
keycloak_request_duration_count{method="PUT",} 2.0
keycloak_request_duration_sum{method="PUT",} 3083.0

This tells you that there have been zero requests that took less than 500ms. There was one request that took less than 1s. All the other requests took less than 2s.

Aside from the buckets there are also the sum and count metrics for every method. In the above example they tell you that there have been two requests total for this http method. The sum of all response times for this combination is 3083ms.

To get the average request duration over the last five minutes for the whole server you can use the following Prometheus query:

rate(keycloak_request_duration_sum[5m]) / rate(keycloak_request_duration_count[5m])
keycloak_response_errors

This counter counts the number of response errors (responses where the http status code is in the 400 or 500 range).

# HELP keycloak_response_errors Total number of error responses
# TYPE keycloak_response_errors counter
keycloak_response_errors{code="500",method="GET",} 1

Metrics URI

The URI can be added to the metrics by setting the environment variable URI_METRICS_ENABLED to true. This will output a consolidated realm URI value to the metrics. The realm value is replaced with a generic {realm} value

# HELP keycloak_request_duration Request duration
# TYPE keycloak_request_duration histogram
keycloak_request_duration_bucket{code="200",method="GET",resource="realms,realms/master/protocol/openid-connect",uri="realms/{realm}/protocol/openid-connect/3p-cookies/step2.html",le="50.0",} 2.0
keycloak_request_duration_bucket{code="200",method="GET",resource="realms,realms/master/protocol/openid-connect",uri="realms/{realm}/protocol/openid-connect/3p-cookies/step2.html",le="100.0",} 2.0
keycloak_request_duration_bucket{code="200",method="GET",resource="realms,realms/master/protocol/openid-connect",uri="realms/{realm}/protocol/openid-connect/3p-cookies/step2.html",le="250.0",} 2.0
keycloak_request_duration_bucket{code="200",method="GET",resource="realms,realms/master/protocol/openid-connect",uri="realms/{realm}/protocol/openid-connect/3p-cookies/step2.html",le="500.0",} 2.0
keycloak_request_duration_bucket{code="200",method="GET",resource="realms,realms/master/protocol/openid-connect",uri="realms/{realm}/protocol/openid-connect/3p-cookies/step2.html",le="1000.0",} 2.0
keycloak_request_duration_bucket{code="200",method="GET",resource="realms,realms/master/protocol/openid-connect",uri="realms/{realm}/protocol/openid-connect/3p-cookies/step2.html",le="2000.0",} 2.0
keycloak_request_duration_bucket{code="200",method="GET",resource="realms,realms/master/protocol/openid-connect",uri="realms/{realm}/protocol/openid-connect/3p-cookies/step2.html",le="10000.0",} 2.0
keycloak_request_duration_bucket{code="200",method="GET",resource="realms,realms/master/protocol/openid-connect",uri="realms/{realm}/protocol/openid-connect/3p-cookies/step2.html",le="30000.0",} 2.0
keycloak_request_duration_bucket{code="200",method="GET",resource="realms,realms/master/protocol/openid-connect",uri="realms/{realm}/protocol/openid-connect/3p-cookies/step2.html",le="+Inf",} 2.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/master/console",uri="admin/{realm}/console/whoami",le="50.0",} 0.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/master/console",uri="admin/{realm}/console/whoami",le="100.0",} 0.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/master/console",uri="admin/{realm}/console/whoami",le="250.0",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/master/console",uri="admin/{realm}/console/whoami",le="500.0",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/master/console",uri="admin/{realm}/console/whoami",le="1000.0",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/master/console",uri="admin/{realm}/console/whoami",le="2000.0",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/master/console",uri="admin/{realm}/console/whoami",le="10000.0",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/master/console",uri="admin/{realm}/console/whoami",le="30000.0",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/master/console",uri="admin/{realm}/console/whoami",le="+Inf",} 1.0

If the quanitiy of metrics is too high they can also be filtered to specific values using the URI_METRICS_FILTER e.g token,clients. This is a comman delimited value of keywords to search and display the required URIs.

# HELP keycloak_request_duration Request duration
# TYPE keycloak_request_duration histogram
keycloak_request_duration_bucket{code="200",method="POST",resource="realms,realms/master/protocol/openid-connect",uri="realms/{realm}/protocol/openid-connect/token",le="50.0",} 0.0
keycloak_request_duration_bucket{code="200",method="POST",resource="realms,realms/master/protocol/openid-connect",uri="realms/{realm}/protocol/openid-connect/token",le="100.0",} 1.0
keycloak_request_duration_bucket{code="200",method="POST",resource="realms,realms/master/protocol/openid-connect",uri="realms/{realm}/protocol/openid-connect/token",le="250.0",} 1.0
keycloak_request_duration_bucket{code="200",method="POST",resource="realms,realms/master/protocol/openid-connect",uri="realms/{realm}/protocol/openid-connect/token",le="500.0",} 1.0
keycloak_request_duration_bucket{code="200",method="POST",resource="realms,realms/master/protocol/openid-connect",uri="realms/{realm}/protocol/openid-connect/token",le="1000.0",} 1.0
keycloak_request_duration_bucket{code="200",method="POST",resource="realms,realms/master/protocol/openid-connect",uri="realms/{realm}/protocol/openid-connect/token",le="2000.0",} 1.0
keycloak_request_duration_bucket{code="200",method="POST",resource="realms,realms/master/protocol/openid-connect",uri="realms/{realm}/protocol/openid-connect/token",le="10000.0",} 1.0
keycloak_request_duration_bucket{code="200",method="POST",resource="realms,realms/master/protocol/openid-connect",uri="realms/{realm}/protocol/openid-connect/token",le="30000.0",} 1.0
keycloak_request_duration_bucket{code="200",method="POST",resource="realms,realms/master/protocol/openid-connect",uri="realms/{realm}/protocol/openid-connect/token",le="+Inf",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/master/console",uri="",le="50.0",} 4.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/master/console",uri="",le="100.0",} 5.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/master/console",uri="",le="250.0",} 6.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/master/console",uri="",le="500.0",} 6.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/master/console",uri="",le="1000.0",} 6.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/master/console",uri="",le="2000.0",} 6.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/master/console",uri="",le="10000.0",} 6.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/master/console",uri="",le="30000.0",} 6.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/master/console",uri="",le="+Inf",} 6.0
keycloak_request_duration_count{code="200",method="GET",resource="admin,admin/master/console",uri="",} 6.0
keycloak_request_duration_sum{code="200",method="GET",resource="admin,admin/master/console",uri="",} 274.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/serverinfo",uri="",le="50.0",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/serverinfo",uri="",le="100.0",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/serverinfo",uri="",le="250.0",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/serverinfo",uri="",le="500.0",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/serverinfo",uri="",le="1000.0",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/serverinfo",uri="",le="2000.0",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/serverinfo",uri="",le="10000.0",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/serverinfo",uri="",le="30000.0",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/serverinfo",uri="",le="+Inf",} 1.0
keycloak_request_duration_count{code="200",method="GET",resource="admin,admin/serverinfo",uri="",} 1.0

To remove the consolidated realm URI, set URI_METRICS_DETAILED to true

# HELP keycloak_request_duration Request duration
# TYPE keycloak_request_duration histogram
keycloak_request_duration_bucket{code="200",method="POST",resource="realms,realms/master/protocol/openid-connect",uri="realms/master/protocol/openid-connect/token",le="50.0",} 0.0
keycloak_request_duration_bucket{code="200",method="POST",resource="realms,realms/master/protocol/openid-connect",uri="realms/master/protocol/openid-connect/token",le="100.0",} 0.0
keycloak_request_duration_bucket{code="200",method="POST",resource="realms,realms/master/protocol/openid-connect",uri="realms/master/protocol/openid-connect/token",le="250.0",} 1.0
keycloak_request_duration_bucket{code="200",method="POST",resource="realms,realms/master/protocol/openid-connect",uri="realms/master/protocol/openid-connect/token",le="500.0",} 1.0
keycloak_request_duration_bucket{code="200",method="POST",resource="realms,realms/master/protocol/openid-connect",uri="realms/master/protocol/openid-connect/token",le="1000.0",} 1.0
keycloak_request_duration_bucket{code="200",method="POST",resource="realms,realms/master/protocol/openid-connect",uri="realms/master/protocol/openid-connect/token",le="2000.0",} 1.0
keycloak_request_duration_bucket{code="200",method="POST",resource="realms,realms/master/protocol/openid-connect",uri="realms/master/protocol/openid-connect/token",le="10000.0",} 1.0
keycloak_request_duration_bucket{code="200",method="POST",resource="realms,realms/master/protocol/openid-connect",uri="realms/master/protocol/openid-connect/token",le="30000.0",} 1.0
keycloak_request_duration_bucket{code="200",method="POST",resource="realms,realms/master/protocol/openid-connect",uri="realms/master/protocol/openid-connect/token",le="+Inf",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/serverinfo",uri="",le="50.0",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/serverinfo",uri="",le="100.0",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/serverinfo",uri="",le="250.0",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/serverinfo",uri="",le="500.0",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/serverinfo",uri="",le="1000.0",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/serverinfo",uri="",le="2000.0",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/serverinfo",uri="",le="10000.0",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/serverinfo",uri="",le="30000.0",} 1.0
keycloak_request_duration_bucket{code="200",method="GET",resource="admin,admin/serverinfo",uri="",le="+Inf",} 1.0
keycloak_request_duration_count{code="200",method="GET",resource="admin,admin/serverinfo",uri="",} 1.0
keycloak_request_duration_sum{code="200",method="GET",resource="admin,admin/serverinfo",uri="",} 19.0

External Access

To disable metrics being externally accessible to a cluster. Set the environment variable 'DISABLE_EXTERNAL_ACCESS'. Once set enable the header 'X-Forwarded-Host' on your proxy. This is enabled by default on HA Proxy on Openshift.

Grafana Dashboard

You can use this dashboard or create yours https://grafana.com/grafana/dashboards/10441-keycloak-metrics-dashboard/

keycloak-metrics-spi's People

Contributors

alexander72 avatar aliok avatar antoinethebaud avatar boomatang avatar camilamacedo86 avatar cathaloconnorrh avatar claudiunicolaa avatar danifr avatar davidffrench avatar diversit avatar ernelio avatar gallardot avatar gdhordain avatar ghenadiibatalski avatar grdryn avatar guerricm avatar josemigallas avatar klinux avatar matskiv avatar matzew avatar mrparkers avatar pb82 avatar raul-verdi avatar saibot94 avatar secondsun avatar soerensilkjaer avatar spidersouleater avatar thomasdarimont avatar tlereste avatar xinau avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

keycloak-metrics-spi's Issues

add metric for total number of requests

currently only response errors are counted, while this it self is useful it would be more complete to also log the total number of requests. by comparing the ratio of errors and total requests a operator is able to determine the healthiness of their installations.

the concrete change needs to be made somewhere along these lines. i'm still unsure how to implement it "correctly", but would like to contribute to the project. 2 solutions that come to my mind would be to either.

  1. drop the if clause and count all responses
  2. add a new metric keycloak_responses_total similar to keycloak_response_errors that counts all responses

// We are only interested in recording the response status if it was an error
// (either a 4xx or 5xx). No point in counting the successful responses
if (status >= 400) {
PrometheusExporter.instance().recordResponseError(status, req.getMethod());
}

Add realm name in the reported events

Description

Add realm name in the reported events

Expected Behavior

A realm name is more useful than the currently reported realm id
Currently the realm's id is reported

Actual Behavior

The realm id is reported in the realm field (except the master realm, which shows as "master")

Environment

  • Operating system:
  • OpenShift versions:
  • Project Versions:

Steps to reproduce

Virtually any event produces realm information. You can try to enter false credentials to a non-master realm to trigger a keycloak_failed_login_attempts event and see that the realm is identified by its id.

Provider not working on redhat-sso 7.3.6

Description

Provider is not working on RHEL branded implementation of keycloak 7.3.6.

Expected Behavior

Metrics such as keycloak_failed_login_attempts should record failed/error logins etc.

Actual Behavior

  • Jvm metrics are recorded ,but no keycloak metrics are recorded under /auth/realms/master/metrics.
  • Deployment of SPI jar is without errors.
  • SPI is not available as dropdown menu item in REALM/Events Config/Event Listeners
  • when [org.keycloak.events] type is logged, we get this error in event log:
"loggerClassName": "org.jboss.logging.Logger",
    "loggerName": "org.keycloak.events.EventBuilder",
    "level": "ERROR",
    "message": "Event listener 'metrics-listener' registered, but provider not found",
    "threadName": "default task-1",
    "threadId": 279,
    "mdc": {
    },
    "ndc": "",
    "hostName": "sbacezsso01.cez.local",
    "processName": "jboss-modules.jar",
    "processId": 23182,
    "sourceClassName": "org.keycloak.events.EventBuilder",
    "sourceFileName": "EventBuilder.java",
    "sourceMethodName": "<init>",
    "sourceLineNumber": 67,
    "sourceModuleName": "org.keycloak.keycloak-server-spi-private",
    "sourceModuleVersion": "4.8.13.Final-redhat-00001"

Environment

  • Operating system: Red Hat Linux 4.8.5-36
  • OpenShift versions:
  • Project Versions: redhat-sso 7.3.6

Steps to reproduce

Deploy redhat-sso 7.3.6, observe keycloak metrics such as logins and failed logins no longer reflected in metrics endpoint.
We have tried to build/ deploy Your SPI with different versions of keycloakVersion in gredel.properties file with no sucess.

As mentioned in related issue #23,
this is most likely due to a divergence from keycloak standards by redhat.

Thank You

Release with Metrics filter

I find your library really useful, especially the recent addition - metrics filter. I have following questions:

  • do you plan to release it in nearby future? I would like to use new filter and I don't want to have a dependency to a SNAPSHOT
  • do you plan to publish artifacts on some public repository? I think that would be great and ease using your spi

newer prometheus and keycloak version

Hey! This is more a question than an issue :-)

it is a cool project but I wanted to know if I could use it with newer versions of Prometheus (v2.9.2) and Keycloak (v6.0.1) ?

I've tried just by running the default ./gradlew jar and it seems to work with my keycloak and prometheus versions mentionned earlier.

No data in grafana

Description

I am following this tutorial https://quarkus.io/guides/security-keycloak-authorization to setup keycloak for a sample app. And I would like to show data in grafana

Expected Behavior

Charts being plotted in grafana with keycloak data

Actual Behavior

No data is shown

Environment

  • Operating system:
  • OpenShift versions:
  • Project Versions:

I am able to access keycloak metrics in the browser http://localhost:8180/auth/realms/quarkus/metrics.

The data is just not plotted in grafana.

My prometheus config is as follows:

  - job_name: "keycloak"
    metrics_path: /auth/realms/quarkus/metrics
    static_configs:
      - targets: ["10.1.1.79:8180"]

Nullpointer in org.jboss.aerogear.keycloak.metrics.MetricsEventListener

we are facing from time to time the following error

Failed to send type to org.jboss.aerogear.keycloak.metrics.MetricsEventListener@34767077: java.lang.IllegalArgumentException: Label cannot be null

this is the full stack trace:

2019-10-28 09:47:43,814 ERROR [org.keycloak.events.EventBuilder] (default task-111) Failed to send type to org.jboss.aerogear.keycloak.metrics.MetricsEventListener@34767077: java.lang.IllegalArgumentException: Label cannot be null.
at io.prometheus.client.SimpleCollector.labels(SimpleCollector.java:68)
at org.jboss.aerogear.keycloak.metrics.PrometheusExporter.recordLoginError(PrometheusExporter.java:192)
at org.jboss.aerogear.keycloak.metrics.MetricsEventListener.onEvent(MetricsEventListener.java:29)
at org.keycloak.keycloak-server-spi-private@4.8.3.Final-redhat-00001//org.keycloak.events.EventBuilder.send(EventBuilder.java:192)
at org.keycloak.keycloak-server-spi-private@4.8.3.Final-redhat-00001//org.keycloak.events.EventBuilder.error(EventBuilder.java:169)
at [email protected]//org.keycloak.services.resources.SessionCodeChecks.restartAuthenticationSessionFromCookie(SessionCodeChecks.java:400)
at [email protected]//org.keycloak.services.resources.SessionCodeChecks.initialVerifyAuthSession(SessionCodeChecks.java:197)
at [email protected]//org.keycloak.services.resources.SessionCodeChecks.initialVerify(SessionCodeChecks.java:204)
at [email protected]//org.keycloak.services.resources.LoginActionsService.checksForCode(LoginActionsService.java:194)
at [email protected]//org.keycloak.services.resources.LoginActionsService.authenticate(LoginActionsService.java:251)
at [email protected]//org.keycloak.services.resources.LoginActionsService.authenticateForm(LoginActionsService.java:320)
at jdk.internal.reflect.GeneratedMethodAccessor652.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at [email protected]//org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:140)
at [email protected]//org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:509)
at [email protected]//org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:399)
at [email protected]//org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$0(ResourceMethodInvoker.java:363)
at [email protected]//org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:358)
at [email protected]//org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:365)
at [email protected]//org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:337)
at [email protected]//org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:137)
at [email protected]//org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:100)
at [email protected]//org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:443)
at [email protected]//org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:233)
at [email protected]//org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:139)
at [email protected]//org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:358)
at [email protected]//org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:142)
at [email protected]//org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:219)
at [email protected]//org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:227)
at [email protected]//org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)
at [email protected]//org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)
at [email protected]//javax.servlet.http.HttpServlet.service(HttpServlet.java:791)
at [email protected]//io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
at [email protected]//io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
at [email protected]//org.keycloak.services.filters.KeycloakSessionServletFilter.doFilter(KeycloakSessionServletFilter.java:90)
at [email protected]//io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at [email protected]//io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at [email protected]//io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
at [email protected]//io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at [email protected]//io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
at [email protected]//io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at [email protected]//org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at [email protected]//io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)
at [email protected]//io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at [email protected]//io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at [email protected]//io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at [email protected]//io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at [email protected]//io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at [email protected]//io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at [email protected]//io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at [email protected]//org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at [email protected]//org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler.handleRequest(GlobalRequestControllerHandler.java:68)
at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
at [email protected]//io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
at [email protected]//io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at [email protected]//org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)
at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1502)
at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1502)
at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1502)
at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1502)
at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104)
at [email protected]//io.undertow.server.Connectors.executeRootHandler(Connectors.java:360)
at [email protected]//io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
at [email protected]//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at [email protected]//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1985)
at [email protected]//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1487)
at [email protected]//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1378)
at java.base/java.lang.Thread.run(Thread.java:834)

Route tag causing huge cardinality

Description

We found our Prometheus server was using a lot of memory and traced it to the face one of the tags used is "route" which includes the ID for each user, which is our case is in the tens of thousands.

keycloak_request_duration_count{method="GET",route="/admin/realms//users/",} 13.0

It would be good if this tag could be disabled as an option.

Currently on version 1.0.1 but I think this is the case in the latest version as well.

java.lang.ClassNotFoundException with version 1.0.3

Description

Deployment of version 1.0.3 fails with
java.lang.NoClassDefFoundError: com/google/common/collect/ImmutableSet
Deployment of version 1.0.2 in the same environment works just fine.

12:48:22,305 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-8) WFLYSRV0027: Starting deployment of "keycloak-metrics-spi-1.0.3.jar" (runtime-name: "keycloak-metrics-spi-1.0.3.jar")
12:48:22,390 INFO  [org.keycloak.subsystem.server.extension.KeycloakProviderDeploymentProcessor] (MSC service thread 1-6) Deploying Keycloak provider: keycloak-metrics-spi-1.0.3.jar
12:48:22,402 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-6) MSC000001: Failed to start service jboss.deployment.unit."keycloak-metrics-spi-1.0.3.jar".POST_MODULE: org.jboss.msc.service.StartException in service jboss.deployment.unit."keycloak-metrics-spi-1.0.3.jar".POST_MODULE: WFLYSRV0153: Failed to process phase POST_MODULE of deployment "keycloak-metrics-spi-1.0.3.jar"
	at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:183)
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1738)
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.execute(ServiceControllerImpl.java:1700)
	at org.jboss.msc.service.ServiceControllerImpl$ControllerTask.run(ServiceControllerImpl.java:1558)
	at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
	at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NoClassDefFoundError: com/google/common/collect/ImmutableSet
	at org.jboss.aerogear.keycloak.metrics.MetricsFilter.<clinit>(MetricsFilter.java:20)
	at org.jboss.aerogear.keycloak.metrics.MetricsEndpointFactory.init(MetricsEndpointFactory.java:19)
	at org.keycloak.services.DefaultKeycloakSessionFactory.loadFactories(DefaultKeycloakSessionFactory.java:217)
	at org.keycloak.services.DefaultKeycloakSessionFactory.deploy(DefaultKeycloakSessionFactory.java:115)
	at org.keycloak.provider.ProviderManagerRegistry.deploy(ProviderManagerRegistry.java:42)
	at org.keycloak.subsystem.server.extension.KeycloakProviderDeploymentProcessor.deploy(KeycloakProviderDeploymentProcessor.java:55)
	at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:176)
	... 8 more
Caused by: java.lang.ClassNotFoundException: com.google.common.collect.ImmutableSet from [Module "deployment.keycloak-metrics-spi-1.0.3.jar" from Service Module Loader]
	at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:255)
	at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:410)
	at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398)
	at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:116)
	... 15 more

12:48:22,410 ERROR [org.jboss.as.controller.management-operation] (DeploymentScanner-threads - 1) WFLYCTL0013: Operation ("deploy") failed - address: ([("deployment" => "keycloak-metrics-spi-1.0.3.jar")]) - failure description: {"WFLYCTL0080: Failed services" => {"jboss.deployment.unit.\"keycloak-metrics-spi-1.0.3.jar\".POST_MODULE" => "WFLYSRV0153: Failed to process phase POST_MODULE of deployment \"keycloak-metrics-spi-1.0.3.jar\"
    Caused by: java.lang.NoClassDefFoundError: com/google/common/collect/ImmutableSet
    Caused by: java.lang.ClassNotFoundException: com.google.common.collect.ImmutableSet from [Module \"deployment.keycloak-metrics-spi-1.0.3.jar\" from Service Module Loader]"}}
12:48:22,476 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 1) WFLYSRV0010: Deployed "keycloak-metrics-spi-1.0.3.jar" (runtime-name : "keycloak-metrics-spi-1.0.3.jar")
12:48:22,477 INFO  [org.jboss.as.controller] (DeploymentScanner-threads - 1) WFLYCTL0183: Service status report
WFLYCTL0186:   Services which failed to start:      service jboss.deployment.unit."keycloak-metrics-spi-1.0.3.jar".POST_MODULE: WFLYSRV0153: Failed to process phase POST_MODULE of deployment "keycloak-metrics-spi-1.0.3.jar"

Environment

  • Operating system: RHEL 7
  • Java versions: java-1.8.0-openjdk-1.8.0.212.b04-0.el7_6.x86_64

Steps to reproduce

  • Download and extract Keycloak archive
  • Start Keycloak
  • cp keycloak-metrics-spi-1.0.3.jar keycloak-6.0.1/standalone/deployments

Metrics aren't available at custom endpoint

In our docker container we modify the path of keycloak to accommodate many instances

RUN sed -i -e 's/auth</web-context>/instance1/auth</web-context>/' $JBOSS_HOME/standalone/configuration/standalone.xml

  | RUN sed -i -e 's/auth</web-context>/instance1/auth</web-context>/' $JBOSS_HOME/standalone/configuration/standalone-ha.xml
  | RUN sed -i -e 's/name="/"/name="/instance1/"/' $JBOSS_HOME/standalone/configuration/standalone.xml
  | RUN sed -i -e 's/name="/"/name="/instance1/"/' $JBOSS_HOME/standalone/configuration/standalone-ha.xml
  | RUN sed -i -e 's//auth//instance1/auth"/' $JBOSS_HOME/welcome-content/index.html

This produces
https://compaysite.com/instance1/auth

Expected Behavior

metrics should be available at
https://compaysite.com/instance1/auth/realms/master/metrics

Actual Behavior

Page not found

Environment

Using docker

Steps to reproduce

Works without the custom path.

  1. Modify the auth endpoint
  2. Add jar
  3. enable jar
  4. try to pull metrics

mymachineuser@mymachine:~$ docker exec -it e2d bash
[jboss@e2da41401798 ~]$ /opt/jboss/keycloak/bin/kcadm.sh config credentials --server http://localhost:8080/instance1/auth --realm master --user admin --password somepw
Logging into http://localhost:8080/instance1/auth as user admin of realm master
[jboss@e2da41401798 ~]$ /opt/jboss/keycloak/bin/kcadm.sh update events/config -s "eventsEnabled=true" -s "adminEventsEnabled=true" -s "eventsListeners+=metrics-listener"
[jboss@e2da41401798 ~]$

is there away to get instance hostname in the labels for keycloak metrics

Description

Add a brief and meaningful description.
i'm not able to find a way to get instance hostname in labels for the keycloak metrics instead of ip address. is it supported?

Expected Behavior

Describe the expected behaviour.
i need to see the hostname.

Actual Behavior

Describe the current/actual behaviour.
instance=ip-address

Environment

prod

  • Operating system: Red Hat Enterprise Linux - 8.2 (Ootpa)
  • OpenShift versions: kubernetes(eks - 1.16)
  • Project Versions: 10.0.1 keycloak version

Steps to reproduce

Describe all steps and pre-requirements which are required to be performed in order to reproduce this scenario. ( E.g 1. Action, 2. Action ... )

Huge number of keycloak_request_duration_bucket entries

Description

After installing the metrics-spi, we saw a huge number of keycloak_request_duration_bucket entries in blocks of 11 entries fro every single user. Since we have a high number of users, the metrics page takes forever to load.

Expected Behavior

Reduce size and load time of the metrics page to a reasonable value.

Actual Behavior

The total size of the metrics page is more than 300 MB (!!!)

Environment

Standalone Keycloak v3.4.2

  • Operating system:
    Ubuntu 18.04.4 LTS

  • Project Versions:

Steps to reproduce

Open metrics page.

keycloak_logins is not exported

Description

The keycloak_logins counter is described but not exported while scraping metrics endpoint

Expected Behavior

keycloak_login should be exported with a value

Actual Behavior

No value is exported. The Only keycloak related values exported are:

  • keycloak_response_errors
  • keycloak_request_duration (containing reasonable realm values)

All other metrics are described but without any value

Environment

  • Operating system: CentOS Linux 7.1906 Atomic Host
  • OpenShift versions: OKD 3.11.0+739ab57-285
  • k8s version: 1.11.0+d4cacc0
  • Project Versions: 1.0.3 u. 1.0.4 / Keycloak 7.0.0 (jboss/keycloak:7.0.0)

Steps to reproduce

Keycloak runs as an single instance statefulset with one realm created. This realm contains an user. The user login is visible in the kc logs but scraping the metrics endpoint does not provide a keycloak_logins counter

Error when metrics-spi is enabled

Description

Using this plugin with KeyCloak 7.0.1 causes exceptions

04:13:52,913 INFO  [org.jboss.aerogear.keycloak.metrics.MetricsEventListener] (default task-1) Received admin event of type UPDATE (REALM) in realm development
04:13:52,914 ERROR [org.keycloak.services] (default task-1) KC-SERVICES0085: Failed to send type to org.jboss.aerogear.keycloak.metrics.MetricsEventListener@5af82742: java.lang.NoClassDefFoundError: com/google/common/base/Strings
        at deployment.keycloak-metrics-spi-1.0.4.jar//org.jboss.aerogear.keycloak.metrics.PrometheusExporter.recordGenericAdminEvent(PrometheusExporter.java:150)
        at deployment.keycloak-metrics-spi-1.0.4.jar//org.jboss.aerogear.keycloak.metrics.MetricsEventListener.onEvent(MetricsEventListener.java:40)
        at [email protected]//org.keycloak.services.resources.admin.AdminEventBuilder.send(AdminEventBuilder.java:256)
        at [email protected]//org.keycloak.services.resources.admin.AdminEventBuilder.success(AdminEventBuilder.java:235)
        at [email protected]//org.keycloak.services.resources.admin.RealmAdminResource.updateRealmEventsConfig(RealmAdminResource.java:687)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at [email protected]//org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:138)
        at [email protected]//org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:517)
        at [email protected]//org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:406)
        at [email protected]//org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$0(ResourceMethodInvoker.java:370)
        at [email protected]//org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:355)
        at [email protected]//org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:372)
        at [email protected]//org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:344)
        at [email protected]//org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:137)
        at [email protected]//org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:106)
        at [email protected]//org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:132)
        at [email protected]//org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:100)
        at [email protected]//org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:440)
        at [email protected]//org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:229)
        at [email protected]//org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:135)
        at [email protected]//org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:355)
        at [email protected]//org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:138)
        at [email protected]//org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:215)
        at [email protected]//org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:227)
        at [email protected]//org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)
        at [email protected]//org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)
        at [email protected]//javax.servlet.http.HttpServlet.service(HttpServlet.java:791)
        at [email protected]//io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
        at [email protected]//io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
        at [email protected]//org.keycloak.services.filters.KeycloakSessionServletFilter.doFilter(KeycloakSessionServletFilter.java:90)
        at [email protected]//io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
        at [email protected]//io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
        at [email protected]//io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
        at [email protected]//io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
        at [email protected]//io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
        at [email protected]//io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
        at [email protected]//org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
        at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at [email protected]//io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)
        at [email protected]//io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
        at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at [email protected]//io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
        at [email protected]//io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
        at [email protected]//io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
        at [email protected]//io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
        at [email protected]//io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
        at [email protected]//io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
        at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at [email protected]//org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
        at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at [email protected]//org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler.handleRequest(GlobalRequestControllerHandler.java:68)
        at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
        at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
        at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
        at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
        at [email protected]//io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
        at [email protected]//io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
        at [email protected]//org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)
        at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1502)
        at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1502)
        at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1502)
        at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1502)
        at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
        at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
        at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104)
        at [email protected]//io.undertow.server.Connectors.executeRootHandler(Connectors.java:364)
        at [email protected]//io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
        at [email protected]//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
        at [email protected]//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982)
        at [email protected]//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
        at [email protected]//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
        at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.ClassNotFoundException: com.google.common.base.Strings from [Module "deployment.keycloak-metrics-spi-1.0.4.jar" from Service Module Loader]
        at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:255)
        at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:410)
        at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398)
        at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:116)
        ... 76 more

Environment

  • Operating system: MacOS / Docker
  • Project Versions: keycloak-metrics-spi-1.0.4.jar

Steps to reproduce

Create a docker-compose:

version: "3.3"

services:
  keycloak:
    build:
      context: ../
      dockerfile: keycloak.Dockerfile
    image: keycloak:metrics
    container_name: "keycloak-oauth"
    depends_on:
      - postgres
    ports:
      - 81:8080
    command:
      - "-b 0.0.0.0"
    environment:
      KEYCLOAK_USER: admin
      KEYCLOAK_PASSWORD: admin

Docker file to build:

FROM jboss/keycloak:7.0.1

COPY keycloak-metrics-spi-1.0.4.jar /opt/jboss/keycloak/standalone/deployments/

"metrics-listener" does not appear in Events Config

Description

After deploy keycloak-metrics-spi-2.3.1.jar, option "metrics-listener" not appear

Expected Behavior

After deploy the file keycloak-metrics-spi-2.3.1.jar, and restart keycloak (i am using v12.0.4), the "metrics-listener" does not appear on the Event Listeners option

Actual Behavior

After deploy the file keycloak-metrics-spi-2.3.1.jar, and restart keycloak (i am using v12.0.4), the "metrics-listener" does not appear on the Event Listeners option
The endpoint $KEYCLOAKIP/auth/realms/master/metrics return some data, but not the relevated to keycloak logins, refresh token to code, etc.
image

Yesterday, it worked for some minutes, and today, i cant do it work anyway. I tried downgrading the spi, keycloak version, and using a new database, but nothings works.

Environment

  • Operating system: Ubuntu 20.04.2 LTS (Focal Fossa)
  • OpenShift versions:
  • Project Versions: keycloak-metrics-spi-2.3.1.jar with keycloak v12.0.4

Steps to reproduce

Install keycloak, copy the keycloak-metrics-spi-2.3.1.jar to /opt/keycloak/standalone/deployments
Start keycloak
The logs:
2021-04-22 16:09:40,618 INFO [org.jboss.as.repository] (DeploymentScanner-threads - 1) WFLYDR0001: Content added at location /opt/keycloak/standalone/data/content/f9/fd8d6ad6d13f4acafdec76a6343928020f580a/content
2021-04-22 16:09:40,624 INFO [org.jboss.as.server.deployment] (MSC service thread 1-5) WFLYSRV0027: Starting deployment of "keycloak-metrics-spi-2.3.1.jar" (runtime-name: "keycloak-metrics-spi-2.3.1.jar")
2021-04-22 16:09:40,720 INFO [org.keycloak.subsystem.server.extension.KeycloakProviderDeploymentProcessor] (MSC service thread 1-2) Deploying Keycloak provider: keycloak-metrics-spi-2.3.1.jar
2021-04-22 16:09:40,729 WARN [org.keycloak.services] (MSC service thread 1-2) KC-SERVICES0047: metrics (org.jboss.aerogear.keycloak.metrics.MetricsEndpointFactory) is implementing the internal SPI realm-restapi-extension. This SPI is internal and may change without notice
2021-04-22 16:09:40,794 INFO [org.jboss.as.server] (DeploymentScanner-threads - 1) WFLYSRV0010: Deployed "keycloak-metrics-spi-2.3.1.jar" (runtime-name : "keycloak-metrics-spi-2.3.1.jar")

Looking providers in the web server info of Keycloak, does not appear too.
image

There is no data in Grafana from Prometheus (Data provided by Prometheus-PushGateway).

Description

I've set up my Keycloak with this plugin and propagate the event data to Prometheus-PushGateway. I've checked the event, and it reaches successfully to the Prometheus server.

Expected Behavior

I should get the data and render it to the Grafana dashboard you guys provided.

Actual Behavior

I'm not getting anything except empty graphs in Grafana..

Environment

Grafana Dashboard: Tested with 7.0.1 and 7.2.1. (No chance to work)

  • Kubernetes

Steps to reproduce

I've followed and applied all necessary steps but failed to read data in Grafanas dashboard which's provided here: https://grafana.com/dashboards/10441

CLIENT_LOGIN and CLIENT_LOGIN_ERROR should be reported using keycloak_logins and keycloak_failed_login_attempts

Description

The events CLIENT_LOGIN and CLIENT_LOGIN_ERROR are currently exported as keycloak_user_event_CLIENT_LOGIN and keycloak_user_event_CLIENT_LOGIN_ERROR. With those metrics, only the realm is exposed, it's not possible to get the client_id. So we know only the number of CLIENT_LOGIN against a realm and not who connected through the metrics.

Expected Behavior

I would suggest to export those metrics using the same keycloak_logins and keycloak_failed_login_attempts or create keycloak_client_logins and keycloak_failed_client_login_attempts to easily track those login including the client_id information in the metrics.

For the moment, on my side I added both events in the switch case present in MetricsEventListener. That's the only change needed BTW.

Do you want me to create a PR with this change ?

add metric for total number of logins

hi. eventhough it might seem to be able to get the total number of login attempts by adding the keycloak_logins and keycloak_failed_login_attempts. it's only possible if metrics for both exist with identical labels.
this is not always the case as show in this example where specific realms haven't had failed logins or logins.
2021-01-06_13-12

Provider no longer works on redhat-sso 7.3

Description

Firstly, thanks for this provider - have been happily using this for our current keycloak/redhat-sso implementation. However, following an upgrade the keycloak specific metrics no longer work on redhat-sso 7.3 (RHEL branded implementation of keycloak)

Expected Behavior

Metrics such as keycloak_failed_login_attempts should record failed logins as per previous version (7.2)

Actual Behavior

jvm metrics are recorded as before but no keycloak metrics are recorded under /auth/realms/master/metrics as previously

Environment

  • Operating system: Centos 7
  • OpenShift versions: kubernetes 1.10
  • Project Versions:

Steps to reproduce

Deploy redhat-sso 7.3, observe keycloak metrics such as logins and failed logins no longer reflected in metrics endpoint.

Appreciate this is most likely due to a divergence from keycloak standards by redhat but wanted to raise for awareness.

Keycloak 11.0.0 support

Description

I just tried to install the plugin to my keycloak v11.0.0 instance and I only get an error message in the log after the start.

keycloak-0 keycloak 16:37:00,987 ERROR [org.jboss.as.server.deployment.scanner] (DeploymentScanner-threads - 1) WFLYDS0021: Deployment content /opt/jboss/keycloak/standalone/deployments/keycloak-metrics-spi-2.0.1.jar appears to be incomplete and is not progressing toward completion. This content cannot be auto-deployed.
keycloak-0 keycloak 16:37:00,991 WARN  [org.jboss.as.server.deployment.scanner] (DeploymentScanner-threads - 1) WFLYDS0014: Scan found content configured for auto-deploy that could not be safely auto-deployed. See details above. Deployment changes will not be processed until all problematic content is either removed or whether to deploy the content or not is indicated via a .dodeploy or .skipdeploy marker file. Problematic deployments are [keycloak-metrics-spi-2.0.1.jar]
keycloak-0 keycloak 16:37:01,035 INFO  [org.jboss.as.server.deployment.scanner] (DeploymentScanner-threads - 2) WFLYDS0015: Re-attempting failed deployment keycloak-metrics-spi-2.0.1.jar

I added the plugin as described into the /opt/jboss/keycloak/standalone/deployments folder and extended the standalone.xml with the following configuration:

/subsystem=keycloak-server/spi="eventsListeners": add()
/subsystem=keycloak-server/spi=eventsListeners/provider="metrics-listener": add(enabled=true)

Environment

  • Docker v19.0.3
  • Kubernetes 1.16.12
  • Project Versions: 2.0.1

Steps to reproduce

docker pull jboss/keycloak:11.0.0
Run the container
Run the following scripts within the container

#!/bin/sh
curl https://github.com/aerogear/keycloak-metrics-spi/releases/download/2.0.1/keycloak-metrics-spi-2.0.1.jar -o /opt/jboss/keycloak/standalone/deployments/keycloak-metrics-spi-2.0.1.jar
echo 'Downloaded metrics plugin'

and

embed-server --server-config=standalone.xml --std-out=echo
/subsystem=keycloak-server/spi="eventsListeners": add()
/subsystem=keycloak-server/spi=eventsListeners/provider="metrics-listener": add(enabled=true)

Management port for metrics endpoint?

Is it possible to expose the metrics endpoint to different port ?
like Spring Boot Actuator we can set properties to change the management port and disable the security?
I see the code in MetricsEndpoint class we can set the environment variable of DISABLE_EXTERNAL_ACCESS to disable access coming from the openshift HA Proxy, I'm still checking and confirming if this way may work in my current architecture and infrastructure, just hoping to see if we can generalize ways to secure the metrics endpoint.

Publish public docker container

It would be great to have a published docker container to be used as an init container to keycloak kubernetes/helm installations, along with instructions to integrate that.

Pushgateway Error code 200

Description

I have an error using prometheus push gateway, i configured the variable with endpoint and keycloak push successfully metrics to pushgateway, but in keycloak log i have an error

Expected Behavior

log 200 ok for push to prometheus pushgatway

Actual Behavior

`

2020-06-22T08:19:33.374 [] [] [Thread-401] ERROR -- o.j.a.k.m.PrometheusExporter : Unable to send to prometheus PushGateway: java.io.IOException: Response code from http://pushgateway.********.svc:9091/metrics/job/keycloak/instance/10.130.14.135 was 200

  | at io.prometheus.client.exporter.PushGateway.doRequest(PushGateway.java:297)
  | at io.prometheus.client.exporter.PushGateway.pushAdd(PushGateway.java:171)
  | at org.jboss.aerogear.keycloak.metrics.PrometheusExporter.push(PrometheusExporter.java:289)
  | at org.jboss.aerogear.keycloak.metrics.PrometheusExporter.lambda$pushAsync$0(PrometheusExporter.java:281)
  | at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1736)
  | at java.base/java.lang.Thread.run(Thread.java:834)

`

Environment

  • Operating system: rhel7
  • OpenShift versions: 3.11
  • Project Versions: 2.0.1

Steps to reproduce

Deploy keycloak on openshift and use the library

update grafana dashboard

Hi,

I want to request dashboard template update.

I installed keycloak on kubernetes cluster using helm chart. (codecentric/keycloak)
And I use 2 replicas.

In this case,
your dashboard does not have job in variable, (I can install keycloak-prod / keycloak-stage , ...)
and user does not want to select instance. (in my case) because instance is just replica (pod) so I want to see in one same page.

I think we can show all realms and all client in one pages.

How about your opinon?

Thanks,

Support Question: Unsure if I'm setting up the SPI correctly

Description

Unsure if I'm setting this up correctly, no indication that I am

Expected Behavior

Data to be displayed under localhost/auth/realms/master/metrics

Actual Behavior

Nothing being displayed

Steps to reproduce

Firstly unsure if this is off topic so apologies if it is. I've been trying to setup this project today but due to a lack of understanding around jar files etc, unsure if i'm doing it correctly

Steps I took:

  1. Downloaded and unzipped github repo to host machine
  2. Ran the command stated "./gradlew jar"
  3. Created a new directory inside the keycloak container called providers (/opt/jboss/keycloak/providers)
    Copied the jar file from /build/libs to the providers folder inside a Keycloak Docker container
    Went to Keycloak GUI and went to mange -> events -> config and added "metrics-listener" as a named entry

What's the best way to find out if my configurations worked correctly? I assume some file(s) are written to on login/logout requests however I can't find any at the moment.

Keycloak won't pick up metrics-listener

Description

I'm trying to deploy the metrics spi to Keycloak 10.0.1 using Docker. I have tried multiple ways of deploying (copy file to standalone/deployments, deploy-command from cli, module add from cli), but it doesn't seem to work as expected. The logs state that the jar is deployed and everything is fine, but still metrics-listener does not appear in the provider list. To make things even more strange, the "metrics" provider appears, along with the metrics endpoint. So it seems only parts of the content of the jar is deployed, with the logs giving no indication of anything being wrong while deploying.

I'm quite stuck at this point, and close to giving up on the whole thing. Any points as to where/how to debug this?

Keycloak Grafana Metrics to Show all instances report in one.

As of right now, Keycloak Grafana's metrics shows report based on instances (Retrieved from Prometheus gateway / cluster-based Keycloak instance). But, logically speaking instances come and go with time, thus it's better to give a cumulative report from all instances.

Metrics doesn't work in a keycloak cluster

If you setup a keycloak cluster with two or more nodes, when you ask to node1 you get X number of logins and when you ask to node2 you can get X-2 number of logins.

This it's because you put a loadbalancer in front with a round-robin balance and you ask to each node independently.

There's any plan to store and read this data from the database or at least share the data between nodes?

Exporter metrics do not persist a Keycloak service restart

Description

Restarting keycloak.service causes Prometheus counters to reset, e.g. keycloak_logins metrics reset from a service restart.

Expected Behavior

Ideally the Prometheus counters persist across service restarts (or a flag was created which allowed the operator to select counter reset behavior).

This functionality would allow us to track things like:

  • total logins since Keycloak was first deployed
  • total registrations since Keycloak was first deployed

Right now we are limited by Prometheus' data retention settings, and the irregular resets can make graphs a bit awkward.

Is such a thing possible?

No license declared

Hi guys,

I was stumbling upon your project while looking for a Keycloak / Prometheus integration. Your SPI looks very promising! However, I wonder in which way I could use it.

Would you mind applying a license to the repo?

Thanks
Cedric

i cant open the metrics endpoint in ha setting

Description

i dont know if this is a issue, when i try to open the endpoint metrics in HA Keycloak Settings. I get the following error:

12:03:52,346 WARN [org.jgroups.protocols.TCP] (TcpServer.Acceptor[7600]-5,null,null) JGRP000006: failed accepting connection from peer: java.net.SocketException: :7600: BaseServer.TcpConnection.readPeerAddress(): cookie sent by /:57222 does not match own cookie; terminating connection
at org.jgroups.blocks.cs.TcpConnection.readPeerAddress(TcpConnection.java:242)
at org.jgroups.blocks.cs.TcpConnection.(TcpConnection.java:53)
at org.jgroups.blocks.cs.TcpServer$Acceptor.handleAccept(TcpServer.java:126)
at org.jgroups.blocks.cs.TcpServer$Acceptor.run(TcpServer.java:111)
at org.jboss.as.clustering.jgroups.ClassLoaderThreadFactory.lambda$newThread$0(ClassLoaderThreadFactory.java:52)
at java.lang.Thread.run(Thread.java:748)

some ideas? :)

does not build with gradle 7

Description

Running gradle jar fails with an error.

Environment

  • Operating system: Arch Linux
  • Project Version: 2.4.0

Steps to reproduce

[jelle@t14][/tmp/keycloak-metrics-spi/trunk/keycloak-metrics-spi-2.4.0]%gradle jar

FAILURE: Build failed with an exception.

* Where:
Build file '/tmp/keycloak-metrics-spi/trunk/keycloak-metrics-spi-2.4.0/build.gradle' line: 33

* What went wrong:
A problem occurred evaluating root project 'keycloak-metrics-spi'.
> Could not find method compile() for arguments [{group=org.keycloak, name=keycloak-server-spi-private, version=12.0.1}] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/7.0.2/userguide/command_line_interface.html#sec:command_line_warnings

BUILD FAILED in 698ms

With keycloack 3.4.3.Final keycloak-metrics-spi is deployed but is not active in SPI providers

hi
with an instance of keycloak 3.2.0.Final everything is good.

But with keycloak 3.4.3.Final keycloak-metrics-spi.jar "Server Info/providers" page doesn't not display metrics-listener.

however jar is deployed with success :

2018-09-12 12:15:25,151 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-8) WFLYSRV0027: Starting deployment of "keycloak-metrics-spi-1.0-SNAPSHOT.jar" (runtime-name: "keycloak-metrics-spi-1.0-SNAPSHOT.jar")
2018-09-12 12:15:25,242 INFO  [org.keycloak.subsystem.server.extension.KeycloakProviderDeploymentProcessor] (MSC service thread 1-4) Deploying Keycloak provider: keycloak-metrics-spi-1.0-SNAPSHOT.jar
2018-09-12 12:15:25,252 WARN  [org.keycloak.services] (MSC service thread 1-4) KC-SERVICES0047: metrics-listener (org.jboss.aerogear.keycloak.metrics.MetricsEventListenerFactory) is implementing the internal SPI eventsListener. This SPI is internal and may change without notice
2018-09-12 12:15:25,260 WARN  [org.keycloak.services] (MSC service thread 1-4) KC-SERVICES0047: metrics (org.jboss.aerogear.keycloak.metrics.MetricsEndpointFactory) is implementing the internal SPI realm-restapi-extension. This SPI is internal and may change without notice
2018-09-12 12:15:25,337 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 1) WFLYSRV0010: Deployed "keycloak-metrics-spi-1.0-SNAPSHOT.jar" (runtime-name : "keycloak-metrics-spi-1.0-SNAPSHOT.jar")

Is it possible to configure the listener via jboss-cli.sh on startup (docker/k8s)?

Description

I would like to configure the SPI via the jboss-clie.sh on startup of a docker container

Expected Behavior

Is something like

/subsystem=keycloak-server/spi=eventsListener:add()
/subsystem=keycloak-server/spi=eventsListener/provider=metrics-listener:add(enabled=true)

meaningful/possible and would it work? How could i enable eventsEnabled=true and adminEventsEnabled=true ?

Thank you

Missing Keycloak metrics

Description

Almost no Keycloak metrics are exported

Expected Behavior

I expect to have all the metrics that are described in the readme.

Actual Behavior

Only jvm metrics and two keycloak metrics (keycloak_request_duration and keycloak_response_errors) are exported.
The logs show the metric exporter getting started, and there are no errors logged. Metrics listener is enabled in the GUI, and the metrics shows up on the Pushgateway. In the pushgateway I see only the two metrics I mentioned above, however when I check the metrics endpoint directly on the server I can see HELP and TYPE for all the missing metrics, but no actual metrics data.

Environment

  • Operating system: CentOS 7
  • Project Versions:
    • keycloak-metric-spi-2.2.0
    • Keycloak 10.0.1 (also tested Keycloak 12 something)

Steps to reproduce

Done all the steps from readme

Endpoint metrics URL not found

Description

We use Keycloak docker image jboss/keycloak:7.0.0 configured in a standalone-ha mode with 2 instances. It's working well.
We followed instructions to use SPI (download it, place it under xxx/providers, and add it through UI).
Logs seem to confirmed it is configured :
12:59:29,851 INFO [org.jboss.aerogear.keycloak.metrics.MetricsEventListener] (default task-3) Received admin event of type UPDATE (REALM) in realm master 13:00:07,319 INFO [org.jboss.aerogear.keycloak.metrics.MetricsEventListener] (default task-3) Received admin event of type UPDATE (REALM) in realm master

Expected Behavior

Metrics should be exposed in /auth/realms/master/metrics

Actual Behavior

I got a 404 when I tried to access to /auth/realms/master/metrics

I found some warning at initialisation related to metrics-listener
12:49:50,140 WARN [org.keycloak.services] (ServerService Thread Pool -- 72) KC-SERVICES0047: metrics-listener (org.jboss.aerogear.keycloak.metrics.MetricsEventListenerFactory) is implementing the internal SPI eventsListener. This SPI is internal and may change without notice

Any Idea ?

Thank you for your help

Keycloak.X support. keycloak-metrics-spi 2.4.0 is not compatible with keycloak.x-14.0.0

Description

keycloak-metrics-spi is breaking startup of Keycloak.X 14.0.0.
Are there any plans to support Keycloak.X distribution?

Actual Behavior

2021-06-30 10:19:59,785 ERROR [org.key.cli.Picocli] (main) ERROR: Failed to start server using profile (dev). 2021-06-30 10:19:59,786 ERROR [org.key.cli.Picocli] (main) ERROR: Details:: java.lang.NoSuchMethodError: org.jboss.resteasy.spi.ResteasyProviderFactory.getContainerRequestFilterRegistry()Lorg/jboss/resteasy/core/interception/ContainerRequestFilterRegistry; at org.jboss.aerogear.keycloak.metrics.MetricsEndpointFactory.init(MetricsEndpointFactory.java:18) at org.keycloak.QuarkusKeycloakSessionFactory.init(QuarkusKeycloakSessionFactory.java:68) at org.keycloak.QuarkusKeycloakApplication.initializeKeycloakSessionFactory(QuarkusKeycloakApplication.java:52) at org.keycloak.QuarkusKeycloakApplication.startup(QuarkusKeycloakApplication.java:31) at org.keycloak.provider.quarkus.QuarkusLifecycleObserver.onStartupEvent(QuarkusLifecycleObserver.java:47) at org.keycloak.provider.quarkus.QuarkusLifecycleObserver_Observer_onStartupEvent_8292a286c9778cb4a07bc3314fcbfb61e7fe81a0.notify(QuarkusLifecycleObserver_Observer_onStartupEvent_8292a286c9778cb4a07bc331 4fcbfb61e7fe81a0.zig:147) at io.quarkus.arc.impl.EventImpl$Notifier.notifyObservers(EventImpl.java:283) at io.quarkus.arc.impl.EventImpl$Notifier.notify(EventImpl.java:268) at io.quarkus.arc.impl.EventImpl.fire(EventImpl.java:70) at io.quarkus.arc.runtime.ArcRecorder.fireLifecycleEvent(ArcRecorder.java:128) at io.quarkus.arc.runtime.ArcRecorder.handleLifecycleEvents(ArcRecorder.java:97) at io.quarkus.deployment.steps.LifecycleEventsBuildStep$startupEvent1144526294.deploy_0(LifecycleEventsBuildStep$startupEvent1144526294.zig:87) at io.quarkus.deployment.steps.LifecycleEventsBuildStep$startupEvent1144526294.deploy(LifecycleEventsBuildStep$startupEvent1144526294.zig:40) at io.quarkus.runner.ApplicationImpl.doStart(ApplicationImpl.zig:794) at io.quarkus.runtime.Application.start(Application.java:90) at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:100) at io.quarkus.runtime.Quarkus.run(Quarkus.java:66) at org.keycloak.cli.KeycloakMain.start(KeycloakMain.java:66) at org.keycloak.cli.KeycloakMain.start(KeycloakMain.java:62) at org.keycloak.cli.MainCommand.startDev(MainCommand.java:114) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.base/java.lang.reflect.Method.invoke(Unknown Source) at picocli.CommandLine.executeUserObject(CommandLine.java:1972) at picocli.CommandLine.access$1300(CommandLine.java:145) at picocli.CommandLine$RunLast.executeUserObjectOfLastSubcommandWithSameParent(CommandLine.java:2352) at picocli.CommandLine$RunLast.handle(CommandLine.java:2346) at picocli.CommandLine$RunLast.handle(CommandLine.java:2311) at picocli.CommandLine$AbstractParseResultHandler.execute(CommandLine.java:2179) at picocli.CommandLine.execute(CommandLine.java:2078) at org.keycloak.cli.KeycloakMain.parseAndRun(KeycloakMain.java:99) at org.keycloak.cli.KeycloakMain.main(KeycloakMain.java:58) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.base/java.lang.reflect.Method.invoke(Unknown Source) at io.quarkus.bootstrap.runner.QuarkusEntryPoint.doRun(QuarkusEntryPoint.java:48) at io.quarkus.bootstrap.runner.QuarkusEntryPoint.main(QuarkusEntryPoint.java:25)

Environment

  • Operating system: Windows 10
  • Project Versions:
    • Keycloak.X 14.0.0
    • keycloak-metrics-spi 2.4.0

Steps to reproduce

  1. Download keycloak.x-preview-14.0.0.zip

  2. Download keycloak-metrics-spi-2.4.0.jar

  3. Unzip keycloak.x-preview-14.0.0.zip

  4. cd keycloak.x-14.0.0/

  5. Copy keycloak-metrics-spi-2.4.0.jar into providers/

  6. Run bin/kc.sh config

  7. Run bin/kc.sh start-dev --verbose

Add RESET_PASSWORD / SEND_RESET_PASSWORD metrics

Description

Add the following new metrics to the exporter related to password resets to monitor potential abuse of password resets.
Keycloak defines the following events for them:

  • SEND_RESET_PASSWORD
  • SEND_RESET_PASSWORD_ERROR
  • RESET_PASSWORD
  • RESET_PASSWORD_ERROR (for example invalid code, expired code)

Expected Behavior

Password reset metrics are exposed.

zip END header not found: cannot deploy in kubernetes environment

We have a HA deployment in kuberenetes, the keycloak docker image is adapted to include the metrics jar file. When starting up I get the following log messages:

15:24:04,336 INFO  [org.jboss.as.repository] (DeploymentScanner-threads - 1) WFLYDR0001: Content added at location /opt/jboss/keycloak/standalone/data/content/ea/2903a5d4983483d20e0c7e3cf6c422e89208f8/content 15:24:04,347 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-2) WFLYSRV0027: Starting deployment of "keycloak-metrics-spi-2.1.0.jar" (runtime-name: "keycloak-metrics-spi-2.1.0.jar")
15:24:04,351 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-1) MSC000001: Failed to start service jboss.deployment.unit."keycloak-metrics-spi-2.1.0.jar".STRUCTURE: org.jboss.msc.service.StartException in service jboss.deployment.unit."keycloak-metrics-spi-2.1.0.jar".STRUCTURE: WFLYSRV0153: Failed to process phase STRUCTURE of deployment "keycloak-metrics-spi-2.1.0.jar"
        at [email protected]//org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:189)
        at [email protected]//org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1739)
        at [email protected]//org.jboss.msc.service.ServiceControllerImpl$StartTask.execute(ServiceControllerImpl.java:1701)
        at [email protected]//org.jboss.msc.service.ServiceControllerImpl$ControllerTask.run(ServiceControllerImpl.java:1559)
        at [email protected]//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
        at [email protected]//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982)
        at [email protected]//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
        at [email protected]//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
        at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: org.jboss.as.server.deployment.DeploymentUnitProcessingException: WFLYSRV0160: Failed to mount deployment content
        at [email protected]//org.jboss.as.server.deployment.module.DeploymentRootMountProcessor.deploy(DeploymentRootMountProcessor.java:95)
        at [email protected]//org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:182)
        ... 8 more
Caused by: java.util.zip.ZipException: zip END header not found
        at java.base/java.util.zip.ZipFile$Source.zerror(ZipFile.java:1567)
        at java.base/java.util.zip.ZipFile$Source.findEND(ZipFile.java:1462)
        at java.base/java.util.zip.ZipFile$Source.initCEN(ZipFile.java:1469)
        at java.base/java.util.zip.ZipFile$Source.<init>(ZipFile.java:1274)
        at java.base/java.util.zip.ZipFile$Source.get(ZipFile.java:1237)
        at java.base/java.util.zip.ZipFile$CleanableResource.<init>(ZipFile.java:727)
        at java.base/java.util.zip.ZipFile$CleanableResource.get(ZipFile.java:844)
        at java.base/java.util.zip.ZipFile.<init>(ZipFile.java:247)
        at java.base/java.util.zip.ZipFile.<init>(ZipFile.java:177)
        at java.base/java.util.jar.JarFile.<init>(JarFile.java:348)
        at java.base/java.util.jar.JarFile.<init>(JarFile.java:319)
        at java.base/java.util.jar.JarFile.<init>(JarFile.java:285)
        at [email protected]//org.jboss.vfs.spi.JavaZipFileSystem.<init>(JavaZipFileSystem.java:90)
        at [email protected]//org.jboss.vfs.spi.JavaZipFileSystem.<init>(JavaZipFileSystem.java:77)
        at [email protected]//org.jboss.vfs.VFS.mountZip(VFS.java:386)
        at [email protected]//org.jboss.vfs.VFS.mountZip(VFS.java:410)
        at [email protected]//org.jboss.as.server.deployment.DeploymentMountProvider$Factory$ServerDeploymentRepositoryImpl.mountDeploymentContent(DeploymentMountProvider.java:108)
        at [email protected]//org.jboss.as.server.deployment.module.DeploymentRootMountProcessor.deploy(DeploymentRootMountProcessor.java:91)
        ... 9 more

15:24:04,354 ERROR [org.jboss.as.controller.management-operation] (DeploymentScanner-threads - 1) WFLYCTL0013: Operation ("deploy") failed - address: ([("deployment" => "keycloak-metrics-spi-2.1.0.jar")]) - failure description: {"WFLYCTL0080: Failed services" => {"jboss.deployment.unit.\"keycloak-metrics-spi-2.1.0.jar\".STRUCTURE" => "WFLYSRV0153: Failed to process phase STRUCTURE of deployment \"keycloak-metrics-spi-2.1.0.jar\"
    Caused by: org.jboss.as.server.deployment.DeploymentUnitProcessingException: WFLYSRV0160: Failed to mount deployment content
    Caused by: java.util.zip.ZipException: zip END header not found"}}
15:24:04,355 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 1) WFLYSRV0010: Deployed "keycloak-metrics-spi-2.1.0.jar" (runtime-name : "keycloak-metrics-spi-2.1.0.jar")
15:24:04,356 INFO  [org.jboss.as.controller] (DeploymentScanner-threads - 1) WFLYCTL0183: Service status report
WFLYCTL0186:   Services which failed to start:      service jboss.deployment.unit."keycloak-metrics-spi-2.1.0.jar".STRUCTURE: WFLYSRV0153: Failed to process phase STRUCTURE of deployment "keycloak-metrics-spi-2.1.0.jar"

Any Ideas how I could solve this?

Multiple KeyCloak clusters on the same Prometheus PushGateway : how to identify them and separate their indicators

Description

We have 2 KeyCloak clusters running into the same Docker Swarn cluster.
As recommanded we put in place the Prometheus Push Gateway.

How to get both views for JVM indicators :

  • per instance
  • per cluster

Actual Behavior

If we do not set PROMETHEUS_GROUPING_KEY_INSTANCE
then we are unable to get a view per cluster because the job's name is the same for the two clusters

If we set PROMETHEUS_GROUPING_KEY_INSTANCE=ENVVALUE:KEYCLOAK_CLUSTER_NAME
then JVM metrics are not correctly taken into account into Prometheus and Grafana, e.g. the JVM memory is really much higher than the truth => back to the issue we tried to solve with using the Prometheus Push Gateway.

Currently we have:
sum(jvm_memory_bytes_used{instance="$instance", area="heap"})*100/sum(jvm_memory_bytes_max{instance="$instance", area="heap"})

Expected Behavior

Be able to define our own custom PROMETHEUS_GROUPING_KEY_JOB in order to separate indicators of different clusters

Environment

  • Project Versions: 2,2.0

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.