mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-11 08:07:15 +00:00
fix: nativets http tracing (#7716)
* fix: nativets http tracing Signed-off-by: pyranota <pyra@duck.com> * ee repo Signed-off-by: pyranota <pyra@duck.com> * nit Signed-off-by: pyranota <pyra@duck.com> * ee ref Signed-off-by: pyranota <pyra@duck.com> * ee repo Signed-off-by: pyranota <pyra@duck.com> * ee repo Signed-off-by: pyranota <pyra@duck.com> * fix Signed-off-by: pyranota <pyra@duck.com> * fix Signed-off-by: pyranota <pyra@duck.com> * fix v2 Signed-off-by: pyranota <pyra@duck.com> * ee repo Signed-off-by: pyranota <pyra@duck.com> * chore: update ee-repo-ref to 5d841b358dd32130c9f34b54f59b96b5c322f213 This commit updates the EE repository reference after PR #396 was merged in windmill-ee-private. Previous ee-repo-ref: 250723c698fceccbc66ae9a6c6c7c09e33465819 New ee-repo-ref: 5d841b358dd32130c9f34b54f59b96b5c322f213 Automated by sync-ee-ref workflow. --------- Signed-off-by: pyranota <pyra@duck.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
windmill-internal-app[bot]
parent
d3d35d4cd8
commit
f50a866430
@@ -1 +1 @@
|
||||
371efb2d7307f588c5ce00d63fd036751cc068f2
|
||||
5d841b358dd32130c9f34b54f59b96b5c322f213
|
||||
|
||||
+12
-28
@@ -668,10 +668,11 @@ async fn windmill_main() -> anyhow::Result<()> {
|
||||
|
||||
// Load OTEL tracing proxy settings and initialize deno_telemetry if nativets tracing is enabled
|
||||
// This must happen before any Deno runtime is created
|
||||
#[cfg(all(feature = "private", feature = "enterprise", feature = "deno_core"))]
|
||||
#[cfg(all(feature = "private", feature = "enterprise"))]
|
||||
{
|
||||
reload_otel_tracing_proxy_setting(&Connection::Sql(db.clone())).await;
|
||||
|
||||
#[cfg(feature = "deno_core")]
|
||||
if windmill_worker::is_otel_tracing_proxy_enabled_for_lang(&ScriptLang::Nativets).await {
|
||||
match windmill_worker::load_internal_otel_exporter().await {
|
||||
Ok(()) => {
|
||||
@@ -1572,34 +1573,17 @@ Windmill Community Edition {GIT_VERSION}
|
||||
|
||||
let otel_tracing_proxy_f = async {
|
||||
#[cfg(all(feature = "private", feature = "enterprise"))]
|
||||
{
|
||||
// Start OTEL tracing proxy for HTTP request interception
|
||||
// Only enabled when: setting is on, worker mode (not server), and single worker (to avoid race conditions)
|
||||
if worker_mode
|
||||
&& num_workers == 1
|
||||
&& windmill_worker::OTEL_TRACING_PROXY_SETTINGS
|
||||
.read()
|
||||
.await
|
||||
.enabled
|
||||
{
|
||||
if let Some(db) = conn.as_sql() {
|
||||
tracing::info!(
|
||||
"Starting jobs OTEL tracing (ports will be dynamically assigned)"
|
||||
);
|
||||
if let Err(e) =
|
||||
windmill_worker::start_jobs_otel_tracing(db.clone(), otel_killpill_rx)
|
||||
.await
|
||||
{
|
||||
tracing::error!("Jobs OTEL tracing error: {}", e);
|
||||
}
|
||||
}
|
||||
} else if windmill_worker::OTEL_TRACING_PROXY_SETTINGS
|
||||
.read()
|
||||
if worker_mode {
|
||||
if let Some(db) = conn.as_sql() {
|
||||
if let Err(e) = windmill_worker::start_jobs_otel_tracing(
|
||||
db.clone(),
|
||||
otel_killpill_rx,
|
||||
num_workers,
|
||||
)
|
||||
.await
|
||||
.enabled
|
||||
&& num_workers > 1
|
||||
{
|
||||
tracing::warn!("OTEL tracing proxy is enabled but num_workers > 1. Disabling to avoid race conditions. Set NUM_WORKERS=1 to enable.");
|
||||
{
|
||||
tracing::error!("Jobs OTEL tracing error: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1328,22 +1328,6 @@ try {{
|
||||
|
||||
let stream_notifier = StreamNotifier::new(conn, job);
|
||||
|
||||
// Set job context for OTEL tracing (EE only)
|
||||
#[cfg(all(feature = "private", feature = "enterprise"))]
|
||||
{
|
||||
let tracing_enabled =
|
||||
crate::worker::is_otel_tracing_proxy_enabled_for_lang(&ScriptLang::Nativets)
|
||||
.await;
|
||||
tracing::debug!(
|
||||
"nativets job {}: OTEL tracing enabled={}",
|
||||
job.id,
|
||||
tracing_enabled
|
||||
);
|
||||
if tracing_enabled {
|
||||
crate::otel_tracing_proxy_ee::set_current_job_context(job.id).await;
|
||||
}
|
||||
}
|
||||
|
||||
let result = crate::js_eval::eval_fetch_timeout(
|
||||
env_code,
|
||||
inner_content.clone(),
|
||||
|
||||
@@ -1135,7 +1135,9 @@ pub async fn eval_fetch_timeout(
|
||||
// We call the function exposed by runtime.js since we can't dynamically import ext: modules.
|
||||
#[cfg(all(feature = "private", feature = "enterprise"))]
|
||||
if crate::DENO_OTEL_INITIALIZED.load(std::sync::atomic::Ordering::SeqCst) {
|
||||
if let Err(e) = js_runtime.execute_script("<otel_bootstrap>", "globalThis.__bootstrapOtel()") {
|
||||
if let Err(e) =
|
||||
js_runtime.execute_script("<otel_bootstrap>", "globalThis.__bootstrapOtel()")
|
||||
{
|
||||
tracing::warn!("Failed to bootstrap OTEL telemetry: {}", e);
|
||||
}
|
||||
}
|
||||
@@ -1331,6 +1333,26 @@ async fn eval_fetch(
|
||||
.context("failed to load module")?;
|
||||
|
||||
let main_override = script_entrypoint_override.unwrap_or("main".to_string());
|
||||
|
||||
// Inject parent trace context using enterSpan with a duck-typed span object.
|
||||
// Uses job_id as trace_id so all spans are linked to the job.
|
||||
// span_id is a placeholder - it gets overwritten by the OTLP handler with the real parent span_id.
|
||||
#[cfg(all(feature = "private", feature = "enterprise"))]
|
||||
let otel_context_inject = if crate::DENO_OTEL_INITIALIZED.load(std::sync::atomic::Ordering::SeqCst) {
|
||||
let trace_id = job_id.as_simple().to_string();
|
||||
format!(
|
||||
r#"globalThis.__enterSpan?.({{
|
||||
isRecording: () => true,
|
||||
spanContext: () => ({{ traceId: "{trace_id}", spanId: "ffffffffffffffff", traceFlags: 1 }})
|
||||
}});"#
|
||||
)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
#[cfg(not(all(feature = "private", feature = "enterprise")))]
|
||||
let otel_context_inject = "";
|
||||
|
||||
let script = js_runtime
|
||||
.execute_script(
|
||||
"<anon>",
|
||||
@@ -1343,7 +1365,7 @@ function isAsyncIterable(obj) {{
|
||||
|
||||
function processStreamIterative(res) {{
|
||||
const iterator = res[Symbol.asyncIterator]();
|
||||
|
||||
|
||||
function processLoop() {{
|
||||
return new Promise(function(resolve) {{
|
||||
function step() {{
|
||||
@@ -1363,10 +1385,12 @@ function processStreamIterative(res) {{
|
||||
step();
|
||||
}});
|
||||
}}
|
||||
|
||||
|
||||
return processLoop();
|
||||
}}
|
||||
|
||||
{otel_context_inject}
|
||||
|
||||
let args = Deno.core.ops.op_get_static_args().map(JSON.parse)
|
||||
import("file:///eval.ts").then((module) => module.{main_override}(...args))
|
||||
.then(res => {{
|
||||
|
||||
@@ -86,7 +86,7 @@ pub use otel_tracing_proxy_ee::{
|
||||
set_current_job_context, start_jobs_otel_tracing, TRACING_PROXY_PORT,
|
||||
};
|
||||
#[cfg(all(feature = "private", feature = "enterprise", feature = "deno_core"))]
|
||||
pub use otel_tracing_proxy_ee::{load_internal_otel_exporter, DENO_OTEL_INITIALIZED};
|
||||
pub use otel_tracing_proxy_ee::{load_internal_otel_exporter, DENO_OTEL_INITIALIZED, OTLP_COLLECTOR_PORT};
|
||||
|
||||
pub use result_processor::handle_job_error;
|
||||
|
||||
|
||||
@@ -52,9 +52,12 @@ Object.assign(globalThis, {
|
||||
// Expose bootstrapOtel globally so it can be called from Rust after runtime creation.
|
||||
// We use dynamic import so deno_telemetry isn't loaded during snapshot creation.
|
||||
// Config: [tracingEnabled, metricsEnabled, consoleConfig, deterministic]
|
||||
// consoleConfig: 0=ignore, 1=capture, 2=replace
|
||||
globalThis.__bootstrapOtel = () => {
|
||||
import("ext:deno_telemetry/telemetry.ts").then(({ bootstrap }) => {
|
||||
bootstrap([1, 0, 0, 0]);
|
||||
import("ext:deno_telemetry/telemetry.ts").then(({ bootstrap, enterSpan }) => {
|
||||
bootstrap([1, 0, 1, 0]);
|
||||
// Expose enterSpan for setting parent trace context
|
||||
globalThis.__enterSpan = enterSpan;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -675,7 +675,6 @@ async fn get_otel_tracing_proxy_envs() -> anyhow::Result<Vec<(&'static str, Stri
|
||||
])
|
||||
}
|
||||
|
||||
|
||||
#[cfg(windows)]
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref SYSTEM_ROOT: String = std::env::var("SystemRoot").unwrap_or_else(|_| "C:\\Windows".to_string());
|
||||
@@ -2704,19 +2703,6 @@ async fn do_nativets(
|
||||
|
||||
let stream_notifier = StreamNotifier::new(conn, job);
|
||||
|
||||
// Set job context for OTEL tracing (EE only)
|
||||
#[cfg(all(feature = "private", feature = "enterprise"))]
|
||||
{
|
||||
let tracing_enabled = is_otel_tracing_proxy_enabled_for_lang(&ScriptLang::Nativets).await;
|
||||
tracing::debug!(
|
||||
"nativets job {}: OTEL tracing enabled={}",
|
||||
job.id, tracing_enabled
|
||||
);
|
||||
if tracing_enabled {
|
||||
crate::otel_tracing_proxy_ee::set_current_job_context(job.id).await;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(eval_fetch_timeout(
|
||||
env_code,
|
||||
code.clone(),
|
||||
@@ -3133,6 +3119,14 @@ pub async fn handle_queued_job(
|
||||
_ => None,
|
||||
});
|
||||
|
||||
// Set job context for OTEL tracing before entering handle_code_execution_job's span
|
||||
#[cfg(all(feature = "private", feature = "enterprise"))]
|
||||
if matches!(job.script_lang, Some(ScriptLang::Nativets) | Some(ScriptLang::Bunnative))
|
||||
&& is_otel_tracing_proxy_enabled_for_lang(&ScriptLang::Nativets).await
|
||||
{
|
||||
crate::otel_tracing_proxy_ee::set_current_job_context(job.id).await;
|
||||
}
|
||||
|
||||
// Box::pin to move large future to heap
|
||||
let r = Box::pin(handle_code_execution_job(
|
||||
job.as_ref(),
|
||||
|
||||
Reference in New Issue
Block a user