ProductMarch 31, 20268 min read

Native OpenTelemetry Support: Send OTLP Data to JustAnalytics

Send traces, logs, and metrics from any OpenTelemetry SDK or Collector to JustAnalytics. No vendor lock-in, no proprietary agents, no migration pain.

Why OpenTelemetry Matters

OpenTelemetry (OTel) has become the industry standard for instrumentation. It's a CNCF project with contributions from Google, Microsoft, Amazon, and hundreds of other companies. It defines a vendor-neutral way to collect traces, metrics, and logs from your applications.

The promise is simple: instrument your code once, send data anywhere. But "anywhere" has historically meant "one of three or four expensive platforms that support OTLP." Today, JustAnalytics joins that list -- and at a fraction of the cost.

JustAnalytics now natively supports OTLP (OpenTelemetry Protocol) ingestion for traces, logs, and metrics. If you've already instrumented your services with OpenTelemetry, you can point them at JustAnalytics and start seeing data in minutes. No code changes required.

What We Support

OTLP Ingestion Endpoints

JustAnalytics provides OTLP-compatible endpoints for all three signal types:

SignalEndpointProtocol
Traceshttps://ingest.justanalytics.app/v1/tracesOTLP/HTTP (protobuf)
Logshttps://ingest.justanalytics.app/v1/logsOTLP/HTTP (protobuf)
Metricshttps://ingest.justanalytics.app/v1/metricsOTLP/HTTP (protobuf)
All signalshttps://ingest.justanalytics.appOTLP/gRPC

Both OTLP/HTTP (protobuf and JSON) and OTLP/gRPC are supported. We recommend protobuf for production workloads due to lower bandwidth and faster serialization.

Authentication

All OTLP endpoints require your JustAnalytics API key in the request headers:

Authorization: Bearer ja_live_abc123...

Or using the standard OpenTelemetry header convention:

x-justanalytics-api-key: ja_live_abc123...

Sending Data from Any OTel SDK

The beauty of OpenTelemetry is language independence. Here's how to configure the most popular SDKs to send data to JustAnalytics.

Node.js

import { NodeSDK } from '@opentelemetry/sdk-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';
import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';

const headers = {
  'Authorization': `Bearer ${process.env.JUSTANALYTICS_API_KEY}`,
};

const sdk = new NodeSDK({
  serviceName: 'my-node-service',
  traceExporter: new OTLPTraceExporter({
    url: 'https://ingest.justanalytics.app/v1/traces',
    headers,
  }),
  logRecordProcessor: new SimpleLogRecordProcessor(
    new OTLPLogExporter({
      url: 'https://ingest.justanalytics.app/v1/logs',
      headers,
    }),
  ),
  metricReader: new PeriodicExportingMetricReader({
    exporter: new OTLPMetricExporter({
      url: 'https://ingest.justanalytics.app/v1/metrics',
      headers,
    }),
    exportIntervalMillis: 30000,
  }),
  instrumentations: [getNodeAutoInstrumentations()],
});

sdk.start();

Python

from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource

resource = Resource.create({"service.name": "my-python-service"})

provider = TracerProvider(resource=resource)
exporter = OTLPSpanExporter(
    endpoint="https://ingest.justanalytics.app/v1/traces",
    headers={"Authorization": f"Bearer {os.environ['JUSTANALYTICS_API_KEY']}"},
)
provider.add_span_processor(BatchSpanProcessor(exporter))
trace.set_tracer_provider(provider)

Go

package main

import (
    "context"
    "os"

    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
    "go.opentelemetry.io/otel/sdk/resource"
    sdktrace "go.opentelemetry.io/otel/sdk/trace"
    semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
)

func initTracer() (*sdktrace.TracerProvider, error) {
    exporter, err := otlptracehttp.New(
        context.Background(),
        otlptracehttp.WithEndpoint("ingest.justanalytics.app"),
        otlptracehttp.WithHeaders(map[string]string{
            "Authorization": "Bearer " + os.Getenv("JUSTANALYTICS_API_KEY"),
        }),
    )
    if err != nil {
        return nil, err
    }

    tp := sdktrace.NewTracerProvider(
        sdktrace.WithBatcher(exporter),
        sdktrace.WithResource(resource.NewWithAttributes(
            semconv.SchemaURL,
            semconv.ServiceName("my-go-service"),
        )),
    )
    otel.SetTracerProvider(tp)
    return tp, nil
}

Java

import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;

OtlpHttpSpanExporter exporter = OtlpHttpSpanExporter.builder()
    .setEndpoint("https://ingest.justanalytics.app/v1/traces")
    .addHeader("Authorization", "Bearer " + System.getenv("JUSTANALYTICS_API_KEY"))
    .build();

SdkTracerProvider tracerProvider = SdkTracerProvider.builder()
    .addSpanProcessor(BatchSpanProcessor.builder(exporter).build())
    .build();

OpenTelemetrySdk sdk = OpenTelemetrySdk.builder()
    .setTracerProvider(tracerProvider)
    .build();

Using Environment Variables

All OpenTelemetry SDKs respect standard environment variables, so you can configure the exporter without code changes:

export OTEL_SERVICE_NAME="my-service"
export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingest.justanalytics.app"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer ja_live_abc123"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"

This is the easiest way to switch from another backend to JustAnalytics -- just change the environment variables and restart your service.

Works with the OpenTelemetry Collector

For teams that use the OpenTelemetry Collector as a central telemetry pipeline, JustAnalytics works as an exporter destination.

Collector Configuration

# otel-collector-config.yaml
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: "0.0.0.0:4317"
      http:
        endpoint: "0.0.0.0:4318"

