Current section
Files
Jump to
Current section
Files
lib/phoenix/socket_client/telemetry.ex
defmodule Phoenix.SocketClient.Telemetry do
@moduledoc """
Telemetry integration for Phoenix.SocketClient.
This module provides telemetry events for monitoring socket connections,
channel joins/leaves, message handling, and connection lifecycle events.
"""
@doc """
Emits a telemetry event with the given name and measurements/metadata.
"""
@spec emit_event(list(atom() | String.t()), map(), map()) :: :ok
def emit_event(event_name, measurements \\ %{}, metadata \\ %{}) do
:telemetry.execute(event_name, measurements, metadata)
end
@doc """
Emits socket connection event.
"""
@spec socket_connected(pid(), String.t(), map()) :: :ok
def socket_connected(pid, url, _metadata \\ %{}) do
emit_event([:phoenix_socket_client, :socket, :connected], %{}, %{
pid: pid,
url: url,
timestamp: System.system_time(:millisecond)
})
end
@doc """
Emits socket disconnection event.
"""
@spec socket_disconnected(pid(), String.t(), atom(), map()) :: :ok
def socket_disconnected(pid, url, reason, _metadata \\ %{}) do
emit_event([:phoenix_socket_client, :socket, :disconnected], %{}, %{
pid: pid,
url: url,
reason: reason,
timestamp: System.system_time(:millisecond)
})
end
@doc """
Emits socket connection attempt event.
"""
@spec socket_connecting(pid(), String.t(), map()) :: :ok
def socket_connecting(pid, url, _metadata \\ %{}) do
emit_event([:phoenix_socket_client, :socket, :connecting], %{}, %{
pid: pid,
url: url,
timestamp: System.system_time(:millisecond)
})
end
@doc """
Emits socket connection error event.
"""
@spec socket_connection_error(pid(), String.t(), any(), map()) :: :ok
def socket_connection_error(pid, url, error, _metadata \\ %{}) do
emit_event([:phoenix_socket_client, :socket, :connection_error], %{}, %{
pid: pid,
url: url,
error: error,
timestamp: System.system_time(:millisecond)
})
end
@doc """
Emits channel join event.
"""
@spec channel_joined(pid(), String.t(), String.t(), map(), map()) :: :ok
def channel_joined(pid, topic, channel_pid, response, _metadata \\ %{}) do
emit_event([:phoenix_socket_client, :channel, :joined], %{}, %{
pid: pid,
topic: topic,
channel_pid: channel_pid,
response: response,
timestamp: System.system_time(:millisecond)
})
end
@doc """
Emits channel join error event.
"""
@spec channel_join_error(pid(), String.t(), any(), map()) :: :ok
def channel_join_error(pid, topic, error, _metadata \\ %{}) do
emit_event([:phoenix_socket_client, :channel, :join_error], %{}, %{
pid: pid,
topic: topic,
error: error,
timestamp: System.system_time(:millisecond)
})
end
@doc """
Emits channel leave event.
"""
@spec channel_left(pid(), String.t(), String.t(), map()) :: :ok
def channel_left(pid, topic, reason, _metadata \\ %{}) do
emit_event([:phoenix_socket_client, :channel, :left], %{}, %{
pid: pid,
topic: topic,
reason: reason,
timestamp: System.system_time(:millisecond)
})
end
@doc """
Emits message sent event.
"""
@spec message_sent(pid(), String.t(), String.t(), map(), map()) :: :ok
def message_sent(pid, topic, event, payload, _metadata \\ %{}) do
emit_event([:phoenix_socket_client, :message, :sent], %{}, %{
pid: pid,
topic: topic,
event: event,
payload: payload,
timestamp: System.system_time(:millisecond)
})
end
@doc """
Emits message received event.
"""
@spec message_received(pid(), String.t(), String.t(), map(), map()) :: :ok
def message_received(pid, topic, event, payload, _metadata \\ %{}) do
emit_event([:phoenix_socket_client, :message, :received], %{}, %{
pid: pid,
topic: topic,
event: event,
payload: payload,
timestamp: System.system_time(:millisecond)
})
end
@doc """
Emits heartbeat event.
"""
@spec heartbeat_sent(pid(), String.t(), map()) :: :ok
def heartbeat_sent(pid, url, _metadata \\ %{}) do
emit_event([:phoenix_socket_client, :socket, :heartbeat], %{}, %{
pid: pid,
url: url,
timestamp: System.system_time(:millisecond)
})
end
@doc """
Emits reconnection attempt event.
"""
@spec reconnecting(pid(), String.t(), integer(), map()) :: :ok
def reconnecting(pid, url, attempt, _metadata \\ %{}) do
emit_event([:phoenix_socket_client, :socket, :reconnecting], %{}, %{
pid: pid,
url: url,
attempt: attempt,
timestamp: System.system_time(:millisecond)
})
end
@doc """
Emits debug event for socket lifecycle debugging.
"""
@spec debug(pid(), String.t(), String.t(), map()) :: :ok
def debug(pid, message, url \\ nil, metadata \\ %{}) do
emit_event([:phoenix_socket_client, :debug], %{}, %{
pid: pid,
message: message,
url: url,
metadata: metadata,
timestamp: System.system_time(:millisecond)
})
end
@doc """
Attaches a telemetry handler for debugging purposes.
## Example
Phoenix.SocketClient.Telemetry.attach_debug_handler()
"""
@spec attach_debug_handler() :: :ok
def attach_debug_handler do
:telemetry.attach_many(
"phoenix-socket-client-debug",
[
[:phoenix_socket_client, :socket, :connected],
[:phoenix_socket_client, :socket, :disconnected],
[:phoenix_socket_client, :socket, :connecting],
[:phoenix_socket_client, :socket, :connection_error],
[:phoenix_socket_client, :channel, :joined],
[:phoenix_socket_client, :channel, :join_error],
[:phoenix_socket_client, :channel, :left],
[:phoenix_socket_client, :message, :sent],
[:phoenix_socket_client, :message, :received],
[:phoenix_socket_client, :socket, :heartbeat],
[:phoenix_socket_client, :socket, :reconnecting],
[:phoenix_socket_client, :debug]
],
&debug_handler/4,
%{}
)
end
@doc """
Detaches the debug handler.
"""
@spec detach_debug_handler() :: :ok
def detach_debug_handler do
:telemetry.detach("phoenix-socket-client-debug")
end
defp debug_handler(event_name, measurements, metadata, _config) do
IO.inspect({event_name, measurements, metadata}, label: "[Phoenix.SocketClient] Telemetry")
end
end