Current section

Files

Jump to
timber lib timber events custom_event.ex
Raw

lib/timber/events/custom_event.ex

defmodule Timber.Events.CustomEvent do
@moduledoc ~S"""
The `CustomEvent` represents events that aren't covered elsewhere.
Custom events can be used to structure information about events that are central
to your line of business like receiving credit card payments, saving a draft of a post,
or changing a user's password.
## Fields
* `type` - (atom, required) This is the type of your event. It should be something unique
and unchanging. It will be used to identify this event. Example: `:my_event`.
* `data` - (map, optional) A map of data. This can be anything that can be JSON encoded.
Example: `%{key: "value"}`.
## Special `data` fields
Timber treats these fields as special. We'll display them on the interface where relevant,
create graphs, etc.:
* `:time_ms` (float, optional) - Represents the execution time in fractional milliseconds.
Example: `45.6`
## Example
There are 2 ways to log custom events:
1. Log a map (simplest)
```elixir
event_data = %{customer_id: "xiaus1934", amount: 1900, currency: "USD"}
Logger.info("Payment rejected", event: %{payment_rejected: event_data})
```
The `:payment_rejected` key is the event `type`, and of course the value is the `data`.
2. Log a struct (advanced)
Defining structs for your events creates a contract around your data structure.
We recommend this approach when you have downstream consumers that will be affected
by data structure changes.
```elixir
def PaymentRejectedEvent do
use Timber.Events.CustomEvent, type: :payment_rejected
@enforce_keys [:customer_id, :amount, :currency]
defstruct [:customer_id, :amount, :currency]
def message(%__MODULE__{customer_id: customer_id}) do
"Payment rejected for #{customer_id}"
end
end
event = %PaymentRejectedEvent{customer_id: "xiaus1934", amount: 1900, currency: "USD"}
message = PaymentRejectedEvent.message(event)
Logger.info(message, event: event)
```
"""
@type t :: %__MODULE__{
type: atom(),
data: map() | nil
}
defmacro __using__(opts) do
quote do
defimpl Timber.Eventable, for: __MODULE__ do
def to_event(event) do
type = Keyword.get(unquote(opts), :type, __MODULE__)
data = Map.from_struct(event)
%Timber.Events.CustomEvent{type: type, data: data}
end
end
end
end
@enforce_keys [:type]
defstruct [
:data,
:type
]
end