Skip to main content
RapidDev - Software Development Agency
cursor-tutorial

How to add tracing and observability with Cursor

Cursor can generate OpenTelemetry tracing instrumentation across your microservices when given proper context about your architecture and tracing conventions. This tutorial shows how to use .cursorrules for consistent span naming, reference your tracing setup with @file, and prompt Cursor to add traces to existing endpoints without breaking your code.

What you'll learn

  • How to configure .cursorrules for consistent tracing patterns
  • How to prompt Cursor to add OpenTelemetry spans to existing code
  • How to generate a tracing setup module with Cursor
  • How to verify Cursor-generated traces follow your naming conventions
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner7 min read15-20 minCursor Free+, Node.js/Python/Go with OpenTelemetryMarch 2026RapidDev Engineering Team
TL;DR

Cursor can generate OpenTelemetry tracing instrumentation across your microservices when given proper context about your architecture and tracing conventions. This tutorial shows how to use .cursorrules for consistent span naming, reference your tracing setup with @file, and prompt Cursor to add traces to existing endpoints without breaking your code.

Adding observability to microservices with Cursor

Adding distributed tracing to an existing codebase is repetitive but detail-sensitive work. Each service needs consistent span names, attribute conventions, and error recording. Cursor can automate this instrumentation if you provide the right context about your tracing setup and naming conventions. This tutorial walks through setting up a reusable tracing pattern that Cursor can apply across your services.

Prerequisites

  • Cursor installed with a microservices project
  • OpenTelemetry SDK installed in your project
  • A tracing backend (Jaeger, Zipkin, or Grafana Tempo) for verification
  • Basic understanding of distributed tracing concepts

Step-by-step guide

1

Generate a tracing setup module with Cursor

Use Cursor Chat (Cmd+L) to generate the initial OpenTelemetry configuration. This module initializes the tracer provider, sets up exporters, and creates a reusable tracer instance. Cursor needs to know your runtime, exporter type, and service name pattern.

src/tracing/setup.ts
1// Cursor Chat prompt (Cmd+L):
2// Generate an OpenTelemetry tracing setup module for a
3// Node.js Express service. Use OTLP/gRPC exporter, batch
4// span processor, and the W3C trace context propagator.
5// Service name should come from environment variable
6// OTEL_SERVICE_NAME. Export a getTracer() function.
7
8// Expected output:
9import { NodeSDK } from '@opentelemetry/sdk-node';
10import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
11import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';
12import { trace } from '@opentelemetry/api';
13
14const sdk = new NodeSDK({
15 traceExporter: new OTLPTraceExporter({
16 url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://localhost:4317',
17 }),
18 instrumentations: [getNodeAutoInstrumentations()],
19 serviceName: process.env.OTEL_SERVICE_NAME || 'unknown-service',
20});
21
22sdk.start();
23
24export function getTracer(name: string) {
25 return trace.getTracer(name);
26}

Expected result: A reusable tracing setup module that initializes OpenTelemetry with your preferred configuration.

2

Add tracing rules to .cursor/rules

Create rules that define your span naming convention, required attributes, and error recording pattern. This ensures every trace Cursor generates follows the same format across all services.

.cursor/rules/tracing.mdc
1---
2description: OpenTelemetry tracing conventions
3globs: "src/**/*.ts"
4alwaysApply: false
5---
6
7## Tracing Rules
8- Import tracer: import { getTracer } from '@/tracing/setup'
9- Span naming: '{service}.{operation}' e.g. 'order-service.createOrder'
10- ALWAYS add these attributes to spans:
11 - 'http.method' for HTTP handlers
12 - 'http.route' for the URL pattern
13 - 'user.id' when available from auth context
14 - 'error' boolean attribute on failures
15- Record exceptions with span.recordException(error)
16- Set span status to ERROR on catch blocks
17- Use startActiveSpan for automatic context propagation
18- NEVER create spans inside tight loops (batch them)
19- End spans in finally blocks to prevent leaks

