Browse documentation

Instrument

OpenTelemetry

Send existing OTLP traces, logs, and metrics to Anectico without replacing your instrumentation.

Anectico accepts OpenTelemetry Protocol data. Keep your current instrumentation and change the exporter destination and authentication header.

Endpoint and authentication

Use the Anectico ingestion host:

OTLP HTTP base: https://api.anectico.com
Header:         X-Anectico-API-Key=an_...

Signal paths follow the OTLP HTTP convention:

/v1/traces
/v1/logs
/v1/metrics

Example environment configuration:

export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.anectico.com"
export OTEL_EXPORTER_OTLP_HEADERS="X-Anectico-API-Key=an_..."
export OTEL_SERVICE_NAME="orders-api"
export OTEL_RESOURCE_ATTRIBUTES="deployment.environment=production"

Use an API key containing only ingest:write for collectors and application exporters.

Add Anectico features to an existing Python SDK

If your Python application already owns OpenTelemetry resources, sampling, providers, processors, exporters, instrumentation, and lifecycle, do not start a second telemetry pipeline. Keep those application providers, point their OTLP exporters or Collector at Anectico, and add Anectico’s identity-only processors before registering the providers:

import os

from opentelemetry import _logs as otel_logs
from opentelemetry import metrics, trace
import anectico

# These are the providers and export processors from your existing OTel setup.
tracer_provider.add_span_processor(anectico.BaggageIdentitySpanProcessor())
tracer_provider.add_span_processor(existing_span_export_processor)
logger_provider.add_log_record_processor(
    anectico.BaggageIdentityLogRecordProcessor()
)
logger_provider.add_log_record_processor(existing_log_export_processor)

trace.set_tracer_provider(tracer_provider)
metrics.set_meter_provider(meter_provider)
otel_logs.set_logger_provider(logger_provider)

client = anectico.AnecticoClient(
    api_key=os.environ["ANECTICO_API_KEY"],
    service_name="marketplace-api",
    open_telemetry_mode="existing",
)
client.start()

ANECTICO_OTEL_MODE=existing is equivalent. Register the identity processors before application work emits spans or logs, and register the application providers before starting Anectico. The processors only stamp anectico.distinct_id; they do not export, register globals, or flush/shut down anything. Do not add person identity to metric labels.

Existing mode creates no providers, exporters, export processors, metric readers, propagator, requests/httpx instrumentation, or standard-library logging bridge. Anectico’s manual spans, captured errors, AI/tool/agent helpers, metrics, and log_event() use the registered global APIs. Without a real application Logger Provider, log_event() is a safe no-op. Ordinary Python logging continues through the application’s existing logging integration only.

The application owns sampling and export decisions. Anectico’s managed resource, sampler, endpoint, batching, exporter, propagation, and logging-bridge settings do not change the existing pipeline; Anectico signal enable flags still gate helper emission. client.flush() returns False, and client.stop() returns attempted=False, success=None, because neither call may flush or shut down application providers. After the final helper call, stop Anectico and use the application’s existing provider lifecycle hook to flush and shut down.

To roll back the Anectico feature layer, remove the client startup and the two identity processors. The original application-owned OTel pipeline stays in place. Restore its prior exporter/Collector destination and authentication separately if the rollback must also stop OTLP delivery to Anectico.

Add Anectico features to an existing Node SDK

If your application already starts NodeSDK or registers its own OpenTelemetry providers, keep that code as the single owner of providers, processors, instrumentation, exporters, flush, and shutdown. Start it first, point its OTLP exporters at Anectico, and initialize Anectico in existing-provider mode:

import { context, trace } from '@opentelemetry/api';
import { NodeSDK } from '@opentelemetry/sdk-node';
import {
  BaggageLogRecordProcessor,
  BaggageSpanProcessor,
  contextWithDistinctId,
  initNode,
} from '@anectico/sdk/node';

const otel = new NodeSDK({
  // Keep your existing resource, instrumentations, and Anectico OTLP exporters.
  // Add these identity-only processors before the application SDK starts.
  spanProcessors: [
    new BaggageSpanProcessor(),
    // ...your existing export processors
  ],
  logRecordProcessors: [
    new BaggageLogRecordProcessor(),
    // ...your existing export processors
  ],
});
otel.start();

const anectico = await initNode({
  apiKey: process.env.ANECTICO_API_KEY,
  serviceName: 'orders-api',
  openTelemetryMode: 'existing',
});

const requestContext = contextWithDistinctId(context.active(), 'customer_8842');
await context.with(requestContext, async () => {
  await trace.getTracer('orders-api').startActiveSpan('orders.create', async span => {
    // Existing application work.
    span.end();
  });
});

openTelemetryMode: 'existing' (or ANECTICO_OTEL_MODE=existing) does not create providers, exporters, propagators, or auto-instrumentations and never shuts down application-owned providers. Anectico’s manual spans, errors, metrics, and logs use the globals your application registered. A signal needs an existing provider to export: for example, logEvent() requires your application to have registered an OpenTelemetry Logger Provider.

Add BaggageSpanProcessor and BaggageLogRecordProcessor to the application-owned providers before they start when request-scoped contextWithDistinctId() or W3C baggage should become the anectico.distinct_id attribute stored on spans and logs. These processors add identity attributes only; they do not export, register globals, or own provider lifecycle. Metrics should remain service-scoped and must not carry customer identity labels.

Keep lifecycle ownership in the application. On graceful or fatal shutdown, finish active work and flush or shut down NodeSDK before calling anectico.stop() to finish Anectico identity requests and remove its process handlers. anectico.flush() cannot flush providers it does not own. Do not combine the default managed mode with an already-started OpenTelemetry SDK, and do not use the Anectico preload in existing-provider mode. Removing the Anectico initialization later leaves the original OTLP-only pipeline unchanged.

Attach customer identity to request evidence

OTLP data without customer identity still appears in service, trace, log, and metric views. To add traces and logs to a customer timeline, attach the stable ID as:

anectico.distinct_id=user_8842

For distributed requests, propagate the same value through trusted W3C baggage. Do not accept a customer identity directly from an unauthenticated public request. Do not copy customer identity onto metric labels: identifiers create high-cardinality series, and metrics are normally service-scoped evidence rather than one-customer timeline entries.

Resource fields that matter

Set these consistently:

Field Purpose
service.name Groups telemetry by application or service
service.version Connects failures to a release
deployment.environment Separates production, staging, and development
anectico.distinct_id Connects request evidence to a customer; do not use it as a metric label

Verify

Send one span, one log, and one recognizable metric, then check Traces, Logs, and Metrics in the same project and environment. Allow for the metric export interval and shut down the Meter Provider cleanly in a short-lived test. If you supplied anectico.distinct_id on the request evidence, also search Customers for that value.