如何在tracing宏中记录带追踪的错误且不设置err字段?
问题:在
tracing中记录错误但不设置索引用的err字段? 我在处理函数里有验证API密钥的步骤,密钥无效时原本会记录错误,导致Datadog里有大量错误噪音。我想把认证失败只标记为警告而非错误,所以手动处理了认证错误用warn!宏,还从instrument过程宏里移除了err字段。
现在认证失败在Datadog里显示正常的绿色,但名称有效性检查这类真正应该失败的场景虽然显示红色,却没有错误日志。看起来移除err字段后,所有错误都不会被记录了。
有没有办法在tracing宏里记录错误,但不设置用于索引的err字段?
我的代码:
#[instrument( name = "ControlPlane.global.create", fields(index_name, project, environment), skip_all )] async fn create( state: State<GlobalAppState>, api_key: APIKey, headers: HeaderMap, index: LoggingJson<GlobalCreateIndexRequest>, ) -> Result<(StatusCode, Json<GlobalIndexMetadata>), ServerError> { let project_id = match authenticate(state.clone(), &api_key).await { Ok(id) => id, Err(e) => { let log_message = format!( "Authentication error in ControlPlane.global.create: code={:?}, message={:?}", e.error.code, e.error.message ); if e.error.code == ErrorCode::Unauthenticated { warn!(log_message); } else { error!(log_message); } return Err(e); } }; let name = index.0.name.as_str(); if let Err(e) = is_valid_resource_name(name) { let error_message = format!("Invalid index name: {:?}", e); error!(error_message); record!( "error" => &format!("{:?}", e) ); return Err(e.into()); } <other parts of the handler>
解决方案
可以通过两种方式实现需求,避开Datadog对err字段的索引逻辑,同时保留必要的错误日志:
1. 自定义错误字段名,不使用默认的err
直接在error!宏里用自定义字段记录错误详情,避开err这个被Datadog用作索引的字段名,比如用error_details:
if let Err(e) = is_valid_resource_name(name) { let error_msg = format!("Invalid index name: {:?}", e); // 用自定义字段记录错误,不触发Datadog的err索引逻辑 error!(message = %error_msg, error_details = ?e); return Err(e.into()); }
这样既会输出完整的错误日志,又不会让Datadog把这类错误归类到索引的错误统计里,同时能保留错误的具体信息。
2. 保留instrument的err字段,仅清除认证失败的字段值
如果想继续用instrument的自动错误注入,只需要在认证失败时手动清除err字段,其他错误正常保留:
#[instrument( name = "ControlPlane.global.create", fields(index_name, project, environment, err), // 重新添加err字段 skip_all )] async fn create(...) -> Result<...> { let project_id = match authenticate(state.clone(), &api_key).await { Ok(id) => id, Err(e) => { let log_message = format!( "Authentication error in ControlPlane.global.create: code={:?}, message={:?}", e.error.code, e.error.message ); if e.error.code == ErrorCode::Unauthenticated { warn!(log_message); // 手动清空err字段,避免被Datadog索引 tracing::field::Empty.record(&tracing::info_span!("err"), &()); } else { error!(log_message); } return Err(e); } }; // 名称验证错误无需额外处理,instrument会自动填充err字段 if let Err(e) = is_valid_resource_name(name) { error!("Invalid index name: {:?}", e); return Err(e.into()); } // ...其他逻辑 }
这种方式下,只有非认证类的错误会被Datadog索引统计,认证失败的警告不会产生错误噪音。
关键提示
tracing的instrument宏默认会在函数返回Err时自动填充err字段,移除该字段后就不会自动记录错误信息,必须手动在error!宏里补充详情。- 核心是避开
err这个字段名,或者在不需要索引的场景下手动清空它,就能实现“记录错误但不触发索引”的效果。
内容的提问来源于stack exchange,提问作者Aviral Srivastava
相关产品推荐
相关产品推荐

