0
# Context Management
1
2
Utilities for managing RPC metadata, trace suppression, and context manipulation including support for disabling tracing in specific execution contexts.
3
4
## Capabilities
5
6
### RPC Metadata Management
7
8
Utilities for storing and retrieving RPC-specific metadata in OpenTelemetry context.
9
10
```typescript { .api }
11
import { Context, Span } from '@opentelemetry/api';
12
13
/**
14
* RPC protocol types
15
*/
16
enum RPCType {
17
HTTP = 'http'
18
}
19
20
/**
21
* HTTP metadata type
22
*/
23
type HTTPMetadata = {
24
type: RPCType.HTTP;
25
route?: string;
26
span: Span;
27
};
28
29
/**
30
* RPC metadata type (currently supports HTTP metadata)
31
*/
32
type RPCMetadata = HTTPMetadata;
33
34
/**
35
* Store RPC metadata in context
36
* @param context - OpenTelemetry context
37
* @param meta - RPC metadata to store
38
* @returns New context with RPC metadata
39
*/
40
function setRPCMetadata(context: Context, meta: RPCMetadata): Context;
41
42
/**
43
* Retrieve RPC metadata from context
44
* @param context - OpenTelemetry context
45
* @returns RPC metadata or undefined if not set
46
*/
47
function getRPCMetadata(context: Context): RPCMetadata | undefined;
48
49
/**
50
* Remove RPC metadata from context
51
* @param context - OpenTelemetry context
52
* @returns New context without RPC metadata
53
*/
54
function deleteRPCMetadata(context: Context): Context;
55
```
56
57
**Usage Examples:**
58
59
```typescript
60
import {
61
setRPCMetadata,
62
getRPCMetadata,
63
deleteRPCMetadata,
64
RPCType
65
} from "@opentelemetry/core";
66
import { context } from "@opentelemetry/api";
67
68
// Store HTTP request metadata
69
const httpMetadata = {
70
type: RPCType.HTTP,
71
method: "GET",
72
url: "https://api.example.com/users",
73
statusCode: 200,
74
userAgent: "MyApp/1.0"
75
};
76
77
// Add metadata to current context
78
const contextWithMetadata = setRPCMetadata(context.active(), httpMetadata);
79
80
// Process request with metadata context
81
context.with(contextWithMetadata, () => {
82
// Retrieve metadata within this context
83
const metadata = getRPCMetadata(context.active());
84
85
if (metadata) {
86
console.log("Processing request:", metadata.method, metadata.url);
87
console.log("Status code:", metadata.statusCode);
88
}
89
90
// Spans created in this context will have access to RPC metadata
91
const span = trace.getTracer("my-service").startSpan("process-request");
92
93
// Add RPC metadata as span attributes
94
if (metadata) {
95
span.setAttributes({
96
"rpc.method": metadata.method,
97
"rpc.url": metadata.url,
98
"rpc.status_code": metadata.statusCode
99
});
100
}
101
102
span.end();
103
});
104
105
// Remove metadata from context
106
const cleanContext = deleteRPCMetadata(contextWithMetadata);
107
const shouldBeUndefined = getRPCMetadata(cleanContext);
108
console.log(shouldBeUndefined); // undefined
109
```
110
111
### Trace Suppression
112
113
Utilities for selectively disabling tracing in specific execution contexts.
114
115
```typescript { .api }
116
/**
117
* Disable tracing for the given context
118
* @param context - OpenTelemetry context
119
* @returns New context with tracing suppressed
120
*/
121
function suppressTracing(context: Context): Context;
122
123
/**
124
* Re-enable tracing for the given context
125
* @param context - OpenTelemetry context
126
* @returns New context with tracing enabled
127
*/
128
function unsuppressTracing(context: Context): Context;
129
130
/**
131
* Check if tracing is suppressed in the given context
132
* @param context - OpenTelemetry context
133
* @returns True if tracing is suppressed, false otherwise
134
*/
135
function isTracingSuppressed(context: Context): boolean;
136
```
137
138
**Usage Examples:**
139
140
```typescript
141
import {
142
suppressTracing,
143
unsuppressTracing,
144
isTracingSuppressed
145
} from "@opentelemetry/core";
146
import { context, trace } from "@opentelemetry/api";
147
148
// Suppress tracing for internal operations
149
function performInternalOperation() {
150
const suppressedContext = suppressTracing(context.active());
151
152
return context.with(suppressedContext, () => {
153
// This operation won't create spans
154
console.log("Tracing suppressed:", isTracingSuppressed(context.active())); // true
155
156
// Any spans created here will be non-recording
157
const span = trace.getTracer("internal").startSpan("internal-op");
158
console.log("Span is recording:", span.isRecording()); // false
159
span.end();
160
161
return "operation complete";
162
});
163
}
164
165
// Suppress tracing for health check endpoints
166
function handleHealthCheck(request: any, response: any) {
167
const suppressedContext = suppressTracing(context.active());
168
169
context.with(suppressedContext, () => {
170
// Health checks don't need tracing
171
response.json({ status: "healthy", timestamp: Date.now() });
172
});
173
}
174
175
// Conditional tracing suppression
176
function handleRequest(request: any) {
177
let currentContext = context.active();
178
179
// Suppress tracing for certain endpoints
180
if (request.path === "/health" || request.path === "/metrics") {
181
currentContext = suppressTracing(currentContext);
182
}
183
184
return context.with(currentContext, () => {
185
const isTracing = !isTracingSuppressed(context.active());
186
console.log(`Tracing enabled for ${request.path}:`, isTracing);
187
188
// Process request
189
const span = trace.getTracer("api").startSpan(`${request.method} ${request.path}`);
190
191
try {
192
// Handle request logic
193
return processRequest(request);
194
} finally {
195
span.end();
196
}
197
});
198
}
199
200
// Re-enable tracing in suppressed context
201
function forceTracing() {
202
const suppressedContext = suppressTracing(context.active());
203
204
context.with(suppressedContext, () => {
205
console.log("Tracing suppressed:", isTracingSuppressed(context.active())); // true
206
207
// Force enable tracing for this specific operation
208
const enabledContext = unsuppressTracing(context.active());
209
210
context.with(enabledContext, () => {
211
console.log("Tracing enabled:", !isTracingSuppressed(context.active())); // true
212
213
// This span will be recorded
214
const span = trace.getTracer("forced").startSpan("important-operation");
215
console.log("Span is recording:", span.isRecording()); // true
216
span.end();
217
});
218
});
219
}
220
```
221
222
### Context Utilities Integration
223
224
Integration examples showing how context management works with other OpenTelemetry features.
225
226
**Usage Examples:**
227
228
```typescript
229
import {
230
setRPCMetadata,
231
getRPCMetadata,
232
suppressTracing,
233
isTracingSuppressed,
234
RPCType
235
} from "@opentelemetry/core";
236
import { context, trace, propagation } from "@opentelemetry/api";
237
238
// Middleware for HTTP request processing
239
function createRequestContext(request: any) {
240
let currentContext = context.active();
241
242
// Add RPC metadata
243
const rpcMetadata = {
244
type: RPCType.HTTP,
245
method: request.method,
246
url: request.url,
247
headers: request.headers,
248
remoteAddress: request.connection?.remoteAddress
249
};
250
251
currentContext = setRPCMetadata(currentContext, rpcMetadata);
252
253
// Suppress tracing for certain requests
254
const suppressedPaths = ["/health", "/metrics", "/favicon.ico"];
255
if (suppressedPaths.includes(request.path)) {
256
currentContext = suppressTracing(currentContext);
257
}
258
259
return currentContext;
260
}
261
262
// Process request with context
263
function handleIncomingRequest(request: any, response: any) {
264
// Extract trace context from headers
265
const extractedContext = propagation.extract(context.active(), request.headers);
266
267
context.with(extractedContext, () => {
268
// Create request-specific context
269
const requestContext = createRequestContext(request);
270
271
context.with(requestContext, () => {
272
// Check if tracing is enabled
273
const tracingEnabled = !isTracingSuppressed(context.active());
274
275
// Get RPC metadata
276
const rpcMetadata = getRPCMetadata(context.active());
277
278
console.log(`Processing ${rpcMetadata?.method} ${rpcMetadata?.url}`);
279
console.log(`Tracing enabled: ${tracingEnabled}`);
280
281
// Create span if tracing is enabled
282
const span = trace.getTracer("http-server").startSpan(`${request.method} ${request.path}`);
283
284
if (span.isRecording() && rpcMetadata) {
285
span.setAttributes({
286
"http.method": rpcMetadata.method,
287
"http.url": rpcMetadata.url,
288
"http.remote_addr": rpcMetadata.remoteAddress
289
});
290
}
291
292
try {
293
// Process the request
294
const result = processRequest(request);
295
296
if (span.isRecording()) {
297
span.setStatus({ code: SpanStatusCode.OK });
298
}
299
300
response.json(result);
301
} catch (error) {
302
if (span.isRecording()) {
303
span.recordException(error);
304
span.setStatus({
305
code: SpanStatusCode.ERROR,
306
message: error.message
307
});
308
}
309
310
response.status(500).json({ error: "Internal server error" });
311
} finally {
312
span.end();
313
}
314
});
315
});
316
}
317
318
// Helper function to create instrumentation that respects context
319
function instrumentFunction<T extends Function>(fn: T, name: string): T {
320
return ((...args: any[]) => {
321
// Check if tracing is suppressed
322
if (isTracingSuppressed(context.active())) {
323
// Execute without instrumentation
324
return fn.apply(this, args);
325
}
326
327
// Execute with instrumentation
328
const span = trace.getTracer("auto-instrument").startSpan(name);
329
330
try {
331
const result = fn.apply(this, args);
332
333
// Handle promises
334
if (result && typeof result.then === "function") {
335
return result.catch((error: any) => {
336
span.recordException(error);
337
span.setStatus({ code: SpanStatusCode.ERROR });
338
throw error;
339
}).finally(() => {
340
span.end();
341
});
342
}
343
344
span.setStatus({ code: SpanStatusCode.OK });
345
return result;
346
} catch (error) {
347
span.recordException(error);
348
span.setStatus({ code: SpanStatusCode.ERROR });
349
throw error;
350
} finally {
351
if (!result || typeof result.then !== "function") {
352
span.end();
353
}
354
}
355
}) as any;
356
}
357
```