DEV Community

Cover image for Custom OpenTelemetry Collector for Oracle WebLogic: Bringing Observability to Enterprise Java
Vinnicius Andrade
Vinnicius Andrade

Posted on

Custom OpenTelemetry Collector for Oracle WebLogic: Bringing Observability to Enterprise Java

Oracle WebLogic Server powers countless enterprise Java systems. But getting observability out of it has always meant juggling multiple tools, agents, and dashboards with no way to correlate signals across applications and infrastructure.

I recently worked on standardizing observability across heterogeneous enterprise architectures at Banco do Brasil — from mainframe COBOL to cloud-native systems to on-premises WebLogic. The goal was simple: one semantic convention, one backend, one view of an entire transaction.

This post walks through building a custom, minimal OpenTelemetry Collector for WebLogic that makes this possible.

Repository: github.com/vinnicius/weblogic-opentelemetry


What We're Building

Application (OTel Java Agent)  ──┐
Host (CPU/memory/disk)         ──┼──→  otelcol-weblogic  ──→  Your Backend
WebLogic logs (domain files)   ──┤     (OTLP only)         (Tempo, Loki,
JVM metrics (via JMX)          ──┘                          Jaeger, etc.)
Enter fullscreen mode Exit fullscreen mode

A single container that ingests four signal types and exports unified OTLP.


Why a Custom Collector?

The standard OpenTelemetry Collector ships with 80+ components. For WebLogic environments, you typically need:

  • otlpreceiver (OTLP gRPC/HTTP ingress)
  • filelogreceiver (tail log files)
  • hostmetricsreceiver (CPU, memory, network)
  • jmxreceiver (JVM metrics)
  • batchprocessor, memorylimiterprocessor, and resourcedetectionprocessor
  • otlpexporter (send to backend)

Everything else is dead weight. The solution: use OCB (OpenTelemetry Collector Builder) to compile a minimal binary containing only what you need.

The philosophy: The collector is a base distribution with the essentials. If you need Prometheus scraping for another app, add prometheusreceiver to the OCB config and recompile. Want Kafka export? Add kafkaexporter. Need mTLS? Add extensions. Your large organization compiles its own variant without bloat or dependency conflicts.


The Build Config

# collector/builder-config.yaml
dist:
  name: otelcol-weblogic
  description: "Custom OpenTelemetry Collector for Oracle WebLogic Server"
  otelcol_version: "0.120.0"
  output_path: ./dist

receivers:
  - gomod: go.opentelemetry.io/collector/receiver/otlpreceiver v0.120.0
  - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/filelogreceiver v0.120.0
  - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/hostmetricsreceiver v0.120.0
  - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/jmxreceiver v0.120.0

processors:
  - gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.120.0
  - gomod: go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.120.0
  - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor v0.120.0
  - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/processor/attributesprocessor v0.120.0

exporters:
  - gomod: go.opentelemetry.io/collector/exporter/otlpexporter v0.120.0
Enter fullscreen mode Exit fullscreen mode

Run ocb --config=builder-config.yaml and you get a static Go binary with only these components.


Signal Pipelines

Application Traces and Metrics

The OTel Java Agent auto-instruments WebLogic applications with zero code changes:

# $DOMAIN_HOME/bin/setUserOverrides.sh
export JAVA_OPTIONS="${JAVA_OPTIONS} \
  -javaagent:/opt/opentelemetry/opentelemetry-javaagent.jar \
  -Dotel.service.name=${SERVER_NAME} \
  -Dotel.exporter.otlp.endpoint=http://otelcol:4318 \
  -Dotel.exporter.otlp.protocol=http/protobuf \
  -Dotel.resource.attributes=weblogic.domain=${DOMAIN_NAME} \
  -Dotel.logs.exporter=otlp \
  -Dotel.metrics.exporter=otlp \
  -Dotel.traces.exporter=otlp"
Enter fullscreen mode Exit fullscreen mode

The agent automatically captures HTTP requests, JDBC queries, JMS operations, EJB calls, JVM metrics, and application logs.

${SERVER_NAME} resolves at startup — each server gets its own service.name without per-server configuration.

WebLogic Logs

WebLogic logs are recognizable by the #### prefix:

####<May 7, 2026 10:00:00,000 AM UTC> <Info> <WebLogicServer> <host> <AdminServer> <main> <> <> <> <BEA-000360> <Server started>
Enter fullscreen mode Exit fullscreen mode

Parse them with regex:

filelog/weblogic:
  include:
    - /u01/oracle/user_projects/domains/${env:WLS_DOMAIN_NAME}/servers/*/logs/*.log
  start_at: end
  multiline:
    line_start_pattern: '^####'
  operators:
    - type: regex_parser
      regex: '^####<(?P<timestamp>[^>]+)> <(?P<severity>[^>]+)> <(?P<subsystem>[^>]+)> <(?P<machine>[^>]+)> <(?P<server>[^>]+)> <(?P<thread>[^>]+)> <[^>]*> <[^>]*> <[^>]*> <(?P<msgid>[^>]*)> <(?P<message>.+)>'
      timestamp:
        parse_from: attributes.timestamp
        layout: 'Jan 2, 2006 3:04:05,000 PM MST'
Enter fullscreen mode Exit fullscreen mode

Logs become structured OTLP records with severity, subsystem, server, and message ID.

JVM and Host Metrics

Collect JVM metrics via standard RMI/JMX:

jmx:
  jar_path: /opt/opentelemetry-jmx-metrics.jar
  endpoint: "service:jmx:rmi:///jndi/rmi://weblogic:9999/jmxrmi"
  target_system: jvm
  collection_interval: 30s
Enter fullscreen mode Exit fullscreen mode

And host metrics:

hostmetrics:
  collection_interval: 15s
  scrapers:
    cpu: {}
    memory: {}
    disk: {}
    network: {}
Enter fullscreen mode Exit fullscreen mode

Integration Tests with Real WebLogic

The project includes genuine integration tests:

make test-integration
Enter fullscreen mode Exit fullscreen mode

This:

  1. Compiles the collector via OCB
  2. Starts a real WebLogic 14.1.1 container with OTel Java Agent
  3. Deploys a test application
  4. Waits for readiness
  5. Fires HTTP requests
  6. Parses the collector's output and asserts traces, metrics, and logs are present

No mocks. Real JMX, real log files, real OTLP spans. The test result: 4 passed, 0 failed.


Extending the Collector

This is the beauty of the approach. Suppose you also need Prometheus metrics from another application:

  1. Edit collector/builder-config.yaml and add:
   receivers:
     - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/prometheusreceiver v0.120.0
Enter fullscreen mode Exit fullscreen mode
  1. Update your runtime config (collector/config/collector.yaml) to include the Prometheus receiver

  2. Recompile: ocb --config=builder-config.yaml

Same for Kafka export, mTLS extensions, or any other OTel component. You're not stuck with the base distribution; you're just not forced to include everything.


Getting Started

git clone https://github.com/vinnicius/weblogic-opentelemetry.git
cd weblogic-opentelemetry
cp .env.example .env
# Edit .env with your WebLogic host and backend endpoint
make build && make up
curl http://localhost:13133/  # health check
Enter fullscreen mode Exit fullscreen mode

Full docs, Java 17 flags, and troubleshooting in the repository.


If you're running WebLogic in production, give this a try. Questions, issues, and contributions welcome. Let me know what other WebLogic-specific metrics or log formats would be useful to support.

Top comments (0)