Telemetry integration for PhxMediaLibrary.
PhxMediaLibrary emits Telemetry events for key operations, enabling monitoring, logging, and metrics collection in your application.
Events
All events are prefixed with [:phx_media_library, ...].
Media Addition
[:phx_media_library, :add, :start]— emitted when media addition begins.Measurements:
%{system_time: integer()}Metadata:
%{collection: atom(), source_type: atom(), model: struct()}[:phx_media_library, :add, :stop]— emitted when media addition completes successfully.Measurements:
%{duration: integer()}(in native time units)Metadata:
%{collection: atom(), source_type: atom(), model: struct(), media: Media.t()}[:phx_media_library, :add, :exception]— emitted when media addition fails with an exception.Measurements:
%{duration: integer()}Metadata:
%{collection: atom(), source_type: atom(), model: struct(), kind: atom(), reason: term(), stacktrace: list()}
Media Deletion
[:phx_media_library, :delete, :start]— emitted when media deletion begins.Measurements:
%{system_time: integer()}Metadata:
%{media: Media.t()}[:phx_media_library, :delete, :stop]— emitted when media deletion completes.Measurements:
%{duration: integer()}Metadata:
%{media: Media.t()}[:phx_media_library, :delete, :exception]— emitted when media deletion fails.Measurements:
%{duration: integer()}Metadata:
%{media: Media.t(), kind: atom(), reason: term(), stacktrace: list()}
Image Conversions
[:phx_media_library, :conversion, :start]— emitted when a conversion begins.Measurements:
%{system_time: integer()}Metadata:
%{media: Media.t(), conversion: atom()}[:phx_media_library, :conversion, :stop]— emitted when a conversion completes.Measurements:
%{duration: integer()}Metadata:
%{media: Media.t(), conversion: atom()}[:phx_media_library, :conversion, :exception]— emitted when a conversion fails.Measurements:
%{duration: integer()}Metadata:
%{media: Media.t(), conversion: atom(), kind: atom(), reason: term(), stacktrace: list()}
Storage Operations
[:phx_media_library, :storage, :start]— emitted when a storage operation begins.Measurements:
%{system_time: integer()}Metadata:
%{operation: atom(), path: String.t(), adapter: module()}[:phx_media_library, :storage, :stop]— emitted when a storage operation completes.Measurements:
%{duration: integer()}Metadata:
%{operation: atom(), path: String.t(), adapter: module()}[:phx_media_library, :storage, :exception]— emitted when a storage operation fails.Measurements:
%{duration: integer()}Metadata:
%{operation: atom(), path: String.t(), adapter: module(), kind: atom(), reason: term(), stacktrace: list()}
Remote Downloads
[:phx_media_library, :download, :start]— emitted when a remote URL download begins.Measurements:
%{system_time: integer()}Metadata:
%{url: String.t()}[:phx_media_library, :download, :stop]— emitted when a remote URL download completes.Measurements:
%{duration: integer()}Metadata:
%{url: String.t(), size: integer(), mime_type: String.t()}[:phx_media_library, :download, :exception]— emitted when a remote URL download fails.Measurements:
%{duration: integer()}Metadata:
%{url: String.t(), error: term(), kind: atom(), reason: term(), stacktrace: list()}
Batch Operations
[:phx_media_library, :batch, :start]— emitted when a batch operation begins.Measurements:
%{system_time: integer()}Metadata:
%{operation: atom(), count: integer()}[:phx_media_library, :batch, :stop]— emitted when a batch operation completes.Measurements:
%{duration: integer()}Metadata:
%{operation: atom(), count: integer()}[:phx_media_library, :batch, :exception]— emitted when a batch operation fails.Measurements:
%{duration: integer()}Metadata:
%{operation: atom(), count: integer(), kind: atom(), reason: term(), stacktrace: list()}
Usage
Attach handlers in your application's start/2 callback:
# In your Application module
def start(_type, _args) do
:telemetry.attach_many(
"my-app-media-handler",
[
[:phx_media_library, :add, :stop],
[:phx_media_library, :add, :exception],
[:phx_media_library, :delete, :stop],
[:phx_media_library, :storage, :stop]
],
&MyApp.TelemetryHandler.handle_event/4,
nil
)
# ... rest of supervision tree
endOr use a Telemetry.Metrics-based approach:
# In your Telemetry module
def metrics do
[
counter("phx_media_library.add.stop.duration"),
counter("phx_media_library.delete.stop.duration"),
distribution("phx_media_library.add.stop.duration",
buckets: [100, 500, 1_000, 5_000, 10_000]
),
counter("phx_media_library.add.exception.duration",
tags: [:reason]
)
]
end
Summary
Functions
Emit a standalone telemetry event (not part of a span).
Execute a span for the given event prefix.
Functions
Emit a standalone telemetry event (not part of a span).
Useful for one-shot events that don't wrap a block of work, such as
:media_reordered or other notification-style events.
Examples
PhxMediaLibrary.Telemetry.event(
[:phx_media_library, :reorder],
%{count: 5},
%{model: post, collection: :images}
)
Execute a span for the given event prefix.
Emits :start, :stop, and :exception events with timing information.
This is a thin wrapper around :telemetry.span/3 that also logs at debug
level for development convenience.
Parameters
event_prefix— list of atoms, e.g.[:phx_media_library, :add]metadata— map of metadata to attach to all three eventsfun— zero-arity function to execute. Must return{result, stop_metadata}wherestop_metadatais merged into the:stopevent metadata
Examples
PhxMediaLibrary.Telemetry.span(
[:phx_media_library, :add],
%{collection: :images, model: post},
fn ->
result = do_add_media(post, source)
{result, %{media: result}}
end
)