|
1 | 1 | defmodule SentinelCp.Observability.Tracer do |
2 | 2 | @moduledoc """ |
3 | | - Telemetry-based tracing for key control plane operations. |
| 3 | + OpenTelemetry tracing for key control plane operations. |
4 | 4 |
|
5 | | - Wraps `:telemetry` to emit span events for bundle compilation, |
6 | | - rollout lifecycle, webhook processing, and node heartbeats. |
7 | | - Compatible with OpenTelemetry exporters when OTEL SDK is configured. |
| 5 | + Wraps `OpenTelemetry.Tracer.with_span/3` to create spans for bundle |
| 6 | + compilation, rollout lifecycle, webhook processing, and node heartbeats. |
8 | 7 | """ |
9 | 8 |
|
10 | | - require Logger |
| 9 | + require OpenTelemetry.Tracer, as: Tracer |
11 | 10 |
|
12 | 11 | @doc """ |
13 | | - Executes a function within a traced span. |
| 12 | + Executes a function within a traced OpenTelemetry span. |
14 | 13 |
|
15 | | - Emits `[:sentinel_cp, span_name, :start]` and `[:sentinel_cp, span_name, :stop]` |
16 | | - telemetry events with timing metadata. |
| 14 | + Attributes from the metadata map are set on the span. |
17 | 15 | """ |
18 | 16 | def span(span_name, metadata, fun) when is_atom(span_name) and is_map(metadata) do |
19 | | - start_time = System.monotonic_time() |
20 | | - trace_id = generate_trace_id() |
21 | | - |
22 | | - :telemetry.execute( |
23 | | - [:sentinel_cp, span_name, :start], |
24 | | - %{system_time: System.system_time()}, |
25 | | - Map.merge(metadata, %{trace_id: trace_id}) |
26 | | - ) |
27 | | - |
28 | | - try do |
29 | | - result = fun.() |
30 | | - |
31 | | - duration = System.monotonic_time() - start_time |
32 | | - |
33 | | - :telemetry.execute( |
34 | | - [:sentinel_cp, span_name, :stop], |
35 | | - %{duration: duration}, |
36 | | - Map.merge(metadata, %{trace_id: trace_id, result: :ok}) |
37 | | - ) |
38 | | - |
39 | | - result |
40 | | - rescue |
41 | | - e -> |
42 | | - duration = System.monotonic_time() - start_time |
43 | | - |
44 | | - :telemetry.execute( |
45 | | - [:sentinel_cp, span_name, :exception], |
46 | | - %{duration: duration}, |
47 | | - Map.merge(metadata, %{ |
48 | | - trace_id: trace_id, |
49 | | - kind: :error, |
50 | | - reason: Exception.message(e), |
51 | | - stacktrace: __STACKTRACE__ |
52 | | - }) |
53 | | - ) |
54 | | - |
55 | | - reraise e, __STACKTRACE__ |
| 17 | + attributes = Enum.map(metadata, fn {k, v} -> {to_string(k), to_string(v)} end) |
| 18 | + |
| 19 | + Tracer.with_span :"sentinel_cp.#{span_name}", %{attributes: attributes} do |
| 20 | + try do |
| 21 | + fun.() |
| 22 | + rescue |
| 23 | + e -> |
| 24 | + Tracer.set_status(:error, Exception.message(e)) |
| 25 | + reraise e, __STACKTRACE__ |
| 26 | + end |
56 | 27 | end |
57 | 28 | end |
58 | 29 |
|
@@ -83,20 +54,4 @@ defmodule SentinelCp.Observability.Tracer do |
83 | 54 | def trace_heartbeat(node_id, fun) do |
84 | 55 | span(:node_heartbeat, %{node_id: node_id}, fun) |
85 | 56 | end |
86 | | - |
87 | | - @doc """ |
88 | | - Returns all telemetry event prefixes emitted by the tracer. |
89 | | - """ |
90 | | - def event_prefixes do |
91 | | - [ |
92 | | - [:sentinel_cp, :bundle_compilation], |
93 | | - [:sentinel_cp, :rollout_tick], |
94 | | - [:sentinel_cp, :webhook_processing], |
95 | | - [:sentinel_cp, :node_heartbeat] |
96 | | - ] |
97 | | - end |
98 | | - |
99 | | - defp generate_trace_id do |
100 | | - :crypto.strong_rand_bytes(16) |> Base.hex_encode32(case: :lower, padding: false) |
101 | | - end |
102 | 57 | end |
0 commit comments