fix: gracefully handle uninitialized OTEL tracing proxy port (#8274)
* fix: gracefully handle uninitialized OTEL tracing proxy port When OTEL tracing proxy is enabled but the MITM proxy port hasn't been assigned yet (race condition at startup, or NUM_WORKERS > 1), fall back to standard proxy envs instead of failing the job with "OTEL tracing proxy port not initialized". Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: log to job logs when OTEL tracing proxy is unavailable When the OTEL tracing proxy is enabled but the port isn't initialized (race at startup or NUM_WORKERS > 1), append a warning to the job logs explaining why HTTP request tracing is unavailable for that job. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -215,7 +215,10 @@ exit $exit_status
|
||||
.current_dir(job_dir)
|
||||
.env_clear()
|
||||
.envs(reserved_variables)
|
||||
.envs(get_proxy_envs_for_lang(&ScriptLang::Bash).await?)
|
||||
.envs(
|
||||
get_proxy_envs_for_lang(&ScriptLang::Bash, &job.id, &job.workspace_id, conn)
|
||||
.await?,
|
||||
)
|
||||
.env("PATH", PATH_ENV.as_str())
|
||||
.env("BASE_INTERNAL_URL", base_internal_url)
|
||||
.args(cmd_args)
|
||||
@@ -241,7 +244,10 @@ exit $exit_status
|
||||
.env_clear()
|
||||
.envs(envs)
|
||||
.envs(reserved_variables)
|
||||
.envs(get_proxy_envs_for_lang(&ScriptLang::Bash).await?)
|
||||
.envs(
|
||||
get_proxy_envs_for_lang(&ScriptLang::Bash, &job.id, &job.workspace_id, conn)
|
||||
.await?,
|
||||
)
|
||||
.env("PATH", PATH_ENV.as_str())
|
||||
.env("BASE_INTERNAL_URL", base_internal_url)
|
||||
.env("HOME", HOME_ENV.as_str())
|
||||
|
||||
@@ -1564,7 +1564,9 @@ try {{
|
||||
.env_clear()
|
||||
.envs(envs)
|
||||
.envs(reserved_variables)
|
||||
.envs(get_proxy_envs_for_lang(&ScriptLang::Bun).await?)
|
||||
.envs(
|
||||
get_proxy_envs_for_lang(&ScriptLang::Bun, &job.id, &job.workspace_id, conn).await?,
|
||||
)
|
||||
.envs(common_bun_proc_envs)
|
||||
.env("PATH", PATH_ENV.as_str())
|
||||
.args(args)
|
||||
@@ -1582,7 +1584,10 @@ try {{
|
||||
.env_clear()
|
||||
.envs(envs)
|
||||
.envs(reserved_variables)
|
||||
.envs(get_proxy_envs_for_lang(&ScriptLang::Bun).await?)
|
||||
.envs(
|
||||
get_proxy_envs_for_lang(&ScriptLang::Bun, &job.id, &job.workspace_id, conn)
|
||||
.await?,
|
||||
)
|
||||
.envs(common_bun_proc_envs)
|
||||
.stdin(Stdio::null())
|
||||
.stdout(Stdio::piped())
|
||||
@@ -1613,7 +1618,10 @@ try {{
|
||||
.env_clear()
|
||||
.envs(envs)
|
||||
.envs(reserved_variables)
|
||||
.envs(get_proxy_envs_for_lang(&ScriptLang::Bun).await?)
|
||||
.envs(
|
||||
get_proxy_envs_for_lang(&ScriptLang::Bun, &job.id, &job.workspace_id, conn)
|
||||
.await?,
|
||||
)
|
||||
.envs(common_bun_proc_envs)
|
||||
.stdin(Stdio::null())
|
||||
.stdout(Stdio::piped())
|
||||
|
||||
@@ -600,7 +600,10 @@ pub async fn handle_csharp_job(
|
||||
.env_clear()
|
||||
.envs(envs)
|
||||
.envs(reserved_variables)
|
||||
.envs(get_proxy_envs_for_lang(&ScriptLang::CSharp).await?)
|
||||
.envs(
|
||||
get_proxy_envs_for_lang(&ScriptLang::CSharp, &job.id, &job.workspace_id, conn)
|
||||
.await?,
|
||||
)
|
||||
.env("PATH", PATH_ENV.as_str())
|
||||
.env("TZ", TZ_ENV.as_str())
|
||||
.env("BASE_INTERNAL_URL", base_internal_url)
|
||||
@@ -633,7 +636,10 @@ pub async fn handle_csharp_job(
|
||||
.env_clear()
|
||||
.envs(envs)
|
||||
.envs(reserved_variables)
|
||||
.envs(get_proxy_envs_for_lang(&ScriptLang::CSharp).await?)
|
||||
.envs(
|
||||
get_proxy_envs_for_lang(&ScriptLang::CSharp, &job.id, &job.workspace_id, conn)
|
||||
.await?,
|
||||
)
|
||||
.env("PATH", PATH_ENV.as_str())
|
||||
.env("TZ", TZ_ENV.as_str())
|
||||
.env("DOTNET_CLI_HOME", &*CSHARP_CACHE_DIR)
|
||||
|
||||
@@ -121,11 +121,13 @@ async fn get_common_deno_proc_envs(
|
||||
}
|
||||
|
||||
// Add proxy envs (including OTEL tracing proxy if enabled for deno)
|
||||
for (k, v) in get_proxy_envs_for_lang(&ScriptLang::Deno)
|
||||
.await
|
||||
.unwrap_or_default()
|
||||
{
|
||||
deno_envs.insert(k.to_string(), v);
|
||||
if let Some(conn) = conn {
|
||||
for (k, v) in get_proxy_envs_for_lang(&ScriptLang::Deno, job_id, w_id, conn)
|
||||
.await
|
||||
.unwrap_or_default()
|
||||
{
|
||||
deno_envs.insert(k.to_string(), v);
|
||||
}
|
||||
}
|
||||
|
||||
return deno_envs;
|
||||
|
||||
@@ -354,7 +354,7 @@ func Run(req Req) (interface{{}}, error){{
|
||||
.env_clear()
|
||||
.envs(envs)
|
||||
.envs(reserved_variables)
|
||||
.envs(get_proxy_envs_for_lang(&ScriptLang::Go).await?)
|
||||
.envs(get_proxy_envs_for_lang(&ScriptLang::Go, &job.id, &job.workspace_id, conn).await?)
|
||||
.env("PATH", PATH_ENV.as_str())
|
||||
.env("TZ", TZ_ENV.as_str())
|
||||
.env("BASE_INTERNAL_URL", base_internal_url)
|
||||
@@ -375,7 +375,7 @@ func Run(req Req) (interface{{}}, error){{
|
||||
.env_clear()
|
||||
.envs(envs)
|
||||
.envs(reserved_variables)
|
||||
.envs(get_proxy_envs_for_lang(&ScriptLang::Go).await?)
|
||||
.envs(get_proxy_envs_for_lang(&ScriptLang::Go, &job.id, &job.workspace_id, conn).await?)
|
||||
.env("PATH", PATH_ENV.as_str())
|
||||
.env("TZ", TZ_ENV.as_str())
|
||||
.env("BASE_INTERNAL_URL", base_internal_url)
|
||||
|
||||
@@ -264,7 +264,7 @@ async fn run<'a>(
|
||||
.env("BASE_INTERNAL_URL", base_internal_url)
|
||||
.envs(envs)
|
||||
.envs(reserved_variables)
|
||||
.envs(get_proxy_envs_for_lang(&ScriptLang::Nu).await?)
|
||||
.envs(get_proxy_envs_for_lang(&ScriptLang::Nu, &job.id, &job.workspace_id, conn).await?)
|
||||
.args(vec![
|
||||
"--config",
|
||||
"run.config.proto",
|
||||
@@ -303,7 +303,7 @@ async fn run<'a>(
|
||||
.env("BASE_INTERNAL_URL", base_internal_url)
|
||||
.envs(envs)
|
||||
.envs(reserved_variables)
|
||||
.envs(get_proxy_envs_for_lang(&ScriptLang::Nu).await?)
|
||||
.envs(get_proxy_envs_for_lang(&ScriptLang::Nu, &job.id, &job.workspace_id, conn).await?)
|
||||
// TODO(v1):
|
||||
// "--plugins",
|
||||
// &format!(
|
||||
|
||||
@@ -841,7 +841,10 @@ mount {{
|
||||
.env_clear()
|
||||
// inject PYTHONPATH here - for some reason I had to do it in nsjail conf
|
||||
.envs(reserved_variables)
|
||||
.envs(get_proxy_envs_for_lang(&ScriptLang::Python3).await?)
|
||||
.envs(
|
||||
get_proxy_envs_for_lang(&ScriptLang::Python3, &job.id, &job.workspace_id, conn)
|
||||
.await?,
|
||||
)
|
||||
.env("PATH", PATH_ENV.as_str())
|
||||
.env("TZ", TZ_ENV.as_str())
|
||||
.env("BASE_INTERNAL_URL", base_internal_url)
|
||||
@@ -867,7 +870,10 @@ mount {{
|
||||
.env_clear()
|
||||
.envs(envs)
|
||||
.envs(reserved_variables)
|
||||
.envs(get_proxy_envs_for_lang(&ScriptLang::Python3).await?)
|
||||
.envs(
|
||||
get_proxy_envs_for_lang(&ScriptLang::Python3, &job.id, &job.workspace_id, conn)
|
||||
.await?,
|
||||
)
|
||||
.env("PATH", PATH_ENV.as_str())
|
||||
.env("TZ", TZ_ENV.as_str())
|
||||
.env("BASE_INTERNAL_URL", base_internal_url)
|
||||
|
||||
@@ -812,7 +812,10 @@ mount {{
|
||||
.envs(envs)
|
||||
.envs(reserved_variables)
|
||||
.envs(RUBY_PROXY_ENVS.clone())
|
||||
.envs(get_proxy_envs_for_lang(&ScriptLang::Ruby).await?)
|
||||
.envs(
|
||||
get_proxy_envs_for_lang(&ScriptLang::Ruby, &job.id, &job.workspace_id, conn)
|
||||
.await?,
|
||||
)
|
||||
.args(vec![
|
||||
"--config",
|
||||
"run.config.proto",
|
||||
@@ -851,7 +854,10 @@ mount {{
|
||||
.env("BASE_INTERNAL_URL", base_internal_url)
|
||||
.envs(reserved_variables)
|
||||
.envs(RUBY_PROXY_ENVS.clone())
|
||||
.envs(get_proxy_envs_for_lang(&ScriptLang::Ruby).await?)
|
||||
.envs(
|
||||
get_proxy_envs_for_lang(&ScriptLang::Ruby, &job.id, &job.workspace_id, conn)
|
||||
.await?,
|
||||
)
|
||||
.envs(envs);
|
||||
|
||||
cmd.stdin(Stdio::null())
|
||||
|
||||
@@ -700,7 +700,10 @@ pub async fn handle_rust_job(
|
||||
.env_clear()
|
||||
.envs(envs)
|
||||
.envs(reserved_variables)
|
||||
.envs(get_proxy_envs_for_lang(&ScriptLang::Rust).await?)
|
||||
.envs(
|
||||
get_proxy_envs_for_lang(&ScriptLang::Rust, &job.id, &job.workspace_id, conn)
|
||||
.await?,
|
||||
)
|
||||
.env("PATH", PATH_ENV.as_str())
|
||||
.env("TZ", TZ_ENV.as_str())
|
||||
.env("BASE_INTERNAL_URL", base_internal_url)
|
||||
@@ -716,7 +719,10 @@ pub async fn handle_rust_job(
|
||||
.env_clear()
|
||||
.envs(envs)
|
||||
.envs(reserved_variables)
|
||||
.envs(get_proxy_envs_for_lang(&ScriptLang::Rust).await?)
|
||||
.envs(
|
||||
get_proxy_envs_for_lang(&ScriptLang::Rust, &job.id, &job.workspace_id, conn)
|
||||
.await?,
|
||||
)
|
||||
.env("PATH", PATH_ENV.as_str())
|
||||
.env("TZ", TZ_ENV.as_str())
|
||||
.env("BASE_INTERNAL_URL", base_internal_url)
|
||||
|
||||
@@ -745,21 +745,37 @@ pub async fn is_otel_tracing_proxy_enabled_for_lang(lang: &ScriptLang) -> bool {
|
||||
/// Otherwise, uses the standard HTTP_PROXY/HTTPS_PROXY from environment.
|
||||
pub async fn get_proxy_envs_for_lang(
|
||||
lang: &ScriptLang,
|
||||
job_id: &uuid::Uuid,
|
||||
w_id: &str,
|
||||
conn: &Connection,
|
||||
) -> anyhow::Result<Vec<(&'static str, String)>> {
|
||||
#[cfg(all(feature = "private", feature = "enterprise"))]
|
||||
if is_otel_tracing_proxy_enabled_for_lang(lang).await {
|
||||
return get_otel_tracing_proxy_envs().await;
|
||||
return get_otel_tracing_proxy_envs(job_id, w_id, conn).await;
|
||||
}
|
||||
let _ = lang;
|
||||
let _ = (lang, job_id, w_id, conn);
|
||||
Ok(PROXY_ENVS.clone())
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "private", feature = "enterprise"))]
|
||||
async fn get_otel_tracing_proxy_envs() -> anyhow::Result<Vec<(&'static str, String)>> {
|
||||
let port = crate::otel_tracing_proxy_ee::TRACING_PROXY_PORT
|
||||
async fn get_otel_tracing_proxy_envs(
|
||||
job_id: &uuid::Uuid,
|
||||
w_id: &str,
|
||||
conn: &Connection,
|
||||
) -> anyhow::Result<Vec<(&'static str, String)>> {
|
||||
let port = match *crate::otel_tracing_proxy_ee::TRACING_PROXY_PORT
|
||||
.read()
|
||||
.await
|
||||
.ok_or_else(|| anyhow::anyhow!("OTEL tracing proxy port not initialized"))?;
|
||||
{
|
||||
Some(p) => p,
|
||||
None => {
|
||||
let reason = "OTEL tracing proxy is enabled but not available (not initialized yet, or NUM_WORKERS > 1). \
|
||||
This job's HTTP requests will not be traced.";
|
||||
tracing::warn!("{}", reason);
|
||||
append_logs(job_id, w_id, format!("\n[warning] {reason}\n"), conn).await;
|
||||
return Ok(PROXY_ENVS.clone());
|
||||
}
|
||||
};
|
||||
let proxy_url = format!("http://127.0.0.1:{}", port);
|
||||
Ok(vec![
|
||||
("HTTP_PROXY", proxy_url.clone()),
|
||||
|
||||
Reference in New Issue
Block a user