Packages
appsignal
1.10.7
2.17.4
2.17.3
2.17.2
2.17.1
2.17.0
2.16.0
2.15.11
2.15.10
2.15.9
2.15.8
2.15.7
2.15.6
2.15.5
2.15.4
2.15.3
2.15.2
2.15.1
2.15.0
2.14.1
2.14.0
2.13.4
2.13.3
2.13.2
2.13.1
2.13.0
2.12.3
2.12.2
2.12.1
2.12.0
2.11.0
2.10.2
2.10.1
2.10.0
2.9.2
2.9.1
2.9.0
2.8.3
2.8.2
2.8.1
2.8.0
2.7.13
2.7.12
2.7.11
2.7.10
2.7.9
2.7.8
2.7.7
2.7.6
2.7.5
2.7.4
2.7.3
2.7.2
2.7.1
2.7.0
2.7.0-beta.1
2.6.1
2.6.0
2.5.3
2.5.2
2.5.1
2.5.0
2.4.3
2.4.2
2.4.1
2.4.0
2.3.1
2.3.0
2.2.19
2.2.18
2.2.17
2.2.16
2.2.15
2.2.14
2.2.13
2.2.12
retired
2.2.11
2.2.10
2.2.9
2.2.8
2.2.7
2.2.6
2.2.5
2.2.4
2.2.3
2.2.2
2.2.1
2.2.0
2.1.15
2.1.14
2.1.13
2.1.12
2.1.11
2.1.10
2.1.9
2.1.8
2.1.7
2.1.7-beta.1
2.1.6
2.1.5
2.1.4
2.1.3
2.1.2
2.1.1
2.1.0
2.0.8
2.0.7
2.0.6
2.0.6-beta.1
2.0.5
retired
2.0.4
retired
2.0.3
retired
2.0.2
retired
2.0.1
retired
2.0.0
retired
2.0.0-beta.11
2.0.0-beta.10
2.0.0-beta.9
2.0.0-beta.8
2.0.0-beta.7
2.0.0-beta.6
2.0.0-beta.5
2.0.0-beta.4
2.0.0-beta.3
2.0.0-beta.2
2.0.0-beta.1
2.0.0-alpha.7
2.0.0-alpha.6
2.0.0-alpha.5
2.0.0-alpha.4
2.0.0-alpha.3
2.0.0-alpha.2
2.0.0-alpha.1
1.13.5
1.13.4
1.13.3
1.13.2
1.13.1
1.13.0
1.13.0-beta.2
1.13.0-beta.1
1.12.1
1.12.0
1.12.0-beta.3
1.12.0-beta.2
1.12.0-beta.1
1.11.8
1.11.7
1.11.6
1.11.5
1.11.4
1.11.3
1.11.2
1.11.1
1.11.0
1.11.0-beta.1
1.10.13
1.10.12
1.10.11
1.10.10
1.10.9
1.10.8
1.10.7
1.10.6
1.10.5
1.10.4
1.10.3
1.10.2
1.10.1
1.10.0
1.9.4
1.9.3
1.9.2
1.9.1
1.9.1-beta.1
1.9.0
1.9.0-beta.1
1.9.0-alpha.1
1.8.2
1.8.1
1.8.1-beta.2
1.8.1-beta.1
1.8.0
1.7.2
1.7.1
1.7.0
1.7.0-beta.2
1.7.0-beta.1
1.7.0-alpha.4
1.7.0-alpha.3
1.7.0-alpha.2
1.7.0-alpha.1
1.6.7
1.6.6
1.6.6-beta.2
1.6.6-beta.1
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.6.0-beta.1
1.6.0-alpha.1
1.5.1
1.5.0
1.5.0-beta.2
1.5.0-beta.1
1.4.11-beta.1
1.4.10
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.4.0-alpha.1
1.3.6
1.3.6-beta.1
1.3.5
1.3.4
1.3.4-beta.1
1.3.3
1.3.2
1.3.1
1.3.0
1.3.0-beta.3
1.3.0-beta.2
1.3.0-beta.1
1.2.3
1.2.2
1.2.1
1.2.0
1.1.1
1.1.0
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
1.0.0-rc.1
0.13.0
0.12.3
0.12.2
0.12.1
0.12.0
0.11.6
0.11.5
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.2
0.9.1
0.9.0
0.8.0
0.7.1
0.7.0
0.6.2
0.6.1
0.6.0
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
0.0.9
0.0.8
0.0.7
0.0.6
0.0.5
0.0.4
0.0.3
0.0.2
0.0.1
Collects error and performance data from your Elixir applications and sends it to AppSignal
Current section
Files
Jump to
Current section
Files
lib/appsignal.ex
defmodule Appsignal do @moduledoc """ AppSignal for Elixir. Follow the [installation guide](https://docs.appsignal.com/elixir/installation.html) to install AppSignal into your Elixir app. This module contains the main AppSignal OTP application, as well as a few helper functions for sending metrics to AppSignal. These metrics do not rely on an active transaction being present. For transaction related-functions, see the [Appsignal.Transaction](Appsignal.Transaction.html) module. """ use Application alias Appsignal.{Backtrace, Config, Error} require Logger @transaction Application.get_env( :appsignal, :appsignal_transaction, Appsignal.Transaction ) if System.otp_release() >= "21" do @report_handler Appsignal.LoggerHandler else @report_handler Appsignal.ErrorLoggerHandler end @doc """ Application callback function """ def start(_type, _args) do import Supervisor.Spec, warn: false initialize() add_report_handler() children = [ worker(Appsignal.TransactionRegistry, []), worker(Appsignal.Probes, []) ] result = Supervisor.start_link(children, strategy: :one_for_one, name: Appsignal.Supervisor) # Add our default system probes. It's important that this is called after # the Suportvisor has started. Otherwise the GenServer cannot register the # probe. add_default_probes() result end def plug? do Code.ensure_loaded?(Plug) end def phoenix? do Code.ensure_loaded?(Phoenix) end @doc """ Application callback function """ def stop(_state) do Logger.debug("AppSignal stopping.") end def config_change(_changed, _new, _removed) do # Spawn a separate process that reloads the configuration. AppSignal can't # reload it in the same process because the GenServer would continue # calling itself once it reached `Application.put_env` in # `Appsignal.Config`. spawn(fn -> :ok = Appsignal.Nif.stop() :ok = initialize() end) end @doc false def initialize do case {Config.initialize(), Config.configured_as_active?()} do {_, false} -> Logger.info("AppSignal disabled.") {:ok, true} -> Logger.debug("AppSignal starting.") Config.write_to_environment() Appsignal.Nif.start() if Appsignal.Nif.loaded?() do Logger.debug("AppSignal started.") else Logger.error( "Failed to start AppSignal. Please run the diagnose task " <> "(https://docs.appsignal.com/elixir/command-line/diagnose.html) " <> "to debug your installation." ) end {{:error, :invalid_config}, true} -> Logger.warn( "Warning: No valid AppSignal configuration found, continuing with " <> "AppSignal metrics disabled." ) end end @doc false def add_report_handler, do: @report_handler.add() @doc false def remove_report_handler, do: @report_handler.remove() @doc false def add_default_probes do Appsignal.Probes.register(:erlang, &Appsignal.Probes.ErlangProbe.call/0) end @doc """ Set a gauge for a measurement of some metric. """ @spec set_gauge(String.t(), float | integer, map) :: :ok def set_gauge(key, value, tags \\ %{}) def set_gauge(key, value, tags) when is_integer(value) do set_gauge(key, value + 0.0, tags) end def set_gauge(key, value, %{} = tags) when is_float(value) do encoded_tags = Appsignal.Utils.DataEncoder.encode(tags) :ok = Appsignal.Nif.set_gauge(key, value, encoded_tags) end @doc """ Increment a counter of some metric. """ @spec increment_counter(String.t(), number, map) :: :ok def increment_counter(key, count \\ 1, tags \\ %{}) def increment_counter(key, count, %{} = tags) when is_number(count) do encoded_tags = Appsignal.Utils.DataEncoder.encode(tags) :ok = Appsignal.Nif.increment_counter(key, count + 0.0, encoded_tags) end @doc """ Add a value to a distribution Use this to collect multiple data points that will be merged into a graph. """ @spec add_distribution_value(String.t(), float | integer, map) :: :ok def add_distribution_value(key, value, tags \\ %{}) def add_distribution_value(key, value, tags) when is_integer(value) do add_distribution_value(key, value + 0.0, tags) end def add_distribution_value(key, value, %{} = tags) when is_float(value) do encoded_tags = Appsignal.Utils.DataEncoder.encode(tags) :ok = Appsignal.Nif.add_distribution_value(key, value, encoded_tags) end @doc """ Send an error to AppSignal When there is no current transaction, this call starts one. ## Examples Appsignal.send_error(%RuntimeError{}) Appsignal.send_error(%RuntimeError{}, "Oops!") Appsignal.send_error(%RuntimeError{}, "", System.stacktrace()) Appsignal.send_error(%RuntimeError{}, "", [], %{foo: "bar"}) Appsignal.send_error(%RuntimeError{}, "", [], %{}, %Plug.Conn{}) Appsignal.send_error(%RuntimeError{}, "", [], %{}, nil, fn(transaction) -> Appsignal.Transaction.set_sample_data(transaction, "key", %{foo: "bar"}) end) """ def send_error( error, prefix \\ "", stack \\ nil, metadata \\ %{}, conn \\ nil, fun \\ fn t -> t end, namespace \\ :http_request ) do stack = case stack do nil -> IO.warn( "Appsignal.send_error/1-7 without passing a stack trace is deprecated, and defaults to passing an empty stacktrace. Please explicitly pass a stack trace or an empty list." ) [] _ -> stack end transaction = @transaction.create("_" <> @transaction.generate_id(), namespace) fun.(transaction) {exception, stacktrace} = Error.normalize(error, stack) {name, message} = Error.metadata(exception) backtrace = Backtrace.from_stacktrace(stacktrace) Appsignal.ErrorHandler.submit_transaction( transaction, name, prefixed(prefix, message), backtrace, metadata, conn ) end defp prefixed("", message), do: message defp prefixed(prefix, message) when is_binary(prefix), do: prefix <> ": " <> message defp prefixed(_, message), do: messageend