Skip to content

Commit 1b8bdc6

Browse files
nitishtotex-dev
andcommitted
Add OpenTelemetry instrumentation
## What changed - `src/telemetry.rs` — created OTel init module with OTLP exporter (HTTP/JSON default), W3C TraceContext propagator, and resource with service.name="parseable" - `src/lib.rs` — registered `pub mod telemetry;` alongside existing module declarations - `src/main.rs` — wired OTel TracerProvider into tracing subscriber in `init_logger()`, added OTel layer with per-layer filter, added provider shutdown before process exit - `src/analytics.rs` — added `#[instrument]` to `get_analytics` handler with span name `GET /analytics` - `src/handlers/http/role.rs` — added `#[instrument]` to `list`, `put_default`, `get_metadata`, and `put_metadata` functions ## Dependencies added - opentelemetry 0.31.0 (features: trace) - opentelemetry_sdk 0.31.0 (features: rt-tokio) - opentelemetry-otlp 0.31.1 (features: grpc-tonic, http-proto, http-json) - tracing-opentelemetry 0.32.1 - tracing-actix-web 0.7 Co-authored-by: otex-dev <dev@otex.dev>
1 parent eacb1b9 commit 1b8bdc6

7 files changed

Lines changed: 290 additions & 9 deletions

File tree

Cargo.lock

Lines changed: 126 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ prost = "0.13.1"
166166
dashmap = "6.1.0"
167167
parking_lot = "0.12.5"
168168
indexmap = { version = "2.13.0", features = ["serde"] }
169+
opentelemetry = { version = "0.31.0", features = ["trace"] }
170+
opentelemetry_sdk = { version = "0.31.0", features = ["rt-tokio"] }
171+
opentelemetry-otlp = { version = "0.31.1", features = ["grpc-tonic", "http-proto", "http-json"] }
172+
tracing-opentelemetry = "0.32.1"
173+
tracing-actix-web = "0.7"
169174

170175
[build-dependencies]
171176
cargo_toml = "0.21"

src/analytics.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use std::collections::HashMap;
2727
use std::sync::Mutex;
2828
use std::time::Duration;
2929
use sysinfo::System;
30-
use tracing::{error, info};
30+
use tracing::{error, info, instrument};
3131
use ulid::Ulid;
3232

3333
use crate::{
@@ -184,6 +184,7 @@ impl Report {
184184
}
185185

186186
/// build the node metrics for the node ingestor endpoint
187+
#[instrument(name = "GET /analytics", skip_all, fields(http.route = "/analytics"))]
187188
pub async fn get_analytics(_: HttpRequest) -> impl Responder {
188189
let json = NodeMetrics::build();
189190
web::Json(json)

src/handlers/http/role.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ use actix_web::{
2525
web::{self, Json},
2626
};
2727

28+
use tracing::instrument;
29+
2830
use crate::rbac::map::roles;
2931
use crate::rbac::role::model::{Role, RoleType, RoleUI};
3032
use crate::{
@@ -109,6 +111,7 @@ pub async fn get(req: HttpRequest, name: web::Path<String>) -> Result<impl Respo
109111

110112
// Handler for GET /api/v1/role
111113
// Fetch all roles in the system
114+
#[instrument(name = "GET /role", skip(req), fields(http.route = "/role"))]
112115
pub async fn list(req: HttpRequest) -> Result<impl Responder, RoleError> {
113116
let tenant_id = get_tenant_id_from_request(&req);
114117
let metadata = get_metadata(&tenant_id).await?;
@@ -164,6 +167,7 @@ pub async fn delete(
164167

165168
// Handler for PUT /api/v1/role/default
166169
// Delete existing role
170+
#[instrument(name = "PUT /role/default", skip(req, name), fields(http.route = "/role/default"))]
167171
pub async fn put_default(
168172
req: HttpRequest,
169173
name: web::Json<String>,
@@ -211,6 +215,7 @@ pub async fn get_default(req: HttpRequest) -> Result<impl Responder, RoleError>
211215
Ok(web::Json(res))
212216
}
213217

218+
#[instrument(name = "get_metadata", skip_all)]
214219
async fn get_metadata(
215220
tenant_id: &Option<String>,
216221
) -> Result<crate::storage::StorageMetadata, ObjectStorageError> {
@@ -223,6 +228,7 @@ async fn get_metadata(
223228
Ok(serde_json::from_slice::<StorageMetadata>(&metadata)?)
224229
}
225230

231+
#[instrument(name = "put_metadata", skip_all)]
226232
async fn put_metadata(
227233
metadata: &StorageMetadata,
228234
tenant_id: &Option<String>,

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ mod static_schema;
4949
mod stats;
5050
pub mod storage;
5151
pub mod sync;
52+
pub mod telemetry;
5253
pub mod tenants;
5354
pub mod users;
5455
pub mod utils;

src/main.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ use std::process::exit;
1717
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1818
*
1919
*/
20+
use opentelemetry::trace::TracerProvider as _;
21+
use opentelemetry_sdk::trace::SdkTracerProvider;
2022
#[cfg(feature = "kafka")]
2123
use parseable::connectors;
2224
use parseable::{
@@ -27,13 +29,14 @@ use tokio::signal::ctrl_c;
2729
use tokio::sync::oneshot;
2830
use tracing::Level;
2931
use tracing::{info, warn};
32+
use tracing_subscriber::Layer as _;
3033
use tracing_subscriber::layer::SubscriberExt;
3134
use tracing_subscriber::util::SubscriberInitExt;
3235
use tracing_subscriber::{EnvFilter, Registry, fmt};
3336

3437
#[actix_web::main]
3538
async fn main() -> anyhow::Result<()> {
36-
init_logger();
39+
let otel_provider = init_logger();
3740
// Install the rustls crypto provider before any TLS operations.
3841
// This is required for rustls 0.23+ which needs an explicit crypto provider.
3942
// If the installation fails, log a warning but continue execution.
@@ -95,11 +98,19 @@ async fn main() -> anyhow::Result<()> {
9598
parseable_server.await?;
9699
}
97100

101+
if let Some(provider) = otel_provider {
102+
if let Err(e) = provider.shutdown() {
103+
warn!("Failed to shutdown OTel tracer provider: {:?}", e);
104+
}
105+
}
106+
98107
Ok(())
99108
}
100109

101-
pub fn init_logger() {
102-
let filter_layer = EnvFilter::try_from_default_env().unwrap_or_else(|_| {
110+
pub fn init_logger() -> Option<SdkTracerProvider> {
111+
let otel_provider = parseable::telemetry::init_tracing();
112+
113+
let fmt_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| {
103114
let default_level = if cfg!(debug_assertions) {
104115
Level::DEBUG
105116
} else {
@@ -116,10 +127,22 @@ pub fn init_logger() {
116127
.with_target(true)
117128
.compact();
118129

130+
let otel_layer = otel_provider.as_ref().map(|provider| {
131+
let otel_filter =
132+
EnvFilter::try_from_env("OTEL_TRACE_LEVEL").unwrap_or_else(|_| EnvFilter::new("info"));
133+
let tracer = provider.tracer("parseable");
134+
tracing_opentelemetry::layer()
135+
.with_tracer(tracer)
136+
.with_filter(otel_filter)
137+
});
138+
119139
Registry::default()
120-
.with(filter_layer)
140+
.with(fmt_filter)
121141
.with(fmt_layer)
142+
.with(otel_layer)
122143
.init();
144+
145+
otel_provider
123146
}
124147

125148
#[cfg(windows)]

0 commit comments

Comments
 (0)