Expected result: Cursor follows consistent tracing conventions whenever it generates or modifies service code.

3

Add traces to an existing endpoint with Cmd+K

Open an existing route handler, select the function body, press Cmd+K, and ask Cursor to wrap it with tracing. Reference the tracing setup file so Cursor uses the correct import path.

src/routes/orders.ts
1// Select the handler function, press Cmd+K:
2// @src/tracing/setup.ts Add OpenTelemetry tracing to this
3// handler. Use startActiveSpan with the naming convention
4// 'order-service.getOrder'. Add http.method, http.route,
5// and user.id attributes. Record errors.
6
7// Cursor output:
8import { getTracer } from '@/tracing/setup';
9import { SpanStatusCode } from '@opentelemetry/api';
10
11const tracer = getTracer('order-service');
12
13app.get('/orders/:id', async (req, res) => {
14 return tracer.startActiveSpan('order-service.getOrder', async (span) => {
15 try {
16 span.setAttribute('http.method', 'GET');
17 span.setAttribute('http.route', '/orders/:id');
18 span.setAttribute('user.id', req.user?.id || 'anonymous');
19
20 const order = await orderRepository.findById(req.params.id);
21 if (!order) {
22 span.setAttribute('error', true);
23 return res.status(404).json({ error: 'Order not found' });
24 }
25 res.json(order);
26 } catch (error) {
27 span.recordException(error as Error);
28 span.setStatus({ code: SpanStatusCode.ERROR });
29 res.status(500).json({ error: 'Internal server error' });
30 } finally {
31 span.end();
32 }
33 });
34});

Pro tip: Always end spans in a finally block. Cursor sometimes forgets this, causing span leaks that distort your tracing data.

Expected result: The endpoint now creates a traced span with proper attributes, error recording, and cleanup.

4

Instrument multiple endpoints with Composer

Use Composer Agent mode (Cmd+I) to add tracing to all endpoints in a service at once. Reference the tracing setup and rules to ensure consistency.

Cursor Composer prompt
1// Composer prompt (Cmd+I):
2// @src/tracing/setup.ts @.cursor/rules/tracing.mdc
3// @src/routes/ Add OpenTelemetry tracing to all route
4// handlers in the routes directory. Follow the tracing
5// rules for span naming, attributes, and error recording.
6// Process one file at a time and show me the diff before
7// proceeding to the next file.

Expected result: Cursor instruments each route file with consistent tracing, waiting for approval between files.

5

Verify traces in your tracing backend

Start your service and send a few test requests. Open your tracing backend (Jaeger, Grafana Tempo) to verify the spans appear with correct names and attributes. Use Cursor Chat to troubleshoot if traces are missing.

Terminal
1// Terminal: Start the service with tracing enabled
2OTEL_SERVICE_NAME=order-service \
3OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 \
4npm run dev
5
6// Send a test request
7curl http://localhost:3000/orders/123
8
9// If traces are missing, ask Cursor:
10// Cmd+L: @src/tracing/setup.ts My traces are not appearing
11// in Jaeger at localhost:16686. The service starts without
12// errors. What could be wrong?

Expected result: Traces appear in your backend with correct service name, span names, and attributes.

Complete working example

src/tracing/setup.ts
1import { NodeSDK } from '@opentelemetry/sdk-node';
2import {
3 getNodeAutoInstrumentations,
4} from '@opentelemetry/auto-instrumentations-node';
5import {
6 OTLPTraceExporter,
7} from '@opentelemetry/exporter-trace-otlp-grpc';
8import {
9 BatchSpanProcessor,
10} from '@opentelemetry/sdk-trace-base';
11import { trace, SpanStatusCode } from '@opentelemetry/api';
12import { W3CTraceContextPropagator } from '@opentelemetry/core';
13
14const exporter = new OTLPTraceExporter({
15 url:
16 process.env.OTEL_EXPORTER_OTLP_ENDPOINT ||
17 'http://localhost:4317',
18});
19
20const sdk = new NodeSDK({
21 traceExporter: exporter,
22 spanProcessor: new BatchSpanProcessor(exporter, {
23 maxExportBatchSize: 512,
24 scheduledDelayMillis: 5000,
25 }),
26 textMapPropagator: new W3CTraceContextPropagator(),
27 instrumentations: [
28 getNodeAutoInstrumentations({
29 '@opentelemetry/instrumentation-fs': { enabled: false },
30 }),
31 ],
32 serviceName:
33 process.env.OTEL_SERVICE_NAME || 'unknown-service',
34});
35
36sdk.start();
37
38process.on('SIGTERM', () => {
39 sdk.shutdown().then(() => process.exit(0));
40});
41
42export function getTracer(name: string) {
43 return trace.getTracer(name, '1.0.0');
44}
45
46export { SpanStatusCode };

Common mistakes when adding tracing and observability with Cursor

Why it's a problem: Forgetting to end spans in finally blocks

How to avoid: Add 'End spans in finally blocks to prevent leaks' to your .cursor/rules and verify every Cursor-generated span has a finally block.

Why it's a problem: Creating spans inside loops

How to avoid: Add a rule: 'NEVER create spans inside tight loops. Create one span for the batch operation with item count as an attribute.'

Why it's a problem: Inconsistent span naming across services

How to avoid: Define the naming convention in .cursor/rules: 'Span naming: {service}.{operation}' and reference the rules in every tracing prompt.

Best practices

  • Define span naming conventions in .cursor/rules for consistent instrumentation across services
  • Always reference @src/tracing/setup.ts when prompting Cursor to add traces
  • End all spans in finally blocks to prevent resource leaks
  • Use startActiveSpan for automatic context propagation between functions
  • Add standard HTTP attributes (method, route, status_code) to all request spans
  • Disable file system instrumentation to reduce noise in traces
  • Use Composer Agent mode to instrument multiple endpoints consistently in one session

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

Generate an OpenTelemetry tracing setup for a Node.js Express microservice. Use OTLP/gRPC exporter with batch span processor. Include a getTracer function. Then show how to instrument a GET /orders/:id endpoint with proper span attributes (http.method, http.route, user.id), error recording with recordException, and span cleanup in a finally block.

Cursor Prompt

In Cursor Composer (Cmd+I): @src/tracing/setup.ts @.cursor/rules/tracing.mdc @src/routes/orders.ts Add OpenTelemetry tracing to all handlers in this route file. Use the getTracer from our setup module. Follow the naming convention 'order-service.{handler}'. Add http.method, http.route, user.id attributes. Record exceptions. End spans in finally blocks.

Frequently asked questions

Does Cursor understand OpenTelemetry APIs?

Yes. Cursor's training data includes OpenTelemetry documentation and examples. However, the API changed significantly between versions, so specify your OpenTelemetry SDK version in .cursorrules to avoid outdated API usage.

Should I use auto-instrumentation or manual spans?

Use both. Auto-instrumentation covers HTTP, database, and gRPC calls automatically. Add manual spans for business-logic operations like 'processPayment' or 'validateOrder' that auto-instrumentation cannot detect.

How do I propagate trace context across services?

OpenTelemetry's W3C TraceContext propagator handles this automatically for HTTP calls. For message queues, you need to manually inject/extract context. Ask Cursor: 'Show how to propagate trace context through an SQS message.'

Will adding tracing to every endpoint slow my service?

The overhead is minimal (microseconds per span) when using a batch span processor. The BatchSpanProcessor buffers spans and sends them in bulk, adding negligible latency to request handling.

Can Cursor add tracing to Python or Go services too?

Yes. Update your .cursor/rules with the language-specific OpenTelemetry API patterns. For Python, reference the opentelemetry-python SDK. For Go, reference the go.opentelemetry.io/otel package.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.