diff --git a/docs/platforms/javascript/common/tracing/configure-sampling/index.mdx b/docs/platforms/javascript/common/tracing/configure-sampling/index.mdx index 952cd149c66733..86173b4b592e7e 100644 --- a/docs/platforms/javascript/common/tracing/configure-sampling/index.mdx +++ b/docs/platforms/javascript/common/tracing/configure-sampling/index.mdx @@ -10,16 +10,16 @@ Sentry's tracing functionality helps you monitor application performance by capt The JavaScript SDK provides two main options for controlling the sampling rate: -### Uniform Sample Rate (`tracesSampleRate`) -This option sets a fixed percentage of transactions to be captured: +1. Uniform Sample Rate (`tracesSampleRate`) +`tracesSampleRate` is floating point value 0.0 and 1.0, which controls the probability that a transaction will be sampled. -With `tracesSampleRate` set to `0.25`, approximately 25% of transactions will be recorded and sent to Sentry. This provides an even cross-section of transactions regardless of where in your app they occur. +With `tracesSampleRate` set to `0.25`, each transaction in your application is randomly sampled with a probability of 25%, so you can expect that one in every four transactions will be sent to Sentry. ### Sampling Function (`tracesSampler`) -For more granular control, you can use the `tracesSampler` function. This approach allows you to: +For more granular control, you provide a `tracesSampler` function. This approach allows you to: - Apply different sampling rates to different types of transactions - Filter out specific transactions entirely @@ -28,7 +28,30 @@ For more granular control, you can use the `tracesSampler` function. This approa -#### Trace Sampler Examples +### The Sampling Context Object + +When the `tracesSampler` function is called, it receives a `samplingContext` object with valuable information to help make sampling decisions: + +```typescript +interface SamplingContext { + // Name of the span/transaction + name: string; + + // Initial attributes of the span/transaction + attributes: SpanAttributes | undefined; + + // Whether the parent span was sampled (undefined if no incoming trace) + parentSampled: boolean | undefined; + + // Sample rate from incoming trace (undefined if no incoming trace) + parentSampleRate: number | undefined; + + // Utility function to inherit parent decision or fallback + inheritOrSampleWith: (fallbackRate: number) => number; +} +``` + +### Trace Sampler Examples 1. Prioritizing Critical User Flows @@ -98,98 +121,17 @@ tracesSampler: (samplingContext) => { } ``` -## The Sampling Context Object - -When the `tracesSampler` function is called, it receives a `samplingContext` object with valuable information to help make sampling decisions: - -```typescript -typescriptCopyinterface SamplingContext { - // Name of the span/transaction - name: string; - - // Initial attributes of the span/transaction - attributes: SpanAttributes | undefined; - - // Whether the parent span was sampled (undefined if no incoming trace) - parentSampled: boolean | undefined; - - // Sample rate from incoming trace (undefined if no incoming trace) - parentSampleRate: number | undefined; - - // Utility function to inherit parent decision or fallback - inheritOrSampleWith: (fallbackRate: number) => number; -} -``` - -The sampling context contains: - -- `name`: The name of the transaction/span -- `attributes`: Initial tags and attributes set on the transaction -- `parentSampled`: Whether the parent transaction was sampled (for distributed tracing) -- `parentSampleRate`: The sample rate used in the parent transaction -- `inheritOrSampleWith`: A utility function to handle inheritance logic (recommended) - -## Inheritance in Distributed Tracing - -In distributed systems, trace information is propagated between services. The inheritOrSampleWith function simplifies handling parent sampling decisions: - -```javascript -tracesSampler: (samplingContext) => { - const { name, inheritOrSampleWith } = samplingContext; - - // Apply specific rules first - if (name.includes('critical-path')) { - return 1.0; // Always sample - } - - // Otherwise inherit parent sampling decision or fall back to 0.1 - return inheritOrSampleWith(0.1); -} -``` -This approach ensures consistent sampling decisions across your entire distributed trace. All transactions in a given trace will share the same sampling decision, preventing broken or incomplete traces. - -**Note:** The `inheritOrSampleWith` helper was introduced in version 9 of the SDK. For earlier versions, you can implement similar logic manually using the `parentSampled` property. - ## Sampling Decision Precedence When multiple sampling mechanisms could apply, Sentry follows this order of precedence: -- If `tracesSampler` is defined, its decision is used (can consider parent sampling) -- If no `tracesSampler` but parent sampling is available, parent decision is used +- If `tracesSampler` is defined, its decision is used. Although the `tracesSampler` can override the parent sampling decision, most users will want to ensure their `tracesSampler` respects the parent sampling decision. +- If no `tracesSampler` is defined, but there is a parent sampling decision from an incoming distributed trace, we use the parent sampling decision - If neither of the above, `tracesSampleRate` is used -- If none of the above are set, no transactions are sampled (0%) - -## How Sampling Propagates in Distributed Traces - -Sentry uses a "head-based" sampling approach: - -- A sampling decision is made in the originating service (the "head") -- This decision is propagated to all downstream services via HTTP headers - -The two key headers are: -- `sentry-trace`: Contains trace ID, span ID, and sampling decision -- `baggage`: Contains additional trace metadata including sample rate - -Sentry automatically attaches these headers to outgoing HTTP requests when using the `browserTracingIntegration`. For other communication channels like WebSockets, you can manually propagate trace information: - -```javascript -// Extract trace data from the current scope -const traceData = Sentry.getTraceData(); -const sentryTraceHeader = traceData["sentry-trace"]; -const sentryBaggageHeader = traceData["baggage"]; - -// Add to your custom request (example using WebSocket) -webSocket.send(JSON.stringify({ - message: "Your data here", - metadata: { - sentryTrace: sentryTraceHeader, - baggage: sentryBaggageHeader - } -})); -``` +- If `tracesSampleRate` is set to 0, no spans will be sampled, and no downstream spans will be sampled either since they inherit the parent sampling decision +- If none of the above are set, no transactions are sampled and tracing will be disabled ## Conclusion Effective sampling is key to getting the most value from Sentry's performance monitoring while minimizing overhead. The `tracesSampler` function gives you precise control over which transactions to record, allowing you to focus on the most important parts of your application. -By implementing a thoughtful sampling strategy, you'll get the performance insights you need without overwhelming your systems or your Sentry quota. diff --git a/docs/platforms/javascript/common/tracing/distributed-tracing/index.mdx b/docs/platforms/javascript/common/tracing/distributed-tracing/index.mdx index 82094819b28b16..6e5d727febc5fa 100644 --- a/docs/platforms/javascript/common/tracing/distributed-tracing/index.mdx +++ b/docs/platforms/javascript/common/tracing/distributed-tracing/index.mdx @@ -60,3 +60,32 @@ Server-side SDKs handle traces automatically on a per-request basis. This means If necessary, you can override the default trace duration by [manually starting a new trace](./custom-instrumentation#starting-a-new-trace). + +## How Sampling Propagates in Distributed Traces + +Sentry uses a "head-based" sampling approach: + +- A sampling decision is made in the originating service (the "head") +- This decision is propagated to all downstream services + +The two key headers are: +- `sentry-trace`: Contains trace ID, span ID, and sampling decision +- `baggage`: Contains additional trace metadata including sample rate + +Sentry automatically attaches these headers to outgoing HTTP requests when using the `browserTracingIntegration`. For other communication channels like WebSockets, you can manually propagate trace information: + +```javascript +// Extract trace data from the current scope +const traceData = Sentry.getTraceData(); +const sentryTraceHeader = traceData["sentry-trace"]; +const sentryBaggageHeader = traceData["baggage"]; + +// Add to your custom request (example using WebSocket) +webSocket.send(JSON.stringify({ + message: "Your data here", + metadata: { + sentryTrace: sentryTraceHeader, + baggage: sentryBaggageHeader + } +})); +``` diff --git a/docs/platforms/javascript/common/tracing/instrumentation/index.mdx b/docs/platforms/javascript/common/tracing/instrumentation/index.mdx index a519703b57b4bc..f67319f7eae424 100644 --- a/docs/platforms/javascript/common/tracing/instrumentation/index.mdx +++ b/docs/platforms/javascript/common/tracing/instrumentation/index.mdx @@ -1,6 +1,6 @@ --- title: Instrumentation -description: "Learn how to configure spans to capture performance data on any action in your app." +description: "Learn how to configure spans to capture trace data on any action in your app." sidebar_order: 40 --- diff --git a/docs/platforms/javascript/common/tracing/span-metrics/examples.mdx b/docs/platforms/javascript/common/tracing/span-metrics/examples.mdx index 0ff0f16004ce29..ddbc956dcaf388 100644 --- a/docs/platforms/javascript/common/tracing/span-metrics/examples.mdx +++ b/docs/platforms/javascript/common/tracing/span-metrics/examples.mdx @@ -330,99 +330,3 @@ The frontend span tracks the user's checkout experience, while the backend span - Monitor inventory availability impact on conversions - Measure end-to-end order completion times - Identify friction points in the user experience - -## Job Scheduling and Processing Pipeline - -**Challenge:** Understanding performance and reliability of distributed job processing systems, from job creation through completion. - -**Solution:** Comprehensive tracking of job lifecycle across scheduling, queueing, and processing stages. - -**Frontend Instrumentation:** -```javascript -// Client-side job submission and monitoring -Sentry.startSpan( - { - name: 'Job Submission Flow', - op: 'job.client', - attributes: { - // Job configuration - 'job.type': 'video_transcoding', - 'job.priority': 'high', - 'job.estimated_duration_ms': 300000, - - // Input metrics - 'input.size_bytes': 52428800, // 50MB - 'input.format': 'mp4', - 'input.segments': 5, - - // Client-side scheduling - 'schedule.requested_start': '2024-03-15T10:00:00Z', - 'schedule.deadline': '2024-03-15T11:00:00Z', - - // Progress monitoring - 'monitor.polling_interval_ms': 5000, - 'monitor.status_updates_received': 12, - 'monitor.last_progress_percent': 45 - } - }, - async () => { - // Job submission and progress tracking implementation - } -); -``` - -**Backend Instrumentation:** -```javascript -// Server-side job processing -Sentry.startSpan( - { - name: 'Job Processing Pipeline', - op: 'job.server', - attributes: { - // Queue metrics - 'queue.name': 'video-processing', - 'queue.provider': 'redis', - 'queue.length_at_enqueue': 23, - 'queue.wait_time_ms': 45000, - - // Worker metrics - 'worker.id': 'worker-pod-123', - 'worker.current_load': 0.75, - 'worker.memory_usage_mb': 1024, - - // Processing stages - 'processing.stages_completed': ['download', 'transcode', 'thumbnail'], - 'processing.stage_durations_ms': { - 'download': 12000, - 'transcode': 180000, - 'thumbnail': 5000 - }, - - // Resource utilization - 'resource.cpu_percent': 85, - 'resource.gpu_utilization': 0.92, - 'resource.memory_peak_mb': 2048, - - // Job outcome - 'outcome.status': 'completed', - 'outcome.retry_count': 0, - 'outcome.output_size_bytes': 31457280 // 30MB - } - }, - async () => { - // Job processing implementation - } - ) -); -``` - -**How the Trace Works Together:** -The frontend span tracks job submission and monitoring, while the backend span captures queue management and processing details. The distributed trace provides visibility into the entire job lifecycle, enabling you to: - -- Monitor end-to-end job processing times and success rates -- Track queue health and worker resource utilization -- Identify bottlenecks in specific processing stages -- Analyze job scheduling efficiency and queue wait times -- Optimize resource allocation based on job characteristics - -For more information about implementing these examples effectively, see our Span Metrics guide which includes detailed best practices and implementation guidelines. diff --git a/docs/platforms/javascript/common/tracing/span-metrics/index.mdx b/docs/platforms/javascript/common/tracing/span-metrics/index.mdx index bc2c011b5f609a..f877c710eaaef5 100644 --- a/docs/platforms/javascript/common/tracing/span-metrics/index.mdx +++ b/docs/platforms/javascript/common/tracing/span-metrics/index.mdx @@ -41,11 +41,11 @@ When adding metrics as span attributes: - Use consistent naming conventions (for example, `category.metric_name`) - Keep attribute names concise but descriptive -- Use appropriate data types (string, number, boolean, or (non-mixed) arrays of these types) +- Use appropriate data types (string, number, boolean, or an array containing only one of these types) ## Creating Dedicated Metric Spans -For more detailed operations, task, or process tracking, you can create custom dedicated spans that focus on specific metrics or attributes that you want to track. This approach provides better discoverability and more precise span configurations, however it can also appear to create more noise in your trace waterfall. +For more detailed operations, tasks, or process tracking, you can create custom dedicated spans that focus on specific metrics or attributes that you want to track. This approach provides better discoverability and more precise span configurations, however it can also create more noise in your trace waterfall. ```javascript Sentry.startSpan(