diff --git a/lib/prima_opentelemetry_ex/instrumentation/opentelemetry_absinthe.ex b/lib/prima_opentelemetry_ex/instrumentation/opentelemetry_absinthe.ex index fb3512e..812a60b 100644 --- a/lib/prima_opentelemetry_ex/instrumentation/opentelemetry_absinthe.ex +++ b/lib/prima_opentelemetry_ex/instrumentation/opentelemetry_absinthe.ex @@ -1,27 +1,13 @@ defmodule PrimaOpentelemetryEx.Instrumentation.OpentelemetryAbsinthe do @moduledoc false - - cond do - Code.ensure_loaded?(OpentelemetryAbsinthe) -> - def maybe_setup do - if PrimaOpentelemetryEx.enabled?(:absinthe) do - :prima_opentelemetry_ex - |> Application.get_env(:graphql, []) - |> OpentelemetryAbsinthe.Instrumentation.setup() - - nil - end - end - - Code.ensure_loaded?(Absinthe) -> - raise """ - Absinthe has been loaded without installing the optional opentelemetry_absinthe dependency. - PrimaOpentelemetryEx will not be able to instrument absinthe unless you add it. - - Note: you can get rid of this warning by excluding absinthe from instrumentation with `config :prima_opentelemetry_ex, exclude: [:absinthe]` - """ - - true -> - def maybe_setup, do: nil + alias PrimaOpentelemetryEx.Instrumentation.Optional + require Optional + + Optional.instrument Absinthe, + with: OpentelemetryAbsinthe, + feature: :absinthe do + :prima_opentelemetry_ex + |> Application.get_env(:graphql, []) + |> OpentelemetryAbsinthe.Instrumentation.setup() end end diff --git a/lib/prima_opentelemetry_ex/instrumentation/opentelemetry_ecto.ex b/lib/prima_opentelemetry_ex/instrumentation/opentelemetry_ecto.ex index 5f8c231..03d8487 100644 --- a/lib/prima_opentelemetry_ex/instrumentation/opentelemetry_ecto.ex +++ b/lib/prima_opentelemetry_ex/instrumentation/opentelemetry_ecto.ex @@ -1,37 +1,24 @@ defmodule PrimaOpentelemetryEx.Instrumentation.OpentelemetryEcto do @moduledoc false - cond do - Code.ensure_loaded?(OpentelemetryEcto) -> - def maybe_setup do - if PrimaOpentelemetryEx.enabled?(:ecto) do - :telemetry.attach( - "repo-init-handler", - [:ecto, :repo, :init], - &__MODULE__.instrument_repo/4, - %{} - ) + alias PrimaOpentelemetryEx.Instrumentation.Optional + require Optional - nil - end - end - - def instrument_repo(_event, _measurements, metadata, _config) do - metadata - |> Map.fetch!(:opts) - |> Keyword.fetch!(:telemetry_prefix) - |> OpentelemetryEcto.setup() - end - - Code.ensure_loaded?(Ecto) -> - raise """ - Ecto has been loaded without installing the optional opentelemetry_ecto dependency. - PrimaOpentelemetryEx will not be able to instrument ecto unless you add it. - - Note: you can get rid of this warning by excluding absinthe from instrumentation with `config :prima_opentelemetry_ex, exclude: [:ecto]` - """ + Optional.instrument Ecto, + with: OpentelemetryEcto, + feature: :ecto do + :telemetry.attach( + "repo-init-handler", + [:ecto, :repo, :init], + &__MODULE__.instrument_repo/4, + %{} + ) + end - true -> - def maybe_setup, do: nil + def instrument_repo(_event, _measurements, metadata, _config) do + metadata + |> Map.fetch!(:opts) + |> Keyword.fetch!(:telemetry_prefix) + |> OpentelemetryEcto.setup() end end diff --git a/lib/prima_opentelemetry_ex/instrumentation/optional.ex b/lib/prima_opentelemetry_ex/instrumentation/optional.ex new file mode 100644 index 0000000..c516d6a --- /dev/null +++ b/lib/prima_opentelemetry_ex/instrumentation/optional.ex @@ -0,0 +1,56 @@ +defmodule PrimaOpentelemetryEx.Instrumentation.Optional do + @moduledoc false + + @doc """ + Creates a maybe_setup function that instruments a library using an optional instrumentation library. + + Executes the `do` block if: + * `to_instrument` is available + * `instrumenting_library` is available + * `feature_name` is not in the prima_opentelemetry_ex exclude list + + * `to_instrument`: the module that will be instrumented(eg. `Ecto`) + * `instrumenting_library`: the module that will be used to instrument(eg. `OpentelemetryEcto`) + * `feature_name`: atom specifying the name of the feature. Typically the name of the to_instrument library in atom format(eg. `:ecto`) + """ + defmacro instrument( + to_instrument, + [ + with: instrumenting_library, + feature: feature_name + ], + do: setup_instrumentation + ) do + quote do + cond do + # First check if the feature is enabled on compile time + not PrimaOpentelemetryEx.enabled?(unquote(feature_name)) -> + def maybe_setup, do: nil + + Code.ensure_loaded?(unquote(instrumenting_library)) -> + def maybe_setup do + # Runtime check to make sure the feature is enabled on runtime time + if PrimaOpentelemetryEx.enabled?(unquote(feature_name)) do + unquote(setup_instrumentation) + nil + end + end + + Code.ensure_loaded?(unquote(to_instrument)) -> + raise """ + #{unquote(to_instrument)} has been loaded without installing the optional #{ + unquote(instrumenting_library) + } dependency. + PrimaOpentelemetryEx will not be able to instrument absinthe unless you add it. + + Note: you can get rid of this warning by excluding absinthe from instrumentation with `config :prima_opentelemetry_ex, exclude: [:#{ + unquote(feature_name) + }]` + """ + + true -> + def maybe_setup, do: nil + end + end + end +end