-
Notifications
You must be signed in to change notification settings - Fork 103
Runtime performance metrics #3276
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Takeno
wants to merge
18
commits into
main
Choose a base branch
from
feat/observability-init
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
139af27
Instrument SubscriptionScope with performance measures
aeplay 407174f
SubscriptionScope metrics to OTel to Inspector
Takeno b89f157
fixup! SubscriptionScope metrics to OTel to Inspector
Takeno 257a8df
fixup! fixup! SubscriptionScope metrics to OTel to Inspector
Takeno cbab130
fix performance.mark compatibility
Takeno 0324fc1
docs
Takeno eee1aa6
fixup! fix performance.mark compatibility
Takeno 97a5cfc
fixup! fix performance.mark compatibility
Takeno 27f8172
changeset
Takeno 35b4302
pr feedback
Takeno a0a8986
optional telemetry
Takeno 4518068
fixup! pr feedback
Takeno 8c59660
fixup! fixup! pr feedback
Takeno 7741778
fix: report if in-app inspector is rendered twice
Takeno c49e8f0
Show only top-level covalue subscriptions in inspector and devtools
Takeno b4b7c88
use resolve in active subscription calcs
Takeno cc28c2e
track covalue without listeners + clean up
Takeno a11bedb
fixup! track covalue without listeners + clean up
Takeno File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| --- | ||
| "jazz-tools": patch | ||
| "cojson": patch | ||
| --- | ||
|
|
||
| Added OpenTelemetry observability support for monitoring subscription performance | ||
|
|
||
| - Instrumented `SubscriptionScope` with metrics (`jazz.subscription.active`, `jazz.subscription.first_load`) and tracing spans | ||
| - Added performance tracking for subscription lifecycle events including storage loading, peer fetching, and transaction parsing | ||
| - Added new "Perf" tab in Jazz Inspector to visualize subscription load times and metrics | ||
| - Added documentation for integrating Jazz with OpenTelemetry-compatible observability backends | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
homepage/homepage/content/docs/code-snippets/tooling-and-resources/inspector/index.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| // #region WithOpenTelemetry | ||
| import React from "react"; | ||
| import { jazzMetricReader, JazzInspector } from "jazz-tools/inspector"; | ||
| import { JazzReactProvider } from "jazz-tools/react"; | ||
| import { | ||
| MeterProvider, | ||
| PeriodicExportingMetricReader, | ||
| ConsoleMetricExporter, | ||
| } from "@opentelemetry/sdk-metrics"; | ||
| import { metrics } from "@opentelemetry/api"; | ||
|
|
||
| // Include jazzMetricReader alongside your other readers | ||
| const meterProvider = new MeterProvider({ | ||
| readers: [ | ||
| // Your existing metric reader | ||
| new PeriodicExportingMetricReader({ | ||
| exporter: new ConsoleMetricExporter(), | ||
| exportIntervalMillis: 10000, | ||
| }), | ||
| // Add this to enable the Inspector's Performance tab | ||
| jazzMetricReader, | ||
| ], | ||
| }); | ||
|
|
||
| metrics.setGlobalMeterProvider(meterProvider); | ||
|
|
||
| function App() { | ||
| return ( | ||
| // @ts-expect-error No sync prop | ||
| <JazzReactProvider> | ||
| {/* Your app components */} | ||
| <JazzInspector /> | ||
| </JazzReactProvider> | ||
| ); | ||
| } | ||
| // #endregion | ||
|
|
||
| export {}; |
96 changes: 96 additions & 0 deletions
96
.../homepage/content/docs/code-snippets/tooling-and-resources/observability/observability.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| // #region Metrics | ||
| import { unstable_setOpenTelemetryInstrumentationEnabled } from "jazz-tools"; | ||
| import { | ||
| MeterProvider, | ||
| PeriodicExportingMetricReader, | ||
| ConsoleMetricExporter, | ||
| } from "@opentelemetry/sdk-metrics"; | ||
| import { metrics } from "@opentelemetry/api"; | ||
|
|
||
| // Enable instrumentation (required for metrics and tracing) | ||
| unstable_setOpenTelemetryInstrumentationEnabled(true); | ||
|
|
||
| // Create a console exporter for development | ||
| const metricExporter = new ConsoleMetricExporter(); | ||
|
|
||
| // Set up the meter provider with periodic export | ||
| const meterProvider = new MeterProvider({ | ||
| readers: [ | ||
| new PeriodicExportingMetricReader({ | ||
| exporter: metricExporter, | ||
| exportIntervalMillis: 10000, // Export every 10 seconds | ||
| }), | ||
| ], | ||
| }); | ||
|
|
||
| // Register the provider globally | ||
| metrics.setGlobalMeterProvider(meterProvider); | ||
| // #endregion | ||
|
|
||
| // #region Tracing | ||
| import { unstable_setOpenTelemetryInstrumentationEnabled } from "jazz-tools"; | ||
| import { | ||
| BasicTracerProvider, | ||
| SimpleSpanProcessor, | ||
| ConsoleSpanExporter, | ||
| } from "@opentelemetry/sdk-trace-base"; | ||
| import { trace } from "@opentelemetry/api"; | ||
|
|
||
| // Enable instrumentation (required for metrics and tracing) | ||
| unstable_setOpenTelemetryInstrumentationEnabled(true); | ||
|
|
||
| // Create a console exporter for development | ||
| const spanExporter = new ConsoleSpanExporter(); | ||
|
|
||
| // Set up the tracer provider | ||
| const tracerProvider = new BasicTracerProvider({ | ||
| spanProcessors: [new SimpleSpanProcessor(spanExporter)], | ||
| }); | ||
|
|
||
| // Register the provider globally | ||
| trace.setGlobalTracerProvider(tracerProvider); | ||
| // #endregion | ||
|
|
||
| // #region Production | ||
| import { unstable_setOpenTelemetryInstrumentationEnabled } from "jazz-tools"; | ||
| import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http"; | ||
| import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"; | ||
| import { | ||
| MeterProvider as MeterProviderProd, | ||
| PeriodicExportingMetricReader as PeriodicExportingMetricReaderProd, | ||
| } from "@opentelemetry/sdk-metrics"; | ||
| import { | ||
| BasicTracerProvider as BasicTracerProviderProd, | ||
| BatchSpanProcessor, | ||
| } from "@opentelemetry/sdk-trace-base"; | ||
| import { metrics as metricsProd, trace as traceProd } from "@opentelemetry/api"; | ||
|
|
||
| // Enable instrumentation (required for metrics and tracing) | ||
| unstable_setOpenTelemetryInstrumentationEnabled(true); | ||
|
|
||
| // Configure OTLP exporters pointing to your collector | ||
| const otlpMetricExporter = new OTLPMetricExporter({ | ||
| url: "https://your-collector.example.com/v1/metrics", | ||
| }); | ||
|
|
||
| const otlpTraceExporter = new OTLPTraceExporter({ | ||
| url: "https://your-collector.example.com/v1/traces", | ||
| }); | ||
|
|
||
| // Set up providers with production exporters | ||
| const prodMeterProvider = new MeterProviderProd({ | ||
| readers: [ | ||
| new PeriodicExportingMetricReaderProd({ | ||
| exporter: otlpMetricExporter, | ||
| exportIntervalMillis: 60000, // Export every minute | ||
| }), | ||
| ], | ||
| }); | ||
|
|
||
| const prodTracerProvider = new BasicTracerProviderProd({ | ||
| spanProcessors: [new BatchSpanProcessor(otlpTraceExporter)], | ||
| }); | ||
|
|
||
| metricsProd.setGlobalMeterProvider(prodMeterProvider); | ||
| traceProd.setGlobalTracerProvider(prodTracerProvider); | ||
| // #endregion |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
154 changes: 154 additions & 0 deletions
154
homepage/homepage/content/docs/tooling-and-resources/observability.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,154 @@ | ||
| import { CodeGroup } from '@/components/forMdx' | ||
|
|
||
| export const metadata = { | ||
| description: "Unstable API: Learn how to integrate Jazz with OpenTelemetry for metrics and tracing." | ||
| }; | ||
|
|
||
| # Observability | ||
|
|
||
| <div className="not-prose rounded-lg border border-amber-500/50 bg-amber-500/10 px-4 py-3 text-sm text-amber-900 dark:text-amber-100"> | ||
| ⚠️ **Unstable API**: The observability API is experimental and subject to breaking changes in future releases. Use with caution in production environments. | ||
| </div> | ||
|
|
||
| Jazz exposes metrics and spans using the [OpenTelemetry](https://opentelemetry.io/) protocol. This allows you to integrate Jazz's internal performance data with your existing observability stack, whether that's a console logger for development or a full observability platform in production. | ||
|
|
||
| ## Enabling instrumentation | ||
|
|
||
| OpenTelemetry instrumentation is **opt-in** and disabled by default for performance reasons. To enable it, call `unstable_setOpenTelemetryInstrumentationEnabled` before setting up your OpenTelemetry providers: | ||
|
|
||
| ```ts | ||
| import { unstable_setOpenTelemetryInstrumentationEnabled } from "jazz-tools"; | ||
|
|
||
| // Enable instrumentation - do this before setting up your OpenTelemetry providers | ||
| unstable_setOpenTelemetryInstrumentationEnabled(true); | ||
| ``` | ||
|
|
||
| <div className="not-prose rounded-lg border border-blue-500/50 bg-blue-500/10 px-4 py-3 text-sm text-blue-900 dark:text-blue-100"> | ||
| 💡 **Note**: You only need to enable instrumentation when you want to collect metrics or traces. If you're not using OpenTelemetry, leave it disabled to avoid any performance overhead. | ||
| </div> | ||
|
|
||
| ## Available metrics | ||
|
|
||
| Jazz tracks the following metrics: | ||
|
|
||
| <table> | ||
| <thead> | ||
| <tr> | ||
| <th>Metric</th> | ||
| <th>Type</th> | ||
| <th>Description</th> | ||
| </tr> | ||
| </thead> | ||
| <tbody> | ||
| <tr> | ||
| <td><code>jazz.subscription.active</code></td> | ||
| <td>UpDownCounter</td> | ||
| <td>Number of active CoValue subscriptions</td> | ||
| </tr> | ||
| <tr> | ||
| <td><code>jazz.subscription.first_load</code></td> | ||
| <td>Histogram</td> | ||
| <td>Time for a subscription to receive its first data (ms)</td> | ||
| </tr> | ||
| <tr> | ||
| <td><code>jazz.peers</code></td> | ||
| <td>UpDownCounter</td> | ||
| <td>Number of connected peers</td> | ||
| </tr> | ||
| <tr> | ||
| <td><code>jazz.transactions.size</code></td> | ||
| <td>Histogram</td> | ||
| <td>Size of transactions (bytes)</td> | ||
| </tr> | ||
| <tr> | ||
| <td><code>jazz.usage.ingress</code></td> | ||
| <td>Counter</td> | ||
| <td>Total bytes received from peers</td> | ||
| </tr> | ||
| <tr> | ||
| <td><code>jazz.usage.egress</code></td> | ||
| <td>Counter</td> | ||
| <td>Total bytes sent to peers</td> | ||
| </tr> | ||
| </tbody> | ||
| </table> | ||
|
|
||
| ## Available spans | ||
|
|
||
| Jazz creates spans to track the subscription lifecycle: | ||
|
|
||
| <table> | ||
| <thead> | ||
| <tr> | ||
| <th>Span</th> | ||
| <th>Description</th> | ||
| </tr> | ||
| </thead> | ||
| <tbody> | ||
| <tr> | ||
| <td><code>jazz.subscription</code></td> | ||
| <td>Parent span for the entire subscription lifecycle</td> | ||
| </tr> | ||
| <tr> | ||
| <td><code>jazz.subscription.first_load</code></td> | ||
| <td>Span for the initial data load</td> | ||
| </tr> | ||
| <tr> | ||
| <td><code>jazz.subscription.first_load.from_storage</code></td> | ||
| <td>Time spent loading from local storage</td> | ||
| </tr> | ||
| <tr> | ||
| <td><code>jazz.subscription.first_load.load_from_peer</code></td> | ||
| <td>Time spent fetching from a peer</td> | ||
| </tr> | ||
| <tr> | ||
| <td><code>jazz.subscription.first_load.transaction_parsing</code></td> | ||
| <td>Time spent parsing transactions</td> | ||
| </tr> | ||
| </tbody> | ||
| </table> | ||
|
|
||
| ## Setting up metrics | ||
|
|
||
| To collect metrics, you need to: | ||
| 1. Enable instrumentation using `unstable_setOpenTelemetryInstrumentationEnabled(true)` | ||
| 2. Configure an OpenTelemetry `MeterProvider` with a reader that exports the data | ||
|
|
||
| Here's a simple example that logs metrics to the console: | ||
|
|
||
| <CodeGroup> | ||
| ```ts tooling-and-resources/observability/observability.ts#Metrics | ||
| ``` | ||
| </CodeGroup> | ||
|
|
||
| **Tip:** If you're using the [Jazz Inspector](/docs/tooling-and-resources/inspector#performance-tab) in your app, add `jazzMetricReader` from `jazz-tools/inspector` to your MeterProvider's readers array to enable the Performance tab. | ||
|
|
||
| ## Setting up tracing | ||
|
|
||
| To collect spans, you need to: | ||
| 1. Enable instrumentation using `unstable_setOpenTelemetryInstrumentationEnabled(true)` | ||
| 2. Configure a `TracerProvider` with a span processor | ||
|
|
||
| Here's an example that logs spans to the console: | ||
|
|
||
| <CodeGroup> | ||
| ```ts tooling-and-resources/observability/observability.ts#Tracing | ||
| ``` | ||
| </CodeGroup> | ||
|
|
||
| Check the [OpenTelemetry JS documentation](https://opentelemetry.io/docs/languages/js/) for more details on available exporters and configuration options. | ||
|
|
||
| ## Production setup | ||
|
|
||
| In production, you'll typically want to use OTLP exporters to send data to your observability platform (like Jaeger, Prometheus, or a managed service). Here's a complete example: | ||
|
|
||
| <CodeGroup> | ||
| ```ts tooling-and-resources/observability/observability.ts#Production | ||
| ``` | ||
| </CodeGroup> | ||
|
|
||
| This example uses HTTP-based OTLP exporters, but you can also use gRPC-based exporters depending on your infrastructure. The key differences from development setup are: | ||
|
|
||
| - Using `BatchSpanProcessor` for more efficient span batching in production | ||
| - Longer export intervals (60 seconds vs 10 seconds) to reduce network overhead | ||
| - OTLP exporters that send data to your collector or observability platform | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.