feat: add OpenTelemetry tracing support behind otel feature flag

- Add tracing::instrument spans to executor (workflow.execute),
  host (workflow.start, event.publish, event.process)
- Add otel feature flag to wfe-core and wfe crates
- Add wfe/src/otel.rs helper for OTLP exporter initialization
- Dependencies: tracing-opentelemetry, opentelemetry, opentelemetry_sdk,
  opentelemetry-otlp (all optional behind otel feature)
- Step execution stays at info level, executor internals at debug
This commit is contained in:
2026-03-25 20:41:34 +00:00
parent bd51517e9f
commit c8582eb514
5 changed files with 73 additions and 1 deletions

View File

@@ -5,6 +5,17 @@ edition.workspace = true
license.workspace = true
description = "WFE workflow engine - umbrella crate"
[features]
default = []
otel = [
"wfe-core/otel",
"opentelemetry",
"opentelemetry_sdk",
"opentelemetry-otlp",
"tracing-opentelemetry",
"tracing-subscriber/registry",
]
[dependencies]
wfe-core = { workspace = true }
tokio = { workspace = true }
@@ -19,6 +30,12 @@ tokio-util = "0.7"
tracing-subscriber = { workspace = true }
# OTel (optional, behind "otel" feature)
tracing-opentelemetry = { workspace = true, optional = true }
opentelemetry = { workspace = true, optional = true }
opentelemetry_sdk = { workspace = true, optional = true }
opentelemetry-otlp = { workspace = true, optional = true }
[dev-dependencies]
wfe-core = { workspace = true, features = ["test-support"] }
wfe-sqlite = { workspace = true }

View File

@@ -2,7 +2,7 @@ use std::sync::Arc;
use tokio::sync::RwLock;
use tokio_util::sync::CancellationToken;
use tracing::{debug, error, warn};
use tracing::{debug, error, info, warn};
use wfe_core::executor::{StepRegistry, WorkflowExecutor};
use wfe_core::models::{
@@ -202,6 +202,15 @@ impl WorkflowHost {
}
/// Start a new workflow instance.
#[tracing::instrument(
name = "workflow.start",
skip(self, data),
fields(
workflow.definition_id = %definition_id,
workflow.version = version,
workflow.id,
)
)]
pub async fn start_workflow(
&self,
definition_id: &str,
@@ -226,6 +235,9 @@ impl WorkflowHost {
// Persist the instance.
let id = self.persistence.create_new_workflow(&instance).await?;
instance.id = id.clone();
tracing::Span::current().record("workflow.id", id.as_str());
info!(workflow_id = %id, "Workflow instance created");
// Queue for execution.
self.queue_provider
@@ -236,6 +248,14 @@ impl WorkflowHost {
}
/// Publish an event that may resume waiting workflows.
#[tracing::instrument(
name = "event.publish",
skip(self, data),
fields(
event.name = %event_name,
event.key = %event_key,
)
)]
pub async fn publish_event(
&self,
event_name: &str,
@@ -312,6 +332,11 @@ impl WorkflowHost {
}
/// Process an event: find matching subscriptions, set event_data on pointers, re-queue workflows.
#[tracing::instrument(
name = "event.process",
skip(persistence, lock_provider, queue),
fields(event.id = %event_id)
)]
async fn process_event(
persistence: &Arc<dyn PersistenceProvider>,
lock_provider: &Arc<dyn DistributedLockProvider>,