OpenGate/ Docs

Logging

OpenGate IAM uses Logback (via Spring Boot) for structured logging. All services emit JSON logs in production for easy ingestion by log aggregation systems.

Log Levels

Default log levels per environment:

LoggerDevelopmentProduction
RootINFOWARN
io.opengateDEBUGINFO
org.springframework.securityDEBUGWARN
org.hibernate.SQLDEBUGOFF

Configure log levels in application.yml:

application.ymlyaml
logging:
level:
  root: INFO
  io.opengate: DEBUG
  org.springframework.security: DEBUG
  org.hibernate.SQL: DEBUG
pattern:
  console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"

JSON Structured Logging (Production)

Add the Logstash encoder for JSON output:

build.gradle.ktskotlin
dependencies {
  implementation("net.logstash.logback:logstash-logback-encoder:7.4")
}
src/main/resources/logback-spring.xmlxml
<configuration>
<springProfile name="prod">
  <appender name="JSON_CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="net.logstash.logback.encoder.LogstashEncoder">
      <includeMdcKeyName>traceId</includeMdcKeyName>
      <includeMdcKeyName>spanId</includeMdcKeyName>
      <includeMdcKeyName>userId</includeMdcKeyName>
      <includeMdcKeyName>realmId</includeMdcKeyName>
    </encoder>
  </appender>
  <root level="INFO">
    <appender-ref ref="JSON_CONSOLE" />
  </root>
</springProfile>
</configuration>

Request Logging

The Gateway ships with a RequestLoggingFilter that logs every inbound request:

RequestLoggingFilter.javajava
// Logs: method, path, status, duration, remote IP
log.info("method={} path={} status={} duration={}ms ip={}",
  method, path, status, duration, remoteIp);

Enable request logging in application.yml:

logging:
level:
  io.opengate.iam.gateway.filter: DEBUG

Audit Logging

Security-sensitive events (login, logout, password change, MFA enable) are published to Kafka topic opengate.audit and can be consumed by your SIEM:

{
"eventType": "USER_LOGIN",
"userId": "usr_abc123",
"realmId": "master",
"ip": "203.0.113.1",
"userAgent": "Mozilla/5.0 ...",
"success": true,
"timestamp": "2025-06-01T10:30:00Z"
}

Centralized Log Aggregation

Loki + Grafana (Docker)

docker-compose.logging.ymlyaml
services:
loki:
  image: grafana/loki:2.9.0
  ports: ["3100:3100"]
  command: -config.file=/etc/loki/local-config.yaml

promtail:
  image: grafana/promtail:2.9.0
  volumes:
    - /var/lib/docker/containers:/var/lib/docker/containers:ro
    - /var/run/docker.sock:/var/run/docker.sock
  command: -config.file=/etc/promtail/config.yml

grafana:
  image: grafana/grafana:10.0.0
  ports: ["3000:3000"]

ELK Stack

Ship Docker container logs to Elasticsearch via Filebeat:

filebeat.ymlyaml
filebeat.inputs:
- type: container
  paths:
    - /var/lib/docker/containers/*/*.log
  processors:
    - add_docker_metadata: ~

output.elasticsearch:
hosts: ["elasticsearch:9200"]
index: "opengate-%{+yyyy.MM.dd}"

Trace correlation

Enable OpenTelemetry tracing to automatically inject traceId and spanId into log MDC. See Tracing.

Log Rotation

For file-based logging, configure Logback rolling policy:

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/opengate.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
  <fileNamePattern>logs/opengate.%d{yyyy-MM-dd}.gz</fileNamePattern>
  <maxHistory>30</maxHistory>
  <totalSizeCap>5GB</totalSizeCap>
</rollingPolicy>
</appender>

Do not log credentials

Never log passwords, tokens, or PII. Spring Security masks sensitive parameters by default but review custom log statements carefully.