Skip to content

Commit 609deb2

Browse files
committed
initial refactor with ETS for span storage
1 parent 08cec4c commit 609deb2

File tree

1 file changed

+53
-59
lines changed

1 file changed

+53
-59
lines changed
Lines changed: 53 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,82 @@
11
defmodule Sentry.Opentelemetry.SpanStorage do
22
use GenServer
33

4-
def start_link(_opts) do
5-
GenServer.start_link(__MODULE__, nil, name: __MODULE__)
6-
end
4+
@table :span_storage
75

8-
def init(_) do
9-
{:ok, %{root_spans: %{}, child_spans: %{}}}
6+
@spec start_link(keyword()) :: GenServer.on_start()
7+
def start_link(opts \\ []) do
8+
name = Keyword.get(opts, :name, __MODULE__)
9+
GenServer.start_link(__MODULE__, nil, name: name)
1010
end
1111

12-
def store_span(span_data) do
13-
GenServer.call(__MODULE__, {:store_span, span_data})
14-
end
12+
# start ets table on initialization
13+
@impl true
14+
def init(nil) do
15+
_table =
16+
if :ets.whereis(@table) == :undefined do
17+
:ets.new(@table, [:named_table, :public, :bag])
18+
end
1519

16-
def get_root_span(span_id) do
17-
GenServer.call(__MODULE__, {:get_root_span, span_id})
20+
{:ok, :no_state}
1821
end
1922

20-
def get_child_spans(parent_span_id) do
21-
GenServer.call(__MODULE__, {:get_child_spans, parent_span_id})
23+
def store_span(span_data) when span_data.parent_span_id == nil do
24+
_ = :ets.insert(@table, {{:root_span, span_data.span_id}, span_data})
2225
end
2326

24-
def update_span(span_data) do
25-
GenServer.call(__MODULE__, {:update_span, span_data})
27+
def store_span(span_data) do
28+
_ = :ets.insert(@table, {span_data.parent_span_id, span_data})
2629
end
2730

28-
def remove_span(span_id) do
29-
GenServer.call(__MODULE__, {:remove_span, span_id})
31+
def get_root_span(span_id) do
32+
case :ets.lookup(@table, {:root_span, span_id}) do
33+
[{{:root_span, ^span_id}, span}] -> span
34+
# how do we handle if span cannot be found?
35+
[] -> nil
36+
end
3037
end
3138

32-
def remove_child_spans(parent_span_id) do
33-
GenServer.call(__MODULE__, {:remove_child_spans, parent_span_id})
34-
end
39+
def get_child_spans(parent_span_id) do
40+
child_spans = :ets.lookup(@table, parent_span_id)
3541

36-
def handle_call({:store_span, span_data}, _from, state) do
37-
if span_data.parent_span_id == nil do
38-
new_state = put_in(state, [:root_spans, span_data.span_id], span_data)
39-
{:reply, :ok, new_state}
42+
if child_spans == [] do
43+
nil
4044
else
41-
new_state =
42-
update_in(state, [:child_spans, span_data.parent_span_id], fn spans ->
43-
(spans || []) ++ [span_data]
44-
end)
45-
46-
{:reply, :ok, new_state}
45+
Enum.map(child_spans, fn {parent_span_id, span} -> span end)
4746
end
4847
end
4948

50-
def handle_call({:get_root_span, span_id}, _from, state) do
51-
{:reply, state.root_spans[span_id], state}
52-
end
53-
54-
def handle_call({:get_child_spans, parent_span_id}, _from, state) do
55-
{:reply, state.child_spans[parent_span_id] || [], state}
56-
end
49+
def update_span(span_data) when span_data.parent_span_id == nil do
50+
case :ets.lookup(@table, {:root_span, span_data.span_id}) do
51+
[] ->
52+
:ets.insert(@table, {{:root_span, span_data.span_id}, span_data})
5753

58-
def handle_call({:update_span, span_data}, _from, state) do
59-
if span_data.parent_span_id == nil do
60-
new_state = put_in(state, [:root_spans, span_data.span_id], span_data)
61-
{:reply, :ok, new_state}
62-
else
63-
new_state =
64-
update_in(state, [:child_spans, span_data.parent_span_id], fn spans ->
65-
Enum.map(spans || [], fn span ->
66-
if span.span_id == span_data.span_id, do: span_data, else: span
67-
end)
68-
end)
69-
70-
{:reply, :ok, new_state}
54+
[{{:root_span, span_data.span_id}, span}] ->
55+
:ets.delete(@table, {:root_span, span_data.span_id})
56+
:ets.insert(@table, {{:root_span, span_data.span_id}, span_data})
7157
end
7258
end
7359

74-
def handle_call({:remove_span, span_id}, _from, state) do
75-
new_state = %{
76-
state
77-
| root_spans: Map.delete(state.root_spans, span_id),
78-
child_spans: Map.delete(state.child_spans, span_id)
79-
}
60+
def update_span(span_data) do
61+
existing_spans = :ets.lookup(@table, span_data.parent_span_id)
62+
63+
:ets.delete(@table, span_data.parent_span_id)
64+
65+
Enum.each(existing_spans, fn {parent_span_id, span} ->
66+
if span.span_id == span_data.span_id do
67+
:ets.delete_object(@table, span)
68+
:ets.insert(@table, {parent_span_id, span_data})
69+
end
70+
end)
71+
end
8072

81-
{:reply, :ok, new_state}
73+
def remove_span(span_id) do
74+
:ets.delete(@table, {:root_span, span_id})
75+
:ok
8276
end
8377

84-
def handle_call({:remove_child_spans, parent_span_id}, _from, state) do
85-
new_state = %{state | child_spans: Map.delete(state.child_spans, parent_span_id)}
86-
{:reply, :ok, new_state}
78+
def remove_child_spans(parent_span_id) do
79+
:ets.delete(@table, parent_span_id)
80+
:ok
8781
end
8882
end

0 commit comments

Comments
 (0)