anchor.diff:           on_start/3,
            on_end/2,
            set_exporter/1,
  -         set_exporter/2]).
  +         set_exporter/2,
  +         report_cb/1]).
   
   -export([init/1,
            callback_mode/0,
  
positive.code:         ignore ->
              undefined
      catch
          error:badarg when ExporterModule =:= opentelemetry_exporter ->
              case maps:get(protocol, Config, undefined) of
                  grpc ->
                      ?LOG_WARNING("OTLP tracer, ~p, failed to initialize when using GRPC protocol. Verify you have the `grpcbox` dependency included.", [ExporterModule]),
                      undefined;
                  _ ->
                      %% leaving out config from the log since it might have secrets
                      ?LOG_WARNING("Trace exporter module ~p threw exception when initializing: error:badarg", [ExporterModule])
              end;
          error:undef when ExporterModule =:= opentelemetry_exporter ->
              ?LOG_WARNING("Trace exporter module ~p not found. Verify you have included the `opentelemetry_exporter` dependency.", [ExporterModule]),
              undefined;
          error:undef ->
              ?LOG_WARNING("Trace exporter module ~p not found. Verify you have included the dependency that contains the exporter module.", [ExporterModule]),
              undefined;
          C:T ->
              %% leaving out config from the log since it might have secrets
              ?LOG_WARNING("Trace exporter module ~p threw exception when initializing: ~p:~p", [ExporterModule, C, T]),
              undefined
      end;
  init_exporter(ExporterModule) when is_atom(ExporterModule) ->
      init_exporter({ExporterModule, []}).
  
negative.code: 
  export(undefined, _, _) ->
      true;
  export({ExporterModule, Config}, Resource, SpansTid) ->
      %% don't let a exporter exception crash us
      %% and return true if exporter failed
      try
          ExporterModule:export(SpansTid, Resource, Config) =:= failed_not_retryable
      catch
          Kind:Reason:StackTrace ->
              ?LOG_INFO(#{source => exporter,
                          during => export,
                          kind => Kind,
                          reason => Reason,
                          exporter => ExporterModule,
                          stacktrace => StackTrace}, #{report_cb => fun ?MODULE:report_cb/1}),
              true
      end.
  
  %% logger format functions
  report_cb(#{source := exporter,
              during := init,
              kind := Kind,
              reason := Reason,
              exporter := ExporterModule,
              stacktrace := StackTrace}) ->
      {"OTLP tracer ~p failed to initialize: ~ts",
       [ExporterModule, format_exception(Kind, Reason, StackTrace)]};
  report_cb(#{source := exporter,
              during := init,
              kind := Kind,
              reason := Reason,
              exporter := ExporterModule}) ->
      {"OTLP tracer ~p failed to initialize with exception ~p:~p", [ExporterModule, Kind, Reason]};
  report_cb(#{source := exporter,
              during := export,
              kind := Kind,
              reason := Reason,
              exporter := ExporterModule}) ->
      {"OTLP tracer ~p failed to initialize with exception ~p:~p", [ExporterModule, Kind, Reason]};
  report_cb(#{source := exporter,
              during := export,
              kind := Kind,
              reason := Reason,
              exporter := ExporterModule,
              stacktrace := StackTrace}) ->
      {"exporter threw exception: exporter=~p ~ts",
       [ExporterModule, format_exception(Kind, Reason, StackTrace)]}.
  
  -if(?OTP_RELEASE >= 24).
  format_exception(Kind, Reason, StackTrace) ->
      erl_error:format_exception(Kind, Reason, StackTrace).
  -else.
  format_exception(Kind, Reason, StackTrace) ->
      io_lib:format("~p:~p ~p", [Kind, Reason, StackTrace]).
  -endif.
  