Skip to content

Commit

Permalink
Add the ability to trace Liveviews to the Phoenix instrumentation (#198)
Browse files Browse the repository at this point in the history
  • Loading branch information
derekkraan authored Aug 23, 2023
1 parent 0b6ccaf commit 79aae55
Showing 1 changed file with 119 additions and 1 deletion.
120 changes: 119 additions & 1 deletion instrumentation/opentelemetry_phoenix/lib/opentelemetry_phoenix.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ defmodule OpentelemetryPhoenix do
default: nil,
doc: "The phoenix server adapter being used.",
type_doc: ":atom"
],
liveview: [
type: :boolean,
default: true,
doc: "Whether LiveView traces will be instrumented."
]
)

Expand Down Expand Up @@ -78,6 +83,10 @@ defmodule OpentelemetryPhoenix do
attach_router_start_handler()
attach_router_dispatch_exception_handler()

if opts[:liveview] do
attach_liveview_handlers()
end

:ok
end

Expand Down Expand Up @@ -121,6 +130,30 @@ defmodule OpentelemetryPhoenix do
)
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
def handle_endpoint_start(_event, _measurements, meta, config) do
Process.put({:otel_phoenix, :adapter}, config.adapter)
Expand Down Expand Up @@ -156,7 +189,8 @@ defmodule OpentelemetryPhoenix do
SemanticConventions.Trace.http_target() => conn.request_path,
SemanticConventions.Trace.http_user_agent() => user_agent,
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_sock_peer_addr() => to_string(:inet_parse.ntoa(peer_ip)),
SemanticConventions.Trace.net_peer_port() => peer_data.port,
Expand Down Expand Up @@ -232,6 +266,90 @@ defmodule OpentelemetryPhoenix do
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
case Map.get(meta, :version) do
:"HTTP/1.0" -> :"1.0"
Expand Down

0 comments on commit 79aae55

Please sign in to comment.