Integrating AppSignal into Phoenix
The AppSignal for Elixir package integrates with Phoenix. To set up the integration, please follow our installation guide.
This page will describe further ways of configuring AppSignal for the Phoenix framework. To add more custom instrumentation to your Phoenix application, read the Elixir instrumentation documentation.
More information can be found in the AppSignal Hex package documentation.
Installation
-
The AppSignal instrumentation for Phoenix is part of a separate package, which depends on the primary
appsignal
package. Add theappsignal_phoenix
package to yourmix.exs
file.# mix.exs defmodule AppsignalPhoenixExample.MixProject do # ... defp deps do [ {:phoenix, "~> 1.5.3"}, {:appsignal_phoenix, "~> 2.0"} # ... ] end end
-
Then run
mix deps.get
. -
Then run
mix appsignal.install YOUR_PUSH_API_KEY
.
Incoming HTTP requests
To start logging HTTP requests in your Phoenix app, make sure you use the
Appsignal.Phoenix
module in your endpoint.ex
file.
defmodule AppsignalPhoenixExampleWeb.Endpoint do
use Phoenix.Endpoint, otp_app: :appsignal_phoenix_example
use Appsignal.Phoenix
# ...
end
This will create a transaction for every HTTP request which is performed on the endpoint.
Template rendering
It's possible to instrument how much time it takes each template render, including subtemplates (partials), in your Phoenix application.
To enable this for AppSignal, add use Appsignal.Phoenix.View
to the view/0
function in your app's web module, after use Phoenix.View
:
defmodule AppsignalPhoenixExampleWeb do
# ...
def view do
quote do
use Phoenix.View,
root: "lib/appsignal_phoenix_example_web/templates",
namespace: AppsignalPhoenixExampleWeb
use Appsignal.Phoenix.View
# Import convenience functions from controllers
import Phoenix.Controller, only: [get_flash: 1, get_flash: 2, view_module: 1]
# Include shared imports and aliases for views
unquote(view_helpers())
end
end
# ...
end
Channels
Channel instrumentation with a channel's handle
Incoming channel requests can be instrumented by wrapping the code in your
handle_in/3
functions with Appsignal.Phoenix.Channel.instrument/5
:
defmodule AppsignalPhoenixExampleWeb.RoomChannel do
use Phoenix.Channel
# ...
def handle_in("new_msg", %{"body" => body} = params, socket) do
Appsignal.Phoenix.Channel.instrument(__MODULE__, "new_msg", params, socket, fn ->
broadcast!(socket, "new_msg", %{body: body})
{:noreply, socket}
end)
end
end
Alternatively, you can use function decorators to instrument channels. While less flexible than the instrumentation function, decorators minimize the amount of code you have to add to your application's channels.
defmodule SomeApp.MyChannel do
use Appsignal.Instrumentation.Decorators
@decorate channel_action()
def handle_in("ping", _payload, socket) do
# your code here..
end
end
Channel events will be displayed under the "Background jobs" tab, showing the channel module and the action argument that you entered.
LiveView
-> Note: The LiveView Telemetry integration is available from AppSignal for Phoenix version 2.1.0
onward.
AppSignal's LiveView Telemetry integration automatically instruments live view event.
To set it up, call Appsignal.Phoenix.LiveView.attach/0
to attach the LiveView Telemetry handlers.
We recommend calling this function from your app's application.ex
:
defmodule AppsignalPhoenixExample.Application do
# ...
def start(_type, _args) do
Appsignal.Phoenix.LiveView.attach() # <--- attach the LiveView Telemetry handlers
children = [
# Start the Ecto repository
AppsignalPhoenixExample.Repo,
# Start the Telemetry supervisor
AppsignalPhoenixExampleWeb.Telemetry,
# Start the PubSub system
{Phoenix.PubSub, name: AppsignalPhoenixExample.PubSub},
# Start the Endpoint (http/https)
AppsignalPhoenixExampleWeb.Endpoint
# Start a worker by calling: AppsignalPhoenixExample.Worker.start_link(arg)
# {AppsignalPhoenixExample.Worker, arg}
]
# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: AppsignalPhoenixExample.Supervisor]
Supervisor.start_link(children, opts)
end
end
AppSignal will now automatically instrument all mount
, handle_event
and handle_param
events, meaning you'll receive both performance and error insights into your live views.
Helper functions
A LiveView action is instrumented by wrapping its contents in a
Appsignal.Phoenix.LiveView.instrument/4
block.
Given a live view that updates its own state every second, we can add
AppSignal instrumentation by wrapping both the mount/2 and handle_info/2
functions with a Appsignal.Phoenix.LiveView.instrument
/4 call:
defmodule AppsignalPhoenixExampleWeb.ClockLive do
use Phoenix.LiveView
import Appsignal.Phoenix.LiveView, only: [instrument: 4]
def render(assigns) do
AppsignalPhoenixExampleWeb.ClockView.render("index.html", assigns)
end
def mount(_session, socket) do
# Wrap the contents of the mount/2 function with a call to
# Appsignal.Phoenix.LiveView.instrument/4
instrument(__MODULE__, "mount", socket, fn ->
:timer.send_interval(1000, self(), :tick)
{:ok, assign(socket, state: Time.utc_now())}
end)
end
def handle_info(:tick, socket) do
# Wrap the contents of the handle_info/2 function with a call to
# Appsignal.Phoenix.LiveView.instrument/4:
instrument(__MODULE__, "tick", socket, fn ->
{:ok, assign(socket, state: Time.utc_now())}
end)
end
end
Calling one of these functions in your app will now automatically create a
sample that's sent to AppSignal. These are displayed under the :live_view
namespace.
Instrumentation for included Plugs
Exceptions in included Plugs are automatically caught by AppSignal, but performance samples need to be set up manually using the custom instrumentation helpers or decorators. See the Plug documentation for more information.
Custom instrumentation
Add custom instrumentation to keep track of more complex code and get more complete breakdowns of slow requests.