View Source Sentry.Context (Sentry v10.8.0)

Provides functionality to store user, tags, extra, and breadcrumbs context when an event is reported.

The contexts will be fetched and merged into the event when it is sent.

Sentry.Context uses Elixir Logger metadata to store the context itself. This imposes some limitations. The metadata will only exist within the current process, and the context will disappear when the process dies. For example, if you add context inside your controller and an error happens in a spawned Task, that context will not be included.

A common use case is to set context when handling requests within Plug or Phoenix applications, as each request is its own process, and so any stored context is included should an error be reported within that request process. For example:

# post_controller.ex
def index(conn, _params) do
  Sentry.Context.set_user_context(%{id: conn.assigns.user_id})
  posts = Blog.list_posts()
  render(conn, "index.html", posts: posts)
end

Merging

The set_*_context/1 functions merge with the existing context rather than entirely overwriting it.

Sentry Documentation

Sentry itself documents the meaning of the various contexts:

Summary

Types

Breadcrumb info.

A map of extra data.

Request context.

A map of tags.

User context.

Functions

Adds an attachment to the current context.

Adds a new breadcrumb to the :breadcrumb context, specific to the current process.

Clears all existing context for the current process.

Clears all attachments from the current context.

Returns the keys used to store context in the current process' logger metadata.

Retrieves all currently-set context on the current process.

Merges new fields into the :extra context, specific to the current process.

Merges new fields into the :request context, specific to the current process.

Merges new fields into the :tags context, specific to the current process.

Merges new fields into the :user context, specific to the current process.

Types

Link to this type

breadcrumb()

View Source (since 9.0.0)
@type breadcrumb() :: %{
  optional(:type) => :default | :debug | :error | :navigation | String.t(),
  optional(:category) => String.t(),
  optional(:message) => String.t(),
  optional(:data) => map(),
  optional(:level) => :fatal | :error | :warning | :info | :debug,
  optional(:timestamp) => String.t() | integer(),
  optional(atom()) => term()
}

Breadcrumb info.

See add_breadcrumb/1.

Example

%{
  type: "default",
  category: "ui.click",
  data: nil,
  level: "info",
  message: "User clicked on the main button",
  timestamp: 1596814007.035
}
@type extra() :: %{optional(atom()) => term()}

A map of extra data.

See set_extra_context/1.

Link to this type

request_context()

View Source (since 9.0.0)
@type request_context() :: %{
  optional(:method) => String.t() | nil,
  optional(:url) => String.t() | nil,
  optional(:query_string) =>
    String.t() | map() | [{String.t(), String.t()}] | nil,
  optional(:data) => term(),
  optional(:cookies) => String.t() | map() | [{String.t(), String.t()}] | nil,
  optional(:headers) => map() | nil,
  optional(:env) => map() | nil
}

Request context.

See set_request_context/1. This map gets eventually converted into a Sentry.Interfaces.Request struct.

@type tags() :: %{optional(atom()) => String.t() | number() | boolean() | nil}

A map of tags.

See set_tags_context/1.

Link to this type

user_context()

View Source (since 9.0.0)
@type user_context() :: %{
  optional(:id) => term(),
  optional(:username) => String.t(),
  optional(:email) => String.t(),
  optional(:ip_address) => term(),
  optional(:segment) => term(),
  optional(:geo) => %{
    optional(:city) => String.t(),
    optional(:country_code) => String.t(),
    optional(:region) => String.t()
  },
  optional(atom()) => term()
}

User context.

See set_user_context/1.

You can use "{{auto}}" as the value of :ip_address to let Sentry infer the IP address (see the documentation for automatic IP addresses).

Other than the keys specified in the typespec below, all other keys are stored as extra information but not specifically processed by Sentry.

Example

%{
  user: %{
    id: "unique_id",
    username: "my_user",
    email: "foo@example.com",
    ip_address: "127.0.0.1",

    # Extra key
    subscription: "basic"
  }
}

Functions

Link to this function

add_attachment(attachment)

View Source (since 10.1.0)
@spec add_attachment(Sentry.Attachment.t()) :: :ok

Adds an attachment to the current context.

Attachments stored in the context will be sent alongside each event that is reported within that context (that is, within the process that the context was set in).

Currently, there is no limit to how many attachments you can add to the context through this function, even though there might be limits on the Sentry server side. To clear attachments, use clear_attachments/0.

Examples

iex> Sentry.Context.add_attachment(%Sentry.Attachment{filename: "foo.txt", data: "foo"})
:ok
iex> Sentry.Context.add_attachment(%Sentry.Attachment{filename: "bar.txt", data: "bar"})
:ok
iex> Sentry.Context.get_all()
%{
  attachments: [
    %Sentry.Attachment{filename: "bar.txt", data: "bar"},
    %Sentry.Attachment{filename: "foo.txt", data: "foo"}
  ],
  breadcrumbs: [],
  extra: %{},
  request: %{},
  tags: %{},
  user: %{}
}
Link to this function

add_breadcrumb(breadcrumb_info)

View Source
@spec add_breadcrumb(keyword() | breadcrumb()) :: :ok

Adds a new breadcrumb to the :breadcrumb context, specific to the current process.

Breadcrumbs are used to record a series of events that led to a specific instance of an error. Breadcrumbs can contain arbitrary key data to assist in understanding what happened before an error occurred.

See the Sentry documentation for more information.

If breadcrumb_info is a keyword list, it should be convertible to a map of type breadcrumb/0.

