Add the ability to trace Liveviews to the Phoenix instrumentation (#198)

This commit is contained in:
Derek Kraan 2023-08-23 13:35:31 +02:00 committed by GitHub
parent 0b6ccafab5
commit 79aae558fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 119 additions and 1 deletions

View File

@ -10,6 +10,11 @@ defmodule OpentelemetryPhoenix do
default: nil, default: nil,
doc: "The phoenix server adapter being used.", doc: "The phoenix server adapter being used.",
type_doc: ":atom" type_doc: ":atom"
],
liveview: [
type: :boolean,
default: true,
doc: "Whether LiveView traces will be instrumented."
] ]
) )
@ -78,6 +83,10 @@ defmodule OpentelemetryPhoenix do
attach_router_start_handler() attach_router_start_handler()
attach_router_dispatch_exception_handler() attach_router_dispatch_exception_handler()
if opts[:liveview] do
attach_liveview_handlers()
end
:ok :ok
end end
@ -121,6 +130,30 @@ defmodule OpentelemetryPhoenix do
) )
end end
def attach_liveview_handlers do
:telemetry.attach_many(
{__MODULE__, :live_view},
[
[:phoenix, :live_view, :mount, :start],
[:phoenix, :live_view, :mount, :stop],
[:phoenix, :live_view, :mount, :exception],
[:phoenix, :live_view, :handle_params, :start],
[:phoenix, :live_view, :handle_params, :stop],
[:phoenix, :live_view, :handle_params, :exception],
[:phoenix, :live_view, :handle_event, :start],
[:phoenix, :live_view, :handle_event, :stop],
[:phoenix, :live_view, :handle_event, :exception],
[:phoenix, :live_component, :handle_event, :start],
[:phoenix, :live_component, :handle_event, :stop],
[:phoenix, :live_component, :handle_event, :exception]
],
&__MODULE__.handle_liveview_event/4,
%{}
)
:ok
end
@doc false @doc false
def handle_endpoint_start(_event, _measurements, meta, config) do def handle_endpoint_start(_event, _measurements, meta, config) do
Process.put({:otel_phoenix, :adapter}, config.adapter) Process.put({:otel_phoenix, :adapter}, config.adapter)
@ -156,7 +189,8 @@ defmodule OpentelemetryPhoenix do
SemanticConventions.Trace.http_target() => conn.request_path, SemanticConventions.Trace.http_target() => conn.request_path,
SemanticConventions.Trace.http_user_agent() => user_agent, SemanticConventions.Trace.http_user_agent() => user_agent,
SemanticConventions.Trace.net_host_name() => conn.host, SemanticConventions.Trace.net_host_name() => conn.host,
SemanticConventions.Trace.net_sock_host_addr() => to_string(:inet_parse.ntoa(conn.remote_ip)), SemanticConventions.Trace.net_sock_host_addr() =>
to_string(:inet_parse.ntoa(conn.remote_ip)),
SemanticConventions.Trace.net_host_port() => conn.port, SemanticConventions.Trace.net_host_port() => conn.port,
SemanticConventions.Trace.net_sock_peer_addr() => to_string(:inet_parse.ntoa(peer_ip)), SemanticConventions.Trace.net_sock_peer_addr() => to_string(:inet_parse.ntoa(peer_ip)),
SemanticConventions.Trace.net_peer_port() => peer_data.port, SemanticConventions.Trace.net_peer_port() => peer_data.port,
@ -232,6 +266,90 @@ defmodule OpentelemetryPhoenix do
end end
end end
def handle_liveview_event(
[:phoenix, _live, :mount, :start],
_measurements,
meta,
_handler_configuration
) do
%{socket: socket} = meta
%{view: live_view} = socket
attributes = %{}
OpentelemetryTelemetry.start_telemetry_span(
@tracer_id,
"#{inspect(live_view)}.mount",
meta,
%{kind: :server}
)
|> OpenTelemetry.Span.set_attributes(attributes)
end
def handle_liveview_event(
[:phoenix, _live, :handle_params, :start],
_measurements,
meta,
_handler_configuration
) do
%{socket: socket} = meta
%{view: live_view} = socket
attributes = %{}
OpentelemetryTelemetry.start_telemetry_span(
@tracer_id,
"#{inspect(live_view)}.handle_params",
meta,
%{kind: :server}
)
|> OpenTelemetry.Span.set_attributes(attributes)
end
def handle_liveview_event(
[:phoenix, _live, :handle_event, :start],
_measurements,
meta,
_handler_configuration
) do
%{socket: socket, event: event, params: _params} = meta
%{view: live_view} = socket
attributes = %{}
OpentelemetryTelemetry.start_telemetry_span(
@tracer_id,
"#{inspect(live_view)}.handle_event##{event}",
meta,
%{kind: :server}
)
|> OpenTelemetry.Span.set_attributes(attributes)
end
def handle_liveview_event(
[:phoenix, _live, _event, :stop],
_measurements,
meta,
_handler_configuration
) do
OpentelemetryTelemetry.end_telemetry_span(@tracer_id, meta)
end
def handle_liveview_event(
[:phoenix, _live, _action, :exception],
_,
%{kind: kind, reason: reason, stacktrace: stacktrace} = meta,
_
) do
ctx = OpentelemetryTelemetry.set_current_telemetry_span(@tracer_id, meta)
exception = Exception.normalize(kind, reason, stacktrace)
OpenTelemetry.Span.record_exception(ctx, exception, stacktrace, [])
OpenTelemetry.Span.set_status(ctx, OpenTelemetry.status(:error, ""))
OpentelemetryTelemetry.end_telemetry_span(@tracer_id, meta)
end
defp http_flavor({_adapter_name, meta}) do defp http_flavor({_adapter_name, meta}) do
case Map.get(meta, :version) do case Map.get(meta, :version) do
:"HTTP/1.0" -> :"1.0" :"HTTP/1.0" -> :"1.0"