0
# OpenTelemetry Express Instrumentation
1
2
OpenTelemetry Express Instrumentation provides automatic tracing and observability for Express.js web applications. It automatically captures HTTP request spans, route information, middleware execution, and request handler performance metrics without requiring code changes to existing applications.
3
4
## Package Information
5
6
- **Package Name**: @opentelemetry/instrumentation-express
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install @opentelemetry/instrumentation-express`
10
11
## Core Imports
12
13
```typescript
14
import { ExpressInstrumentation } from "@opentelemetry/instrumentation-express";
15
```
16
17
For additional types and enums:
18
19
```typescript
20
import {
21
ExpressInstrumentation,
22
ExpressLayerType,
23
AttributeNames,
24
type ExpressInstrumentationConfig,
25
type ExpressRequestInfo,
26
type ExpressRequestCustomAttributeFunction,
27
type IgnoreMatcher,
28
type LayerPathSegment,
29
type SpanNameHook,
30
} from "@opentelemetry/instrumentation-express";
31
```
32
33
For CommonJS:
34
35
```javascript
36
const { ExpressInstrumentation } = require("@opentelemetry/instrumentation-express");
37
```
38
39
## Basic Usage
40
41
```typescript
42
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
43
import { registerInstrumentations } from "@opentelemetry/instrumentation";
44
import { HttpInstrumentation } from "@opentelemetry/instrumentation-http";
45
import { ExpressInstrumentation } from "@opentelemetry/instrumentation-express";
46
47
const provider = new NodeTracerProvider();
48
provider.register();
49
50
registerInstrumentations({
51
instrumentations: [
52
// Express instrumentation requires HTTP layer to be instrumented
53
new HttpInstrumentation(),
54
new ExpressInstrumentation(),
55
],
56
});
57
```
58
59
## Architecture
60
61
The Express instrumentation works by patching Express Router methods (`route`, `use`) and Application methods (`use`) to automatically create spans for middleware, routers, and request handlers. It uses a layered approach where:
62
63
- **Router Spans**: Created for Express Router instances
64
- **Middleware Spans**: Created for middleware functions
65
- **Request Handler Spans**: Created for route handlers and final request processors
66
- **Layer Path Tracking**: Maintains a stack of route paths to construct accurate route information
67
- **Context Propagation**: Ensures proper OpenTelemetry context flow through the Express middleware chain
68
69
## Capabilities
70
71
### Express Instrumentation Class
72
73
Main instrumentation class that extends OpenTelemetry's InstrumentationBase to provide automatic Express.js tracing.
74
75
```typescript { .api }
76
/**
77
* Express instrumentation for OpenTelemetry
78
* Automatically instruments Express.js applications for distributed tracing
79
*/
80
class ExpressInstrumentation extends InstrumentationBase<ExpressInstrumentationConfig> {
81
/**
82
* Creates a new Express instrumentation instance
83
* @param config - Optional configuration for the instrumentation
84
*/
85
constructor(config?: ExpressInstrumentationConfig);
86
87
/**
88
* Initializes the instrumentation by returning module definitions
89
* @returns Array of InstrumentationNodeModuleDefinition for express module
90
*/
91
init(): InstrumentationNodeModuleDefinition[];
92
}
93
```
94
95
### Layer Type Classification
96
97
Enumeration defining the types of Express layers that can be instrumented.
98
99
```typescript { .api }
100
/**
101
* Types of Express layers that can be instrumented
102
*/
103
enum ExpressLayerType {
104
ROUTER = 'router',
105
MIDDLEWARE = 'middleware',
106
REQUEST_HANDLER = 'request_handler',
107
}
108
```
109
110
### Attribute Names
111
112
Standard attribute names used by the Express instrumentation for OpenTelemetry spans.
113
114
```typescript { .api }
115
/**
116
* OpenTelemetry attribute names used by Express instrumentation
117
*/
118
enum AttributeNames {
119
EXPRESS_TYPE = 'express.type',
120
EXPRESS_NAME = 'express.name',
121
}
122
```
123
124
### Configuration Interface
125
126
Configuration options for customizing Express instrumentation behavior.
127
128
```typescript { .api }
129
/**
130
* Configuration options for Express Instrumentation
131
*/
132
interface ExpressInstrumentationConfig extends InstrumentationConfig {
133
/** Ignore specific layers based on their name using matchers */
134
ignoreLayers?: IgnoreMatcher[];
135
/** Ignore specific layers based on their type */
136
ignoreLayersType?: ExpressLayerType[];
137
/** Custom function for span naming */
138
spanNameHook?: SpanNameHook;
139
/** Function for adding custom attributes on Express request */
140
requestHook?: ExpressRequestCustomAttributeFunction;
141
}
142
```
143
144
### Request Information Interface
145
146
Information about Express requests passed to hooks and callbacks.
147
148
```typescript { .api }
149
/**
150
* Information about Express request for hooks and callbacks
151
*/
152
interface ExpressRequestInfo<T = any> {
153
/** An express request object */
154
request: T;
155
/** The matched route path */
156
route: string;
157
/** Type of the Express layer handling the request */
158
layerType: ExpressLayerType;
159
}
160
```
161
162
### Custom Attribute Function
163
164
Function type for adding custom attributes to spans based on Express request information.
165
166
```typescript { .api }
167
/**
168
* Function that can be used to add custom attributes to the current span
169
* @param span - The Express middleware layer span
170
* @param info - Express request information including route and layer type
171
*/
172
interface ExpressRequestCustomAttributeFunction {
173
(span: Span, info: ExpressRequestInfo): void;
174
}
175
```
176
177
### Span Name Hook
178
179
Function type for customizing span names based on Express request information.
180
181
```typescript { .api }
182
/**
183
* Function for customizing span names
184
* @param info - Express request information
185
* @param defaultName - Default name supplied by the instrumentation
186
* @returns Custom span name
187
*/
188
type SpanNameHook = (
189
info: ExpressRequestInfo,
190
defaultName: string
191
) => string;
192
```
193
194
### Ignore Matcher
195
196
Type for matching patterns to ignore specific layers during instrumentation.
197
198
```typescript { .api }
199
/**
200
* Pattern matching for ignoring layers during instrumentation
201
*/
202
type IgnoreMatcher = string | RegExp | ((name: string) => boolean);
203
```
204
205
### Layer Path Segment
206
207
Type representing individual segments of Express layer paths.
208
209
```typescript { .api }
210
/**
211
* Individual segment of Express layer path
212
*/
213
type LayerPathSegment = string | RegExp | number;
214
```
215
216
## Usage Examples
217
218
### Basic Instrumentation Setup
219
220
```typescript
221
import { ExpressInstrumentation } from "@opentelemetry/instrumentation-express";
222
import { registerInstrumentations } from "@opentelemetry/instrumentation";
223
224
registerInstrumentations({
225
instrumentations: [
226
new ExpressInstrumentation(),
227
],
228
});
229
```
230
231
### Configuration with Layer Filtering
232
233
```typescript
234
import { ExpressInstrumentation, ExpressLayerType } from "@opentelemetry/instrumentation-express";
235
236
const expressInstrumentation = new ExpressInstrumentation({
237
ignoreLayers: [
238
// Ignore health check endpoints
239
'/health',
240
/^\/static\//,
241
// Ignore specific middleware by name
242
(name) => name === 'helmet',
243
],
244
ignoreLayersType: [
245
// Ignore all router spans
246
ExpressLayerType.ROUTER,
247
],
248
});
249
```
250
251
### Custom Request Attributes
252
253
```typescript
254
import { ExpressInstrumentation, ExpressLayerType } from "@opentelemetry/instrumentation-express";
255
256
const expressInstrumentation = new ExpressInstrumentation({
257
requestHook: (span, info) => {
258
// Add custom attributes for request handlers only
259
if (info.layerType === ExpressLayerType.REQUEST_HANDLER) {
260
span.setAttribute('http.method', info.request.method);
261
span.setAttribute('express.base_url', info.request.baseUrl);
262
span.setAttribute('user.id', info.request.user?.id || 'anonymous');
263
}
264
},
265
});
266
```
267
268
### Custom Span Naming
269
270
```typescript
271
import { ExpressInstrumentation } from "@opentelemetry/instrumentation-express";
272
273
const expressInstrumentation = new ExpressInstrumentation({
274
spanNameHook: (info, defaultName) => {
275
// Customize span names for request handlers
276
if (info.layerType === 'request_handler') {
277
return `${info.request.method} ${info.route}`;
278
}
279
return defaultName;
280
},
281
});
282
```
283
284
## Important Notes
285
286
- **HTTP Instrumentation Required**: Express instrumentation expects the HTTP layer to also be instrumented using `@opentelemetry/instrumentation-http`
287
- **Supported Express Versions**: Works with Express 4.x and 5.x (>=4.0.0 <6)
288
- **Asynchronous Middleware Limitation**: Time reported for asynchronous middleware represents only synchronous execution time, not asynchronous work
289
- **Node.js Version Support**: Requires Node.js ^18.19.0 || >=20.6.0
290
- **Semantic Conventions**: Uses OpenTelemetry semantic conventions v1.27.0 and sets `http.route` attribute
291
292
## Error Handling
293
294
The instrumentation automatically captures and records exceptions that occur in Express middleware and request handlers. Errors are recorded as span exceptions with proper error status codes.
295
296
## Integration with Other Instrumentations
297
298
Express instrumentation is designed to work alongside other OpenTelemetry instrumentations, particularly:
299
300
- **HTTP Instrumentation**: Required for complete request lifecycle tracing
301
- **Database Instrumentations**: For tracing database queries within Express handlers
302
- **External HTTP Client Instrumentations**: For tracing outbound HTTP calls