Instrument your Phoenix and Plug applications with New Relic.
New Relixir currently supports instrumenting bare-bones Plug endpoints, Phoenix controllers and Ecto repositories, to record response times of web transactions and database queries.
The following instructions show how to add instrumentation with New Relixir to a hypothetical
Phoenix application named MyApp
.
-
Add
new_relixir
to your list of dependencies and start-up applications inmix.exs
:# mix.exs defmodule MyApp.Mixfile do use Mix.Project # ... def application do [mod: {MyApp, []}, applications: [:new_relixir]] end defp deps do [{:new_relixir, "~> 0.4"}] end end
-
Add your New Relic application name and license key to
config/config.exs
. You may wish to use environment variables to keep production, staging, and development environments separate:# config/config.exs config :new_relixir, application_name: System.get_env("NEWRELIC_APP_NAME"), license_key: System.get_env("NEWRELIC_LICENSE_KEY")
-
Add
NewRelixir.Instrumenters.Phoenix
to the list of instrumenters in yourEndpoint
configuration:# config/config.exs config :my_app, MyAppWeb.Endpoint, instrumenters: [NewRelixir.Instrumenters.Phoenix], # ...
-
If your app also uses
Ecto
, define a module to wrap your repository's methods with New Relic instrumentation:# lib/my_app/repo.ex defmodule MyApp.Repo do use Ecto.Repo, otp_app: :my_app defmodule NewRelic do use NewRelixir.Plug.Repo, repo: MyApp.Repo end end
Now
MyApp.Repo.NewRelic
can be used as a substitute forMyApp.Repo
. It will dispatch and instrument the response time for allRepo
calls.If you've defined custom functions on your
Repo
, you will need to define them on your wrapper module as well. In the wrapper module, simply call your repository's original function inside a closure that you pass toinstrument_db
:# lib/my_app/repo.ex defmodule MyApp.Repo do use Ecto.Repo, otp_app: :my_app def my_custom_operation(queryable, opts \\ []) do # ... end defmodule NewRelic do use NewRelixir.Plug.Repo, repo: MyApp.Repo def my_custom_operation(queryable, opts \\ []) do instrument_db(:my_custom_operation, queryable, opts, fn() -> MyApp.Repo.my_custom_operation(queryable, opts) end) end end end
When using the wrapper module's
my_custom_operation
, the time it takes to callMyApp.Repo.my_custom_operation/2
will be recorded to New Relic.
If you want to report all errors to new relic
Configure your router
# lib/my_app/router.ex
defmodule MyApp.Router do
use MyApp, :router
use NewRelixir.Plug.Exception
...
end
If you want to report caught errors
try do
raise "oops"
catch
kind, reason ->
transaction =
case NewRelixir.CurrentTransaction.get() do
{:ok, transaction} -> transaction
{:error, _} -> NewRelixir.CurrentTransaction.set(conn.request_path)
end
NewRelixir.Transaction.record_error(transaction, {kind, reason})
# You may want to re-raise this exception
:erlang.raise(kind, reason, System.stacktrace)
end
-
Remove
NewRelixir.Plug.Phoenix
from your Plug pipeline and all further references to that module. -
Add
NewRelixir.Instrumenters.Phoenix
to the list of instrumenters in yourEndpoint
configuration. See more in usage. -
Passing a
conn
to the functions of yourRepo
wrapper is no longer required, calls to the wrapper can now be made the same way as calls to the originalRepo
:# web/controllers/users.ex defmodule MyApp.UserController do use MyApp.Web, :controller def index(conn, _params) do # Before users = Repo.all(User, conn: conn) # Now users = Repo.all(User) end end
Copyright © 2016 The RealReal, Inc.
Distributed under the MIT License.