Conversation
All done. Compilation passed and code is formatted. Here's a summary of what was modified: ## Files Modified | File | Change | |---|---| | **`Cargo.toml`** | Added dependencies: `opentelemetry@0.31.0`, `opentelemetry_sdk@0.31.0` (rt-tokio), `opentelemetry-otlp@0.31.1` (grpc-tonic, http-proto, http-json), `tracing-opentelemetry@0.32.1`, `tracing-actix-web@0.7` | | **`src/telemetry.rs`** | **Created** — `init_tracing()` function that reads `OTEL_EXPORTER_OTLP_ENDPOINT` (returns `None` if unset to disable OTel), builds an OTLP exporter (gRPC on explicit `"grpc"`, HTTP otherwise — SDK reads protocol env var automatically), configures a `SdkTracerProvider` with `service.name=parseable`, registers the W3C `TraceContextPropagator` globally, and returns the provider | | **`src/lib.rs`** | Added `pub mod telemetry;` | | **`src/main.rs`** | `init_logger()` now returns `Option<SdkTracerProvider>`, calls `parseable::telemetry::init_tracing()`, wires the OTel layer (with `OTEL_TRACE_LEVEL` env filter) into the tracing `Registry`. `main()` captures the provider and calls `provider.shutdown()` before exit | | **`src/handlers/http/role.rs`** | Added `#[instrument(name = "PUT /role/default", skip(req, name), fields(role_name))]` on `put_default` with dynamic `role_name` recording; `#[instrument(name = "role::get_metadata", skip_all)]` on `get_metadata`; `#[instrument(name = "role::put_metadata", skip_all)]` on `put_metadata` | | **`src/storage/store_metadata.rs`** | Added `#[instrument(name = "storage::put_remote_metadata", skip_all)]` on `put_remote_metadata`; `#[instrument(name = "storage::put_staging_metadata", skip_all)]` on `put_staging_metadata` | ## How to activate Set the environment variable before starting the server: ```bash export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318" # Optional: defaults to http/json export OTEL_EXPORTER_OTLP_PROTOCOL="http/json" # Optional: control OTel trace verbosity (default: info) export OTEL_TRACE_LEVEL="info" ``` When `OTEL_EXPORTER_OTLP_ENDPOINT` is **not set**, OTel is completely disabled and the server behaves exactly as before. Co-authored-by: otex-dev <dev@otex.dev>
WalkthroughOpenTelemetry tracing instrumentation is introduced across the codebase. A new telemetry module is created to initialize OTLP exporters supporting gRPC and HTTP protocols. Tracing spans are added to handlers and storage functions. The main initialization is updated to return and conditionally shutdown the OTel provider. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
src/telemetry.rs (1)
80-82: Consider enriching the resource with additional attributes.Using
builder_empty()omits default resource attributes likehost.name,process.pid, etc. These can be helpful for observability. If desired, consider usingResource::builder()(with defaults) or manually adding attributes likeservice.version.🔧 Optional enhancement to add version attribute
let resource = Resource::builder_empty() .with_service_name("parseable") + .with_attribute(opentelemetry::KeyValue::new("service.version", env!("CARGO_PKG_VERSION"))) .build();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/telemetry.rs` around lines 80 - 82, The resource is built with Resource::builder_empty(), which omits default attributes; change to Resource::builder() or augment the existing builder by adding common attributes (e.g., host.name, process.pid) and optional metadata like service.version so observability gets useful context. Locate the Resource construction (Resource::builder_empty() and .with_service_name("parseable")) and either replace builder_empty() with Resource::builder() or chain additional .with_* calls to add attributes such as service.version and host/process attributes before calling .build() so the telemetry resource contains defaults and version info.src/handlers/http/role.rs (1)
217-228: Consider recording tenant_id for multi-tenant observability.While
skip_allis appropriate for avoiding metadata serialization, recording thetenant_idcould be valuable for filtering and debugging in multi-tenant deployments. This is optional but could improve trace analysis.🔧 Optional: Record tenant_id in span
-#[instrument(name = "role::get_metadata", skip_all)] +#[instrument(name = "role::get_metadata", skip(tenant_id), fields(tenant_id = tenant_id.as_deref().unwrap_or("default")))] async fn get_metadata( tenant_id: &Option<String>, ) -> Result<crate::storage::StorageMetadata, ObjectStorageError> {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/handlers/http/role.rs` around lines 217 - 228, The get_metadata function currently uses #[instrument(name = "role::get_metadata", skip_all)] which skips all fields; update the instrument span to record the tenant_id for observability by removing skip_all (or adding fields) and include tenant_id as a traced field (e.g., tenant_id = ?tenant_id) so the span for role::get_metadata contains the tenant identifier; adjust the attribute on fn get_metadata and ensure any sensitive handling (Option<String>) is formatted appropriately for the span while leaving existing error mapping and return logic unchanged (references: function get_metadata and the call to PARSEABLE.metastore.get_parseable_metadata).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/handlers/http/role.rs`:
- Around line 217-228: The get_metadata function currently uses
#[instrument(name = "role::get_metadata", skip_all)] which skips all fields;
update the instrument span to record the tenant_id for observability by removing
skip_all (or adding fields) and include tenant_id as a traced field (e.g.,
tenant_id = ?tenant_id) so the span for role::get_metadata contains the tenant
identifier; adjust the attribute on fn get_metadata and ensure any sensitive
handling (Option<String>) is formatted appropriately for the span while leaving
existing error mapping and return logic unchanged (references: function
get_metadata and the call to PARSEABLE.metastore.get_parseable_metadata).
In `@src/telemetry.rs`:
- Around line 80-82: The resource is built with Resource::builder_empty(), which
omits default attributes; change to Resource::builder() or augment the existing
builder by adding common attributes (e.g., host.name, process.pid) and optional
metadata like service.version so observability gets useful context. Locate the
Resource construction (Resource::builder_empty() and
.with_service_name("parseable")) and either replace builder_empty() with
Resource::builder() or chain additional .with_* calls to add attributes such as
service.version and host/process attributes before calling .build() so the
telemetry resource contains defaults and version info.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: d51aa545-020b-4cc3-8dcb-37e24fc8ea12
📒 Files selected for processing (5)
src/handlers/http/role.rssrc/lib.rssrc/main.rssrc/storage/store_metadata.rssrc/telemetry.rs
All done. Compilation passed and code is formatted. Here's a summary of what was modified:
Files Modified
Cargo.tomlopentelemetry@0.31.0,opentelemetry_sdk@0.31.0(rt-tokio),opentelemetry-otlp@0.31.1(grpc-tonic, http-proto, http-json),tracing-opentelemetry@0.32.1,tracing-actix-web@0.7src/telemetry.rsinit_tracing()function that readsOTEL_EXPORTER_OTLP_ENDPOINT(returnsNoneif unset to disable OTel), builds an OTLP exporter (gRPC on explicit"grpc", HTTP otherwise — SDK reads protocol env var automatically), configures aSdkTracerProviderwithservice.name=parseable, registers the W3CTraceContextPropagatorglobally, and returns the providersrc/lib.rspub mod telemetry;src/main.rsinit_logger()now returnsOption<SdkTracerProvider>, callsparseable::telemetry::init_tracing(), wires the OTel layer (withOTEL_TRACE_LEVELenv filter) into the tracingRegistry.main()captures the provider and callsprovider.shutdown()before exitsrc/handlers/http/role.rs#[instrument(name = "PUT /role/default", skip(req, name), fields(role_name))]onput_defaultwith dynamicrole_namerecording;#[instrument(name = "role::get_metadata", skip_all)]onget_metadata;#[instrument(name = "role::put_metadata", skip_all)]onput_metadatasrc/storage/store_metadata.rs#[instrument(name = "storage::put_remote_metadata", skip_all)]onput_remote_metadata;#[instrument(name = "storage::put_staging_metadata", skip_all)]onput_staging_metadataHow to activate
Set the environment variable before starting the server:
When
OTEL_EXPORTER_OTLP_ENDPOINTis not set, OTel is completely disabled and the server behaves exactly as before.Co-authored-by: otex-dev dev@otex.dev
Summary by CodeRabbit
OTEL_EXPORTER_OTLP_ENDPOINT,OTEL_EXPORTER_OTLP_PROTOCOL(gRPC or HTTP, defaults to HTTP), andOTEL_TRACE_LEVEL(defaults to "info") for configuration.