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

Commit 6683a93

Browse files
committed
feat: base for migrating oc_reporter to gen_event
1 parent b73a12f commit 6683a93

File tree

6 files changed

+174
-96
lines changed

6 files changed

+174
-96
lines changed

src/oc_internal.hrl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
%%%------------------------------------------------------------------------
2+
%% Copyright 2017, OpenCensus Authors
3+
%% Licensed under the Apache License, Version 2.0 (the "License");
4+
%% you may not use this file except in compliance with the License.
5+
%% You may obtain a copy of the License at
6+
%%
7+
%% http://www.apache.org/licenses/LICENSE-2.0
8+
%%
9+
%% Unless required by applicable law or agreed to in writing, software
10+
%% distributed under the License is distributed on an "AS IS" BASIS,
11+
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
%% See the License for the specific language governing permissions and
13+
%% limitations under the License.
14+
%%%------------------------------------------------------------------------
15+
16+
-define(SPAN_TAB, oc_span_tab).
17+
18+
-define(SPAN_CTX, oc_span_ctx_key).
19+
-define(TAG_CTX, oc_tag_ctx_key).

src/oc_internal_timer.erl

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
-module(oc_internal_timer).
2+
3+
-callback ping() -> ok.
4+
5+
-export([start_link/1,
6+
init/1,
7+
handle_call/3,
8+
handle_cast/2,
9+
handle_info/2]).
10+
11+
-record(state, {timer :: reference(),
12+
interval :: pos_integer(),
13+
module :: module()}).
14+
15+
start_link(Opts) ->
16+
gen_server:start_link(?MODULE, [Opts], []).
17+
18+
init(Opts) ->
19+
Interval = proplists:get_value(interval, Opts),
20+
Module = proplists:get_value(module, Opts),
21+
Ref = erlang:send_after(Interval, self(), ping),
22+
23+
{ok, #state{timer = Ref,
24+
interval = Interval,
25+
module = Module}}.
26+
27+
handle_call(_Msg, _From, State) -> {reply, ok, State}.
28+
29+
handle_cast(_Msg, State) -> {noreply, State}.
30+
31+
handle_info(ping, #state{timer = Ref, interval = Interval, module = Mod}) ->
32+
_ = erlang:cancel_timer(Ref),
33+
ok = Mod:ping(),
34+
NewRef = erlang:send_after(Interval, self(), ping),
35+
36+
{noreply, #state{timer = NewRef,
37+
interval = Interval,
38+
module = Mod}}.

src/oc_reporter_stdout.erl

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
-module(oc_reporter_stdout).
22

3+
-behaviour(gen_event).
4+
35
-export([init/1,
4-
report/2]).
6+
handle_call/2,
7+
handle_event/2]).
58

69
init(_) ->
710
ok.
811

9-
report(Spans, _) ->
10-
[io:format("~p~n", [Span]) || Span <- Spans].
12+
handle_call(_Msg, State) -> {ok, ok, State}.
13+
14+
handle_event({spans, Spans}, State) ->
15+
[io:format("~p~n", [Span]) || Span <- Spans],
16+
17+
{ok, State}.

src/oc_trace.erl

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@
4949

5050
message_event/4,
5151

52-
set_status/3]).
52+
set_status/3,
53+
54+
add_handler/1,
55+
add_handler/2,
56+
delete_handler/1]).
5357

5458
-dialyzer({nowarn_function, update_trace_options/2}).
5559

@@ -327,6 +331,29 @@ link(LinkType, TraceId, SpanId, Attributes) ->
327331
span_id=SpanId,
328332
attributes=Attributes}.
329333

334+
%%--------------------------------------------------------------------
335+
%% @doc
336+
%% @equiv add_handler(Handler, []).
337+
%% @end
338+
%%--------------------------------------------------------------------
339+
add_handler(Handler) -> add_handler(Handler, []).
340+
341+
%%--------------------------------------------------------------------
342+
%% @doc
343+
%% Add new handler
344+
%% @end
345+
%%--------------------------------------------------------------------
346+
add_handler(Handler, Args) ->
347+
gen_event:add_handler(oc_trace_reporter, Handler, Args).
348+
349+
%%--------------------------------------------------------------------
350+
%% @doc
351+
%% Delete handler
352+
%% @end
353+
%%--------------------------------------------------------------------
354+
delete_handler(Handler) ->
355+
gen_event:delete_handler(oc_trace_reporter, Handler, []).
356+
330357
%% Internal functions
331358

