OpenTelemetry logging
| OpenTelemetry (OTEL) logging is an Evolving feature in PingIDM. It’s subject to change without notice, even in a minor or maintenance release. |
OTEL logging collects and exports logs using the OpenTelemetry Protocol (OTLP). It’s a part of the broader OpenTelemetry observability framework that provides a unified way to collect logs, traces, and metrics from applications. Learn more in Distributed tracing.
In PingIDM, logs are sent directly from IDM to an OTEL collector using JSON format and OTLP, rather than through traditional logging pipelines. Learn more in Server logs.
Benefits of OTEL logging
OTEL logging makes it easier to:
-
Correlate logs across Ping Identity products using trace IDs and span IDs. When a request flows through multiple systems, such as PingAM, IDM, and PingDS, you can track the entire journey using a single trace ID. Learn more in Understand a trace object.
-
Troubleshoot and pinpoint where issues occur in complex workflows. Trace IDs provide a high-level overview of a request, while span IDs show specific tasks within that trace.
-
Standardize observability. You can use your preferred observability tools, such as Splunk, Datadog, or Grafana that support OTLP.
-
Simplify setup because logs go directly to the OTEL collector and bypass previous processing steps.
-
Enhance visibility to efficiently identify patterns, bottlenecks, or errors across distributed systems.
Configuring OTEL logging
To configure and implement OpenTelemetry logging:
-
Enable distributed tracing in IDM, which includes trace and span IDs in the logs.
-
Start the OTEL collector. Learn more in the OTEL Collector Quick Start and in Visualize traces with a trace collector.
-
Configure the
OpenTelemetryAppender. Learn more in Log appenders. -
Initialize the OTEL
LoggerProvider, which contains information about the OTEL collector endpoint where logs are sent and default settings for batched log processing.-
Add the
LoggerProviderconfiguration to thetrace.jsonfile created when you enabled distributed tracing in step 1:{ "logging": { "enabled": true, "exporter": { "type": "otlp", "config": { "endpoint": "http://localhost:4318/v1/logs" } } } }The following example shows all available
LoggerProviderconfiguration options:{ "logging": { "enabled": true, "exporter": { "type": "otlp", "config": { "endpoint": "http://localhost:4318/v1/logs", "headers": "<headers>", "connectionTimeout": "10 seconds", "timeout": "10 seconds", "compressionMethod": "gzip", "retries": { "backoffMultiplier": 1.5, "initialBackoff": "1 second", "maxAttempts": 5, "maxBackoff": "5 seconds" } }, "batch": { "maxExportBatchSize": 512, "maxQueueSize": 2048, "scheduleDelay": "5 seconds", "exporterTimeout": "30 seconds" } } } }OpenTelemetry logging configuration properties
- enabled: boolean, optional
-
Set to
trueto enable OpenTelemetry logging.Default:
false - resourceAttributes: object, optional
-
A map of additional resource attributes for processing logs. Find more information in the OpenTelemetry documentation on Semantic Attributes with SDK-provided Default Value.
For example, if there are multiple Ping Identity Platform instances in a deployment, you could set the
"service.instance.id"resource attribute differently for each one to distinguish between them:{ "resourceAttributes": { "service.instance.id": "idm-server-1" } } - exporter: object, optional
-
Configuration for the exporter, which pushes logs to the OpenTelemetry service:
- type: string, optional
-
Set to
otlpfor OpenTelemetry Protocol (OTLP) support. This is currently the only supported protocol.Default:
otlp - config: object, optional
-
Endpoint and timeout configuration:
-
compressionMethod: enumeration, optionalMethod used to compress log data; either
gzipornone.Default:
gzip -
connectionTimeout: duration, optionalTime out a connection to the endpoint after this duration.
Default: 10 seconds.
-
endpoint: string, optionalThe endpoint to publish traces to.
For HTTPS, IDM trusts the default JVM CAs. To override this, set the
-Djavax.net.ssl.trustStoreand associated JVM settings when starting IDM. Learn more about the optional settings in the Java Secure Socket Extension (JSSE) Reference Guide.IDM doesn’t support TLS configuration for the tracing endpoint at this time. Default:
http://localhost:4318/v1/traces -
headers: object, optionalMap of additional headers to include in the export span request.
The following example sets the authorization header,
Authorization: Bearer ${bearer.token}:"headers": { "Authorization": "Bearer ${bearer.token}" } -
retries: object, optionalDefines a retry policy for the export span requests.
Default: Enabled
-
backoffMultiplier: number, optional Multiplier for the backoff wait time before retries.Default: 1.5
-
enabled: boolean, optionalRetry failed requests.
Default:
true -
initialBackoff: duration, optionalHow long to wait before the first retry.
Default: 1 second
-
maxAttempts: number, optionalMaximum number of retries.
Default: 5
-
maxBackoff: duration, optionalMaximum wait time between retries.
Default: 5 seconds
-
-
timeout: duration, optionalTime out a request to publish data to the endpoint after this duration.
Default: 10 seconds.
-
batch: object, optional-
Enable and configure batch processing for log data.
-
enabled: boolean, optionalLeave batch processing enabled in deployment.
Default:
true -
exporterTimeout: duration, optionalTime out a data exporter after this duration.
Default: 30 seconds
-
exportUnsampledSpans: boolean, optionalWhether to report on unsampled spans.
Default:
false -
maxExportBatchSize: number, optionalMaximum number of spans in a batch.
Default: 512
-
maxQueueSize: number, optionalMaximum number of spans to queue before dropping them.
Default: 2048
-
scheduleDelay: duration, optionalMaximum interval between sending batches of log data.
Default: 5 seconds
-
-
-
At the end of the
resolver/boot.propertiesfile, add the location of thetrace.jsonfile:openidm.tracing.config.path=trace/trace.json
-
Go to your OTEL collector and view the logs sent from IDM.
OTEL log records
In the OTEL collector, you can view log records in the OTLP format to find the trace and span IDs to follow a request across multiple systems.
This is an example of an IDM log record in the OTEL collector:
Trace ID:
Span ID:
Flags: 0
LogRecord #238
ObservedTimestamp: 2025-11-14 18:23:29.219669 +0000 UTC
Timestamp: 2025-11-14 18:23:29.219661 +0000 UTC
SeverityText: DEBUG
SeverityNumber: Debug(5)
Body: Str(Bundle xstream not matched by org.forgerock.*)
Attributes:
-> thread.name: Str(HealthCheck Bundles Started)
Log record fields
| Field Name | Description |
|---|---|
|
Represents the recording of an event. In OpenTelemetry, a log record contains two kinds of fields:
|
|
Time when the event was observed. |
|
Time when the event occurred. |
|
The severity text (also known as log level). |
|
Numerical value of the severity. |
|
The body of the log record. |
|
Additional information about the event. |
|
Request trace ID. |
|
Request span ID. |
|
A binary encoding that contains trace information. |
Learn more about Log Record fields and descriptions.
OTEL logging for HTTP inbound requests
When tracing is enabled, incoming HTTP requests automatically generate trace and span IDs. These IDs are included in log records sent to the OTEL collector. The trace and span ID fields are blank if the request doesn’t come from an HTTP inbound request.
For an HTTP inbound request, here’s an example scenario to find the trace and span IDs in the OTEL collector logs:
-
Sign on to the IDM admin user interface (UI).
-
Go to the OTEL collector and view the span for the sign-on request that contains the trace ID:
Span #7 (1) Trace ID: 4cafb0e638a8c2ba58a8288e0e12470fd (2) Parent ID: ID: 6bdc24e07a2c9754 Name: GET /openidm Kind: Server Start time: 2025-11-14 18:26:24.104794 +0000 UTC End time: 2025-11-14 18:26:24.110788 +0000 UTC Status code: Unset Status message: Attributes: -> http.request.method: Str(GET) -> url.path: Str(/openidm/info/version) -> url.full: Str(https://localhost:8443/openidm/info/version) -> network.protocol.name: Str(http) -> forgerock.transaction.id: Str(3caddd39-2942-4ccd-b527-9dfbd1f6353-1380) -> {"resource": "{service.instance.id": "5f481198b-5fc4-416b-a8d5-1d2cd5581f64", "service.name": "otelcol-contrib", "service.version": "0.128.0"}, "otelcol.component.id": "debug", "otelcol.component.kind": "exporter", "otelcol.signal": "traces"} 2025-11-14T18:26:27.590Z info Metrics {"resource": "{service.instance.id": "5f481198b-5fc4-416b-a8d5-1d2cd5581f64", "service.name": "otelcol-contrib", "service.version": "0.128.0"}, "otelcol.component.id": "debug", "otelcol.component.kind": "exporter", "otelcol.signal": "metrics", "resource metrics": 1, "metrics": 27, "data points": 28} 2025-11-14T18:26:27.591Z info Resource@Metrics #0 Resource SchemaURL: Resource attributes: -> service.name: Str(otelcol-contrib) -> service.instance.id: Str(5f481198b-5fc4-416b-a8d5-1d2cd5581f64) -> server.port: Str(8888)1 Span for the sign-on request 2 Associated trace ID for the span -
Find the matching trace ID in the log records to see the associated span ID:
LogRecord #23 ObservedTimestamp: 2025-11-14 18:26:24.107832 +0000 UTC Timestamp: 2025-11-14 18:26:24.107823 +0000 UTC SeverityText: DEBUG SeverityNumber: Debug(5) Body: Str(Invoking read access) Attributes: -> thread.name: Str(qtp1868624459-218) Trace ID: 4cafb0e638a8c2ba58a8288e0e12470fd (1) Span ID: 6bdc24e07a2c9754 (2) Flags: 11 Matching trace ID in the log record 2 Matching associated span ID -
View the log record body and attributes for more details about the sign-on request.
In this example, the
Bodyfield forLogRecord #23shows the string(Invoking read access)because the user requested read access to the admin dashboard. This inbound HTTP request generated the trace and span IDs in the previous steps:LogRecord #23 ObservedTimestamp: 2025-11-14 18:26:24.107832 +0000 UTC Timestamp: 2025-11-14 18:26:24.107823 +0000 UTC SeverityText: DEBUG SeverityNumber: Debug(5) Body: Str(Invoking read access) (1) Attributes: -> thread.name: Str(qtp1868624459-218) Trace ID: 4cafb0e638a8c2ba58a8288e0e12470fd Span ID: 6bdc24e07a2c9754 Flags: 11 This string shows the user requested read access to the admin dashboard.