How do you set up basic OpenTelemetry instrumentation in a Python/Node.js application?
Quick Answer
For Python, install the OpenTelemetry SDK and auto-instrumentation packages, then run your app with the opentelemetry-instrument wrapper. For Node.js, install the SDK and auto-instrumentation packages, then set the NODE_OPTIONS environment variable to require the instrumentation module at startup. Both approaches send telemetry to an OTLP endpoint without modifying application code.
Detailed Answer
Setting up OpenTelemetry is like installing a security camera system. You choose the cameras (SDK and instrumentation libraries), connect them to a recording station (the Collector), and configure where the footage is stored (the backend). The cameras start recording automatically once installed, but you can also add extra cameras (manual instrumentation) in areas where you need more detailed coverage.
For a Python application like payments-api built with Flask and PostgreSQL, the setup involves three steps. First, install the core packages: opentelemetry-api and opentelemetry-sdk provide the tracing and metrics foundation, opentelemetry-exporter-otlp provides the exporter to send data to the Collector, and opentelemetry-instrumentation packages provide auto-instrumentation for specific libraries. Second, run opentelemetry-bootstrap -a install, which scans your installed Python packages and automatically installs the matching instrumentation libraries (e.g., it detects Flask and installs opentelemetry-instrumentation-flask). Third, wrap your application startup command with opentelemetry-instrument, which initializes the SDK, activates all installed instrumentations, and runs your app. You configure the service name and exporter endpoint through environment variables like OTEL_SERVICE_NAME and OTEL_EXPORTER_OTLP_ENDPOINT.
For a Node.js application like checkout-service built with Express and MongoDB, the setup is similar but uses a different mechanism. Install @opentelemetry/api, @opentelemetry/sdk-node, @opentelemetry/auto-instrumentations-node, and @opentelemetry/exporter-trace-otlp-http. The auto-instrumentations-node package is a meta-package that bundles instrumentations for Express, HTTP, MongoDB, Redis, gRPC, and many other libraries. To activate auto-instrumentation without code changes, set the NODE_OPTIONS environment variable to --require @opentelemetry/auto-instrumentations-node/register. This loads the instrumentation before your application code, ensuring that library imports are intercepted and wrapped with tracing logic. Alternatively, you can create a tracing.js file that programmatically configures the SDK with custom settings like sampling rate and resource attributes, then require it before your app starts.
In production, environment variables are the preferred configuration method because they keep instrumentation settings out of application code. The key variables are OTEL_SERVICE_NAME (identifies the service in traces), OTEL_EXPORTER_OTLP_ENDPOINT (the Collector address), OTEL_TRACES_SAMPLER (controls sampling strategy), and OTEL_RESOURCE_ATTRIBUTES (adds metadata like deployment.environment=production). For Kubernetes deployments of order-processing-service or inventory-sync, these variables are set in the Deployment manifest or injected via ConfigMaps. The OpenTelemetry Operator for Kubernetes can even inject auto-instrumentation automatically by adding an annotation to the pod spec, eliminating the need to modify Dockerfiles or deployment scripts.
Common setup pitfalls include forgetting to install instrumentation libraries for specific frameworks (Flask spans will not appear without opentelemetry-instrumentation-flask), pointing the exporter to the wrong Collector port (gRPC uses 4317, HTTP uses 4318), and not running opentelemetry-bootstrap after adding new dependencies. Another frequent mistake is testing instrumentation without a running Collector: the SDK will silently drop telemetry if the exporter endpoint is unreachable, making it look like instrumentation is not working when the issue is actually a networking problem between user-auth-service and the Collector pod.