332359
lookup_and_replace(#span_ctx{span_id=SpanId,
Lines changed: 27 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,14 @@
1616
%% and creates the buffer of trace spans to be reported.
1717
%% @end
1818
%%%-----------------------------------------------------------------------
19-
-module(oc_reporter).
19+
-module(oc_trace_reporter).
2020

21-
-behaviour(gen_server).
21+
-behaviour(oc_internal_timer).
2222

23-
-compile({no_auto_import, [register/2]}).
23+
-export([start_link/1,
24+
store_span/1]).
2425

25-
-export([start_link/0,
26-
store_span/1,
27-
register/1,
28-
register/2]).
29-
30-
-export([init/1,
31-
handle_call/3,
32-
handle_cast/2,
33-
handle_info/2,
34-
code_change/3,
35-
terminate/2]).
26+
-export([ping/0]).
3627

3728
-include("opencensus.hrl").
3829
-include("oc_logger.hrl").
@@ -50,29 +41,20 @@
5041
%% until it returns.
5142
-callback report(nonempty_list(opencensus:span()), opts()) -> ok.
5243

53-
-record(state, {reporters :: [{module(), term()}],
54-
send_interval_ms :: integer(),
55-
timer_ref :: reference()}).
56-
5744
-define(BUFFER_1, oc_report_buffer1).
5845
-define(BUFFER_2, oc_report_buffer2).
5946
-define(BUFFER_STATUS, oc_report_status).
6047

61-
start_link() ->
48+
start_link(Handlers) ->
6249
maybe_init_ets(),
63-
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
50+
case gen_event:start_link({local, ?MODULE}, []) of
51+
{ok, Pid} ->
52+
[gen_event:add_handler(Pid, Handler, Opts)
53+
|| {Handler, Opts} <- Handlers],
6454

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})}).
55+
{ok, Pid};
56+
Other -> Other
57+
end.
7658

