storeTransaction stores a parsed transaction with its spans, upserting the trace registry entry. Returns the transaction's generated UUID.
(db *sql.DB, txn *Transaction, payload json.RawMessage)
| 13 | // storeTransaction stores a parsed transaction with its spans, upserting the |
| 14 | // trace registry entry. Returns the transaction's generated UUID. |
| 15 | func storeTransaction(db *sql.DB, txn *Transaction, payload json.RawMessage) (string, error) { |
| 16 | dbTx, err := db.Begin() |
| 17 | if err != nil { |
| 18 | return "", err |
| 19 | } |
| 20 | defer dbTx.Rollback() |
| 21 | |
| 22 | traceID := "" |
| 23 | if txn.Contexts != nil && txn.Contexts.Trace != nil { |
| 24 | traceID = txn.Contexts.Trace.TraceID |
| 25 | } |
| 26 | |
| 27 | if traceID == "" { |
| 28 | // Try to get trace_id from spans. |
| 29 | for _, s := range txn.Spans { |
| 30 | if s.TraceID != "" { |
| 31 | traceID = s.TraceID |
| 32 | break |
| 33 | } |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | if traceID == "" { |
| 38 | return "", fmt.Errorf("transaction has no trace_id") |
| 39 | } |
| 40 | |
| 41 | spanCount := len(txn.Spans) |
| 42 | |
| 43 | // Upsert sentry_traces. |
| 44 | _, err = dbTx.Exec( |
| 45 | `INSERT INTO sentry_traces (trace_id, span_count) |
| 46 | VALUES (?, ?) |
| 47 | ON CONFLICT(trace_id) DO UPDATE SET |
| 48 | last_seen = datetime('now'), |
| 49 | span_count = sentry_traces.span_count + excluded.span_count`, |
| 50 | traceID, spanCount, |
| 51 | ) |
| 52 | if err != nil { |
| 53 | return "", fmt.Errorf("upsert sentry_traces: %w", err) |
| 54 | } |
| 55 | |
| 56 | // Insert transaction. |
| 57 | txnID := event.GenerateUUID() |
| 58 | startTS := parseTimestamp(txn.StartTime) |
| 59 | endTS := parseTimestamp(txn.Timestamp) |
| 60 | durationMS := computeDurationMS(txn.StartTime, txn.Timestamp) |
| 61 | |
| 62 | op := txn.Op |
| 63 | status := txn.Status |
| 64 | // Fallback: extract op/status from contexts.trace if not on root. |
| 65 | if op == "" && txn.Contexts != nil && txn.Contexts.Trace != nil { |
| 66 | // Some SDKs put these in the transaction's contexts.trace. |
| 67 | } |
| 68 | |
| 69 | var measurements *string |
| 70 | if txn.Measurements != nil { |
| 71 | s := string(txn.Measurements) |
| 72 | measurements = &s |