Skip to content

Add OpenTelemetry instrumentation#1614

Closed
nitisht wants to merge 1 commit intomainfrom
otel/instrument-1775467953311
Closed

Add OpenTelemetry instrumentation#1614
nitisht wants to merge 1 commit intomainfrom
otel/instrument-1775467953311

Conversation

@nitisht
Copy link
Copy Markdown
Member

@nitisht nitisht commented Apr 6, 2026

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 Createdinit_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:

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

Summary by CodeRabbit

  • Chores
    • Added OpenTelemetry instrumentation for improved application tracing and observability. New environment variables available: OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_PROTOCOL (gRPC or HTTP, defaults to HTTP), and OTEL_TRACE_LEVEL (defaults to "info") for configuration.

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>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 6, 2026

Walkthrough

OpenTelemetry 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

Cohort / File(s) Summary
Telemetry Infrastructure
src/telemetry.rs, src/lib.rs
New telemetry.rs module with init_tracing() function that conditionally initializes OTLP exporters (gRPC and HTTP), configures a SdkTracerProvider, and sets global trace context propagation. Public module export added to lib.rs.
Main Initialization
src/main.rs
Updated init_logger() to return Option<SdkTracerProvider>, call init_tracing(), and apply OTel layer with env-configurable OTEL_TRACE_LEVEL. Main function captures return value and conditionally shuts down provider.
Request Handler Instrumentation
src/handlers/http/role.rs
Added #[instrument] macros to put_default (naming span PUT /role/default, recording role_name) and helper functions get_metadata/put_metadata with skip_all configuration.
Storage Function Instrumentation
src/storage/store_metadata.rs
Added #[instrument] macros with skip_all to put_remote_metadata and put_staging_metadata for trace span collection.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Hops through traces, spans light the way,
OTel observes every call and delay,
Metrics and logs dance in telemetry's glow,
From handlers to storage, the insights now flow!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding OpenTelemetry instrumentation. It is directly related to the changeset.
Description check ✅ Passed The PR description provides a comprehensive overview with detailed file modifications and activation instructions. While the optional template sections (testing, comments, documentation) are not explicitly marked, the description adequately documents the changes and how to use them.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch otel/instrument-1775467953311

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
src/telemetry.rs (1)

80-82: Consider enriching the resource with additional attributes.

Using builder_empty() omits default resource attributes like host.name, process.pid, etc. These can be helpful for observability. If desired, consider using Resource::builder() (with defaults) or manually adding attributes like service.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_all is appropriate for avoiding metadata serialization, recording the tenant_id could 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

📥 Commits

Reviewing files that changed from the base of the PR and between 79656f6 and 57b830d.

📒 Files selected for processing (5)
  • src/handlers/http/role.rs
  • src/lib.rs
  • src/main.rs
  • src/storage/store_metadata.rs
  • src/telemetry.rs

@nitisht nitisht closed this Apr 6, 2026
@nitisht nitisht deleted the otel/instrument-1775467953311 branch April 6, 2026 09:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant