diff --git a/docs/concepts/key-terms/tracing/distributed-tracing.mdx b/docs/concepts/key-terms/tracing/distributed-tracing.mdx index b0c386a502329..70194d202a337 100644 --- a/docs/concepts/key-terms/tracing/distributed-tracing.mdx +++ b/docs/concepts/key-terms/tracing/distributed-tracing.mdx @@ -1,6 +1,6 @@ --- title: Distributed Tracing -sidebar_order: 10 +sidebar_order: 20 description: With distributed tracing, you can track software performance and measure throughput & latency, while seeing the impact of errors across multiple systems. --- diff --git a/docs/product/tracing/img/Performance-page.png b/docs/concepts/key-terms/tracing/img/Performance-page.png similarity index 100% rename from docs/product/tracing/img/Performance-page.png rename to docs/concepts/key-terms/tracing/img/Performance-page.png diff --git a/docs/product/tracing/img/The-anatomy-of-a-trace.png b/docs/concepts/key-terms/tracing/img/The-anatomy-of-a-trace.png similarity index 100% rename from docs/product/tracing/img/The-anatomy-of-a-trace.png rename to docs/concepts/key-terms/tracing/img/The-anatomy-of-a-trace.png diff --git a/docs/product/tracing/img/Trace-view-page.png b/docs/concepts/key-terms/tracing/img/Trace-view-page.png similarity index 100% rename from docs/product/tracing/img/Trace-view-page.png rename to docs/concepts/key-terms/tracing/img/Trace-view-page.png diff --git a/docs/product/tracing/img/Traces-details-page.png b/docs/concepts/key-terms/tracing/img/Traces-details-page.png similarity index 100% rename from docs/product/tracing/img/Traces-details-page.png rename to docs/concepts/key-terms/tracing/img/Traces-details-page.png diff --git a/docs/product/tracing/img/Traces-page.png b/docs/concepts/key-terms/tracing/img/Traces-page.png similarity index 100% rename from docs/product/tracing/img/Traces-page.png rename to docs/concepts/key-terms/tracing/img/Traces-page.png diff --git a/docs/concepts/key-terms/tracing/index.mdx b/docs/concepts/key-terms/tracing/index.mdx index 379a55336585f..b0e1e6491f24c 100644 --- a/docs/concepts/key-terms/tracing/index.mdx +++ b/docs/concepts/key-terms/tracing/index.mdx @@ -4,11 +4,73 @@ sidebar_order: 70 description: "Learn more about the tracing features Sentry offers to help you track your software performance across multiple systems." --- -[Distributed tracing](/product/sentry-basics/tracing/distributed-tracing/) provides a connected view of related errors and transactions by capturing interactions among your software systems. With tracing, Sentry tracks your software performance and displays the impact of errors across multiple systems. Tracing issues back through services connects your front-end to your back-end. +## What's Tracing? -The [Trace View](/product/sentry-basics/tracing/trace-view/) allows you to drill down into the details of a single trace and traverse every transaction in that trace. This accelerates your ability to debug slow services, identify related errors, and root out other bottlenecks. +Tracing involves capturing the timing and flow of requests and operations as they happen in your application. This powerful debugging tool helps you identify which link in a sequence of events may be causing a problem, such as slow performance. -The [Trace Explorer](/product/explore/traces/) allows you to explore traces by querying [span properties](/concepts/search/searchable-properties/spans/). This helps you find relevant distributed traces that will give you more information to debug and optimize your code. +![An illustrated image of the anatomy of a trace, showing 8 span blocks cascading in a waterfall pattern.](./img/The-anatomy-of-a-trace.png) + +### What's Distributed Tracing? + +Distributed tracing provides a unified view of how a single request moves from the frontend to the backend and beyond. This is particularly useful in modern applications, which are often composed of multiple separate services working together. To get a distributed view of your application, instrument Sentry in both your frontend and your backend. + +With [distributed tracing](/concepts/key-terms/tracing/distributed-tracing/), you can identify performance bottlenecks that are affecting your application across different services and platforms. You can then use Sentry tools such as the [Trace Explorer](/product/explore/traces/) or [Trace View](/concepts/key-terms/tracing/trace-view/) page to dig deeper and find the root cause of the problem. Distributed tracing is particularly helpful for identifying problems that take place between multiple services that you can't debug using console logs, such as race conditions, [N+1 queries](/product/issues/issue-details/performance-issues/n-one-queries/), and [caching issues](/product/insights/caches/). + +### What's a Trace? + +A trace is a record of a series of connected events and operations coming from your application. Each trace has a string of globally unique characters called a trace ID that's passed between frontend and backend services. The trace ID connects all the actions that take place, starting from the moment a user performs an action on the frontend, all the way through to the actions this triggers across your application and services. Each trace is composed of multiple spans. + +### What's a Span? + +A span is a named, timed operation that represents a part of the application workflow. The data captured for each span provides granular insights into specific tasks, like API requests or database queries. Multiple spans are pieced together to create a trace, providing a comprehensive overview of how your application works. This makes it easier to troubleshoot and analyze performance issues. + +### What are Span Attributes and Metrics? + +Span attributes and metrics are key pieces of information that are captured for each span. Attributes are key-value pairs that provide additional context about the span, such as the name of the operation or the user ID. Metrics are numerical values that measure the performance of the span, such as the duration of the operation or the number of database queries. + +### What's a Transaction? + +In Sentry, a "transaction" is a specific unit that represents any event that your application sends to Sentry, like loading a web page or processing an API call. Each transaction is made up of one or more spans. Transactions have a unique transaction ID and include the associated child spans that capture the operation’s entire process from start to finish. + +## How to Use Tracing in Sentry + +If you instrument Sentry for a single part of your app (just the frontend for example), looking at a trace will provide useful context for debugging issues within that app or service. But to get the most out of tracing in Sentry, you'll need to instrument the frontend, the backend, and any services in-between with Sentry's SDK. Once this is done, there are several places where you can view and interact with tracing data: + +### Traces to Trace View + +You can view all the traces in your organization by going to the [Traces](https://sentry.io/orgredirect/organizations/:orgslug/traces/) page in Sentry. You'll see a chart and a list of traces letting you know how long each trace took to complete and the number of spans it contains. + +![A view of the Sentry Traces page showing traces and spans](./img/Traces-page.png) + +If you want more information, click on any trace ID. This will take you to the [Trace View](/concepts/key-terms/tracing/trace-view/) page, which provides a more detailed view of the trace and its spans. Here, you'll see a waterfall view of the spans in the trace, which will show you how much time each service and operation took to complete, and may give you an indicator of where a problem may originate. + +![A detailed view of the Senty Traces page showing an expaned trace and spans](./img/Trace-view-page.png) + +Alternatively, you can use the search bar to look for spans by name, project, or other criteria. You can also use the tags section to filter spans by specific tags. Learn more about the Sentry [Trace Explorer](/product/explore/traces/). + +![An illustrated image of the anatomy of a trace, showing 8 span blocks cascading in a waterfall pattern.](./img/Traces-details-page.png) + +### Performance to Trace View + +Depending on the size and volume of your app, you may have a lot of traces to sort through. The [Insights](https://sentry.io/orgredirect/organizations/:orgslug/insights/backend/) page in Sentry is a good place to get a high-level, aggregated view of your application's performance and focus in on the traces you care about. You'll see a list of transactions for specific pages, endpoints and parts of your application. Clicking on the transaction ID will take you to the Trace View page for that transaction. Learn more about using Sentry's [Insights](/product/insights/). + +![An overview of the Performance page in Sentry.](./img/Performance-page.png) + +## How Tracing Can Help You Debug + +Sentry’s tracing lets you follow each request across various services, databases, and functions. This makes it easier to find exactly when and where an error occurred or a performance bottleneck started. Below, you'll find some real-world scenarios where tracing saved the day. + +### Debug Slowdowns Across Your Integrations + +When debugging integrations or a microservice architecture, you'll likely run into issues where the root cause is tricky to discover, especially when it's a performance issue. At Sentry, we make sure to add spans whenever we’re working with external services, like Slack. Because of this, when our users started experiencing a 4-second delay in receiving Sentry alerts via Slack, we were able to go to the [Trace View](/concepts/key-terms/tracing/trace-view/) and quickly narrow down which task was causing the slowdown and deploy a fix quickly. Read more about the details of [debugging Sentry’s Slack Integration](https://blog.sentry.io/debugging-a-slack-integration-with-sentrys-trace-view/). + +### Improve Core Web Vitals + +While everyone is sharing Lighthouse scores, we all know that the true determination of healthy web vitals is when your actual users are using your application in their authentic environments. Sentry offers real insights and analysis of your application in the real world, and while tracing can be leveraged to reactively solve issues, you can also use it to proactively discover opportunities to improve your application performance. In fact, this blog post describes [how you can improve performance before your web page even loads](https://blog.sentry.io/how-to-make-your-web-page-faster-before-it-even-loads/). + +### Debug New Code Bases Faster + +Tracing can even give you the power to debug unfamiliar codebases. Although this benefit is not often discussed, a lot of time can be saved when debugging applications instrumented with Tracing, even if the codebase is completely new to you. Being able to trace actual user journeys throughout your application and see what happens across your entire stack contextualizes issues without even needing to recreate the issue locally. Read about other ways [tracing helps developers debug various issues](https://blog.sentry.io/everyone-needs-to-know-how-to-trace/). ## Learn More diff --git a/docs/concepts/key-terms/tracing/span-metrics.mdx b/docs/concepts/key-terms/tracing/span-metrics.mdx new file mode 100644 index 0000000000000..8b4ad8f63da5f --- /dev/null +++ b/docs/concepts/key-terms/tracing/span-metrics.mdx @@ -0,0 +1,293 @@ +--- +title: Span Metrics +description: "Learn how attaching attributes to spans provides enhanced application performance monitoring and improved debugging." +sidebar_order: 10 +--- + +Span metrics enable you to attach user defined attributes to spans, which might include application metrics or important debugging context within your application's traces. This approach provides context-rich performance monitoring by connecting attributes directly to the operations that generate them. + +These attributes allow you to enrich trace spans with attributes that represent various types of measurement data: + +- Performance attributes (memory usage, processing time, latency) +- Business metrics (transaction value, user engagement rates) +- Technical indicators (queue depth, cache hit ratios) +- Debugging context (input parameters, process states) + +By attaching attributes directly to spans, you create a unified view of both the execution path and its associated performance data. + +```javascript +// Adding performance metrics to a database span +// Simple database query with dynamic attributes +Sentry.startSpan( + { + name: 'Database Query', + op: 'db.query' + }, + () => { + // Get active span to set attributes as data becomes available + const span = Sentry.getActiveSpan(); + + // Execute query and add results to span + const result = executeQuery('SELECT * FROM users WHERE active = true'); + + // Set attributes with the results data + if (span) { + span.setAttribute('db.rows_returned', result.length); + span.setAttribute('db.execution_time_ms', result.executionTime); + } + + return result; + } +); +``` + +## Benefits of Configuring Span Attributes + +### Contextual Observability + +Span attributes provide contextual data that connects execution flow with specific metrics that developers care about, or performance measurements. When investigating an issue, you can view both what occurred (the trace) and the performance characteristics in a single view. + +### Unified Telemetry + +By integrating these attributes into tracing, you can maintain a single telemetry pipeline rather than managing separate systems for traces and metrics, resulting in simplified instrumentation and more efficient monitoring. + +```javascript +// Adding business context to a payment processing span +Sentry.startSpan( + { + name: 'Process Payment', + op: 'payment.process', + attributes: { + 'payment.amount': 99.99, + 'payment.currency': 'USD', + 'payment.method': 'credit_card', + 'customer.type': 'returning' + } + }, + async () => { + // Payment processing implementation + } +); +``` + +### Accelerated Troubleshooting + +When performance issues arise, these attributes provide the necessary context to quickly identify bottlenecks. For example, when investigating slow checkout processes, you can immediately see which specific component (payment gateway, database query, third-party API) is causing the delay. + +### Technical-Business Correlation + +Span attributes enable correlation between technical performance data and business outcomes by connecting metrics like response time or error rates directly to business metrics such as conversion rates or revenue. + +## Implementation Approaches + +There are two primary methods for implementing attributes on spans: + +### 1. Enhancing Existing Spans + +Augment automatically-created or manually-defined spans with additional attributes: + +```javascript +// Adding metrics to an existing file upload span +const span = Sentry.getActiveSpan(); +if (span) { + // User context + span.setAttribute('user.subscription_tier', 'premium'); + + // Multiple metrics in a single operation + span.setAttributes({ + 'memory.heap_used': 1024000, + 'processing.total_steps': 5 + }); +} +``` + +### 2. Creating Dedicated Metric Spans + +Create spans specifically for grouping related attributes or metrics, particularly useful for complex operations: + +```javascript +// Creating a span for monitoring external API usage +Sentry.startSpan( + { + name: 'Third-Party API Usage', + op: 'external.api', + attributes: { + // Performance metrics + 'api.response_time_ms': 245, + + // Context data + 'feature.using_api': 'image_recognition', + 'user.plan': 'enterprise' + } + }, + async () => { + // API call implementation + } +); +``` + +## Implementation Use Cases + +The following examples demonstrate how attributes can be applied to common application scenarios: + +### User Interface Performance + +Monitor client-side performance metrics related to user experience: + +```javascript +// UI performance monitoring +Sentry.startSpan( + { + name: 'Page Interaction', + op: 'ui.interaction', + attributes: { + 'ui.first_input_delay_ms': 24, + 'ui.time_to_interactive_ms': 320, + 'ui.frames_dropped': 0, + 'user.device_type': 'mobile', + 'feature.being_used': 'image_carousel' + } + }, + async () => { + // UI interaction handling + } +); +``` + +### Database Operation Monitoring + +Track database performance characteristics and their impact on application behavior: + +```javascript +// Database query monitoring +Sentry.startSpan( + { + name: 'Product Search Query', + op: 'db.query', + attributes: { + 'db.query_type': 'SELECT', + 'db.table': 'products', + 'db.execution_time_ms': 145, + 'db.rows_returned': 87, + 'db.index_used': 'product_category_idx', + 'business.search_term': 'winter jacket', + 'business.search_filters_applied': 3 + } + }, + async () => { + // Database query execution + } +); +``` + +### File Processing Operations + +Monitor file handling operations across your application stack: + +```javascript +// File processing monitoring +Sentry.startSpan( + { + name: 'Process Uploaded Image', + op: 'file.process', + attributes: { + // Technical metrics + 'file.size_bytes': 2500000, + 'file.type': 'image/jpeg', + + // Processing metrics + 'processing.steps_completed': ['virus_scan', 'resize', 'compress'], + 'processing.total_time_ms': 850, + + // Context data + 'feature.using_upload': 'user_avatar', + 'subscription.allows_hd': true + } + }, + async () => { + // Image processing implementation + } +); +``` + +### External Service Integration + +Monitor performance and reliability of third-party service interactions: + +```javascript +// Payment gateway monitoring +Sentry.startSpan( + { + name: 'Payment Gateway', + op: 'payment.gateway', + attributes: { + // Performance metrics + 'gateway.response_time_ms': 980, + 'gateway.retry_count': 0, + + // Transaction data + 'order.total_amount': 159.99, + 'order.items_count': 3, + + // Service metrics + 'gateway.fee_amount': 4.50, + 'gateway.fee_percent': 0.029 + } + }, + async () => { + // Payment gateway integration + } +); +``` + +## Implementation Guidelines + +### Best Practices + +#### Metric Selection and Design + +Select metrics that provide actionable insights for debugging or performance monitoring. Consider which data points would help diagnose issues or make informed decisions about your application. + +#### Naming Conventions + +Maintain consistent naming patterns following the format `category.metric_name` to ensure metrics are discoverable and understandable across your organization. + +#### Data Type Selection + +Choose appropriate data types for your metrics: +- Numeric values for measurements (`response_time_ms`: 250) +- Boolean values for state indicators (`cache.hit`: true) +- String values for categorical data (`user.subscription`: 'premium') +- Arrays for multi-value data (`processing.steps_completed`: ['download', 'process', 'upload']) + +#### Performance Considerations + +Be mindful of the performance impact of collecting metrics, especially for high-volume operations: +- Consider implementing sampling for high-frequency operations +- Prioritize metrics with the highest analytical value +- Avoid redundant or closely correlated metrics + +## Migrating from Standalone Metrics + +If you're currently using Sentry's standalone Metrics product, migrating to span attributes offers several advantages: + +- **Enhanced context**: Attributes are connected directly to the operations that generate them +- **Implementation efficiency**: A single consistent API for both traces and metrics +- **Improved correlation**: Direct association between attributes, traces, and errors + +Migration process: +1. Identify your current metric instrumentation points +2. Locate corresponding spans in your application +3. Transfer your metrics to span attributes +4. Update any dashboards or alerts to reference the new metric sources + +## Additional Resources + +For more detailed implementation examples, refer to these guides: + +- [E-Commerce use case](/platforms/javascript/tracing/span-metrics/examples/#e-commerce-transaction-flow) +- [LLM integration monitoring](/platforms/javascript/tracing/span-metrics/examples/#llm-integration-monitoring) +- [File upload and processing](/platforms/javascript/tracing/span-metrics/examples/#file-upload-and-processing-pipeline) +- [Job scheduling and processing](/platforms/javascript/tracing/span-metrics/examples/#job-scheduling-and-processing-pipeline) + +These examples demonstrate how to implement comprehensive attribute tracking across distributed systems, providing end-to-end visibility into application performance and behavior. diff --git a/docs/platforms/javascript/common/tracing/configure-sampling/index.mdx b/docs/platforms/javascript/common/tracing/configure-sampling/index.mdx new file mode 100644 index 0000000000000..80eacce971700 --- /dev/null +++ b/docs/platforms/javascript/common/tracing/configure-sampling/index.mdx @@ -0,0 +1,193 @@ +--- +title: Configure Sampling +description: "Learn how to configure sampling in your app." +sidebar_order: 30 +--- + +Sentry's tracing functionality helps you monitor application performance by capturing distributed traces, attaching attributes, and span performance across your application. However, Capturing traces for every transaction can generate significant volumes of data. Sampling allows you to control the amount of spans that are sent to Sentry from your application. + +## Sampling Configuration Options + +The JavaScript SDK provides two main options for controlling the sampling rate: + +1. Uniform Sample Rate (`tracesSampleRate`) +This option sets a fixed percentage of transactions to be captured: + + + +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. + +2. Sampling Function (`tracesSampler`) + +For more granular control, you can use the `tracesSampler` function. This approach allows you to: + +- Apply different sampling rates to different types of transactions +- Filter out specific transactions entirely +- Make sampling decisions based on transaction data +- Control the inheritance of sampling decisions in distributed traces + + + +### Trace Sampler Examples + +1. Prioritizing Critical User Flows + +```javascript +tracesSampler: (samplingContext) => { + const { name, attributes } = samplingContext; + + // Sample all checkout transactions + if (name.includes('/checkout') || attributes?.flow === 'checkout') { + return 1.0; + } + + // Sample 50% of login transactions + if (name.includes('/login') || attributes?.flow === 'login') { + return 0.5; + } + + // Sample 10% of everything else + return 0.1; +} +``` + +2. Handling Different Environments + +```javascript +tracesSampler: (samplingContext) => { + // Sample all transactions in development + if (process.env.NODE_ENV === 'development') { + return 1.0; + } + + // Sample 5% in production + if (process.env.NODE_ENV === 'production') { + return 0.05; + } + + // Sample 20% in staging + return 0.2; +} +``` + +3. Controlling Sampling Based on User or Transaction Properties + +```javascript +tracesSampler: (samplingContext) => { + const { attributes, inheritOrSampleWith } = samplingContext; + + // Always sample for premium users + if (attributes?.userTier === 'premium') { + return 1.0; + } + + // Sample more transactions for users experiencing errors + if (attributes?.hasRecentErrors === true) { + return 0.8; + } + + // Sample less for high-volume, low-value paths + if (attributes?.path?.includes('/api/metrics')) { + return 0.01; + } + + // Default sampling rate + return inheritOrSampleWith(0.2); +} +``` + +## 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 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 + } +})); +``` + +## 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. \ No newline at end of file diff --git a/docs/platforms/javascript/common/tracing/trace-propagation/custom-instrumentation/index.mdx b/docs/platforms/javascript/common/tracing/distributed-tracing/custom-instrumentation/index.mdx similarity index 100% rename from docs/platforms/javascript/common/tracing/trace-propagation/custom-instrumentation/index.mdx rename to docs/platforms/javascript/common/tracing/distributed-tracing/custom-instrumentation/index.mdx diff --git a/docs/platforms/javascript/common/tracing/trace-propagation/dealing-with-cors-issues/index.mdx b/docs/platforms/javascript/common/tracing/distributed-tracing/dealing-with-cors-issues/index.mdx similarity index 100% rename from docs/platforms/javascript/common/tracing/trace-propagation/dealing-with-cors-issues/index.mdx rename to docs/platforms/javascript/common/tracing/distributed-tracing/dealing-with-cors-issues/index.mdx diff --git a/docs/platforms/javascript/common/tracing/trace-propagation/index.mdx b/docs/platforms/javascript/common/tracing/distributed-tracing/index.mdx similarity index 92% rename from docs/platforms/javascript/common/tracing/trace-propagation/index.mdx rename to docs/platforms/javascript/common/tracing/distributed-tracing/index.mdx index 2003aaf5422c0..82094819b28b1 100644 --- a/docs/platforms/javascript/common/tracing/trace-propagation/index.mdx +++ b/docs/platforms/javascript/common/tracing/distributed-tracing/index.mdx @@ -1,15 +1,11 @@ --- -title: Trace Propagation +title: Set Up Distributed Tracing description: "Learn how to connect events across applications/services." -sidebar_order: 3000 +sidebar_order: 20 notSupported: - javascript.cordova --- -If the overall application landscape that you want to observe with Sentry consists of more than just a single service or application, distributed tracing can add a lot of value. - -## What is Distributed Tracing? - ## Basic Example @@ -25,8 +21,22 @@ What happens in the background is that Sentry uses reads and further propagates - `sentry-trace` - `baggage` + + If you run any JavaScript applications in your distributed system, make sure that those two headers are added to your CORS allowlist and won't be blocked or stripped by your proxy servers, gateways, or firewalls. + + +## How to Use Distributed Tracing? + + + + + +Remember that in order to propagate trace information through your whole distributed system, you have to use Sentry in all of the involved services and applications. Take a look at the respective SDK documentation to learn how distributed tracing can be enabled for each platform. + + + ## Trace Duration @@ -50,13 +60,3 @@ 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 to Use Distributed Tracing? - - - - - -Remember that in order to propagate trace information through your whole distributed system, you have to use Sentry in all of the involved services and applications. Take a look at the respective SDK documentation to learn how distributed tracing can be enabled for each platform. - - diff --git a/docs/platforms/javascript/common/tracing/index.mdx b/docs/platforms/javascript/common/tracing/index.mdx index a747d667c8f21..a2dc21aba13ee 100644 --- a/docs/platforms/javascript/common/tracing/index.mdx +++ b/docs/platforms/javascript/common/tracing/index.mdx @@ -4,11 +4,7 @@ description: "Learn how to enable tracing in your app." sidebar_order: 4000 --- -With [tracing](/product/insights/overview/), Sentry tracks your software performance, measuring metrics like throughput and latency, and displaying the impact of errors across multiple systems. Sentry captures distributed traces consisting of transactions and spans, which measure individual services and individual operations within those services. Learn more about our model in [Distributed Tracing](/product/sentry-basics/tracing/distributed-tracing/). - - - You can additionally set up Profiling to get even more detailed tracing information like stack traces and flame graphs. - +With [tracing](/product/insights/overview/), Sentry automatically tracks your software performance across your application services, measuring metrics like throughput and latency, and displaying the impact of errors across multiple systems. @@ -34,24 +30,27 @@ With [tracing](/product/insights/overview/), Sentry tracks your software perform ## Configure - First, enable tracing and configure the sampling rate for transactions. Set + Enable tracing by configuring the sampling rate for transactions. Set the sample rate for your transactions by either: - First, configure the sampling rate for transactions. Set the sample rate for - your transactions by either: + Enable tracing by setting the sample rate for your transactions. -- Setting a uniform sample rate for all transactions using the option in your SDK config to a number between `0` and `1`. (For example, to send 20% of transactions, set to `0.2`.) -- Controlling the sample rate based on the transaction itself and the context in which it's captured, by providing a function to the config option. + -The two options are meant to be mutually exclusive. If you set both, will take precedence. +- You can establish a uniform sample rate for all transactions by setting the option in your SDK config to a number between `0` and `1`. (For example, to send 20% of transactions, set to `0.2`.) +- For more granular control over sampling, you can set the sample rate based on the transaction itself and the context in which it's captured, by providing a function to the config option. - +The two options are mutually exclusive. If both are set, will take precedence. Learn more about tracing options, how to use the tracesSampler function, or how to sample transactions. +## Distributed Tracing + +Sentry captures distributed traces consisting of transactions and spans, which measure individual services and individual operations within those services, respectively. Learn more about our model in [Distributed Tracing](/product/sentry-basics/tracing/distributed-tracing/). + ## Verify @@ -74,7 +73,7 @@ If you leave your sample rate at `1.0`, a transaction will be sent every time a You can also manually start spans to instrument specific parts of your code. This is useful when you want to measure the performance of a specific operation or function. -See Custom Instrumentation to learn how to manually start spans. +See Sending Span Metrics to learn how to manually start spans. ## Next Steps diff --git a/docs/platforms/javascript/common/tracing/instrumentation/custom-instrumentation/caches-module.mdx b/docs/platforms/javascript/common/tracing/instrumentation/caches-module.mdx similarity index 100% rename from docs/platforms/javascript/common/tracing/instrumentation/custom-instrumentation/caches-module.mdx rename to docs/platforms/javascript/common/tracing/instrumentation/caches-module.mdx diff --git a/docs/platforms/javascript/common/tracing/instrumentation/custom-instrumentation/index.mdx b/docs/platforms/javascript/common/tracing/instrumentation/custom-instrumentation/index.mdx deleted file mode 100644 index afab97efc10a2..0000000000000 --- a/docs/platforms/javascript/common/tracing/instrumentation/custom-instrumentation/index.mdx +++ /dev/null @@ -1,284 +0,0 @@ ---- -title: Custom Span Instrumentation -description: "Learn how to capture performance data on any action in your app." -sidebar_order: 20 ---- - - - -To capture transactions and spans customized to your organization's needs, you must first set up tracing. - - - -To add custom performance data to your application, you need to add custom instrumentation in the form of spans. Spans are a way to measure the time it takes for a specific action to occur. For example, you can create a span to measure the time it takes for a function to execute. - -To get started, import the SDK. - - - -There are three key functions for creating spans: - -- [startSpan](#starting-an-active-span-startspan): Creates a new span that is active, and which is automatically ended. You'll likely want to use this function. -- [startSpanManual](#starting-an-active-span-with-manual-end-startspanmanual): Creates a new span that is active, which has to be ended manually. -- [startInactiveSpan](#starting-inactive-spans-startinactivespan): Creates a new span that is inactive, which has to be ended manually. - -## Active vs. Inactive Spans - -When a new span is started, it will automatically be started as a child of the currently active span, if there is one. This means that if a span is started as an **active span**, any spans that are created inside of the callback where the span is active will be children of that span. Additionally, errors will be tied to the currently active span, if there is one. - -In contrast, **inactive spans** will never have children automatically associated with them. This is useful if you do not care about capturing child activity. - -A key constraint for active spans is that they can only be made active inside of a callback. This constraint exists because otherwise it becomes impossible to associate spans with the correct parent span when working with asynchronous code. - -In places where you are not able to wrap executing code in a callback (e.g. when working with hooks or similar) you have to work with inactive spans, and can combine this with [withActiveSpan](#withactivespan) to manually associate child spans with the correct parent span. - - - -## Span Hierarchy in the Browser - -In browser environments, spans are by default collected in a flat hierarchy where every span is the direct child of the root span. You can opt into a more fine-grained hierarchy but there are trade-offs. - -The key reason for keeping a flat hierarchy is because in browsers it's impossible to reliably keep track of the active span across asynchronous boundaries. This means that if multiple asynchronous operations are started in parallel, it is not possible to determine which span is the parent of which child span. Imagine the following example: - -```javascript -Sentry.startSpan({ name: "span 1" }, async () => { - await fetch("https://example.com/1"); - await fetch("https://example.com/2"); - await fetch("https://example.com/3"); -}); - -Sentry.startSpan({ name: "span 2" }, async () => { - await fetch("https://example.com/4"); - await fetch("https://example.com/5"); - await fetch("https://example.com/6"); -}); -``` - -In the browser, there would be no way to know that `span 1` is only active inside of its callback, while `span 2` is active in the other callback. Because of this, in reality, _all_ fetch spans would become children of `span 2`. This is misleading and confusing, which is why by default in the browser, **all spans will become children of the root span** (which is usually the pageload or navigation span). This means that you will always have a flat hierarchy of spans. - -This is a tradeoff that we have made to ensure that the data that is captured is accurate and reliable. If you need to capture a more complex hierarchy of spans, you can opt-out of this behavior by setting `parentSpanIsAlwaysRootSpan: false`: - -```javascript -Sentry.init({ - parentSpanIsAlwaysRootSpan: false, -}); -``` - -This will revert to use the full hierarchy behavior, where spans are children of the currently active span. However, this may lead to incorrect data in the case of multiple parallel asynchronous operations - it is up to you to ensure there are no multiple parallel asynchronous operations that start spans in this case. - - - -## Span Starting Options - -The following options can be used for all span starting functions: - -| Option | Type | Description | -| ------------------ | --------------------------- | ---------------------------------------------------------------------------------------------------------------------- | -| `name` | `string` | The name of the span. | -| `op` | `string` | The operation of the span. | -| `startTime` | `number` | The start time of the span. | -| `attributes` | `Record` | Attributes to attach to the span. | -| `parentSpan` | `Span` | If set, make the span a child of the specified span. Otherwise, the span will be a child of the currently active span. | -| `onlyIfParent` | `boolean` | If true, ignore the span if there is no active parent span. | -| `forceTransaction` | `boolean` | If true, ensure this span shows up as transaction in the Sentry UI. | - -Only `name` is required, all other options are optional. - -## Starting an Active Span (`startSpan`) - -For most scenarios, we recommend to start active spans with `Sentry.startSpan()`. This will start a new span that is active in the provided callback, and will automatically end the span when the callback is done. The callback can be synchronous, or asynchronous (a promise). In the case of an asynchronous callback, the span will be ended when the promise is resolved or rejected. If the provided callback errors or rejects, the span will be marked as failed. - - - -## Starting an Active Span with Manual End (`startSpanManual`) - -Sometimes, you do not want the span to be ended automatically when the callback is done. In this case, you can use `Sentry.startSpanManual()`. This will start a new span that is active in the provided callback, but will not be automatically ended when the callback is done. You have to manually end the span by calling `span.end()`. - - - -## Starting Inactive Spans (`startInactiveSpan`) - -To add spans that aren't active, you can create independent spans. This is useful when you have work that is grouped together under a single parent span, but is independent from the currently active span. However, in most cases you'll want to create and use the [startSpan](#starting-an-active-span-startspan) API from above. - - - -## Starting Spans as Children of a Specific Span - -By default, any span that is started will be the child of the currently active span. If you want to have a different behavior, you can force spans to be the children of a specific span with the `parentSpan` option: - -```js -const parentSpan = Sentry.startInactiveSpan({ name: "Parent Span" }); -const childSpan = Sentry.startInactiveSpan({ name: "Child Span", parentSpan }); - -childSpan.end(); -parentSpan.end(); -``` - -This option is also available for `startSpan` and `startSpanManual`. - -## Utilities to work with Spans - -We expose some helpful utilities that can help you with custom instrumentation. - -### `getActiveSpan` - -Returns the currently active span. - -```javascript -const activeSpan = Sentry.getActiveSpan(); -``` - -### `getRootSpan` - -Returns the root span of a given span. If the span is already the root span, it will return the span itself. - -```javascript -const activeSpan = Sentry.getActiveSpan(); -const rootSpan = activeSpan ? Sentry.getRootSpan(activeSpan) : undefined; -``` - -### `withActiveSpan` - -This method allows you to make a span active for the duration of a callback. You can use this in combination with `startInactiveSpan` to manually associate child spans with the correct parent span: - -```javascript -const span = Sentry.startInactiveSpan({ name: "Parent Span" }); - -Sentry.withActiveSpan(span, () => { - // `span` is now active, any other spans will be children of it - Sentry.startSpan({ name: "Child Span" }, () => { - // Do something - }); -}); -``` - -You can also pass `null` to `withActiveSpan` to ensure a span will not have any parent: - -```javascript -Sentry.withActiveSpan(null, () => { - // This will not have a parent span, no matter what - Sentry.startSpan({ name: "Parent Span" }, () => { - // Do something - }); -}); -``` - -Alternatively you can also use the `parentSpan` option to achieve the same: - -```javascript -const span = Sentry.startInactiveSpan({ name: "Parent Span" }); -const childSpan = Sentry.startInactiveSpan({ - name: "Child Span", - parentSpan: span, -}); -``` - -### `suppressTracing` - -Suppress the creation of sampled spans for the duration of the callback. This is useful when you want to prevent certain spans from being captured. For example, if you do not want to create spans for a given fetch request, you can do: - -```javascript -Sentry.suppressTracing(() => { - fetch("https://example.com"); -}); -``` - - -### Distributed Tracing - -See Distributed Tracing for details on how to manually set up distributed tracing. - - - -## Improving Span Data - -### Adding Span Attributes - -You can capture span attributes along with your spans. Span attributes can be of type `string`, `number` or `boolean`, as well as (non-mixed) arrays of these types. You can specify attributes when starting a span: - -```javascript -Sentry.startSpan( - { - attributes: { - attr1: "value1", - attr2: 42, - attr3: true, - }, - }, - () => { - // Do something - } -); -``` - -Or you can also add attributes to an existing span: - -```javascript -const span = Sentry.getActiveSpan(); -if (span) { - span.setAttribute("attr1", "value1"); - // Or set multiple attributes at once: - span.setAttributes({ - attr2: 42, - attr3: true, - }); -} -``` - -### Adding attributes to all spans - -To add an attribute to all spans, use the `beforeSendTransaction` callback: - -```javascript -Sentry.init({ - // dsn, ... - beforeSendTransaction(event) { - - // set the attribute on the root span - event.contexts.trace.data = { - ...event.contexts.trace.data, - myAttribute: "myValue", - } - - // and on all child spans - event.spans.forEach(span => { - span.data = { - ...span.data, - myAttribute: "myValue", - } - }); - } -}); -``` - - - -### Adding Span Operations ("op") - -Spans can have an operation associated with them, which help activate Sentry identify additional context about the span. For example database related spans have the `db` span operation associated with them. The Sentry product offers additional controls, visualizations and filters for spans with known operations. - -Sentry maintains a [list of well known span operations](https://develop.sentry.dev/sdk/performance/span-operations/#list-of-operations) and it is recommended that you use one of those operations if it is applicable to your span. - - - -### Updating the Span Name - -_Available since: v8.47.0_ - -You can update the name of a span at any time: - -```javascript -const span = Sentry.getActiveSpan(); -if (span) { - Sentry.updateSpanName(span, "New Name"); -} -``` - -Prior to v8.39.0, you had to use `span.updateName('New Name')`, which had some limitations in `@sentry/node` and SDKs depending on it (for example, `@sentry/nextjs`): - -- Spans with `http.method` or `http.request.method` attributes would automatically have their name set to the method + the URL path. -- Spans with `db.system` attributes would automatically have their name set to the system + the statement. - -Using `Sentry.updateSpanName()` ensures that the name is updated correctly and no longer overwritten in these cases. - -If you use `@sentry/browser`, `@sentry/react`, and so on in browser environments, `span.updateName()` and `Sentry.updateSpanName()` will function identically, so you can use either one of them. diff --git a/docs/platforms/javascript/common/tracing/instrumentation/index.mdx b/docs/platforms/javascript/common/tracing/instrumentation/index.mdx index eaac9e016be4c..a519703b57b4b 100644 --- a/docs/platforms/javascript/common/tracing/instrumentation/index.mdx +++ b/docs/platforms/javascript/common/tracing/instrumentation/index.mdx @@ -1,7 +1,284 @@ --- title: Instrumentation -description: "Learn how to instrument tracing in your app." -sidebar_order: 20 +description: "Learn how to configure spans to capture performance data on any action in your app." +sidebar_order: 40 --- - + + +To capture transactions and spans customized to your organization's needs, you must first set up tracing. + + + +To add custom performance data to your application, you need to add custom instrumentation in the form of spans. Spans are a way to measure the time it takes for a specific action to occur. For example, you can create a span to measure the time it takes for a function to execute. + +To get started, import the SDK. + + + +There are three key functions for creating spans: + +- [startSpan](#starting-an-active-span-startspan): Creates a new span that is active, and which will end automatically. You'll likely want to use this function. +- [startSpanManual](#starting-an-active-span-with-manual-end-startspanmanual): Creates a new span that is active, which has to be ended manually. +- [startInactiveSpan](#starting-inactive-spans-startinactivespan): Creates a new span that is inactive, which has to be ended manually. + +## Active vs. Inactive Spans + +When a new span is started, it will automatically be started as a child of the currently active span, if there is one. This means that if a span is started as an **active span**, any spans that are created inside of the callback where the span is active will be children of that span. Additionally, errors will be tied to the currently active span, if there is one. + +In contrast, **inactive spans** will never have children automatically associated with them. This is useful if you do not care about capturing child activity. + +A key constraint for active spans is that they can only be made active inside of a callback. This constraint exists because otherwise it becomes impossible to associate spans with the correct parent span when working with asynchronous code. + +In places where you are not able to execute your code in a callback (for example, when working with hooks or similar) you have to work with inactive spans, and can combine this with [withActiveSpan](#withactivespan) to manually associate child spans with the correct parent span. + + + +## Span Hierarchy in the Browser + +In browser environments, spans are by default collected in a flat hierarchy where every span is the direct child of the root span (the initial operation that kicks off the entire trace.). You can opt into a more fine-grained hierarchy but there are trade-offs. + +The key reason for keeping a flat hierarchy is because in browsers it's impossible to reliably keep track of the active span across asynchronous boundaries. This means that if multiple asynchronous operations are started in parallel, it is not possible to determine which span is the parent of which child span. Imagine the following example: + +```javascript +Sentry.startSpan({ name: "span 1" }, async () => { + await fetch("https://example.com/1"); + await fetch("https://example.com/2"); + await fetch("https://example.com/3"); +}); + +Sentry.startSpan({ name: "span 2" }, async () => { + await fetch("https://example.com/4"); + await fetch("https://example.com/5"); + await fetch("https://example.com/6"); +}); +``` + +In the browser, there would be no way to know that `span 1` is only active inside of its callback, while `span 2` is active in the other callback. Because of this, in reality, _all_ fetch spans would become children of `span 2`. This is misleading and confusing, which is why by default in the browser, **all spans will become children of the root span** (which is usually the pageload or navigation span). This means that you will always have a flat hierarchy of spans. + +This is a tradeoff that we have made to ensure that the data that is captured is accurate and reliable. If you need to capture a more complex hierarchy of spans, you can opt-out of this behavior by setting `parentSpanIsAlwaysRootSpan: false`: + +```javascript +Sentry.init({ + parentSpanIsAlwaysRootSpan: false, +}); +``` + +This will revert to use the full hierarchy behavior, where spans are children of the currently active span. However, this may lead to incorrect data in the case of multiple parallel asynchronous operations - it is up to you to ensure there are no multiple parallel asynchronous operations that start spans in this case. + + + +## Span Starting Options + +The following options can be used for all span starting functions: + +| Option | Type | Description | +| ------------------ | --------------------------- | ---------------------------------------------------------------------------------------------------------------------- | +| `name` | `string` | The name of the span. | +| `op` | `string` | The operation of the span. | +| `startTime` | `number` | The start time of the span. | +| `attributes` | `Record` | Attributes to attach to the span. | +| `parentSpan` | `Span` | If set, make the span a child of the specified span. Otherwise, the span will be a child of the currently active span. | +| `onlyIfParent` | `boolean` | If true, ignore the span if there is no active parent span. | +| `forceTransaction` | `boolean` | If true, ensure this span shows up as transaction in the Sentry UI. | + +Only `name` is required, all other options are optional. + +## Starting an Active Span (`startSpan`) + +For most scenarios, we recommend to start active spans with `Sentry.startSpan()`. This will start a new span that is active in the provided callback, and will automatically end the span when the callback is done. The callback can be synchronous or asynchronous (a promise). In the case of an asynchronous callback, the span will be ended when the promise is resolved or rejected. If the provided callback throws an error or rejects a promise, the span will be marked as failed. + + + +## Starting an Active Span with Manual End (`startSpanManual`) + +Sometimes, you do not want the span to be ended automatically when the callback is done. In this case, you can use `Sentry.startSpanManual()`. This will start a new span that is active in the provided callback, but will not be automatically ended when the callback is done. You have to manually end the span by calling `span.end()`. + + + +## Starting Inactive Spans (`startInactiveSpan`) + +To add spans that aren't active, you can create independent spans. This is useful when you have work that is grouped together under a single parent span, but is independent from the currently active span. However, in most cases you'll want to create and use the [startSpan](#starting-an-active-span-startspan) API from above. + + + +## Starting Spans as Children of a Specific Span + +By default, any span that is started will be the child of the currently active span. If you want to have a different behavior, you can force spans to be the children of a specific span with the `parentSpan` option: + +```js +const parentSpan = Sentry.startInactiveSpan({ name: "Parent Span" }); +const childSpan = Sentry.startInactiveSpan({ name: "Child Span", parentSpan }); + +childSpan.end(); +parentSpan.end(); +``` + +This option is also available for `startSpan` and `startSpanManual`. + +## Utilities To Work With Spans + +We expose some helpful utilities that can help you with custom instrumentation. + +### `getActiveSpan` + +Returns the currently active span. + +```javascript +const activeSpan = Sentry.getActiveSpan(); +``` + +### `getRootSpan` + +Returns the root span of a given span. If the span is already the root span, it will return the span itself. + +```javascript +const activeSpan = Sentry.getActiveSpan(); +const rootSpan = activeSpan ? Sentry.getRootSpan(activeSpan) : undefined; +``` + +### `withActiveSpan` + +This method allows you to make a span active for the duration of a callback. You can use this in combination with `startInactiveSpan` to manually associate child spans with the correct parent span: + +```javascript +const span = Sentry.startInactiveSpan({ name: "Parent Span" }); + +Sentry.withActiveSpan(span, () => { + // `span` is now active, any other spans will be children of it + Sentry.startSpan({ name: "Child Span" }, () => { + // Do something + }); +}); +``` + +You can also pass `null` to `withActiveSpan` to ensure a span will not have any parent: + +```javascript +Sentry.withActiveSpan(null, () => { + // This will not have a parent span, no matter what + Sentry.startSpan({ name: "Parent Span" }, () => { + // Do something + }); +}); +``` + +Alternatively you can also use the `parentSpan` option to achieve the same: + +```javascript +const span = Sentry.startInactiveSpan({ name: "Parent Span" }); +const childSpan = Sentry.startInactiveSpan({ + name: "Child Span", + parentSpan: span, +}); +``` + +### `suppressTracing` + +Suppresses the creation of sampled spans for the duration of the callback. This is useful when you want to prevent certain spans from being captured. For example, if you do not want to create spans for a given fetch request, you can do: + +```javascript +Sentry.suppressTracing(() => { + fetch("https://example.com"); +}); +``` + + +### Distributed Tracing + +See Distributed Tracing for details on how to manually set up distributed tracing. + + + +## Improving Span Data + +### Adding Span Attributes + +You can capture span attributes along with your spans. Span attributes can be of type `string`, `number` or `boolean`, as well as (non-mixed) arrays of these types. You can specify attributes when starting a span: + +```javascript +Sentry.startSpan( + { + attributes: { + attr1: "value1", + attr2: 42, + attr3: true, + }, + }, + () => { + // Do something + } +); +``` + +Or you can also add attributes to an existing span: + +```javascript +const span = Sentry.getActiveSpan(); +if (span) { + span.setAttribute("attr1", "value1"); + // Or set multiple attributes at once: + span.setAttributes({ + attr2: 42, + attr3: true, + }); +} +``` + +### Adding attributes to all spans + +To add an attribute to all spans, use the `beforeSendTransaction` callback: + +```javascript +Sentry.init({ + // dsn, ... + beforeSendTransaction(event) { + + // set the attribute on the root span + event.contexts.trace.data = { + ...event.contexts.trace.data, + myAttribute: "myValue", + } + + // and on all child spans + event.spans.forEach(span => { + span.data = { + ...span.data, + myAttribute: "myValue", + } + }); + } +}); +``` + + + +### Adding Span Operations ("op") + +Spans can have an operation associated with them, which help Sentry identify additional context about the span. For example, database related spans have the `db` span operation associated with them. The Sentry product offers additional controls, visualizations, and filters for spans with known operations. + +Sentry maintains a [list of well-known span operations](https://develop.sentry.dev/sdk/performance/span-operations/#list-of-operations) and it is recommended that you use one of those operations if it is applicable to your span. + + + +### Updating the Span Name + +_Available since: v8.47.0_ + +You can update the name of a span at any time: + +```javascript +const span = Sentry.getActiveSpan(); +if (span) { + Sentry.updateSpanName(span, "New Name"); +} +``` + +Prior to v8.39.0, you had to use `span.updateName('New Name')`, which had some limitations in `@sentry/node` and SDKs depending on it (for example, `@sentry/nextjs`): + +- Spans with `http.method` or `http.request.method` attributes would automatically have their name set to the method + the URL path. +- Spans with `db.system` attributes would automatically have their name set to the system + the statement. + +Using `Sentry.updateSpanName()` ensures that the name is updated correctly and no longer overwritten in these cases. + +If you use `@sentry/browser`, `@sentry/react`, and so on in browser environments, `span.updateName()` and `Sentry.updateSpanName()` will function identically, so you can use either one of them. diff --git a/docs/platforms/javascript/common/tracing/instrumentation/custom-instrumentation/queues-module.mdx b/docs/platforms/javascript/common/tracing/instrumentation/queues-module.mdx similarity index 100% rename from docs/platforms/javascript/common/tracing/instrumentation/custom-instrumentation/queues-module.mdx rename to docs/platforms/javascript/common/tracing/instrumentation/queues-module.mdx diff --git a/docs/platforms/javascript/common/tracing/instrumentation/custom-instrumentation/requests-module.mdx b/docs/platforms/javascript/common/tracing/instrumentation/requests-module.mdx similarity index 100% rename from docs/platforms/javascript/common/tracing/instrumentation/custom-instrumentation/requests-module.mdx rename to docs/platforms/javascript/common/tracing/instrumentation/requests-module.mdx diff --git a/docs/platforms/javascript/common/tracing/span-metrics/examples.mdx b/docs/platforms/javascript/common/tracing/span-metrics/examples.mdx new file mode 100644 index 0000000000000..0ff0f16004ce2 --- /dev/null +++ b/docs/platforms/javascript/common/tracing/span-metrics/examples.mdx @@ -0,0 +1,428 @@ +--- +title: Example Instrumentation +description: "Examples of using span metrics to debug performance issues and monitor application behavior across frontend and backend services." +sidebar_order: 10 +--- + + + +These examples assume you have already set up tracing in your application. + + + +This guide provides practical examples of using span attributes and metrics to solve common monitoring and debugging challenges across your entire application stack. Each example demonstrates how to instrument both frontend and backend components, showing how they work together within a distributed trace to provide end-to-end visibility. + +## File Upload and Processing Pipeline + +**Challenge:** Understanding bottlenecks and failures in multi-step file processing operations across client and server components. + +**Solution:** Track the entire file processing pipeline with detailed metrics at each stage, from client-side upload preparation through server-side processing. + +**Frontend Instrumentation:** +```javascript +// Client-side file upload handling +Sentry.startSpan( + { + name: 'Client File Upload', + op: 'file.upload.client', + attributes: { + // Static details available at the start + 'file.size_bytes': 15728640, // 15MB + 'file.type': 'image/jpeg', + 'file.name': 'user-profile.jpg', + 'client.compression_applied': true + } + }, + async () => { + // Get the current active span to update during upload + const span = Sentry.getActiveSpan(); + + try { + // Begin upload process + const uploader = new FileUploader(file); + + // Update progress as upload proceeds + uploader.on('progress', (progressEvent) => { + if (span) { + span.setAttribute('upload.percent_complete', progressEvent.percent); + span.setAttribute('upload.bytes_transferred', progressEvent.loaded); + } + }); + + uploader.on('retry', (retryCount) => { + if (span) { + span.setAttribute('upload.retry_count', retryCount); + } + }); + + const result = await uploader.start(); + + // Set final attributes after completion + if (span) { + span.setAttribute('upload.total_time_ms', result.totalTime); + span.setAttribute('upload.success', true); + span.setAttribute('upload.server_file_id', result.fileId); + } + + return result; + } catch (error) { + // Record failure information + if (span) { + span.setAttribute('upload.success', false); + span.setAttribute('upload.error_type', error.name); + span.setAttribute('upload.error_message', error.message); + span.setStatus({ code: 'ERROR' }); + } + throw error; + } + } +); +``` + +**Backend Instrumentation:** +```javascript +// Server-side processing +Sentry.startSpan( + { + name: 'Server File Processing', + op: 'file.process.server', + attributes: { + // Server processing steps + 'processing.steps_completed': ['virus_scan', 'resize', 'compress', 'metadata'], + + // Storage operations + 'storage.provider': 's3', + 'storage.region': 'us-west-2', + 'storage.upload_time_ms': 850, + + // CDN configuration + 'cdn.provider': 'cloudfront', + 'cdn.propagation_ms': 1500 + } + }, + async () => { + // Server-side processing implementation + } +); +``` + +**How the Trace Works Together:** +The frontend span initiates the trace and handles the file upload process. It propagates the trace context to the backend through the upload request headers. The backend span continues the trace, processing the file and storing it. This creates a complete picture of the file's journey from client to CDN, allowing you to: + +- Identify bottlenecks at any stage (client prep, upload, server processing, CDN propagation) +- Track end-to-end processing times and success rates +- Monitor resource usage across the stack +- Correlate client-side upload issues with server-side processing errors + +## LLM Integration Monitoring + +**Challenge:** Managing cost (token usage) and performance of LLM integrations across frontend and backend coponents. + +**Solution:** Tracking of the entire LLM interaction flow, from user input to response rendering. + +**Frontend Instrumentation:** +```javascript +// Client-side LLM interaction handling +Sentry.startSpan( + { + name: 'LLM Client Interaction', + op: 'ai.client', + attributes: { + // Initial metrics available at request time + 'input.char_count': 280, + 'input.language': 'en', + 'input.type': 'question' + } + }, + async () => { + const span = Sentry.getActiveSpan(); + const startTime = performance.now(); + + // Begin streaming response from LLM API + const stream = await llmClient.createCompletion({ + prompt: userInput, + stream: true + }); + + // Record time to first token when received + let firstTokenReceived = false; + let tokensReceived = 0; + + for await (const chunk of stream) { + tokensReceived++; + + // Record time to first token + if (!firstTokenReceived && chunk.content) { + firstTokenReceived = true; + const timeToFirstToken = performance.now() - startTime; + + if (span) { + span.setAttribute('ui.time_to_first_token_ms', timeToFirstToken); + } + } + + // Process and render the chunk + renderChunkToUI(chunk); + } + + // Record final metrics after stream completes + const totalRequestTime = performance.now() - startTime; + + if (span) { + span.setAttribute('ui.total_request_time_ms', totalRequestTime); + span.setAttribute('stream.rendering_mode', 'markdown'); + span.setAttribute('stream.tokens_received', tokensReceived); + } + } +); +``` + +**Backend Instrumentation:** +```javascript +// Server-side LLM processing +Sentry.startSpan( + { + name: 'LLM API Processing', + op: 'ai.server', + attributes: { + // Model configuration - known at start + 'llm.model': 'claude-3-5-sonnet-20241022', + 'llm.temperature': 0.5, + 'llm.max_tokens': 4096 + } + }, + async () => { + const span = Sentry.getActiveSpan(); + const startTime = Date.now(); + + try { + // Check rate limits before processing + const rateLimits = await getRateLimits(); + if (span) { + span.setAttribute('llm.rate_limit_remaining', rateLimits.remaining); + } + + // Make the actual API call to the LLM provider + const response = await llmProvider.generateCompletion({ + model: 'claude-3-5-sonnet-20241022', + prompt: preparedPrompt, + temperature: 0.5, + max_tokens: 4096 + }); + + // Record token usage and performance metrics + if (span) { + span.setAttribute('llm.prompt_tokens', response.usage.prompt_tokens); + span.setAttribute('llm.completion_tokens', response.usage.completion_tokens); + span.setAttribute('llm.total_tokens', response.usage.total_tokens); + span.setAttribute('llm.api_latency_ms', Date.now() - startTime); + + // Calculate and record cost based on token usage + const cost = calculateCost( + response.usage.prompt_tokens, + response.usage.completion_tokens, + 'claude-3-5-sonnet-20241022' + ); + span.setAttribute('llm.cost_usd', cost); + } + + return response; + } catch (error) { + // Record error details + if (span) { + span.setAttribute('error', true); + span.setAttribute('error.type', error.name); + span.setAttribute('error.message', error.message); + span.setAttribute('error.is_rate_limit', error.code === 'rate_limit_exceeded'); + span.setStatus({ code: 'ERROR' }); + } + throw error; + } + } +); +``` + +**How the Trace Works Together:** +The frontend span captures the user interaction and UI rendering performance, while the backend span tracks the actual LLM API interaction. The distributed trace shows the complete flow from user input to rendered response, enabling you to: + +- Analyze end-to-end response times and user experience +- Track costs and token usage patterns +- Optimize streaming performance and UI rendering +- Monitor rate limits and queue times +- Correlate user inputs with model performance + +## E-Commerce Transaction Flow + +**Challenge:** Understanding the complete purchase flow and identifying revenue-impacting issues across the entire stack. + +**Solution:** Track the full checkout process from cart interaction to order fulfillment. + +**Frontend Instrumentation:** +```javascript +// Client-side checkout process +Sentry.startSpan( + { + name: 'Checkout UI Flow', + op: 'commerce.checkout.client', + attributes: { + // Cart interaction metrics + 'cart.items_added': 3, + 'cart.items_removed': 0, + 'cart.update_count': 2, + + // User interaction tracking + 'ui.form_completion_time_ms': 45000, + 'ui.payment_method_changes': 1, + 'ui.address_validation_retries': 0, + + // Client performance + 'client.page_load_time_ms': 850, + 'client.payment_widget_load_ms': 650, + 'client.total_interaction_time_ms': 120000 + } + }, + async () => { + // Client-side checkout implementation + } +); +``` + +**Backend Instrumentation:** +```javascript +// Server-side order processing +Sentry.startSpan( + { + name: 'Order Processing', + op: 'commerce.order.server', + attributes: { + // Order details + 'order.id': 'ord_123456789', + 'order.total_amount': 159.99, + 'order.currency': 'USD', + 'order.items': ['SKU123', 'SKU456', 'SKU789'], + + // Payment processing + 'payment.provider': 'stripe', + 'payment.method': 'credit_card', + 'payment.processing_time_ms': 1200, + + // Inventory checks + 'inventory.check_time_ms': 150, + 'inventory.all_available': true, + + // Fulfillment + 'fulfillment.warehouse': 'WEST-01', + 'fulfillment.shipping_method': 'express', + 'fulfillment.estimated_delivery': '2024-03-20' + } + }, + async () => { + // Server-side order processing + } +); +``` + +**How the Trace Works Together:** +The frontend span tracks the user's checkout experience, while the backend span handles order processing and fulfillment. The distributed trace provides visibility into the entire purchase flow, allowing you to: + +- Analyze checkout funnel performance and drop-off points +- Track payment processing success rates and timing +- 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 new file mode 100644 index 0000000000000..bc2c011b5f609 --- /dev/null +++ b/docs/platforms/javascript/common/tracing/span-metrics/index.mdx @@ -0,0 +1,140 @@ +--- +title: Sending Span Metrics +description: "Learn how to add attributes to spans to monitor performance and debug applications " +sidebar_order: 10 +--- + + + +To use span metrics, you must first configure tracing in your application. + + + +Span metrics allow you to extend the default metrics that are collected by tracing and track custom performance data and debugging information within your application's traces. There are two main approaches to instrumenting metrics: + +1. [Adding metrics to existing spans](#adding-metrics-to-existing-spans) +2. [Creating dedicated spans with custom metrics](#creating-dedicated-metric-spans) + +## Adding Metrics to Existing Spans + +You can enhance existing spans with custom metrics by adding attributes. This is useful when you want to augment automatic instrumentation or add contextual data to spans you've already created. + +```javascript +const span = Sentry.getActiveSpan(); +if (span) { + // Add individual metrics + span.setAttribute('database.rows_affected', 42); + span.setAttribute('cache.hit_rate', 0.85); + + // Add multiple metrics at once + span.setAttributes({ + 'memory.heap_used': 1024000, + 'queue.length': 15, + 'processing.duration_ms': 127 + }); +} +``` + +### Best Practices for Span Attributes + +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) + +## 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. + +```javascript +Sentry.startSpan( + { + name: 'Database Query Metrics', + op: 'db.metrics', + attributes: { + 'db.query_type': 'SELECT', + 'db.table': 'users', + 'db.execution_time_ms': 45, + 'db.rows_returned': 100, + 'db.connection_pool_size': 5 + } + }, + () => { + // Your database operation here + } +); +``` + +For detailed examples of how to implement span metrics in common scenarios, see our Span Metrics Examples guide. + +## Adding Metrics to All Spans + +To consistently add metrics across all spans in your application, you can use the `beforeSendTransaction` callback: + +```javascript +Sentry.init({ + beforeSendTransaction(event) { + // Add metrics to the root span + event.contexts.trace.data = { + ...event.contexts.trace.data, + 'app.version': '1.2.3', + 'environment.region': 'us-west-2' + }; + + // Add metrics to all child spans + event.spans.forEach(span => { + span.data = { + ...span.data, + 'app.component_version': '2.0.0', + 'app.deployment_stage': 'production' + }; + }); + + return event; + } +}); +``` + +## Best Practices for Span Metrics + +1. **Metric Naming** + - Use clear, consistent naming patterns + - Include the metric category (examples: `db`, `cache`, `http`) + - Use snake_case for metric names + +2. **Data Types** + - Use appropriate numeric types for measurements + - Use booleans for status flags + - Use strings for categorical data + - Use arrays when grouping related values + +3. **Performance Considerations** + - Consider the overhead of metric collection + - Use sampling when collecting high-frequency metrics + - Balance metric granularity with system performance + +4. **Debugging and Monitoring** + - Include correlation IDs for related operations + - Add context that helps with troubleshooting + +## Best Practices for Implementation + +When implementing span metrics in your application: + +1. **Start Small and Iterate** + - Begin with basic metrics that directly relate to your debugging or performance monitoring needs + - Add more detailed tracking as specific debugging needs emerge + - Remove metrics that aren't providing actionable insights + +2. **Maintain Consistency** + - Use consistent naming patterns across your application + - Document metric meanings and units in your codebase + - Share common metrics across similar operations + +3. **Focus on Actionability** + - Track metrics that help diagnose specific issues + - Consider what alerts or dashboard visualizations you'll want to create + - Ensure metrics can drive issue resolution or decision making + +For detailed examples of how to implement span metrics in common scenarios, see our Span Metrics Examples guide. \ No newline at end of file diff --git a/docs/platforms/javascript/common/tracing/instrumentation/performance-metrics.mdx b/docs/platforms/javascript/common/tracing/span-metrics/performance-metrics.mdx similarity index 98% rename from docs/platforms/javascript/common/tracing/instrumentation/performance-metrics.mdx rename to docs/platforms/javascript/common/tracing/span-metrics/performance-metrics.mdx index 6b1a9ff117f9d..a539f5d0bf12a 100644 --- a/docs/platforms/javascript/common/tracing/instrumentation/performance-metrics.mdx +++ b/docs/platforms/javascript/common/tracing/span-metrics/performance-metrics.mdx @@ -1,5 +1,5 @@ --- -title: Performance Metrics +title: Sending Performance Metrics description: "Learn how to attach performance metrics to your transactions." sidebar_order: 20 notSupported: diff --git a/docs/product/tracing/index.mdx b/docs/product/tracing/index.mdx deleted file mode 100644 index 7c26744345724..0000000000000 --- a/docs/product/tracing/index.mdx +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: Tracing -sidebar_order: 20 -description: "Learn how instrumenting tracing for both your frontend and backend can help identify and debug application performance issues. Distributed tracing will allow you to see the impact of errors across your full stack and microservices." ---- - -## What's Tracing? - -Tracing is the process of capturing the timing and flow of requests and operations as they happen in your application. It's a powerful debugging tool, helping you identify which link in a sequence of events may be causing a problem, such as slow performance. - -![An illustrated image of the anatomy of a trace, showing 8 span blocks cascading in a waterfall pattern.](./img/The-anatomy-of-a-trace.png) - -### What's Distributed Tracing? - -Distributed tracing provides a unified view of how a single request moves from the frontend to the backend and beyond. This is particularly useful in modern applications, which are often composed of multiple separate services working together. To get a distributed view of your application, instrument Sentry in both your frontend and your backend. - -With distributed tracing, you can identify performance bottlenecks that are affecting your application no matter where in your application's workflow they occur. You can then use Sentry tools such as the [Trace Explorer](/product/explore/traces/) or [Trace View](/concepts/key-terms/tracing/trace-view/) page to dig deeper and find the root cause of the problem. Distributed tracing is particularly helpful for identifying problems in production that you can't debug using console logs, such as race conditions, [N+1 queries](/product/issues/issue-details/performance-issues/n-one-queries/), and [caching issues](/product/insights/caches/). - -### What's a Trace? - -A trace is a record of a series of connected events and operations coming from your application. Each trace has a string of globally unique characters called a trace ID that's passed between frontend and backend services. The trace ID connects all the actions that take place, starting from the moment a user performs an action on the frontend, all the way through to the actions this triggers across your application and services. Each trace is composed of multiple spans. - -### What's a Span? -A span is a named, timed operation that represents a part of the application workflow. The data captured for each span provides granular insights into specific tasks, like API requests or database queries. Multiple spans are pieced together to create a trace, providing a comprehensive overview of how your application works. This makes it easier to troubleshoot and analyze performance issues. - -### What's a Transaction? - -In Sentry, a "transaction" is a specific unit that represents any event that your application sends to Sentry, like loading a web page or processing an API call. Each transaction is made up of one or more spans. Transactions have a unique transaction ID and include the associated child spans that capture the operation’s entire process from start to finish. - -## How to Use Tracing in Sentry - -If you instrument Sentry for a single part of your app (just the frontend for example), looking at a trace will provide useful context for debugging issues within that app or service. But to get the most out of tracing in Sentry, you'll need to instrument the frontend, the backend, and any services in-between with Sentry's SDK. Once this is done, there are several places where you can view and interact with tracing data: - -### Traces to Trace View - -You can view all the traces in your organization by going to the [Traces](https://sentry.io/orgredirect/organizations/:orgslug/traces/) page in Sentry. You'll see a chart and a list of traces and be able to see at-a-glance how long each trace took to complete and the number of spans it contains. - -![A view of the Sentry Traces page showing traces and spans](./img/Traces-page.png) - -If you want more information, click on any trace ID. This will take you to the [Trace View](/concepts/key-terms/tracing/trace-view/) page, which provides a more detailed view of the trace and its spans. Here, you'll see a waterfall view of the spans in the trace, which will show you how much time each service and operation took to complete, and may give you an indicator of where a problem may be coming from. - -![A detailed view of the Senty Traces page showing an expaned trace and spans](./img/Trace-view-page.png) - -Alternatively, you can use the search bar to look for spans by name, project, or other criteria. You can also use the tags section to filter spans by specific tags. Learn more about the Sentry [Trace Explorer](/product/explore/traces/). - -![An illustrated image of the anatomy of a trace, showing 8 span blocks cascading in a waterfall pattern.](./img/Traces-details-page.png) - -### Performance to Trace View - -Depending on the size and volume of your app, you may have a lot of traces to sort through. The [Insights](https://sentry.io/orgredirect/organizations/:orgslug/insights/backend/) page in Sentry is a good place to get a high-level, aggregated view of your application's performance and focus in on the traces you care about. You'll see a list of transactions for specific pages, endpoints and parts of your application. Clicking on the transaction ID will take you to the Trace View page for that transaction. Learn more about using Sentry's [Insights](/product/insights/). - -![An overview of the Performance page in Sentry.](./img/Performance-page.png) - -## How Tracing Can Help You Debug - -Sentry’s tracing lets you follow each request across various services, databases, and functions. This makes it easier to find exactly where an error occured or a performance bottleneck started. Below, you'll find some real-world scenarios where tracing saved the day. - -### Debug Slowdowns Across Your Integrations - -When debugging integrations or a microservice architecture, you'll likely run into issues where the root cause is tricky to discover, especially when it's a performance issue. At Sentry, we make sure to add spans whenever we’re working with external services, like Slack. Because of this, when our users started experiencing a 4-second delay in receiving Sentry alerts via Slack, we were able to go to the [Trace View](/concepts/key-terms/tracing/trace-view/) and quickly narrow down which task was causing the slowdown and deploy a fix quickly. Read more about the details of [debugging Sentry’s Slack Integration](https://blog.sentry.io/debugging-a-slack-integration-with-sentrys-trace-view/). - -### Improve Core Web Vitals - -While everyone is sharing Lighthouse scores, we all know that the true determination of healthy web vitals is when your actual users are using your application in their authentic environments. Sentry offers real insights and analysis of your application in the real world, and while tracing can be leveraged to reactively solve issues, you can also use it to proactively discover opportunities to improve your application performance. In fact, this blog post describes [how you can improve performance before your web page even loads](https://blog.sentry.io/how-to-make-your-web-page-faster-before-it-even-loads/). - -### Debug New Code Bases Faster - -Tracing can even give you the power to debug unfamiliar codebases. Although this benefit is not often discussed, a lot of time can be saved when debugging applications instrumented with Tracing, even if the codebase is completely new to you. Being able to trace actual user journeys throughout your application and see what happens across your entire stack contextualizes issues without even needing to recreate the issue locally. Read more about other ways [tracing helps developers debug](https://blog.sentry.io/everyone-needs-to-know-how-to-trace/) various issues here. - diff --git a/platform-includes/distributed-tracing/explanation/javascript.mdx b/platform-includes/distributed-tracing/explanation/javascript.mdx index dddfe68569b47..37efbb1864b69 100644 --- a/platform-includes/distributed-tracing/explanation/javascript.mdx +++ b/platform-includes/distributed-tracing/explanation/javascript.mdx @@ -1,3 +1,3 @@ -In the context of tracing events across a distributed system, distributed tracing acts as a powerful debugging tool. Imagine your application as a vast network of interconnected parts. For example, your system might be spread across different servers or your application might split into different backend and frontend services, each potentially having their own technology stack. +Distributed tracing connects and records the path of requests as they travel through the different tiers of your application architecture. If your architecture consists of multiple services that live on different sub-domains (e.g. `fe.example.com` and `api.example.com`), distributed tracing will help you follow the path of events as they move from one service to another. -When an error or performance issue occurs, it can be challenging to pinpoint the root cause due to the complexity of such a system. Distributed tracing helps you follow the path of an event as it travels through this intricate web, recording every step it takes. By examining these traces, you can reconstruct the sequence of events leading up to the event of interest, identify the specific components involved, and understand their interactions. This detailed visibility enables you to diagnose and resolve issues more effectively, ultimately improving the reliability and performance of your distributed system. +This end-to-end visibility allows developers to identify bottlenecks, pinpoint the root cause of errors, and understand component interactions—turning what would be a complex debugging nightmare into a manageable process that improves system reliability and performance. \ No newline at end of file diff --git a/platform-includes/distributed-tracing/how-to-use/javascript.astro.mdx b/platform-includes/distributed-tracing/how-to-use/javascript.astro.mdx index 9f6b5255560cc..09d81ff38ae00 100644 --- a/platform-includes/distributed-tracing/how-to-use/javascript.astro.mdx +++ b/platform-includes/distributed-tracing/how-to-use/javascript.astro.mdx @@ -1,15 +1,68 @@ If you're using our Astro SDK, distributed tracing will work out of the box for the client and server runtimes. -To get around possible [Browser CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) issues, you should define `tracePropagationTargets` on the client-side. + +When you are interacting with other external API systems, you might have to define `tracePropagationTargets` to get around possible [Browser CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) issues. ```javascript // sentry.client.config.js Sentry.init({ dsn: "___PUBLIC_DSN___", integrations: [Sentry.browserTracingIntegration()], + // Capture 100% of spans. This is useful for development and debugging. Consider reducing in production or using traceSampler + tracesSampleRate: 1.0, tracePropagationTargets: ["https://myproject.org", /^\/api\//], }); ``` +### Trace Propagation Examples + +#### Example 1: Microservices E-commerce Platform + +```javascript +// sentry.client.config.js +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.browserTracingIntegration()], + // Capture 100% of spans. This is useful for development and debugging. Consider reducing in production or using traceSampler + tracesSampleRate: 1.0, + tracePropagationTargets: [ + "https://api.myecommerce.com", + "https://auth.myecommerce.com", + /^\/internal-api\// + ], +}); +``` + +This tells Sentry to track user journeys across three places: + +* Your main API server (where product data comes from) +* Your authentication server (where logins happen) +* Any API calls that start with "/internal-api/" on your current domain + +This way, if a customer experiences an error during checkout, you can see the complete path their request took across these different services. + +#### Example 2: Mobile App with Backend Services + +```javascript +// sentry.client.config.js +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.browserTracingIntegration()], + tracePropagationTargets: [ + "https://api.myapp.com", + "https://media.myapp.com", + /^\/local-api\// + ], +}); +``` + +This configuration lets your app track user actions across: + +* Your main API server (handles most app functions) +* Your media server (handles images, videos, etc.) +* Any local API endpoints in your app + +If your app crashes while a user is uploading a photo, you can trace exactly where the problem occurred - in the app itself, the main API, or the media service. + ### Disabling Distributed Tracing If you want to disable distributed tracing and ensure no Sentry trace headers are sent, you can configure your SDK like this: diff --git a/platform-includes/distributed-tracing/how-to-use/javascript.cloudflare.mdx b/platform-includes/distributed-tracing/how-to-use/javascript.cloudflare.mdx index c9216191c31e2..7688ad53e0f19 100644 --- a/platform-includes/distributed-tracing/how-to-use/javascript.cloudflare.mdx +++ b/platform-includes/distributed-tracing/how-to-use/javascript.cloudflare.mdx @@ -11,8 +11,55 @@ If you want to disable distributed tracing, set the `tracePropagationTargets` op ```javascript Sentry.init({ dsn: "___PUBLIC_DSN___", - + // Capture 100% of spans. This is useful for development and debugging. Consider reducing in production or using traceSampler + tracesSampleRate: 1.0, // Overwrite the defaults to ensure no trace headers are sent tracePropagationTargets: [], }); ``` + +### Trace Propagation Examples + +#### Example 1: Microservices E-commerce Platform + +```javascript +Sentry.init({ + dsn: "___PUBLIC_DSN___", + // Capture 100% of spans. This is useful for development and debugging. Consider reducing in production or using traceSampler + tracesSampleRate: 1.0, + tracePropagationTargets: [ + "https://api.myecommerce.com", + "https://auth.myecommerce.com", + /^\/internal-api\// + ], +}); +``` + +This tells Sentry to track user journeys across three places: + +* Your main API server (where product data comes from) +* Your authentication server (where logins happen) +* Any API calls that start with "/internal-api/" on your current domain + +This way, if a customer experiences an error during checkout, you can see the complete path their request took across these different services. + +#### Example 2: Mobile App with Backend Services + +```javascript +Sentry.init({ + dsn: "___PUBLIC_DSN___", + tracePropagationTargets: [ + "https://api.myapp.com", + "https://media.myapp.com", + /^\/local-api\// + ], +}); +``` + +This configuration lets your app track user actions across: + +* Your main API server (handles most app functions) +* Your media server (handles images, videos, etc.) +* Any local API endpoints in your app + +If your app crashes while a user is uploading a photo, you can trace exactly where the problem occurred - in the app itself, the main API, or the media service. diff --git a/platform-includes/distributed-tracing/how-to-use/javascript.mdx b/platform-includes/distributed-tracing/how-to-use/javascript.mdx index 1be3ba83ab3b6..e295015ca993d 100644 --- a/platform-includes/distributed-tracing/how-to-use/javascript.mdx +++ b/platform-includes/distributed-tracing/how-to-use/javascript.mdx @@ -1,9 +1,13 @@ -If you're using the current version of our JavaScript SDK and have enabled the `BrowserTracing` integration, distributed tracing will work out of the box. To get around possible [Browser CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) issues, define your `tracePropagationTargets`. +If you're using the current version of our JavaScript SDK and have enabled the `BrowserTracing` integration, distributed tracing will work out of the box. + +To get around possible [Browser CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) issues, define your `tracePropagationTargets`. ```javascript Sentry.init({ dsn: "___PUBLIC_DSN___", integrations: [Sentry.browserTracingIntegration()], + // Capture 100% of spans. This is useful for development and debugging. Consider reducing in production or using traceSampler + tracesSampleRate: 1.0, tracePropagationTargets: ["https://myproject.org", /^\/api\//], }); ``` @@ -29,6 +33,54 @@ If you don't want to use `browserTracingIntegration`, you can set up tracing feature enabled in order for distributed tracing to work. +### Trace Propagation Examples + +#### Example 1: Microservices E-commerce Platform + +```javascript +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.browserTracingIntegration()], + // Capture 100% of spans. This is useful for development and debugging. Consider reducing in production or using traceSampler + tracesSampleRate: 1.0, + tracePropagationTargets: [ + "https://api.myecommerce.com", + "https://auth.myecommerce.com", + /^\/internal-api\// + ], +}); +``` + +This tells Sentry to track user journeys across three places: + +* Your main API server (where product data comes from) +* Your authentication server (where logins happen) +* Any API calls that start with "/internal-api/" on your current domain + +This way, if a customer experiences an error during checkout, you can see the complete path their request took across these different services. + +#### Example 2: Mobile App with Backend Services + +```javascript +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.browserTracingIntegration()], + tracePropagationTargets: [ + "https://api.myapp.com", + "https://media.myapp.com", + /^\/local-api\// + ], +}); +``` + +This configuration lets your app track user actions across: + +* Your main API server (handles most app functions) +* Your media server (handles images, videos, etc.) +* Any local API endpoints in your app + +If your app crashes while a user is uploading a photo, you can trace exactly where the problem occurred - in the app itself, the main API, or the media service. + ### Disabling Distributed Tracing If you want to disable distributed tracing and ensure no Sentry trace headers are sent, you can configure your SDK like this: diff --git a/platform-includes/distributed-tracing/how-to-use/javascript.nextjs.mdx b/platform-includes/distributed-tracing/how-to-use/javascript.nextjs.mdx index 82a8256f84290..5cfc5362d3345 100644 --- a/platform-includes/distributed-tracing/how-to-use/javascript.nextjs.mdx +++ b/platform-includes/distributed-tracing/how-to-use/javascript.nextjs.mdx @@ -1,6 +1,6 @@ If you're using the current version of our Next.js SDK, distributed tracing will work out of the box for the client, server, and edge runtimes. -For client-side you might have to define `tracePropagationTargets` to get around possible [Browser CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) issues. +For client-side, when you are interacting with other external API systems, you might have to define `tracePropagationTargets` to get around possible [Browser CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) issues. ```javascript // sentry.client.config.js @@ -13,6 +13,56 @@ Sentry.init({ If you're using version `7.57.x` or below, you'll need to have our tracing feature enabled in order for distributed tracing to work. +### Trace Propagation Examples + +#### Example 1: Microservices E-commerce Platform + +```javascript +// sentry.client.config.js +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.browserTracingIntegration()], + tracePropagationTargets: [ + "https://api.myecommerce.com", + "https://auth.myecommerce.com", + /^\/internal-api\// + ], +}); +``` + +This tells Sentry to track user journeys across three places: + +* Your main API server (where product data comes from) +* Your authentication server (where logins happen) +* Any API calls that start with "/internal-api/" on your current domain + +This way, if a customer experiences an error during checkout, you can see the complete path their request took across these different services. + +#### Example 2: Mobile App with Backend Services + +```javascript +// sentry.client.config.js +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.browserTracingIntegration()], + // Capture 100% of spans. This is useful for development and debugging. Consider reducing in production or using traceSampler + tracesSampleRate: 1.0, + tracePropagationTargets: [ + "https://api.myapp.com", + "https://media.myapp.com", + /^\/local-api\// + ], +}); +``` + +This configuration lets your app track user actions across: + +* Your main API server (handles most app functions) +* Your media server (handles images, videos, etc.) +* Any local API endpoints in your app + +If your app crashes while a user is uploading a photo, you can trace exactly where the problem occurred - in the app itself, the main API, or the media service. + ### Disabling Distributed Tracing If you want to disable distributed tracing and ensure no Sentry trace headers are sent, you can configure your SDK like this: diff --git a/platform-includes/distributed-tracing/how-to-use/javascript.node.mdx b/platform-includes/distributed-tracing/how-to-use/javascript.node.mdx index 1bd53fe1f439b..2c00dffbf78be 100644 --- a/platform-includes/distributed-tracing/how-to-use/javascript.node.mdx +++ b/platform-includes/distributed-tracing/how-to-use/javascript.node.mdx @@ -12,6 +12,50 @@ Sentry.init({ If you don't want to use tracing, you can set up Custom Instrumentation for distributed tracing. +#### Example 1: Microservices E-commerce Platform + +```javascript +Sentry.init({ + dsn: "___PUBLIC_DSN___", + tracePropagationTargets: [ + "https://api.myecommerce.com", + "https://auth.myecommerce.com", + /^\/internal-api\// + ], +}); +``` + +This tells Sentry to track user journeys across three places: + +* Your main API server (where product data comes from) +* Your authentication server (where logins happen) +* Any API calls that start with "/internal-api/" on your current domain + +This way, if a customer experiences an error during checkout, you can see the complete path their request took across these different services. + +#### Example 2: Mobile App with Backend Services + +```javascript +Sentry.init({ + dsn: "___PUBLIC_DSN___", + // Capture 100% of spans. This is useful for development and debugging. Consider reducing in production or using traceSampler + tracesSampleRate: 1.0, + tracePropagationTargets: [ + "https://api.myapp.com", + "https://media.myapp.com", + /^\/local-api\// + ], +}); +``` + +This configuration lets your app track user actions across: + +* Your main API server (handles most app functions) +* Your media server (handles images, videos, etc.) +* Any local API endpoints in your app + +If your app crashes while a user is uploading a photo, you can trace exactly where the problem occurred - in the app itself, the main API, or the media service. + ### Disabling Distributed Tracing If you want to disable distributed tracing and ensure no Sentry trace headers are sent, you can configure your SDK like this: diff --git a/platform-includes/distributed-tracing/how-to-use/javascript.nuxt.mdx b/platform-includes/distributed-tracing/how-to-use/javascript.nuxt.mdx index d3a0ab9f8845e..f9c359e2de920 100644 --- a/platform-includes/distributed-tracing/how-to-use/javascript.nuxt.mdx +++ b/platform-includes/distributed-tracing/how-to-use/javascript.nuxt.mdx @@ -1,8 +1,56 @@ -If you're using the current version of our Nuxt SDK, distributed tracing will work out of the box for the client and server runtimes. To get around possible [Browser CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) issues, you should define `tracePropagationTargets` for client-side. +If you're using the current version of our Nuxt SDK, distributed tracing will work out of the box for the client and server runtimes. + +To get around possible [Browser CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) issues, you should define `tracePropagationTargets` for client-side. ```javascript {filename:sentry.client.config.(js|ts)} Sentry.init({ dsn: "___PUBLIC_DSN___", + // Capture 100% of spans. This is useful for development and debugging. Consider reducing in production or using traceSampler + tracesSampleRate: 1.0, tracePropagationTargets: ["https://myproject.org", /^\/api\//], }); ``` + +#### Example 1: Microservices E-commerce Platform + +```javascript +Sentry.init({ + dsn: "___PUBLIC_DSN___", + // Capture 100% of spans. This is useful for development and debugging. Consider reducing in production or using traceSampler + tracesSampleRate: 1.0, + tracePropagationTargets: [ + "https://api.myecommerce.com", + "https://auth.myecommerce.com", + /^\/internal-api\// + ], +}); +``` + +This tells Sentry to track user journeys across three places: + +* Your main API server (where product data comes from) +* Your authentication server (where logins happen) +* Any API calls that start with "/internal-api/" on your current domain + +This way, if a customer experiences an error during checkout, you can see the complete path their request took across these different services. + +#### Example 2: Mobile App with Backend Services + +```javascript +Sentry.init({ + dsn: "___PUBLIC_DSN___", + tracePropagationTargets: [ + "https://api.myapp.com", + "https://media.myapp.com", + /^\/local-api\// + ], +}); +``` + +This configuration lets your app track user actions across: + +* Your main API server (handles most app functions) +* Your media server (handles images, videos, etc.) +* Any local API endpoints in your app + +If your app crashes while a user is uploading a photo, you can trace exactly where the problem occurred - in the app itself, the main API, or the media service. \ No newline at end of file diff --git a/platform-includes/distributed-tracing/how-to-use/javascript.remix.mdx b/platform-includes/distributed-tracing/how-to-use/javascript.remix.mdx index 510da24aa609a..446ceae36ee0d 100644 --- a/platform-includes/distributed-tracing/how-to-use/javascript.remix.mdx +++ b/platform-includes/distributed-tracing/how-to-use/javascript.remix.mdx @@ -38,12 +38,62 @@ To get around possible [Browser CORS](https://developer.mozilla.org/en-US/docs/W Sentry.init({ dsn: "___PUBLIC_DSN___", integrations: [Sentry.browserTracingIntegration()], + // Capture 100% of spans. This is useful for development and debugging. Consider reducing in production or using traceSampler + tracesSampleRate: 1.0, tracePropagationTargets: ["https://myproject.org", /^\/api\//], }); ``` If you're using version `7.57.x` or below, you'll need to have our tracing feature enabled in order for distributed tracing to work. +#### Example 1: Microservices E-commerce Platform + +```javascript +// entry.client.tsx +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.browserTracingIntegration()], + // Capture 100% of spans. This is useful for development and debugging. Consider reducing in production or using traceSampler + tracesSampleRate: 1.0, + tracePropagationTargets: [ + "https://api.myecommerce.com", + "https://auth.myecommerce.com", + /^\/internal-api\// + ], +}); +``` + +This tells Sentry to track user journeys across three places: + +* Your main API server (where product data comes from) +* Your authentication server (where logins happen) +* Any API calls that start with "/internal-api/" on your current domain + +This way, if a customer experiences an error during checkout, you can see the complete path their request took across these different services. + +#### Example 2: Mobile App with Backend Services + +```javascript +// entry.client.tsx +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.browserTracingIntegration()], + tracePropagationTargets: [ + "https://api.myapp.com", + "https://media.myapp.com", + /^\/local-api\// + ], +}); +``` + +This configuration lets your app track user actions across: + +* Your main API server (handles most app functions) +* Your media server (handles images, videos, etc.) +* Any local API endpoints in your app + +If your app crashes while a user is uploading a photo, you can trace exactly where the problem occurred - in the app itself, the main API, or the media service. + ### Disabling Distributed Tracing If you want to disable distributed tracing and ensure no Sentry trace headers are sent, you can configure your SDK like this: diff --git a/platform-includes/distributed-tracing/how-to-use/javascript.solidstart.mdx b/platform-includes/distributed-tracing/how-to-use/javascript.solidstart.mdx index eba37ae021768..629b78fd8a284 100644 --- a/platform-includes/distributed-tracing/how-to-use/javascript.solidstart.mdx +++ b/platform-includes/distributed-tracing/how-to-use/javascript.solidstart.mdx @@ -32,6 +32,58 @@ To get around possible [Browser CORS](https://developer.mozilla.org/en-US/docs/W Sentry.init({ dsn: "___PUBLIC_DSN___", integrations: [Sentry.solidRouterBrowserTracingIntegration()], + // Capture 100% of spans. This is useful for development and debugging. Consider reducing in production or using traceSampler + tracesSampleRate: 1.0, tracePropagationTargets: ["https://myproject.org", /^\/api\//], }); ``` + +### Trace Propagation Examples + +#### Example 1: Microservices E-commerce Platform + +```javascript +// hooks.client.js +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.solidRouterBrowserTracingIntegration()], + // Capture 100% of spans. This is useful for development and debugging. Consider reducing in production or using traceSampler + tracesSampleRate: 1.0, + tracePropagationTargets: [ + "https://api.myecommerce.com", + "https://auth.myecommerce.com", + /^\/internal-api\// + ], +}); +``` + +This tells Sentry to track user journeys across three places: + +* Your main API server (where product data comes from) +* Your authentication server (where logins happen) +* Any API calls that start with "/internal-api/" on your current domain + +This way, if a customer experiences an error during checkout, you can see the complete path their request took across these different services. + +#### Example 2: Mobile App with Backend Services + +```javascript +// hooks.client.js +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.solidRouterBrowserTracingIntegration()], + tracePropagationTargets: [ + "https://api.myapp.com", + "https://media.myapp.com", + /^\/local-api\// + ], +}); +``` + +This configuration lets your app track user actions across: + +* Your main API server (handles most app functions) +* Your media server (handles images, videos, etc.) +* Any local API endpoints in your app + +If your app crashes while a user is uploading a photo, you can trace exactly where the problem occurred - in the app itself, the main API, or the media service. diff --git a/platform-includes/distributed-tracing/how-to-use/javascript.sveltekit.mdx b/platform-includes/distributed-tracing/how-to-use/javascript.sveltekit.mdx index a1d337e79f727..89f7186e25f18 100644 --- a/platform-includes/distributed-tracing/how-to-use/javascript.sveltekit.mdx +++ b/platform-includes/distributed-tracing/how-to-use/javascript.sveltekit.mdx @@ -1,16 +1,70 @@ -If you're using the current version of our SvelteKit SDK, distributed tracing will work out of the box for the client and server runtimes. To get around possible [Browser CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) issues, you should define `tracePropagationTargets` for client-side. +If you're using the current version of our SvelteKit SDK, distributed tracing will work out of the box for the client and server runtimes. + +When you are interacting with other external API systems, you might have to define `tracePropagationTargets` to get around possible [Browser CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) issues. ```javascript // hooks.client.js Sentry.init({ dsn: "___PUBLIC_DSN___", integrations: [Sentry.browserTracingIntegration()], + // Capture 100% of spans. This is useful for development and debugging. Consider reducing in production or using traceSampler + tracesSampleRate: 1.0, tracePropagationTargets: ["https://myproject.org", /^\/api\//], }); ``` If you're using version `7.57.x` or below, you'll need to have our tracing feature enabled for distributed tracing to work. +### Trace Propagation Examples + +#### Example 1: Microservices E-commerce Platform + +```javascript +// hooks.client.js +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.browserTracingIntegration()], + // Capture 100% of spans. This is useful for development and debugging. Consider reducing in production or using traceSampler + tracesSampleRate: 1.0, + tracePropagationTargets: [ + "https://api.myecommerce.com", + "https://auth.myecommerce.com", + /^\/internal-api\// + ], +}); +``` + +This tells Sentry to track user journeys across three places: + +* Your main API server (where product data comes from) +* Your authentication server (where logins happen) +* Any API calls that start with "/internal-api/" on your current domain + +This way, if a customer experiences an error during checkout, you can see the complete path their request took across these different services. + +#### Example 2: Mobile App with Backend Services + +```javascript +// hooks.client.js +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.browserTracingIntegration()], + tracePropagationTargets: [ + "https://api.myapp.com", + "https://media.myapp.com", + /^\/local-api\// + ], +}); +``` + +This configuration lets your app track user actions across: + +* Your main API server (handles most app functions) +* Your media server (handles images, videos, etc.) +* Any local API endpoints in your app + +If your app crashes while a user is uploading a photo, you can trace exactly where the problem occurred - in the app itself, the main API, or the media service. + ### Disabling Distributed Tracing If you want to disable distributed tracing and ensure no Sentry trace headers are sent, you can configure your SDK like this: diff --git a/platform-includes/tracing/sample-rate/javascript.astro.mdx b/platform-includes/tracing/sample-rate/javascript.astro.mdx new file mode 100644 index 0000000000000..571c9a00bf36f --- /dev/null +++ b/platform-includes/tracing/sample-rate/javascript.astro.mdx @@ -0,0 +1,9 @@ +```javascript +// sentry.client.config.js +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.browserTracingIntegration()], + // Capture 25% of all transactions + tracesSampleRate: 0.25 +}); +``` \ No newline at end of file diff --git a/platform-includes/tracing/sample-rate/javascript.cloudflare.mdx b/platform-includes/tracing/sample-rate/javascript.cloudflare.mdx new file mode 100644 index 0000000000000..f394c2c0e866b --- /dev/null +++ b/platform-includes/tracing/sample-rate/javascript.cloudflare.mdx @@ -0,0 +1,7 @@ +```javascript +Sentry.init({ + dsn: "___PUBLIC_DSN___", + // Capture 25% of all transactions + tracesSampleRate: 0.25 +}); +``` \ No newline at end of file diff --git a/platform-includes/tracing/sample-rate/javascript.mdx b/platform-includes/tracing/sample-rate/javascript.mdx new file mode 100644 index 0000000000000..84a58a80b68d0 --- /dev/null +++ b/platform-includes/tracing/sample-rate/javascript.mdx @@ -0,0 +1,8 @@ +```javascript +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.browserTracingIntegration()], + // Capture 25% of all transactions + tracesSampleRate: 0.25 +}); +``` \ No newline at end of file diff --git a/platform-includes/tracing/sample-rate/javascript.nextjs.mdx b/platform-includes/tracing/sample-rate/javascript.nextjs.mdx new file mode 100644 index 0000000000000..571c9a00bf36f --- /dev/null +++ b/platform-includes/tracing/sample-rate/javascript.nextjs.mdx @@ -0,0 +1,9 @@ +```javascript +// sentry.client.config.js +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.browserTracingIntegration()], + // Capture 25% of all transactions + tracesSampleRate: 0.25 +}); +``` \ No newline at end of file diff --git a/platform-includes/tracing/sample-rate/javascript.node.mdx b/platform-includes/tracing/sample-rate/javascript.node.mdx new file mode 100644 index 0000000000000..f394c2c0e866b --- /dev/null +++ b/platform-includes/tracing/sample-rate/javascript.node.mdx @@ -0,0 +1,7 @@ +```javascript +Sentry.init({ + dsn: "___PUBLIC_DSN___", + // Capture 25% of all transactions + tracesSampleRate: 0.25 +}); +``` \ No newline at end of file diff --git a/platform-includes/tracing/sample-rate/javascript.nuxt.mdx b/platform-includes/tracing/sample-rate/javascript.nuxt.mdx new file mode 100644 index 0000000000000..f394c2c0e866b --- /dev/null +++ b/platform-includes/tracing/sample-rate/javascript.nuxt.mdx @@ -0,0 +1,7 @@ +```javascript +Sentry.init({ + dsn: "___PUBLIC_DSN___", + // Capture 25% of all transactions + tracesSampleRate: 0.25 +}); +``` \ No newline at end of file diff --git a/platform-includes/tracing/sample-rate/javascript.remix.mdx b/platform-includes/tracing/sample-rate/javascript.remix.mdx new file mode 100644 index 0000000000000..1bb8ff4fdbad1 --- /dev/null +++ b/platform-includes/tracing/sample-rate/javascript.remix.mdx @@ -0,0 +1,9 @@ +```javascript +// entry.client.tsx +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.browserTracingIntegration()], + // Capture 25% of all transactions + tracesSampleRate: 0.25 +}); +``` \ No newline at end of file diff --git a/platform-includes/tracing/sample-rate/javascript.solidstart.mdx b/platform-includes/tracing/sample-rate/javascript.solidstart.mdx new file mode 100644 index 0000000000000..774b0ccdc4924 --- /dev/null +++ b/platform-includes/tracing/sample-rate/javascript.solidstart.mdx @@ -0,0 +1,9 @@ +```javascript +// hooks.client.js +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.solidRouterBrowserTracingIntegration()], + // Capture 25% of all transactions + tracesSampleRate: 0.25 +}); +``` \ No newline at end of file diff --git a/platform-includes/tracing/sample-rate/javascript.sveltekit.mdx b/platform-includes/tracing/sample-rate/javascript.sveltekit.mdx new file mode 100644 index 0000000000000..c85156fc4736c --- /dev/null +++ b/platform-includes/tracing/sample-rate/javascript.sveltekit.mdx @@ -0,0 +1,9 @@ +```javascript +// hooks.client.js +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.browserTracingIntegration()], + // Capture 25% of all transactions + tracesSampleRate: 0.25 +}); +``` \ No newline at end of file diff --git a/platform-includes/tracing/trace-sampler/javascript.astro.mdx b/platform-includes/tracing/trace-sampler/javascript.astro.mdx new file mode 100644 index 0000000000000..49c354feb2b17 --- /dev/null +++ b/platform-includes/tracing/trace-sampler/javascript.astro.mdx @@ -0,0 +1,29 @@ +```javascript +// sentry.client.config.js +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.browserTracingIntegration()], + tracesSampler: (samplingContext) => { + // Access transaction details from the sampling context + const { name, attributes, inheritOrSampleWith } = samplingContext; + + // Skip health checks entirely + if (name.includes('healthcheck')) { + return 0; + } + + // Capture all auth-related transactions + if (name.includes('auth')) { + return 1; + } + + // Sample only 1% of comment-related transactions + if (name.includes('comment')) { + return 0.01; + } + + // For everything else, inherit parent sampling decision or use 0.5 + return inheritOrSampleWith(0.5); + } +}); +``` \ No newline at end of file diff --git a/platform-includes/tracing/trace-sampler/javascript.cloudflare.mdx b/platform-includes/tracing/trace-sampler/javascript.cloudflare.mdx new file mode 100644 index 0000000000000..d86fb7bf7f8be --- /dev/null +++ b/platform-includes/tracing/trace-sampler/javascript.cloudflare.mdx @@ -0,0 +1,28 @@ +```javascript +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.browserTracingIntegration()], + tracesSampler: (samplingContext) => { + // Access transaction details from the sampling context + const { name, attributes, inheritOrSampleWith } = samplingContext; + + // Skip health checks entirely + if (name.includes('healthcheck')) { + return 0; + } + + // Capture all auth-related transactions + if (name.includes('auth')) { + return 1; + } + + // Sample only 1% of comment-related transactions + if (name.includes('comment')) { + return 0.01; + } + + // For everything else, inherit parent sampling decision or use 0.5 + return inheritOrSampleWith(0.5); + } +}); +``` \ No newline at end of file diff --git a/platform-includes/tracing/trace-sampler/javascript.mdx b/platform-includes/tracing/trace-sampler/javascript.mdx new file mode 100644 index 0000000000000..d86fb7bf7f8be --- /dev/null +++ b/platform-includes/tracing/trace-sampler/javascript.mdx @@ -0,0 +1,28 @@ +```javascript +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.browserTracingIntegration()], + tracesSampler: (samplingContext) => { + // Access transaction details from the sampling context + const { name, attributes, inheritOrSampleWith } = samplingContext; + + // Skip health checks entirely + if (name.includes('healthcheck')) { + return 0; + } + + // Capture all auth-related transactions + if (name.includes('auth')) { + return 1; + } + + // Sample only 1% of comment-related transactions + if (name.includes('comment')) { + return 0.01; + } + + // For everything else, inherit parent sampling decision or use 0.5 + return inheritOrSampleWith(0.5); + } +}); +``` \ No newline at end of file diff --git a/platform-includes/tracing/trace-sampler/javascript.nextjs.mdx b/platform-includes/tracing/trace-sampler/javascript.nextjs.mdx new file mode 100644 index 0000000000000..49c354feb2b17 --- /dev/null +++ b/platform-includes/tracing/trace-sampler/javascript.nextjs.mdx @@ -0,0 +1,29 @@ +```javascript +// sentry.client.config.js +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.browserTracingIntegration()], + tracesSampler: (samplingContext) => { + // Access transaction details from the sampling context + const { name, attributes, inheritOrSampleWith } = samplingContext; + + // Skip health checks entirely + if (name.includes('healthcheck')) { + return 0; + } + + // Capture all auth-related transactions + if (name.includes('auth')) { + return 1; + } + + // Sample only 1% of comment-related transactions + if (name.includes('comment')) { + return 0.01; + } + + // For everything else, inherit parent sampling decision or use 0.5 + return inheritOrSampleWith(0.5); + } +}); +``` \ No newline at end of file diff --git a/platform-includes/tracing/trace-sampler/javascript.node.mdx b/platform-includes/tracing/trace-sampler/javascript.node.mdx new file mode 100644 index 0000000000000..26f4b91c25bb7 --- /dev/null +++ b/platform-includes/tracing/trace-sampler/javascript.node.mdx @@ -0,0 +1,27 @@ +```javascript +Sentry.init({ + dsn: "___PUBLIC_DSN___", + tracesSampler: (samplingContext) => { + // Access transaction details from the sampling context + const { name, attributes, inheritOrSampleWith } = samplingContext; + + // Skip health checks entirely + if (name.includes('healthcheck')) { + return 0; + } + + // Capture all auth-related transactions + if (name.includes('auth')) { + return 1; + } + + // Sample only 1% of comment-related transactions + if (name.includes('comment')) { + return 0.01; + } + + // For everything else, inherit parent sampling decision or use 0.5 + return inheritOrSampleWith(0.5); + } +}); +``` \ No newline at end of file diff --git a/platform-includes/tracing/trace-sampler/javascript.nuxt.mdx b/platform-includes/tracing/trace-sampler/javascript.nuxt.mdx new file mode 100644 index 0000000000000..26f4b91c25bb7 --- /dev/null +++ b/platform-includes/tracing/trace-sampler/javascript.nuxt.mdx @@ -0,0 +1,27 @@ +```javascript +Sentry.init({ + dsn: "___PUBLIC_DSN___", + tracesSampler: (samplingContext) => { + // Access transaction details from the sampling context + const { name, attributes, inheritOrSampleWith } = samplingContext; + + // Skip health checks entirely + if (name.includes('healthcheck')) { + return 0; + } + + // Capture all auth-related transactions + if (name.includes('auth')) { + return 1; + } + + // Sample only 1% of comment-related transactions + if (name.includes('comment')) { + return 0.01; + } + + // For everything else, inherit parent sampling decision or use 0.5 + return inheritOrSampleWith(0.5); + } +}); +``` \ No newline at end of file diff --git a/platform-includes/tracing/trace-sampler/javascript.remix.mdx b/platform-includes/tracing/trace-sampler/javascript.remix.mdx new file mode 100644 index 0000000000000..2e74af10e8e3d --- /dev/null +++ b/platform-includes/tracing/trace-sampler/javascript.remix.mdx @@ -0,0 +1,29 @@ +```javascript +// entry.client.tsx +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.browserTracingIntegration()], + tracesSampler: (samplingContext) => { + // Access transaction details from the sampling context + const { name, attributes, inheritOrSampleWith } = samplingContext; + + // Skip health checks entirely + if (name.includes('healthcheck')) { + return 0; + } + + // Capture all auth-related transactions + if (name.includes('auth')) { + return 1; + } + + // Sample only 1% of comment-related transactions + if (name.includes('comment')) { + return 0.01; + } + + // For everything else, inherit parent sampling decision or use 0.5 + return inheritOrSampleWith(0.5); + } +}); +``` \ No newline at end of file diff --git a/platform-includes/tracing/trace-sampler/javascript.solidstart.mdx b/platform-includes/tracing/trace-sampler/javascript.solidstart.mdx new file mode 100644 index 0000000000000..bf662728b51fd --- /dev/null +++ b/platform-includes/tracing/trace-sampler/javascript.solidstart.mdx @@ -0,0 +1,29 @@ +```javascript +// hooks.client.js +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.solidRouterBrowserTracingIntegration()], + tracesSampler: (samplingContext) => { + // Access transaction details from the sampling context + const { name, attributes, inheritOrSampleWith } = samplingContext; + + // Skip health checks entirely + if (name.includes('healthcheck')) { + return 0; + } + + // Capture all auth-related transactions + if (name.includes('auth')) { + return 1; + } + + // Sample only 1% of comment-related transactions + if (name.includes('comment')) { + return 0.01; + } + + // For everything else, inherit parent sampling decision or use 0.5 + return inheritOrSampleWith(0.5); + } +}); +``` \ No newline at end of file diff --git a/platform-includes/tracing/trace-sampler/javascript.sveltekit.mdx b/platform-includes/tracing/trace-sampler/javascript.sveltekit.mdx new file mode 100644 index 0000000000000..2c46054e409a0 --- /dev/null +++ b/platform-includes/tracing/trace-sampler/javascript.sveltekit.mdx @@ -0,0 +1,29 @@ +```javascript +// hooks.client.js +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.browserTracingIntegration()], + tracesSampler: (samplingContext) => { + // Access transaction details from the sampling context + const { name, attributes, inheritOrSampleWith } = samplingContext; + + // Skip health checks entirely + if (name.includes('healthcheck')) { + return 0; + } + + // Capture all auth-related transactions + if (name.includes('auth')) { + return 1; + } + + // Sample only 1% of comment-related transactions + if (name.includes('comment')) { + return 0.01; + } + + // For everything else, inherit parent sampling decision or use 0.5 + return inheritOrSampleWith(0.5); + } +}); +``` \ No newline at end of file diff --git a/redirects.js b/redirects.js index a3521ae2e5217..dd24870b0f9e9 100644 --- a/redirects.js +++ b/redirects.js @@ -977,10 +977,6 @@ const userDocsRedirects = [ source: '/platforms/kotlin-multiplatform/:path*', destination: '/platforms/kotlin/guides/kotlin-multiplatform/:path*', }, - { - source: '/product/explore/feature-flags/:path*', - destination: '/product/issues/issue-details/feature-flags/:path*', - }, { source: '/platforms/python/:productfeature/troubleshooting/:path*', destination: '/platforms/python/troubleshooting/:path*', @@ -1000,6 +996,39 @@ const userDocsRedirects = [ { source: '/platforms/php/:productfeature/troubleshooting/:path*', destination: '/platforms/php/troubleshooting/:path*', + }, + { + source: '/product/explore/feature-flags/:path*', + destination: '/product/issues/issue-details/feature-flags/:path*', + }, + { + source: '/product/explore/metrics/:path*', + destination: '/concepts/key-terms/tracing/span-metrics/', + }, + { + source: '/product/tracing/:path*', + destination: '/concepts/key-terms/tracing/:path*', + }, + // Redirects for JavaScript tracing docs + { + source: '/platforms/javascript/tracing/trace-propagation/:path*', + destination: '/platforms/javascript/tracing/distributed-tracing/:path*', + }, + { + source: '/platforms/javascript/guides/:guide/tracing/instrumentation/performance-metrics/', + destination: '/platforms/javascript/guides/:guide/tracing/span-metrics/performance-metrics/', + }, + { + source: '/platforms/javascript/guides/:guide/tracing/trace-propagation/:path*', + destination: '/platforms/javascript/guides/:guide/tracing/distributed-tracing/:path*', + }, + { + source: '/platforms/javascript/tracing/instrumentation/custom-instrumentation/:path*', + destination: '/platforms/javascript/tracing/instrumentation/:path*', + }, + { + source: '/platforms/javascript/guides/:guide/tracing/instrumentation/custom-instrumentation/:path*', + destination: '/platforms/javascript/guides/:guide/tracing/instrumentation/:path*', }, { source: '/platforms/flutter/:path*',