From f9c8d2f83238df5242fb9c4dfbbd1a4eb2b5b7e4 Mon Sep 17 00:00:00 2001 From: Michael Ruoss Date: Sun, 20 Feb 2022 14:50:46 +0100 Subject: [PATCH] only create module if deps loaded --- guides/observability.md | 1 + lib/k8s/sys/open_telemetry.ex | 160 +++++++++++++++++----------------- lib/k8s/sys/spandex.ex | 158 ++++++++++++++++----------------- mix.exs | 8 +- 4 files changed, 168 insertions(+), 159 deletions(-) diff --git a/guides/observability.md b/guides/observability.md index 86ad2223..a2a14712 100644 --- a/guides/observability.md +++ b/guides/observability.md @@ -31,6 +31,7 @@ K8s.Sys.OpenTelemetry.attach() ### Spandex +:warning: Requires Elixir ~> 1.10 If you're using a [Spandex](https://github.com/spandex-project/spandex) tracer, Attach `:telemetry` spans/events to the Spandex handler. Pass the tracer you created according diff --git a/lib/k8s/sys/open_telemetry.ex b/lib/k8s/sys/open_telemetry.ex index b88f7f3f..13a810ec 100644 --- a/lib/k8s/sys/open_telemetry.ex +++ b/lib/k8s/sys/open_telemetry.ex @@ -1,93 +1,95 @@ -defmodule K8s.Sys.OpenTelemetry do - @moduledoc """ - This module is still in beta! It has not been tested well and feedback is welcome! +if Code.ensure_loaded?(OpenTelemetry) and Code.ensure_loaded?(OpentelemetryTelemetry) do + defmodule K8s.Sys.OpenTelemetry do + @moduledoc """ + This module is still in beta! It has not been tested well and feedback is welcome! - Converts telemetry spans to opentelemetry tracing spans + Converts telemetry spans to opentelemetry tracing spans - ### Usage + ### Usage - K8s.Sys.OpenTelemetry.attach() - """ + K8s.Sys.OpenTelemetry.attach() + """ - @doc """ - Attaches telemetry spans to the opentelemetry processor - """ - @spec attach() :: :ok - def attach do - for span <- K8s.Sys.Telemetry.spans() do - span_name = Enum.join(span, ".") + @doc """ + Attaches telemetry spans to the opentelemetry processor + """ + @spec attach() :: :ok + def attach do + for span <- K8s.Sys.Telemetry.spans() do + span_name = Enum.join(span, ".") - :ok = - :telemetry.attach( - "k8s-otel-tracer-#{span_name}-start", - span ++ [:start], - &__MODULE__.handle_event/4, - %{tracer_id: :k8s, type: :start, span_name: "k8s." <> span_name} - ) + :ok = + :telemetry.attach( + "k8s-otel-tracer-#{span_name}-start", + span ++ [:start], + &__MODULE__.handle_event/4, + %{tracer_id: :k8s, type: :start, span_name: "k8s." <> span_name} + ) - :ok = - :telemetry.attach( - "k8s-otel-tracer-#{span_name}-stop", - span ++ [:stop], - &__MODULE__.handle_event/4, - %{tracer_id: :k8s, type: :stop} - ) + :ok = + :telemetry.attach( + "k8s-otel-tracer-#{span_name}-stop", + span ++ [:stop], + &__MODULE__.handle_event/4, + %{tracer_id: :k8s, type: :stop} + ) - :ok = - :telemetry.attach( - "k8s-otel-tracer-#{span_name}-exception", - span ++ [:exception], - &__MODULE__.handle_event/4, - %{tracer_id: :k8s, type: :exception} - ) + :ok = + :telemetry.attach( + "k8s-otel-tracer-#{span_name}-exception", + span ++ [:exception], + &__MODULE__.handle_event/4, + %{tracer_id: :k8s, type: :exception} + ) + end + + :ok end - :ok - end + @doc false + @spec handle_event( + :telemetry.event_name(), + :telemetry.event_measurements(), + :telemetry.event_metadata(), + :telemetry.handler_config() + ) :: any() + def handle_event( + _event, + %{system_time: start_time}, + metadata, + %{type: :start, tracer_id: tracer_id, span_name: name} + ) do + start_opts = %{start_time: start_time} + OpentelemetryTelemetry.start_telemetry_span(tracer_id, name, metadata, start_opts) + :ok + end - @doc false - @spec handle_event( - :telemetry.event_name(), - :telemetry.event_measurements(), - :telemetry.event_metadata(), - :telemetry.handler_config() - ) :: any() - def handle_event( - _event, - %{system_time: start_time}, - metadata, - %{type: :start, tracer_id: tracer_id, span_name: name} - ) do - start_opts = %{start_time: start_time} - OpentelemetryTelemetry.start_telemetry_span(tracer_id, name, metadata, start_opts) - :ok - end + def handle_event( + _event, + %{duration: duration}, + metadata, + %{type: :stop, tracer_id: tracer_id} + ) do + OpentelemetryTelemetry.set_current_telemetry_span(tracer_id, metadata) + OpenTelemetry.Tracer.set_attribute(:duration, duration) + OpentelemetryTelemetry.end_telemetry_span(tracer_id, metadata) + :ok + end - def handle_event( - _event, - %{duration: duration}, - metadata, - %{type: :stop, tracer_id: tracer_id} - ) do - OpentelemetryTelemetry.set_current_telemetry_span(tracer_id, metadata) - OpenTelemetry.Tracer.set_attribute(:duration, duration) - OpentelemetryTelemetry.end_telemetry_span(tracer_id, metadata) - :ok - end + def handle_event( + _event, + %{duration: duration}, + %{kind: kind, reason: reason, stacktrace: stacktrace} = metadata, + %{type: :exception, tracer_id: tracer_id} + ) do + ctx = OpentelemetryTelemetry.set_current_telemetry_span(tracer_id, metadata) + status = OpenTelemetry.status(:error, inspect(reason)) + OpenTelemetry.Span.record_exception(ctx, kind, stacktrace, duration: duration) + OpenTelemetry.Tracer.set_status(status) + OpentelemetryTelemetry.end_telemetry_span(tracer_id, metadata) + :ok + end - def handle_event( - _event, - %{duration: duration}, - %{kind: kind, reason: reason, stacktrace: stacktrace} = metadata, - %{type: :exception, tracer_id: tracer_id} - ) do - ctx = OpentelemetryTelemetry.set_current_telemetry_span(tracer_id, metadata) - status = OpenTelemetry.status(:error, inspect(reason)) - OpenTelemetry.Span.record_exception(ctx, kind, stacktrace, duration: duration) - OpenTelemetry.Tracer.set_status(status) - OpentelemetryTelemetry.end_telemetry_span(tracer_id, metadata) - :ok + def handle_event(_event, _measurements, _metadata, _config), do: :ok end - - def handle_event(_event, _measurements, _metadata, _config), do: :ok end diff --git a/lib/k8s/sys/spandex.ex b/lib/k8s/sys/spandex.ex index 6df391aa..a13eb239 100644 --- a/lib/k8s/sys/spandex.ex +++ b/lib/k8s/sys/spandex.ex @@ -1,94 +1,96 @@ -defmodule K8s.Sys.Spandex do - @moduledoc """ - This module is still in beta! It has not been tested well and feedback is welcome! +if Code.ensure_loaded?(Spandex) do + defmodule K8s.Sys.Spandex do + @moduledoc """ + This module is still in beta! It has not been tested well and feedback is welcome! - Converts telemetry spans to Spandex tracing spans. + Converts telemetry spans to Spandex tracing spans. - ### Usage + ### Usage - K8s.Sys.Spandex.attach(MyApp.Tracer) - """ + K8s.Sys.Spandex.attach(MyApp.Tracer) + """ - require Spandex + require Spandex - @doc """ - Attaches telemetry spans to the spandex processor - """ - @spec attach(atom()) :: :ok - def attach(tracer) do - for span <- K8s.Sys.Telemetry.spans() do - span_name = Enum.join(span, ".") + @doc """ + Attaches telemetry spans to the spandex processor + """ + @spec attach(atom()) :: :ok + def attach(tracer) do + for span <- K8s.Sys.Telemetry.spans() do + span_name = Enum.join(span, ".") - :ok = - :telemetry.attach( - "k8s-spandex-tracer-#{span_name}-start", - span ++ [:start], - &__MODULE__.handle_event/4, - %{tracer: tracer, type: :start, span_name: "k8s." <> span_name} - ) + :ok = + :telemetry.attach( + "k8s-spandex-tracer-#{span_name}-start", + span ++ [:start], + &__MODULE__.handle_event/4, + %{tracer: tracer, type: :start, span_name: "k8s." <> span_name} + ) - :ok = - :telemetry.attach( - "k8s-spandex-tracer-#{span_name}-stop", - span ++ [:stop], - &__MODULE__.handle_event/4, - %{tracer: tracer, type: :stop} - ) + :ok = + :telemetry.attach( + "k8s-spandex-tracer-#{span_name}-stop", + span ++ [:stop], + &__MODULE__.handle_event/4, + %{tracer: tracer, type: :stop} + ) - :ok = - :telemetry.attach( - "k8s-spandex-tracer-#{span_name}-exception", - span ++ [:exception], - &__MODULE__.handle_event/4, - %{tracer: tracer, type: :exception} - ) + :ok = + :telemetry.attach( + "k8s-spandex-tracer-#{span_name}-exception", + span ++ [:exception], + &__MODULE__.handle_event/4, + %{tracer: tracer, type: :exception} + ) + end + + :ok end - :ok - end + @doc false + @spec handle_event( + :telemetry.event_name(), + :telemetry.event_measurements(), + :telemetry.event_metadata(), + :telemetry.handler_config() + ) :: any() + def handle_event( + _event, + %{system_time: _start_time}, + metadata, + %{type: :start, tracer: tracer, span_name: name} + ) do + tracer.start_span(name, service: :k8s, type: :custom, tags: Map.to_list(metadata)) + :ok + end - @doc false - @spec handle_event( - :telemetry.event_name(), - :telemetry.event_measurements(), - :telemetry.event_metadata(), - :telemetry.handler_config() - ) :: any() - def handle_event( - _event, - %{system_time: _start_time}, - metadata, - %{type: :start, tracer: tracer, span_name: name} - ) do - tracer.start_span(name, service: :k8s, type: :custom, tags: Map.to_list(metadata)) - :ok - end + def handle_event( + _event, + %{duration: _duration}, + metadata, + %{type: :stop, tracer: tracer} + ) do + tracer.update_span(tags: Map.to_list(metadata)) + tracer.finish_span() + :ok + end - def handle_event( - _event, - %{duration: _duration}, - metadata, - %{type: :stop, tracer: tracer} - ) do - tracer.update_span(tags: Map.to_list(metadata)) - tracer.finish_span() - :ok - end + def handle_event( + _event, + %{duration: _duration}, + %{kind: kind, reason: reason, stacktrace: stacktrace} = metadata, + %{type: :exception, tracer: tracer} + ) do + metadata = + metadata + |> Map.put(:error, reason) + |> Map.delete(:reason) - def handle_event( - _event, - %{duration: _duration}, - %{kind: kind, reason: reason, stacktrace: stacktrace} = metadata, - %{type: :exception, tracer: tracer} - ) do - metadata = - metadata - |> Map.put(:error, reason) - |> Map.delete(:reason) + tracer.span_error(kind, stacktrace, error: reason, tags: metadata) + :ok + end - tracer.span_error(kind, stacktrace, error: reason, tags: metadata) - :ok + def handle_event(_event, _measurements, _metadata, _config), do: :ok end - - def handle_event(_event, _measurements, _metadata, _config), do: :ok end diff --git a/mix.exs b/mix.exs index 4c1d580b..9a470834 100644 --- a/mix.exs +++ b/mix.exs @@ -31,14 +31,13 @@ defmodule K8s.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do - [ + deps = [ {:yaml_elixir, "~> 2.8"}, {:httpoison, "~> 1.7"}, {:jason, "~> 1.0"}, {:telemetry, "~> 1.0"}, {:opentelemetry_telemetry, "~> 1.0.0-beta.4", optional: true}, {:opentelemetry, "~> 1.0", optional: true}, - {:spandex, "~> 3.0.3", optional: true}, # dev/test deps (e.g. code coverage) {:inch_ex, github: "rrrene/inch_ex", only: [:dev, :test]}, @@ -48,6 +47,11 @@ defmodule K8s.MixProject do {:excoveralls, "~> 0.14", only: [:test]}, {:mix_test_watch, "~> 1.1", only: :dev, runtime: false} ] + + # spandex requires 1.10 + if Version.match?(System.version(), "~> 1.10"), + do: [{:spandex, "~> 3.0.3", optional: true} | deps], + else: deps end defp package do