Current section
Files
Jump to
Current section
Files
lib/pulsekit.ex
defmodule PulseKit do
@moduledoc """
PulseKit SDK for Elixir - Error tracking and event monitoring.
## Configuration
Add to your `config/config.exs`:
config :pulsekit,
endpoint: "https://your-pulsekit-instance.com",
api_key: "pk_your_api_key",
environment: "production",
release: "1.0.0"
## Usage
# Capture an exception
try do
raise "Something went wrong"
rescue
e -> PulseKit.capture_exception(e, __STACKTRACE__)
end
# Send a custom event
PulseKit.capture(%{
type: "payment.success",
level: :info,
message: "Payment completed",
metadata: %{amount: 99.99, currency: "USD"},
tags: %{customer_id: "cust_123"}
})
# Send a simple message
PulseKit.capture_message("User signed up", :info, tags: %{user_id: "user_789"})
"""
alias PulseKit.Client
@type level :: :debug | :info | :warning | :error | :fatal
@type event :: %{
required(:type) => String.t(),
optional(:level) => level(),
optional(:message) => String.t(),
optional(:metadata) => map(),
optional(:stacktrace) => list() | String.t(),
optional(:tags) => map(),
optional(:timestamp) => DateTime.t() | String.t(),
optional(:fingerprint) => String.t()
}
@doc """
Capture an exception with its stacktrace.
## Examples
try do
raise "Something went wrong"
rescue
e -> PulseKit.capture_exception(e, __STACKTRACE__)
end
# With additional options
PulseKit.capture_exception(error, stacktrace,
tags: %{user_id: "123"},
metadata: %{request_id: "abc"}
)
"""
@spec capture_exception(Exception.t(), list(), keyword()) :: :ok | {:error, term()}
def capture_exception(exception, stacktrace, opts \\ []) do
event = %{
type: Keyword.get(opts, :type, "error"),
level: Keyword.get(opts, :level, :error),
message: Exception.message(exception),
metadata: Map.merge(
%{exception_type: exception.__struct__ |> to_string()},
Keyword.get(opts, :metadata, %{})
),
stacktrace: format_stacktrace(stacktrace),
tags: Keyword.get(opts, :tags, %{}),
fingerprint: Keyword.get(opts, :fingerprint)
}
capture(event)
end
@doc """
Capture a custom event.
## Examples
PulseKit.capture(%{
type: "payment.success",
level: :info,
message: "Payment completed",
metadata: %{amount: 99.99},
tags: %{customer_id: "cust_123"}
})
"""
@spec capture(event()) :: :ok | {:error, term()}
def capture(event) when is_map(event) do
Client.send_event(event)
end
@doc """
Capture a simple message.
## Examples
PulseKit.capture_message("User signed up", :info)
PulseKit.capture_message("Warning!", :warning, tags: %{user_id: "123"})
"""
@spec capture_message(String.t(), level(), keyword()) :: :ok | {:error, term()}
def capture_message(message, level \\ :info, opts \\ []) do
event = %{
type: Keyword.get(opts, :type, "message"),
level: level,
message: message,
metadata: Keyword.get(opts, :metadata, %{}),
tags: Keyword.get(opts, :tags, %{})
}
capture(event)
end
@doc """
Flush all queued events to the server.
"""
@spec flush() :: :ok
def flush do
Client.flush()
end
defp format_stacktrace(stacktrace) when is_list(stacktrace) do
Enum.map(stacktrace, fn
{module, function, arity, location} when is_integer(arity) ->
%{
module: inspect(module),
function: "#{function}/#{arity}",
file: Keyword.get(location, :file) |> to_string(),
line: Keyword.get(location, :line)
}
{module, function, args, location} when is_list(args) ->
%{
module: inspect(module),
function: "#{function}/#{length(args)}",
file: Keyword.get(location, :file) |> to_string(),
line: Keyword.get(location, :line)
}
other ->
%{raw: inspect(other)}
end)
end
defp format_stacktrace(stacktrace), do: stacktrace
end