From 39094da031279af298c590700c04d1d7a86c3d5e Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Thu, 4 Nov 2021 15:12:32 -0600 Subject: [PATCH] skip exporting if batch table is empty --- .../src/otel_batch_processor.erl | 57 ++++++++++++------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/apps/opentelemetry/src/otel_batch_processor.erl b/apps/opentelemetry/src/otel_batch_processor.erl index 790987b2..a7c0888e 100644 --- a/apps/opentelemetry/src/otel_batch_processor.erl +++ b/apps/opentelemetry/src/otel_batch_processor.erl @@ -143,11 +143,19 @@ exporting({timeout, export_spans}, export_spans, _) -> {keep_state_and_data, [postpone]}; exporting(enter, _OldState, Data=#data{exporting_timeout_ms=ExportingTimeout, scheduled_delay_ms=SendInterval}) -> - {OldTableName, RunnerPid} = export_spans(Data), - {keep_state, Data#data{runner_pid=RunnerPid, - handed_off_table=OldTableName}, - [{state_timeout, ExportingTimeout, exporting_timeout}, - {{timeout, export_spans}, SendInterval, export_spans}]}; + case export_spans(Data) of + ok -> + %% in an `enter' handler we can't return a `next_state' or `next_event' + %% so we rely on a timeout to trigger the transition to `idle' + {keep_state, Data#data{runner_pid=undefined}, [{state_timeout, 0, empty_table}]}; + {OldTableName, RunnerPid} -> + {keep_state, Data#data{runner_pid=RunnerPid, + handed_off_table=OldTableName}, + [{state_timeout, ExportingTimeout, exporting_timeout}, + {{timeout, export_spans}, SendInterval, export_spans}]} + end; +exporting(state_timeout, empty_table, Data) -> + {next_state, idle, Data}; exporting(state_timeout, exporting_timeout, Data=#data{handed_off_table=ExportingTable}) -> %% kill current exporting process because it is taking too long %% which deletes the exporting table, so create a new one and @@ -224,6 +232,9 @@ do_insert(Span) -> complete_exporting(Data=#data{handed_off_table=ExportingTable}) when ExportingTable =/= undefined -> new_export_table(ExportingTable), + {next_state, idle, Data#data{runner_pid=undefined, + handed_off_table=undefined}}; +complete_exporting(Data) -> {next_state, idle, Data#data{runner_pid=undefined, handed_off_table=undefined}}. @@ -317,22 +328,28 @@ shutdown_exporter({ExporterModule, Config}) -> export_spans(#data{exporter=Exporter, resource=Resource}) -> CurrentTable = ?CURRENT_TABLE, - NewCurrentTable = case CurrentTable of - ?TABLE_1 -> - ?TABLE_2; - ?TABLE_2 -> - ?TABLE_1 - end, - - %% an atom is a single word so this does not trigger a global GC - persistent_term:put(?CURRENT_TABLES_KEY, NewCurrentTable), - %% set the table to accept inserts - enable(), + case ets:info(CurrentTable, size) of + 0 -> + %% nothing to do if the table is empty + ok; + _ -> + NewCurrentTable = case CurrentTable of + ?TABLE_1 -> + ?TABLE_2; + ?TABLE_2 -> + ?TABLE_1 + end, + + %% an atom is a single word so this does not trigger a global GC + persistent_term:put(?CURRENT_TABLES_KEY, NewCurrentTable), + %% set the table to accept inserts + enable(), - Self = self(), - RunnerPid = erlang:spawn_link(fun() -> send_spans(Self, Resource, Exporter) end), - ets:give_away(CurrentTable, RunnerPid, export), - {CurrentTable, RunnerPid}. + Self = self(), + RunnerPid = erlang:spawn_link(fun() -> send_spans(Self, Resource, Exporter) end), + ets:give_away(CurrentTable, RunnerPid, export), + {CurrentTable, RunnerPid} + end. %% Additional benefit of using a separate process is calls to `register` won't %% timeout if the actual exporting takes longer than the call timeout