Otel Agent

An OpenTelemetry Collector receives application telemetry and exports it to Middleware using the OpenTelemetry Protocol (OTLP). This integration supports traces, metrics, and logs through the configured signal pipelines.

Use this integration if your applications are already instrumented with OpenTelemetry or you want to collect and process telemetry from multiple services through a centralized Collector.

How it works#

The OpenTelemetry Collector receives telemetry from applications, processes it, and exports it to Middleware.

The collection pipeline consists of three components:

  • Receivers: Accept telemetry from OpenTelemetry SDKs and other supported sources using OTLP/gRPC or OTLP/HTTP.
  • Processors: Batch, filter, enrich, or sample telemetry before exporting it.
  • Exporters: Send processed traces, metrics, and logs to Middleware over HTTPS.

You can send telemetry directly from an application or route it through an OpenTelemetry Collector for centralized configuration and processing.

Prerequisites#

Before configuring OpenTelemetry, make sure you have:

  • A Middleware account with an API key (MW_API_KEY) and target URL.
  • An OpenTelemetry Collector installed, or an existing Collector deployment.
  • Applications instrumented using OpenTelemetry SDKs or other supported telemetry sources.
  • Outbound HTTPS access to your Middleware target on port 443.

Supported protocols#

Middleware supports traces, metrics, and logs through OTLP/gRPC and OTLP/HTTP.

SignalProtocolMiddleware endpoint
TracesOTLP/gRPChttps://<MW_UID>.middleware.io:443
MetricsOTLP/gRPChttps://<MW_UID>.middleware.io:443
LogsOTLP/gRPChttps://<MW_UID>.middleware.io:443
TracesOTLP/HTTPhttps://<MW_UID>.middleware.io:443/v1/traces
MetricsOTLP/HTTPhttps://<MW_UID>.middleware.io:443/v1/metrics
LogsOTLP/HTTPhttps://<MW_UID>.middleware.io:443/v1/logs

Note: Use the root endpoint for OTLP/gRPC. For OTLP/HTTP, use the appropriate signal endpoint.

Installation#

1 Configure the OpenTelemetry Collector#

Create or update your Collector configuration file, typically named config.yaml. Add the following configuration to receive traces, metrics, and logs and forward them to Middleware.

yml
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

processors:
  memory_limiter:
    check_interval: 1s
    limit_mib: 512
    spike_limit_mib: 128
  batch: {}

exporters:
  otlphttp:
    endpoint: https://<MW_UID>.middleware.io:443
    headers:
      authorization: <MW_API_KEY>

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [otlphttp]

    metrics:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [otlphttp]

    logs:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [otlphttp]

Replace the placeholders with your Middleware account details.

The OTLP/HTTP exporter automatically appends /v1/traces, /v1/metrics, and /v1/logs to the configured base endpoint.

Note: This example uses the standard OTLP/HTTP exporter. Adjust the memory limits to match the resources available to your Collector. For production deployments, provide the API key through a secret or environment variable rather than storing it in plaintext.

2 Start the Collector#

Start the OpenTelemetry Collector using your configuration file.

For a standalone Collector installation:

bash
otelcol --config=config.yaml

If you use the OpenTelemetry Collector Contrib distribution:

bash
otelcol-contrib --config=config.yaml

If the Collector is already running as a Kubernetes Deployment, Docker container, or system service, update its configuration and restart the service using your existing deployment method.

3 Configure applications to send telemetry#

Configure your OpenTelemetry-instrumented applications to send telemetry to the Collector.

For OTLP/gRPC:

js
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc

export OTEL_SERVICE_NAME=my-service
export OTEL_RESOURCE_ATTRIBUTES="service.version=1.0.0,deployment.environment=production"
For OTLP/HTTP:
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf

export OTEL_SERVICE_NAME=my-service

Replace localhost with the Collector's reachable hostname or IP address if it runs on a different host or container.

Restart your application after updating the environment variables.

Note: The Collector must be accessible from your application on the configured OTLP receiver port. Use TLS or restrict network access when receiving telemetry across untrusted networks.

4 Verify data collection#

After the Collector starts receiving telemetry, allow a few moments for data to appear in Middleware.

Verify the following:

  • Traces: Go to APM → Traces to view application traces.
  • Services: Go to APM → Services to view instrumented services.
  • Logs: Go to Log Monitoring to view collected logs.
  • Metrics: Open the relevant metrics view or custom dashboard to query received metrics.

If data does not appear, check the Collector logs for exporter or connection errors.

Alternative: Send telemetry directly to Middleware#

You can export telemetry directly from an OpenTelemetry SDK without deploying a separate Collector.

Configure the following environment variables in your application:

js
export OTEL_EXPORTER_OTLP_ENDPOINT=https://<MW_UID>.middleware.io:443
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_HEADERS="authorization=<MW_API_KEY>"

export OTEL_TRACES_EXPORTER=otlp
export OTEL_METRICS_EXPORTER=otlp
export OTEL_LOGS_EXPORTER=otlp

export OTEL_SERVICE_NAME=my-service

This configuration uses OTLP/gRPC to export telemetry directly to Middleware.

If your application uses OTLP/HTTP, change the protocol:

js
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf

The SDK uses the appropriate signal-specific paths when configured with the base endpoint.

For applications requiring separate HTTP endpoints, configure:

js
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://<MW_UID>.middleware.io:443/v1/traces
export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=https://<MW_UID>.middleware.io:443/v1/metrics
export OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://<MW_UID>.middleware.io:443/v1/logs

Application instrumentation#

If your application is not already instrumented, configure an OpenTelemetry SDK before exporting telemetry.

Middleware supports standard OpenTelemetry instrumentation across multiple languages.

