Skip to content

Commit 4fca665

Browse files
jdaisonchargome
andauthored
docs(js): Add example docs for non-HTTP protocols (#12933)
* feat(distributed-tracing): add docs or manual instrumentation of non-HTTP protocols * update example --------- Co-authored-by: Charly Gomez <[email protected]>
1 parent 44fea31 commit 4fca665

File tree

2 files changed

+117
-1
lines changed

2 files changed

+117
-1
lines changed

platform-includes/distributed-tracing/custom-instrumentation/javascript.mdx

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,119 @@ Once the callback ends, the SDK will continue the previous trace (if available).
6565
## Verification
6666

6767
If you make outgoing requests from your project to other services, check if the headers `sentry-trace` and `baggage` are present in the request. If so, distributed tracing is working.
68+
69+
<PlatformCategorySection supported={["server"]}>
70+
## Example: Manual Instrumentation for gRPC
71+
72+
### Server-Side Propagation
73+
74+
```javascript
75+
// gRPC server interceptor with Sentry instrumentation
76+
function sentryInterceptor(methodDescriptor, nextCall) {
77+
// Extract Sentry trace headers from the incoming metadata
78+
const metadata = nextCall.metadata.getMap();
79+
const sentryTrace = metadata['sentry-trace'];
80+
const baggage = metadata['baggage'];
81+
82+
return new grpc.ServerInterceptingCall(nextCall, {
83+
start: (next) => {
84+
// Continue the trace using the extracted context
85+
Sentry.continueTrace({ sentryTrace, baggage }, () => {
86+
// Create a manual span that won't auto-close until we end it
87+
Sentry.startSpanManual(
88+
{
89+
name: methodDescriptor.path,
90+
op: 'grpc.server',
91+
forceTransaction: true, // Make this a transaction in the Sentry UI
92+
attributes: {
93+
'grpc.method': methodDescriptor.path,
94+
'grpc.service': methodDescriptor.service.serviceName,
95+
'grpc.status_code': grpc.status.OK,
96+
},
97+
},
98+
(span) => {
99+
// Store the span for later use
100+
nextCall.sentrySpan = span;
101+
next();
102+
}
103+
);
104+
});
105+
},
106+
sendStatus: (status, next) => {
107+
const span = nextCall.sentrySpan;
108+
if (span) {
109+
// Update status based on the gRPC result
110+
if (status.code !== grpc.status.OK) {
111+
span.setStatus({ code: 'error' });
112+
span.setAttribute('grpc.status_code', status.code);
113+
span.setAttribute('grpc.status_description', status.details);
114+
}
115+
// End the span when the call completes
116+
span.end();
117+
}
118+
next(status);
119+
}
120+
});
121+
}
122+
123+
// Add the interceptor to your gRPC server
124+
const server = new grpc.Server({
125+
interceptors: [sentryInterceptor]
126+
});
127+
128+
// In your service implementation, use the active span
129+
const serviceImplementation = {
130+
myMethod: async (call, callback) => {
131+
try {
132+
const span = call.call?.nextCall?.sentrySpan;
133+
134+
// Use withActiveSpan to make the span active during service execution
135+
await Sentry.withActiveSpan(span, async () => {
136+
// Create child spans for operations within the service
137+
await Sentry.startSpan({ name: 'database.query', op: 'db' }, async (childSpan) => {
138+
// Database operations here
139+
const result = await database.query('SELECT * FROM table');
140+
childSpan.setAttribute('db.rows_affected', result.rowCount);
141+
});
142+
143+
callback(null, { result: 'success' });
144+
});
145+
} catch (error) {
146+
// Capture the error with the current span as context
147+
Sentry.captureException(error);
148+
callback(error);
149+
}
150+
}
151+
};
152+
```
153+
154+
### Client-Side Propagation
155+
156+
```javascript
157+
function createGrpcClient() {
158+
// Create client with interceptor
159+
return new MyServiceClient(address, grpc.credentials.createInsecure(), {
160+
interceptors: [(options, nextCall) => {
161+
// Create metadata for the call
162+
const metadata = new grpc.Metadata();
163+
164+
// Get current trace information
165+
const traceData = Sentry.getTraceData();
166+
167+
// Add trace headers to metadata
168+
if (traceData) {
169+
metadata.set('sentry-trace', traceData['sentry-trace']);
170+
metadata.set('baggage', traceData['baggage']);
171+
}
172+
173+
// Add metadata to the call
174+
return new grpc.InterceptingCall(nextCall(options), {
175+
start: (metadata_, listener, next) => {
176+
next(metadata, listener);
177+
}
178+
});
179+
}]
180+
});
181+
}
182+
```
183+
</PlatformCategorySection>

platform-includes/distributed-tracing/custom-instrumentation/server/javascript.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,4 @@ function renderHtml() {
8686
</html>
8787
`;
8888
}
89-
```
89+
```

0 commit comments

Comments
 (0)