7759
-spec store_span(opencensus:span()) -> true | {error, invalid_span} | {error, no_report_buffer}.
7860
store_span(Span=#span{}) ->
@@ -86,55 +68,7 @@ store_span(Span=#span{}) ->
8668
store_span(_) ->
8769
{error, invalid_span}.
8870

89-
init(_Args) ->
90-
SendInterval = application:get_env(opencensus, send_interval_ms, 500),
91-
Reporters = [init_reporter(Config) || Config <- application:get_env(opencensus, reporters, [])],
92-
Ref = erlang:send_after(SendInterval, self(), report_spans),
93-
{ok, #state{reporters=Reporters,
94-
send_interval_ms=SendInterval,
95-
timer_ref=Ref}}.
96-
97-
handle_call({register, Reporter}, _From, #state{reporters=Reporters} = State) ->
98-
{reply, ok, State#state{reporters=[Reporter | Reporters]}};
99-
handle_call(_, _From, State) ->
100-
{noreply, State}.
101-
102-
handle_cast(_, State) ->
103-
{noreply, State}.
104-
105-
handle_info(report_spans, State=#state{reporters=Reporters,
106-
send_interval_ms=SendInterval,
107-
timer_ref=Ref}) ->
108-
erlang:cancel_timer(Ref),
109-
Ref1 = erlang:send_after(SendInterval, self(), report_spans),
110-
send_spans(Reporters),
111-
{noreply, State#state{timer_ref=Ref1}}.
112-
113-
code_change(_, State, _) ->
114-
{ok, State}.
115-
116-
terminate(_, #state{timer_ref=Ref}) ->
117-
erlang:cancel_timer(Ref),
118-
ok.
119-
120-
init_reporter({Reporter, Config}) ->
121-
{Reporter, Reporter:init(Config)};
122-
init_reporter(Reporter) when is_atom(Reporter) ->
123-
{Reporter, Reporter:init([])}.
124-
125-
maybe_init_ets() ->
126-
case ets:info(?BUFFER_STATUS, name) of
127-
undefined ->
128-
[ets:new(Tab, [named_table, public | TableProps ]) ||
129-
{Tab, TableProps} <- [{?BUFFER_1, [{write_concurrency, true}, {keypos, #span.span_id}]},
130-
{?BUFFER_2, [{write_concurrency, true}, {keypos, #span.span_id}]},
131-
{?BUFFER_STATUS, [{read_concurrency, true}]}]],
132-
ets:insert(?BUFFER_STATUS, {current_buffer, ?BUFFER_1});
133-
_ ->
134-
ok
135-
end.
136-
137-
send_spans(Reporters) ->
71+
ping() ->
13872
[{_, Buffer}] = ets:lookup(?BUFFER_STATUS, current_buffer),
13973
NewBuffer = case Buffer of
14074
?BUFFER_1 ->
@@ -148,19 +82,20 @@ send_spans(Reporters) ->
14882
ok;
14983
Spans ->
15084
ets:delete_all_objects(Buffer),
151-
[report(Reporter, Spans, Config)
152-
|| {Reporter, Config} <- Reporters],
85+
gen_event:sync_notify(?MODULE, {spans, Spans}),
15386
ok
15487
end.
15588

156-
report(undefined, _, _) ->
157-
ok;
158-
report(Reporter, Spans, Config) ->
159-
%% don't let a reporter exception crash us
160-
try
161-
Reporter:report(Spans, Config)
162-
catch
163-
?WITH_STACKTRACE(Class, Exception, StackTrace)
164-
?LOG_INFO("reporter threw exception: reporter=~p ~p:~p stacktrace=~p",
165-
[Reporter, Class, Exception, StackTrace])
89+
maybe_init_ets() ->
90+
case ets:info(?BUFFER_STATUS, name) of
91+
undefined ->
92+
[ets:new(Tab, [named_table, public | TableProps]) ||
93+
{Tab, TableProps} <- [{?BUFFER_1, [{write_concurrency, true}, {keypos, #span.span_id}]},
94+
{?BUFFER_2, [{write_concurrency, true}, {keypos, #span.span_id}]},
95+
{?BUFFER_STATUS, [{read_concurrency, true}]}]],
96+
ets:insert(?BUFFER_STATUS, {current_buffer, ?BUFFER_1}),
97+
98+
ok;
99+
_ ->
100+
ok
166101
end.

src/oc_trace_sup.erl

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
%%%------------------------------------------------------------------------
2+
%% Copyright 2017, OpenCensus Authors
3+
%% Licensed under the Apache License, Version 2.0 (the "License");
4+
%% you may not use this file except in compliance with the License.
5+
%% You may obtain a copy of the License at
6+
%%
7+
%% http://www.apache.org/licenses/LICENSE-2.0
8+
%%
9+
%% Unless required by applicable law or agreed to in writing, software
10+
%% distributed under the License is distributed on an "AS IS" BASIS,
11+
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
%% See the License for the specific language governing permissions and
13+
%% limitations under the License.
14+
%%%------------------------------------------------------------------------
15+
16+
-module(oc_trace_sup).
17+
18+
-behaviour(supervisor).
19+
20+
-export([start_link/1, init/1]).
21+
22+
-include("opencensus.hrl").
23+
24+
start_link(Opts) ->
25+
supervisor:start_link(?MODULE, Opts).
26+
27+
init(Opts) ->
28+
Interval = proplists:get_value(Opts, interval, 500),
29+
Handlers = proplists:get_value(Opts, handlers, []),
30+
31+
Exporter = #{id => exporter,
32+
start => {oc_trace_reporter, start_link, [Handlers]}},
33+
% TODO: Rename oc_span_sweeper to oc_trace_sweeper
34+
Sweeper = #{id => sweeper,
35+
start => {oc_span_sweeper, start_link, []}},
36+
Timer = #{id => timer,
37+
start => {oc_internal_timer, start_link, [{interval, Interval},
38+
{module, oc_trace_reporter}]}
39+
},
40+
41+
ok = maybe_init_span_tab(),
42+
43+
{ok, {#{strategy => one_for_one}, [Exporter, Timer, Sweeper]}}.
44+
45+
maybe_init_span_tab() ->
46+
case ets:info(?SPAN_TAB, name) of
47+
undefined ->
48+
ets:new(?SPAN_TAB, [named_table, public, {write_concurrency, true}, {keypos, #span.span_id}]),
49+
ok;
50+
_ ->
51+
ok
52+
end.

0 commit comments

Comments
 (0)