LanguageRecommended baseline
Node.js18 or later
Python3.8 or later
JavaJava 8/11 or later, depending on SDK and agent version
.NET6 or later
Go1.20 or later
PHP8.1 or later
Ruby3.0 or later
Rust1.70 or later

Use automatic instrumentation where supported, and manual instrumentation for custom spans and metrics.

Node.js#

Install the OpenTelemetry SDK, auto-instrumentation package, and OTLP exporters:

bash
npm install \
  @opentelemetry/sdk-node \
  @opentelemetry/auto-instrumentations-node \
  @opentelemetry/exporter-trace-otlp-grpc \
  @opentelemetry/exporter-metrics-otlp-grpc

{Retain the existing Node.js otel.js initialization and custom span code blocks.}

Python#

Install the OpenTelemetry distribution and exporter:

bash
pip install opentelemetry-distro opentelemetry-exporter-otlp
bash
opentelemetry-bootstrap -a install

Run the application with auto-instrumentation:

py
export OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true
export OTEL_PYTHON_LOG_CORRELATION=true

opentelemetry-instrument \
  --traces_exporter otlp \
  --metrics_exporter otlp \
  --logs_exporter otlp \
  --service_name my-service \
  python app.py

Java#

Use the OpenTelemetry Java Agent or SDK to instrument your application.

{Retain the existing Java Gradle dependencies and Java Agent execution code blocks.}

.NET#

Install the OpenTelemetry exporter and instrumentation packages:

js
dotnet add package OpenTelemetry.Extensions.Hosting
dotnet add package OpenTelemetry.Instrumentation.AspNetCore
dotnet add package OpenTelemetry.Instrumentation.Http
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol

{Retain the existing .NET tracing, metrics, and logging configuration code blocks.}

Advanced configuration#

Configure sampling#

Sampling controls the amount of trace data collected and exported.

Head-based sampling#

Configure sampling at the application SDK level.

For example, to sample approximately 20% of root traces:

js
export OTEL_TRACES_SAMPLER=parentbased_traceidratio
export OTEL_TRACES_SAMPLER_ARG=0.2

Child spans follow the parent's sampling decision.

Tail-based sampling#

Tail-based sampling is configured in the Collector after trace data is received.

Use it when you want to retain traces based on conditions such as error status or latency.

Add the tail_sampling processor to your Collector configuration.

{Retain the existing tail-sampling configuration example, updating the exporter endpoint to use the OTLP/HTTP base URL.}

Note: Tail sampling requires a Collector distribution that includes the tail_sampling processor. Configure the batch processor after sampling.

Configure context propagation#

Context propagation connects spans across services and enables correlation between frontend sessions, backend traces, and logs.

Use a consistent propagation format across applications.

For standard OpenTelemetry environments:

js
export OTEL_PROPAGATORS=tracecontext,baggage

For applications using Middleware RUM with B3 propagation:

js
export OTEL_PROPAGATORS=b3

Make sure your frontend, backend, and API gateway use compatible propagation headers.

To correlate logs with traces, include trace_id and span_id in application log records.

Configure resource attributes#

Use OpenTelemetry resource attributes to identify services and environments.

js
export OTEL_RESOURCE_ATTRIBUTES="service.name=checkout-service,service.version=1.2.3,deployment.environment=production"

Common attributes include:

AttributeDescription
service.nameName of the instrumented service
service.versionApplication version
deployment.environmentDeployment environment
service.namespaceLogical grouping of services

Use consistent resource attributes across applications to make telemetry easier to filter and correlate.

Configure custom metrics#

Use OpenTelemetry metrics APIs to record application-specific measurements such as request counts, processing duration, and queue sizes.

Supported instruments include counters, histograms, and gauges.

{Retain the existing Node.js, Python, and Java custom metric examples from the source documentation.}

Use consistent metric names, appropriate units, and low-cardinality attributes.

Troubleshooting#

No telemetry in Middleware#

If the Collector is running but no data appears:

  • Verify that the Collector can connect to your Middleware target URL over HTTPS on port 443.
  • Confirm that the authorization header contains a valid Middleware API key.
  • Check that the exporter protocol matches the configured endpoint.
  • Verify that applications can reach the Collector on port 4317 or 4318.
  • Check the Collector logs for exporter or authentication errors.

OTLP exporter connection errors#

If the Collector reports connection failures:

  • Verify that the Middleware target URL is correct.
  • Confirm that outbound HTTPS traffic is allowed.
  • Check DNS resolution and TLS connectivity.
  • Make sure OTLP/gRPC uses the root endpoint and OTLP/HTTP uses the correct signal paths.

Application traces are missing#

If metrics or logs appear but application traces are missing:

  • Verify that tracing is enabled in the application SDK.
  • Confirm that the application is generating requests.
  • Check that OTEL_TRACES_EXPORTER is set to otlp, if required by the SDK.
  • Verify that the Collector traces pipeline includes the OTLP receiver and Middleware exporter.

Trace correlation is not working#

If traces are not connected across services:

  • Verify that the same context propagation format is used across services.
  • Check that API gateways and proxies forward the required propagation headers.
  • Confirm that application logs contain trace and span identifiers.

High telemetry volume#

If the amount of collected telemetry is higher than expected:

  • Configure head-based sampling in application SDKs.
  • Use tail-based sampling in the Collector to retain selected traces.
  • Apply filtering or attribute processors where appropriate.
  • Review the Collector's batching and memory configuration.

If the issue persists, contact Middleware Support at support@middleware.io.

Need assistance or want to learn more about Middleware? Get in touch with us via our Contact Us or join our Slack channel.

What did you think of this content?