1 -module(beam_stats_producer).
3 -include("beam_stats.hrl").
5 -behaviour(gen_server).
13 % Force production and distribution. Blocks. Mainly for testing.
17 %% gen_server callbacks
27 %% ============================================================================
29 %% ============================================================================
31 -define(SIGNAL_PRODUCTION , beam_stats_production_signal).
32 -define(FORCE_PRODUCTION , beam_stats_force_production).
35 { consumers = ordsets:new() :: ordsets:ordset(pid())
41 %% ============================================================================
43 %% ============================================================================
46 gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
48 -spec subscribe(pid()) ->
51 gen_server:cast(?MODULE, {subscribe, PID}).
53 -spec unsubscribe(pid()) ->
56 gen_server:cast(?MODULE, {unsubscribe, PID}).
58 -spec force_production() ->
61 gen_server:call(?MODULE, ?FORCE_PRODUCTION).
63 %% ============================================================================
64 %% gen_server callbacks (unused)
65 %% ============================================================================
67 code_change(_OldVsn, State, _Extra) ->
70 terminate(_Reason, _State) ->
73 %% ============================================================================
74 %% gen_server callbacks
75 %% ============================================================================
78 ok = schedule_first_production(),
79 Consumers = ordsets:new(),
80 {ok, #state{consumers=Consumers}}.
82 handle_cast({subscribe, PID}, #state{consumers=Consumers1}=State) ->
83 Consumers2 = ordsets:add_element(PID, Consumers1),
84 {noreply, State#state{consumers=Consumers2}};
86 handle_cast({unsubscribe, PID}, #state{consumers=Consumers1}=State) ->
87 Consumers2 = ordsets:del_element(PID, Consumers1),
88 {noreply, State#state{consumers=Consumers2}}.
90 handle_call(?FORCE_PRODUCTION, _From, State) ->
94 handle_info(?SIGNAL_PRODUCTION, #state{}=State) ->
96 ok = schedule_next_production(),
99 %% ============================================================================
101 %% ============================================================================
103 -spec produce(state()) ->
105 produce(#state{consumers=ConsumersSet}) ->
106 ConsumersList = ordsets:to_list(ConsumersSet),
107 ok = collect_and_push_to_consumers(ConsumersList),
110 -spec schedule_first_production() ->
112 schedule_first_production() ->
113 _ = self() ! ?SIGNAL_PRODUCTION,
116 -spec schedule_next_production() ->
118 schedule_next_production() ->
119 ProductionInterval = beam_stats_config:production_interval(),
120 _ = erlang:send_after(ProductionInterval, self(), ?SIGNAL_PRODUCTION),
123 -spec collect_and_push_to_consumers([pid()]) ->
125 collect_and_push_to_consumers(Consumers) ->
126 BEAMStats = beam_stats:collect(),
127 Push = fun (Consumer) -> gen_server:cast(Consumer, BEAMStats) end,
128 lists:foreach(Push, Consumers).