If not present, the :timestamp key is filled in automatically with the current Unix timestamp (in seconds).

Example

iex> Sentry.Context.add_breadcrumb(message: "first_event")
:ok
iex> Sentry.Context.add_breadcrumb(%{message: "second_event", type: "auth"})
%{breadcrumbs: [%{:message => "first_event", "timestamp" => 1562007480}]}
iex> Sentry.Context.add_breadcrumb(%{message: "response"})
%{
  breadcrumbs: [
    %{:message => "second_event", :type => "auth", "timestamp" => 1562007505},
    %{:message => "first_event", "timestamp" => 1562007480}
  ]
}
iex> Sentry.Context.get_all()
%{
  attachments: [],
  breadcrumbs: [
    %{:message => "first_event", "timestamp" => 1562007480},
    %{:message => "second_event", :type => "auth", "timestamp" => 1562007505},
    %{:message => "response", "timestamp" => 1562007517}
  ],
  extra: %{},
  request: %{},
  tags: %{},
  user: %{}
}
@spec clear_all() :: :ok

Clears all existing context for the current process.

Example

iex> Sentry.Context.set_tags_context(%{id: 123})
:ok
iex> Sentry.Context.clear_all()
:ok
iex> Sentry.Context.get_all()
%{breadcrumbs: [], extra: %{}, request: %{}, tags: %{}, user: %{}, attachments: []}
Link to this function

clear_attachments()

View Source (since 10.1.0)
@spec clear_attachments() :: :ok

Clears all attachments from the current context.

See add_attachment/1.

Examples

iex> Sentry.Context.add_attachment(%Sentry.Attachment{filename: "foo.txt", data: "foo"})
:ok
iex> Sentry.Context.clear_attachments()
:ok
iex> Sentry.Context.get_all().attachments
[]
@spec context_keys() :: [atom(), ...]

Returns the keys used to store context in the current process' logger metadata.

Example

iex> Sentry.Context.context_keys()
[:breadcrumbs, :tags, :user, :extra, :request, :attachments]
@spec get_all() :: %{
  user: user_context(),
  request: request_context(),
  tags: tags(),
  extra: extra(),
  breadcrumbs: list(),
  attachments: [Sentry.Attachment.t()]
}

Retrieves all currently-set context on the current process.

Example

iex> Sentry.Context.set_user_context(%{id: 123})
iex> Sentry.Context.set_tags_context(%{message_id: 456})
iex> Sentry.Context.get_all()
%{
  user: %{id: 123},
  tags: %{message_id: 456},
  extra: %{},
  request: %{},
  breadcrumbs: [],
  attachments: []
}
@spec set_extra_context(extra()) :: :ok

Merges new fields into the :extra context, specific to the current process.

This is used to set fields which should display when looking at a specific instance of an error.

Example

iex> Sentry.Context.set_extra_context(%{id: 123})
:ok
iex> Sentry.Context.set_extra_context(%{detail: "bad_error"})
:ok
iex> Sentry.Context.set_extra_context(%{message: "Oh no"})
:ok
iex> Sentry.Context.get_all()
%{
  user: %{},
  tags: %{},
  extra: %{detail: "bad_error", id: 123, message: "Oh no"},
  request: %{},
  breadcrumbs: [],
  attachments: []
}
Link to this function

set_request_context(request_context)

View Source
@spec set_request_context(request_context()) :: :ok

Merges new fields into the :request context, specific to the current process.

This is used to set metadata that identifies the request associated with a specific instance of an error.

The request context is documented in the Sentry documentation.

Invalid Keys

While this function accepts any map with atom keys, the only keys that are valid are those in request_context/0. We don't validate keys because of performance concerns, so it's up to you to ensure that you're passing valid keys.

Example

iex> Sentry.Context.set_request_context(%{url: "example.com"})
:ok
iex> headers = %{"accept" => "application/json"}
iex> Sentry.Context.set_request_context(%{headers: headers, method: "GET"})
:ok
iex> Sentry.Context.get_all()
%{
    attachments: [],
    breadcrumbs: [],
    extra: %{},
    request: %{method: "GET", headers: %{"accept" => "application/json"}, url: "example.com"},
    tags: %{},
    user: %{}
}
@spec set_tags_context(tags()) :: :ok

Merges new fields into the :tags context, specific to the current process.

This is used to set fields which should display when looking at a specific instance of an error. These fields can also be used to search and filter on.

Example

iex> Sentry.Context.set_tags_context(%{id: 123})
:ok
iex> Sentry.Context.set_tags_context(%{other_id: 456})
:ok
iex> Sentry.Context.get_all()
%{
    attachments: [],
    breadcrumbs: [],
    extra: %{},
    request: %{},
    tags: %{id: 123, other_id: 456},
    user: %{}
}
Link to this function

set_user_context(user_context)

View Source
@spec set_user_context(Sentry.Interfaces.user()) :: :ok

Merges new fields into the :user context, specific to the current process.

This is used to set certain fields which identify the actor who experienced a specific instance of an error.

The user context is documented in the Sentry documentation.

Additional Keys

While at least one of the keys described in Sentry.Interfaces.user/0 is recommended, you can also add any arbitrary key to the user context.

Example

iex> Sentry.Context.set_user_context(%{id: 123})
:ok
iex> Sentry.Context.set_user_context(%{username: "george"})
:ok
iex> Sentry.Context.get_all()
%{
  user: %{id: 123, username: "george"},
  tags: %{},
  extra: %{},
  request: %{},
  breadcrumbs: [],
  attachments: []
}