Skip to content

Commit

Permalink
docs(js): Add example docs for non-HTTP protocols (#12933)
Browse files Browse the repository at this point in the history
* feat(distributed-tracing): add docs or manual instrumentation of non-HTTP protocols

* update example

---------

Co-authored-by: Charly Gomez <[email protected]>
  • Loading branch information
jdaison and chargome authored Mar 7, 2025
1 parent 44fea31 commit 4fca665
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,119 @@ Once the callback ends, the SDK will continue the previous trace (if available).
## Verification

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.

<PlatformCategorySection supported={["server"]}>
## Example: Manual Instrumentation for gRPC

### Server-Side Propagation

```javascript
// gRPC server interceptor with Sentry instrumentation
function sentryInterceptor(methodDescriptor, nextCall) {
// Extract Sentry trace headers from the incoming metadata
const metadata = nextCall.metadata.getMap();
const sentryTrace = metadata['sentry-trace'];
const baggage = metadata['baggage'];

return new grpc.ServerInterceptingCall(nextCall, {
start: (next) => {
// Continue the trace using the extracted context
Sentry.continueTrace({ sentryTrace, baggage }, () => {
// Create a manual span that won't auto-close until we end it
Sentry.startSpanManual(
{
name: methodDescriptor.path,
op: 'grpc.server',
forceTransaction: true, // Make this a transaction in the Sentry UI
attributes: {
'grpc.method': methodDescriptor.path,
'grpc.service': methodDescriptor.service.serviceName,
'grpc.status_code': grpc.status.OK,
},
},
(span) => {
// Store the span for later use
nextCall.sentrySpan = span;
next();
}
);
});
},
sendStatus: (status, next) => {
const span = nextCall.sentrySpan;
if (span) {
// Update status based on the gRPC result
if (status.code !== grpc.status.OK) {
span.setStatus({ code: 'error' });
span.setAttribute('grpc.status_code', status.code);
span.setAttribute('grpc.status_description', status.details);
}
// End the span when the call completes
span.end();
}
next(status);
}
});
}

// Add the interceptor to your gRPC server
const server = new grpc.Server({
interceptors: [sentryInterceptor]
});

// In your service implementation, use the active span
const serviceImplementation = {
myMethod: async (call, callback) => {
try {
const span = call.call?.nextCall?.sentrySpan;

// Use withActiveSpan to make the span active during service execution
await Sentry.withActiveSpan(span, async () => {
// Create child spans for operations within the service
await Sentry.startSpan({ name: 'database.query', op: 'db' }, async (childSpan) => {
// Database operations here
const result = await database.query('SELECT * FROM table');
childSpan.setAttribute('db.rows_affected', result.rowCount);
});

callback(null, { result: 'success' });
});
} catch (error) {
// Capture the error with the current span as context
Sentry.captureException(error);
callback(error);
}
}
};
```
### Client-Side Propagation
```javascript
function createGrpcClient() {
// Create client with interceptor
return new MyServiceClient(address, grpc.credentials.createInsecure(), {
interceptors: [(options, nextCall) => {
// Create metadata for the call
const metadata = new grpc.Metadata();

// Get current trace information
const traceData = Sentry.getTraceData();

// Add trace headers to metadata
if (traceData) {
metadata.set('sentry-trace', traceData['sentry-trace']);
metadata.set('baggage', traceData['baggage']);
}

// Add metadata to the call
return new grpc.InterceptingCall(nextCall(options), {
start: (metadata_, listener, next) => {
next(metadata, listener);
}
});
}]
});
}
```
</PlatformCategorySection>
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,4 @@ function renderHtml() {
</html>
`;
}
```
```

0 comments on commit 4fca665

Please sign in to comment.