Use the official library now instead of this one.
Instrument your Phoenix applications with New Relic.
It currently supports instrumenting Phoenix controllers and Ecto repositories to record response times for web transactions and database queries.
Based on newrelic-erlang and new-relixir
newrelic-erlang
&new-relixir
look abandoned, so the main goal is to create a maintainable integration with NewRelic open to pull requests.newrelic-erlang
has a performance issue related tostatman
usage. Look at a real-world example ofnew-relixir
usage (the project handles about 25 rps):
The new_relic
isn't suffer from such the leaks.
The following instructions show how to add instrumentation with New Relic to a hypothetical
Phoenix application named MyApp
.
-
Add
new_relic
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_relic]] end defp deps do [{:new_relic, "~> 0.1.2"}] 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_relic, application_name: System.get_env("NEWRELIC_APP_NAME"), license_key: System.get_env("NEWRELIC_LICENSE_KEY"), poll_interval: 60_000 # push data to NewRelic once per 1 minute
-
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 Elixir.NewRelic.Plug.Repo, repo: MyApp.Repo end end
Now
MyApp.Repo.NewRelic
can be used as a substitute forMyApp.Repo
. If aPlug.Conn
is provided as the:conn
option to any of the wrapper's methods, it will instrument the response time for that call. Otherwise, the repository will behave the same as the repository that it wraps. -
For any Phoenix controller that you want to instrument, add
NewRelic.Plug.Phoenix
and replace existing aliases to your application's repository with an alias to your New Relic repository wrapper. If instrumenting all controllers, updateweb/web.ex
:# web/web.ex defmodule MyApp.Web do def controller do quote do # ... plug NewRelic.Plug.Phoenix alias MyApp.Repo.NewRelic, as: Repo # Replaces `alias MyApp.Repo` end end end
It is also possible to specify a custom transaction name function to provide your transaction name, falling back to the default naming scheme as needed:
defmodule MyApp.Web do def controller do quote do # ... plug(NewRelic.Plug.Phoenix, transaction_name_fn: &MyApp.Web.get_front_transaction_name/1) end end def get_front_transaction_name(%{assigns: %{route: route_name}}) do to_string(route_name) end # Fallback to the default Plug transaction name def get_front_transaction_name(conn), do: NewRelic.Plug.Phoenix.generate_transaction_name(conn) end
-
Your db calls will automatically be captured inside of any New Relic transaction. However, this only works if the database work is done in the same process as the transaction. This is most likely acceptable, but you may need to instrument database calls across the process boundary. In that case:
Update your cross-boundary code to pass
conn
as an option to your New Relic repo wrapper:# web/controllers/users.ex defmodule MyApp.UserController do use MyApp.Web, :controller def index(conn, _params) do users = UserProcess.all(User, conn: conn) # UserProcess is a separate process that fetches Users # ... end end
It is possible to add New Relic transaction monitoring to any part of your application.
This can be useful to place inside of background workers, channels, or message processors.
In order to do so, wrap your code inside of a function and pass it to
NewRelic.Transaction.record_custom_transaction
:
NewRelic.Transaction.record_custom_transaction(
fn ->
my_custom_code
end,
"MyCustom.TransactionName"
)
If you've defined custom methods on your repository, you will need to define them on your wrapper
module as well. In the wrapper module, simply call your repository's original method inside a
closure that you pass to instrument_db
:
# lib/my_app/repo.ex
defmodule MyApp.Repo do
use Ecto.Repo, otp_app: :my_app
def custom_method(queryable, opts \\ []) do
# ...
end
defmodule NewRelic do
use NewRelic.Plug.Repo, repo: MyApp.Repo
def custom_method(queryable, opts \\ []) do
instrument_db(:custom_method, queryable, opts, fn() ->
MyApp.Repo.custom_method(queryable, opts)
end)
end
end
end
When using the wrapper module's custom_method
, the time it takes to call
MyApp.Repo.custom_method/2
will be recorded to New Relic.
Distributed under the MIT License.