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.)
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, andresourcedetectionprocessor -
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
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"
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>
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'
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
And host metrics:
hostmetrics:
collection_interval: 15s
scrapers:
cpu: {}
memory: {}
disk: {}
network: {}
Integration Tests with Real WebLogic
The project includes genuine integration tests:
make test-integration
This:
- Compiles the collector via OCB
- Starts a real WebLogic 14.1.1 container with OTel Java Agent
- Deploys a test application
- Waits for readiness
- Fires HTTP requests
- 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:
- Edit
collector/builder-config.yamland add:
receivers:
- gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/prometheusreceiver v0.120.0
Update your runtime config (
collector/config/collector.yaml) to include the Prometheus receiverRecompile:
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
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)