processors:
  batch:
    timeout: 5s
    send_batch_size: 1024
  memory_limiter:
    check_interval: 1s
    limit_mib: 512
  resource:
    attributes:
      - key: deployment.environment
        value: production
        action: upsert

exporters:
  otlphttp/justanalytics:
    endpoint: "https://ingest.justanalytics.app"
    headers:
      Authorization: "Bearer ja_live_abc123"
    compression: gzip
    retry_on_failure:
      enabled: true
      initial_interval: 5s
      max_interval: 30s
    sending_queue:
      enabled: true
      num_consumers: 4
      queue_size: 1000

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, batch, resource]
      exporters: [otlphttp/justanalytics]
    logs:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [otlphttp/justanalytics]
    metrics:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [otlphttp/justanalytics]

Multi-Destination Fan-Out

The Collector lets you send data to multiple backends simultaneously. This is useful during migration or for redundancy:

exporters:
  otlphttp/justanalytics:
    endpoint: "https://ingest.justanalytics.app"
    headers:
      Authorization: "Bearer ja_live_abc123"
  otlphttp/existing-vendor:
    endpoint: "https://api.existing-vendor.com/v1"
    headers:
      api-key: "existing-key"

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlphttp/justanalytics, otlphttp/existing-vendor]

This lets you evaluate JustAnalytics alongside your current tool with zero risk. Both receive the same data, and you can compare the experience side by side.

Semantic Conventions

JustAnalytics understands and respects OpenTelemetry semantic conventions. Resource attributes, span attributes, and log fields are mapped to our data model automatically.

Resource Attributes

OTel AttributeJustAnalytics Mapping
service.nameService name (trace explorer, service map)
service.versionRelease version (release tracking)
deployment.environmentEnvironment filter
host.nameInfrastructure host
container.idContainer identifier
k8s.pod.nameKubernetes pod name

Span Attributes

OTel AttributeJustAnalytics Mapping
http.methodHTTP method in span details
http.urlURL in span details
http.status_codeStatus code with error detection
db.systemDatabase type (PostgreSQL, Redis, etc.)
db.statementQuery in span details
rpc.servicegRPC service name

Log Attributes

OTel AttributeJustAnalytics Mapping
severity_textLog level (INFO, WARN, ERROR)
bodyLog message
trace_idTrace correlation
span_idSpan correlation
attributes.*Structured log fields

No Vendor Lock-In

This is the core principle behind our OpenTelemetry support: your instrumentation is yours.

If you instrument with the JustAnalytics Node.js SDK, your traces are in our format. If you ever want to switch, you'd need to re-instrument. That's vendor lock-in.

If you instrument with OpenTelemetry, your traces use an open standard. You can send them to JustAnalytics today, Datadog tomorrow, and Grafana Cloud next month -- without changing a single line of application code. You just change the exporter configuration.

We believe this is the right model for the industry. Observability vendors should compete on the quality of their analysis, visualization, and alerting -- not on proprietary agents that make switching painful.

Migration Path from Other Vendors

Already using a vendor-specific agent? Here's how to migrate:

From Datadog:

  1. Install the OTel SDK alongside the Datadog agent
  2. Configure dual export (Datadog + JustAnalytics)
  3. Validate data in JustAnalytics
  4. Remove the Datadog agent

From New Relic:

  1. New Relic supports OTLP export natively
  2. Add JustAnalytics as a second OTLP destination
  3. Validate and switch

From Sentry (performance/tracing):

  1. Replace Sentry SDK with OTel SDK
  2. Use Sentry's OTel integration during transition
  3. Point OTel exporter to JustAnalytics

Data Processing and Retention

Ingestion Limits

PlanTraces/monthLogs/monthMetrics/month
Free100K spans500K logs1M data points
Pro10M spans50M logs100M data points
Business100M spans500M logs1B data points
EnterpriseCustomCustomCustom

Sampling at the Collector

For high-volume services, configure sampling at the OTel Collector to control costs:

processors:
  probabilistic_sampler:
    sampling_percentage: 10  # Keep 10% of traces
  tail_sampling:
    decision_wait: 10s
    policies:
      - name: errors
        type: status_code
        status_code: { status_codes: [ERROR] }
      - name: slow-traces
        type: latency
        latency: { threshold_ms: 1000 }
      - name: default
        type: probabilistic
        probabilistic: { sampling_percentage: 5 }

This configuration keeps 100% of error traces, 100% of slow traces, and 5% of everything else. It's the most cost-effective way to get comprehensive observability without storing every trace.

Getting Started

Option 1: Direct SDK Configuration

Set environment variables and restart your service:

export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingest.justanalytics.app"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer YOUR_API_KEY"

Option 2: OTel Collector

Deploy the Collector with JustAnalytics as an exporter (see configuration above).

Option 3: JustAnalytics SDK with OTel Compatibility

If you're starting fresh, the JustAnalytics Node.js SDK provides auto-instrumentation with zero config. It uses OpenTelemetry under the hood, so you get OTel-compatible traces without managing the OTel SDK yourself:

npm install @justanalyticsapp/node
import { init } from '@justanalyticsapp/node';

init({
  apiKey: 'ja_live_abc123',
  serviceName: 'my-service',
});
// That's it. HTTP, database, and framework traces are captured automatically.

Verify Your Data

Once configured, check the Trace Explorer in your JustAnalytics dashboard. You should see spans arriving within seconds. The Service Map will populate as JustAnalytics discovers service-to-service communication patterns from your trace data.

No proprietary agents. No vendor lock-in. Just open standards and a great dashboard.

Start your 7-day free trial and send your first OTLP data today.

JT
JustAnalytics TeamEngineering Team

The engineering and product team behind JustAnalytics. We're on a mission to make web observability simpler, faster, and more private.

Related posts