Skip to content
This repository was archived by the owner on Jul 31, 2023. It is now read-only.

Commit 60077b8

Browse files
haulethdeadtrickster
authored andcommitted
Allow registering multiple span reporters (#130)
Merge `oc_reporter_sequential` with `oc_reporter` to allow defining multiple reporters at once. Additionally this allows registering new reporters during runtime (no deregistering available). This makes `oc_reporter` API similar to the `oc_stats_reporter`. Marked as breaking change as: - configuration option `reporter` was removed and replaced with option `reporters`, which takes a list of `{Reporter, Options}` tuples or just `Reporter` atoms. In the second case `[]` will be used as `Options`. - removed `oc_reporter_sequential` as it is no longer needed - removed `oc_reporter_noop` as it can be replaced by setting `reporters` configuration option to `[]` (empty list, this is default) Close #116
1 parent 6cf47ea commit 60077b8

File tree

9 files changed

+87
-98
lines changed

9 files changed

+87
-98
lines changed

src/oc_reporter.erl

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,12 @@
2020

2121
-behaviour(gen_server).
2222

23+
-compile({no_auto_import, [register/2]}).
24+
2325
-export([start_link/0,
24-
store_span/1]).
26+
store_span/1,
27+
register/1,
28+
register/2]).
2529

2630
-export([init/1,
2731
handle_call/3,
@@ -46,8 +50,7 @@
4650
%% until it returns.
4751
-callback report(nonempty_list(opencensus:span()), opts()) -> ok.
4852

49-
-record(state, {reporter :: module(),
50-
reporter_config :: #{},
53+
-record(state, {reporters :: [{module(), term()}],
5154
send_interval_ms :: integer(),
5255
timer_ref :: reference()}).
5356

@@ -59,6 +62,18 @@ start_link() ->
5962
maybe_init_ets(),
6063
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
6164

65+
%% @doc
66+
%% @equiv register(Reporter, []).
67+
%% @end
68+
register(Reporter) -> register(Reporter, []).
69+
70+
%% @doc
71+
%% Register new traces reporter `Reporter' with `Config'.
72+
%% @end
73+
-spec register(module(), term()) -> ok.
74+
register(Reporter, Options) ->
75+
gen_server:call(?MODULE, {register, init_reporter({Reporter, Options})}).
76+
6277
-spec store_span(opencensus:span()) -> true | {error, invalid_span} | {error, no_report_buffer}.
6378
store_span(Span=#span{}) ->
6479
try
@@ -73,27 +88,26 @@ store_span(_) ->
7388

7489
init(_Args) ->
7590
SendInterval = application:get_env(opencensus, send_interval_ms, 500),
76-
{Reporter, ReporterOpts} = application:get_env(opencensus, reporter, {oc_reporter_noop, []}),
77-
ReporterConfig = Reporter:init(ReporterOpts),
91+
Reporters = [init_reporter(Config) || Config <- application:get_env(opencensus, reporters, [])],
7892
Ref = erlang:send_after(SendInterval, self(), report_spans),
79-
{ok, #state{reporter=Reporter,
80-
reporter_config=ReporterConfig,
93+
{ok, #state{reporters=Reporters,
8194
send_interval_ms=SendInterval,
8295
timer_ref=Ref}}.
8396

97+
handle_call({register, Reporter}, _From, #state{reporters=Reporters} = State) ->
98+
{reply, ok, State#state{reporters=[Reporter | Reporters]}};
8499
handle_call(_, _From, State) ->
85100
{noreply, State}.
86101

87102
handle_cast(_, State) ->
88103
{noreply, State}.
89104

90-
handle_info(report_spans, State=#state{reporter=Reporter,
91-
reporter_config=Config,
105+
handle_info(report_spans, State=#state{reporters=Reporters,
92106
send_interval_ms=SendInterval,
93107
timer_ref=Ref}) ->
94108
erlang:cancel_timer(Ref),
95109
Ref1 = erlang:send_after(SendInterval, self(), report_spans),
96-
send_spans(Reporter, Config),
110+
send_spans(Reporters),
97111
{noreply, State#state{timer_ref=Ref1}}.
98112

99113
code_change(_, State, _) ->
@@ -103,6 +117,11 @@ terminate(_, #state{timer_ref=Ref}) ->
103117
erlang:cancel_timer(Ref),
104118
ok.
105119

120+
init_reporter({Reporter, Config}) ->
121+
{Reporter, Reporter:init(Config)};
122+
init_reporter(Reporter) when is_atom(Reporter) ->
123+
{Reporter, Reporter:init([])}.
124+
106125
maybe_init_ets() ->
107126
case ets:info(?BUFFER_STATUS, name) of
108127
undefined ->
@@ -115,7 +134,7 @@ maybe_init_ets() ->
115134
ok
116135
end.
117136

118-
send_spans(Reporter, Config) ->
137+
send_spans(Reporters) ->
119138
[{_, Buffer}] = ets:lookup(?BUFFER_STATUS, current_buffer),
120139
NewBuffer = case Buffer of
121140
?BUFFER_1 ->
@@ -129,8 +148,9 @@ send_spans(Reporter, Config) ->
129148
ok;
130149
Spans ->
131150
ets:delete_all_objects(Buffer),
132-
report(Reporter, Spans, Config)
133-
151+
[report(Reporter, Spans, Config)
152+
|| {Reporter, Config} <- Reporters],
153+
ok
134154
end.
135155

136156
report(undefined, _, _) ->

src/oc_reporter_noop.erl

Lines changed: 0 additions & 29 deletions
This file was deleted.

src/oc_reporter_sequential.erl

Lines changed: 0 additions & 38 deletions
This file was deleted.

test/oc_reporter_pid.erl

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,8 @@
2222
-export([init/1,
2323
report/2]).
2424

25-
init(_) ->
26-
application:get_env(opencensus, pid_reporter, #{}).
25+
init(Pid) -> Pid.
2726

28-
report(Spans, Opts) ->
29-
Pid = maps:get(pid, Opts),
27+
report(Spans, Pid) ->
3028
[Pid ! {span, Span} || Span <- Spans],
3129
ok.

test/oc_reporters_SUITE.erl

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
all() ->
1515
[pid_reporter,
16+
dynamically_register_reporter,
1617
sequential_reporter].
1718

1819
init_per_suite(Config) ->
@@ -25,15 +26,16 @@ end_per_suite(_Config) ->
2526

2627
init_per_testcase(pid_reporter, Config) ->
2728
application:set_env(opencensus, send_interval_ms, 1),
28-
application:set_env(opencensus, reporter, {oc_reporter_pid, []}),
29-
application:set_env(opencensus, pid_reporter, #{pid => self()}),
29+
application:set_env(opencensus, reporters, [{oc_reporter_pid, self()}]),
30+
{ok, _} = application:ensure_all_started(opencensus),
31+
Config;
32+
init_per_testcase(dynamically_register_reporter, Config) ->
33+
application:set_env(opencensus, send_interval_ms, 1),
3034
{ok, _} = application:ensure_all_started(opencensus),
3135
Config;
3236
init_per_testcase(sequential_reporter, Config) ->
3337
application:set_env(opencensus, send_interval_ms, 1),
34-
application:set_env(opencensus, reporter, {oc_reporter_sequential, [{oc_reporter_pid, []},
35-
{oc_reporter_pid, []}]}),
36-
application:set_env(opencensus, pid_reporter, #{pid => self()}),
38+
application:set_env(opencensus, reporters, [{oc_reporter_pid, self()}, {oc_reporter_pid, self()}]),
3739
{ok, _} = application:ensure_all_started(opencensus),
3840
Config.
3941

@@ -65,6 +67,39 @@ pid_reporter(_Config) ->
6567
andalso is_integer(O), S#span.start_time),
6668
?assertMatch({ST, O} when is_integer(ST)
6769
andalso is_integer(O), S#span.end_time)
70+
after
71+
5000 -> ct:fail("Do not received any message in requested time (5s)")
72+
end
73+
end, [SpanName1, ChildSpanName1]).
74+
75+
dynamically_register_reporter(_Config) ->
76+
oc_reporter:register(oc_reporter_pid, self()),
77+
78+
SpanName1 = <<"span-1">>,
79+
SpanCtx = oc_trace:start_span(SpanName1, undefined),
80+
81+
ChildSpanName1 = <<"child-span-1">>,
82+
ChildSpanCtx = oc_trace:start_span(ChildSpanName1, SpanCtx),
83+
84+
[ChildSpanData] = ets:lookup(?SPAN_TAB, ChildSpanCtx#span_ctx.span_id),
85+
?assertEqual(ChildSpanName1, ChildSpanData#span.name),
86+
?assertEqual(SpanCtx#span_ctx.span_id, ChildSpanData#span.parent_span_id),
87+
88+
oc_trace:finish_span(ChildSpanCtx),
89+
oc_trace:finish_span(SpanCtx),
90+
91+
%% Order the spans are reported is undefined, so use a selective receive to make
92+
%% sure we get them all
93+
lists:foreach(fun(Name) ->
94+
receive
95+
{span, S=#span{name = Name}} ->
96+
%% Verify the end time and duration are set when the span was finished
97+
?assertMatch({ST, O} when is_integer(ST)
98+
andalso is_integer(O), S#span.start_time),
99+
?assertMatch({ST, O} when is_integer(ST)
100+
andalso is_integer(O), S#span.end_time)
101+
after
102+
5000 -> ct:fail("Do not received any message in requested time (5s)")
68103
end
69104
end, [SpanName1, ChildSpanName1]).
70105

@@ -90,4 +125,3 @@ sequential_reporter(_Config) ->
90125
end, SortedNames), %% receive order is undefined though
91126

92127
?assertMatch(SortedNames, lists:sort(Received)).
93-

test/oc_sweeper_SUITE.erl

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ init_per_testcase(storage_size, Config) ->
3434
storage_size => 100}),
3535

3636
application:set_env(opencensus, send_interval_ms, 1),
37-
application:set_env(opencensus, reporter, {oc_reporter_pid, []}),
38-
application:set_env(opencensus, pid_reporter, #{pid => self()}),
37+
application:set_env(opencensus, reporters, [{oc_reporter_pid, self()}]),
3938
{ok, _} = application:ensure_all_started(opencensus),
4039
Config;
4140
init_per_testcase(Type, Config) ->
@@ -44,8 +43,7 @@ init_per_testcase(Type, Config) ->
4443
span_ttl => 500}),
4544

4645
application:set_env(opencensus, send_interval_ms, 1),
47-
application:set_env(opencensus, reporter, {oc_reporter_pid, []}),
48-
application:set_env(opencensus, pid_reporter, #{pid => self()}),
46+
application:set_env(opencensus, reporters, [{oc_reporter_pid, self()}]),
4947
{ok, _} = application:ensure_all_started(opencensus),
5048
Config.
5149

@@ -104,6 +102,8 @@ drop(_Config) ->
104102
andalso is_integer(O), S#span.start_time),
105103
?assertMatch({ST, O} when is_integer(ST)
106104
andalso is_integer(O), S#span.end_time)
105+
after
106+
1000 -> ct:fail("Do not received any message after 1s")
107107
end,
108108

109109
%% sleep long enough that the reporter would have run again for sure
@@ -137,6 +137,8 @@ finish(_Config) ->
137137
andalso is_integer(O), S#span.start_time),
138138
?assertMatch({ST, O} when is_integer(ST)
139139
andalso is_integer(O), S#span.end_time)
140+
after
141+
1000 -> ct:fail("Do not received any message after 1s")
140142
end
141143
end, [SpanName1, ChildSpanName1]).
142144

@@ -167,4 +169,6 @@ failed_attribute_and_finish(_Config) ->
167169
andalso is_integer(O), S#span.start_time),
168170
?assertMatch({ST, O} when is_integer(ST)
169171
andalso is_integer(O), S#span.end_time)
172+
after
173+
1000 -> ct:fail("Do not received any message after 1s")
170174
end.

test/oc_transform_SUITE.erl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ end_per_suite(_Config) ->
2525
ok.
2626

2727
init_per_testcase(_, Config) ->
28-
application:set_env(opencensus, reporter, {oc_reporter_pid, []}),
28+
application:set_env(opencensus, reporters, [{oc_reporter_pid, self()}]),
2929
application:set_env(opencensus, pid_reporter, #{pid => self()}),
3030

3131
{ok, _} = application:ensure_all_started(opencensus),
@@ -52,7 +52,7 @@ trace_transform(_Config) ->
5252
?assertMatch({ST, O} when is_integer(ST)
5353
andalso is_integer(O), S#span.end_time)
5454
after 1000 ->
55-
error(timeout)
55+
ct:fail("Did not receive any message in 1s")
5656
end
5757
end, [SpanName1, <<"oc_transform_SUITE:traced_function/0">>, <<"my_name">>]).
5858

test/ocp_SUITE.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ init_per_testcase(_, Config) ->
3030
Tab = ets:new(reporter_tab, [public, {write_concurrency, true},
3131
{read_concurrency, true}, {keypos, #span.span_id}]),
3232
application:set_env(opencensus, send_interval_ms, 1),
33-
application:set_env(opencensus, reporter, {oc_tab_reporter, []}),
33+
application:set_env(opencensus, reporters, [{oc_tab_reporter, []}]),
3434
application:set_env(opencensus, tab_reporter, #{tid => Tab}),
3535
{ok, _} = application:ensure_all_started(opencensus),
3636
[{tid, Tab} | Config].

test/opencensus_SUITE.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ init_per_testcase(_, Config) ->
2727
Tab = ets:new(reporter_tab, [public, {write_concurrency, true},
2828
{read_concurrency, true}, {keypos, #span.span_id}]),
2929
application:set_env(opencensus, send_interval_ms, 1),
30-
application:set_env(opencensus, reporter, {oc_tab_reporter, []}),
30+
application:set_env(opencensus, reporters, [{oc_tab_reporter, []}]),
3131
application:set_env(opencensus, tab_reporter, #{tid => Tab}),
3232
application:set_env(opencensus, sampler, {oc_sampler_always, []}),
3333
{ok, _} = application:ensure_all_started(opencensus),

0 commit comments

Comments
 (0)