Tracing: DAO layer + handler spans on tracing, drop all Context params (#141)
trace_db_call no longer takes an OpenTelemetry Context: it opens a db.<query_type>.<operation> span (same name via otel.name, same db.query_type / db.operation attrs) on the caller's ambient tracing span and runs the DAO body inside it. The cx / ctx / context parameter is gone from every DAO trait method, impl and call site, and from the helpers and background drains that only threaded it. The remaining request-handler spans (files, tags, faces, image, video, favorites, duplicates, memories) move to #[instrument]; the Context::current_with_span / with_remote_span_context plumbing is gone, as is extract_context_from_request (the tracing-actix-web root span covers it). otel::set_span_attributes replaces BoxedSpan::set_attributes. Background-job raw spans (thumbnails, video actors) are left for #142. tests/otel_db_spans.rs pins name, attributes, status and nesting (across an instrumented spawn); otel_traceparent now uses an #[instrument] handler. CLAUDE.md documents the tracing conventions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1c508cdabd
commit
b6deca2a52
55 files changed
+1942
-3852
No files matched your search
+19
-31
@@ -156,7 +156,6 @@ async fn process_one(
|
||||
orientation: None,
|
||||
model_version: None,
|
||||
};
|
||||
let ctx = opentelemetry::Context::current();
|
||||
|
||||
match face_client.detect(bytes, meta).await {
|
||||
Ok(resp) => {
|
||||
@@ -167,7 +166,6 @@ async fn process_one(
|
||||
let mut dao = face_dao.lock().expect("face dao");
|
||||
if resp.faces.is_empty() {
|
||||
if let Err(e) = dao.mark_status(
|
||||
&ctx,
|
||||
library_id,
|
||||
&cand.content_hash,
|
||||
&cand.rel_path,
|
||||
@@ -195,21 +193,18 @@ async fn process_one(
|
||||
};
|
||||
// Decode the f32 vector once for auto-bind comparison.
|
||||
let emb_floats = faces::decode_embedding_bytes(&emb);
|
||||
match dao.store_detection(
|
||||
&ctx,
|
||||
InsertFaceDetectionInput {
|
||||
library_id,
|
||||
content_hash: cand.content_hash.clone(),
|
||||
rel_path: cand.rel_path.clone(),
|
||||
bbox: Some((face.bbox.x, face.bbox.y, face.bbox.w, face.bbox.h)),
|
||||
embedding: Some(emb),
|
||||
confidence: Some(face.confidence),
|
||||
source: "auto".to_string(),
|
||||
person_id: None,
|
||||
status: "detected".to_string(),
|
||||
model_version: resp.model_version.clone(),
|
||||
},
|
||||
) {
|
||||
match dao.store_detection(InsertFaceDetectionInput {
|
||||
library_id,
|
||||
content_hash: cand.content_hash.clone(),
|
||||
rel_path: cand.rel_path.clone(),
|
||||
bbox: Some((face.bbox.x, face.bbox.y, face.bbox.w, face.bbox.h)),
|
||||
embedding: Some(emb),
|
||||
confidence: Some(face.confidence),
|
||||
source: "auto".to_string(),
|
||||
person_id: None,
|
||||
status: "detected".to_string(),
|
||||
model_version: resp.model_version.clone(),
|
||||
}) {
|
||||
Ok(row) => {
|
||||
if let Some(floats) = emb_floats {
|
||||
stored_for_autobind.push((row.id, floats));
|
||||
@@ -233,7 +228,6 @@ async fn process_one(
|
||||
// serialize with concurrent detect tasks.
|
||||
if !stored_for_autobind.is_empty() {
|
||||
try_auto_bind(
|
||||
&ctx,
|
||||
&cand.rel_path,
|
||||
&resp.model_version,
|
||||
stored_for_autobind,
|
||||
@@ -251,14 +245,9 @@ async fn process_one(
|
||||
// model_version is best-effort here — the engine that rejected
|
||||
// the bytes may not have echoed one. Empty string is fine; this
|
||||
// row is purely a "don't retry" sentinel.
|
||||
if let Err(e) = dao.mark_status(
|
||||
&ctx,
|
||||
library_id,
|
||||
&cand.content_hash,
|
||||
&cand.rel_path,
|
||||
"failed",
|
||||
"",
|
||||
) {
|
||||
if let Err(e) =
|
||||
dao.mark_status(library_id, &cand.content_hash, &cand.rel_path, "failed", "")
|
||||
{
|
||||
warn!(
|
||||
"face_watch: mark failed errored for {}: {:?}",
|
||||
cand.rel_path, e
|
||||
@@ -293,7 +282,6 @@ async fn process_one(
|
||||
/// additional matching. Those faces stay unassigned for the cluster
|
||||
/// suggester (Phase 6) to handle.
|
||||
fn try_auto_bind(
|
||||
ctx: &opentelemetry::Context,
|
||||
rel_path: &str,
|
||||
model_version: &str,
|
||||
new_faces: Vec<(i32, Vec<f32>)>, // (face_id, decoded embedding)
|
||||
@@ -303,7 +291,7 @@ fn try_auto_bind(
|
||||
// 1. Pull the photo's tags.
|
||||
let tag_names: Vec<String> = {
|
||||
let mut td = tag_dao.lock().expect("tag dao");
|
||||
match td.get_tags_for_path(ctx, rel_path) {
|
||||
match td.get_tags_for_path(rel_path) {
|
||||
Ok(tags) => tags.into_iter().map(|t| t.name).collect(),
|
||||
Err(e) => {
|
||||
warn!(
|
||||
@@ -321,7 +309,7 @@ fn try_auto_bind(
|
||||
// 2. Find tags that map to existing persons (case-insensitive).
|
||||
let person_for_tag: std::collections::HashMap<String, i32> = {
|
||||
let mut fd = face_dao.lock().expect("face dao");
|
||||
match fd.find_persons_by_names_ci(ctx, &tag_names) {
|
||||
match fd.find_persons_by_names_ci(&tag_names) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
warn!(
|
||||
@@ -357,7 +345,7 @@ fn try_auto_bind(
|
||||
// 4. Reference embedding (if any) under the same model_version.
|
||||
let reference: Option<Vec<f32>> = {
|
||||
let mut fd = face_dao.lock().expect("face dao");
|
||||
match fd.person_reference_embedding(ctx, person_id, model_version) {
|
||||
match fd.person_reference_embedding(person_id, model_version) {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
warn!(
|
||||
@@ -402,7 +390,7 @@ fn try_auto_bind(
|
||||
}
|
||||
}
|
||||
};
|
||||
if bind && let Err(e) = fd.assign_face_to_person(ctx, face_id, person_id) {
|
||||
if bind && let Err(e) = fd.assign_face_to_person(face_id, person_id) {
|
||||
warn!(
|
||||
"face_watch: assign_face_to_person failed (face={}, person={}): {:?}",
|
||||
face_id, person_id, e
|
||||
|
||||
Reference in new issue
Block a user