Packages

appsignal

1.13.3
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
appsignal lib appsignal nif.ex
Raw

lib/appsignal/nif.ex

defmodule Appsignal.NifBehaviour do
@callback loaded?() :: boolean()
@callback running_in_container?() :: boolean()
end
defmodule Appsignal.Nif do
@behaviour Appsignal.NifBehaviour
@moduledoc """
It's a NIF! Oh no!
While people generally think NIFs are a bad idea, the overhead of
this particular NIF is low. The C code that the NIF calls has been
designed to be as fast as possible and to do as little as possible
on the calling thread.
Internally, the AppSignal NIF works as follows: it fork/execs a
separate agent process, to which the NIF sends its data (protobuf)
over a unix socket. This agent process (which is a separate unix
process!) then takes care of sending the data the server
periodically.
The C library that the NIF interfaces with, is specifically written
with performance in mind and is very robust and battle tested;
written in Rust and it is the same code that the Ruby AppSignal Gem
uses, which is used in production in thousands of sites.
While doing native Elixir protobufs to communicate directly with
this agent makes more sense from a BEAM standpoint, from a
maintainability point the NIF choice is more logical because
AppSignal is planning more language integrations in the future (PHP,
Java) which all will use this same C library and agent process.
"""
@on_load :init
def init do
path = :filename.join(:code.priv_dir(:appsignal), 'appsignal_extension')
case :erlang.load_nif(path, 1) do
:ok ->
:ok
{:error, {:load_failed, reason}} ->
arch = :erlang.system_info(:system_architecture)
IO.warn(
"Error loading NIF (Is your operating system (#{arch}) supported? Please check http://docs.appsignal.com/support/operating-systems.html):\n#{
reason
}"
)
:ok
end
end
def agent_version do
case :appsignal
|> :code.priv_dir()
|> Path.join("appsignal.version")
|> File.read() do
{:ok, contents} -> String.trim(contents)
_ -> nil
end
end
def env_put(key, value) do
_env_put(key, value)
end
def env_get(key) do
_env_get(key)
end
def env_delete(key) do
_env_delete(key)
end
def env_clear do
_env_clear()
end
def start do
_start()
end
def stop do
_stop()
end
def diagnose do
_diagnose()
end
def start_transaction(transaction_id, namespace) do
_start_transaction(transaction_id, namespace)
end
def start_event(transaction_resource) do
_start_event(transaction_resource)
end
def finish_event(transaction_resource, name, title, body, body_format) do
_finish_event(transaction_resource, name, title, body, body_format)
end
def finish_event_data(transaction_resource, name, title, body, body_format) do
_finish_event_data(transaction_resource, name, title, body, body_format)
end
def record_event(transaction_resource, name, title, body, body_format, duration) do
_record_event(transaction_resource, name, title, body, body_format, duration)
end
def set_error(transaction_resource, error, message, backtrace) do
_set_error(transaction_resource, error, message, backtrace)
end
def set_sample_data(transaction_resource, key, payload) do
_set_sample_data(transaction_resource, key, payload)
end
def set_action(transaction_resource, action) do
_set_action(transaction_resource, action)
end
def set_namespace(transaction_resource, namespace) do
_set_namespace(transaction_resource, namespace)
end
def set_queue_start(transaction_resource, start) do
_set_queue_start(transaction_resource, start)
end
def set_meta_data(transaction_resource, key, value) do
_set_meta_data(transaction_resource, key, value)
end
def finish(transaction_resource) do
_finish(transaction_resource)
end
def complete(transaction_resource) do
_complete(transaction_resource)
end
def set_gauge(key, value, tags) do
_set_gauge(key, value, tags)
end
def increment_counter(key, count, tags) do
_increment_counter(key, count, tags)
end
def add_distribution_value(key, value, tags) do
_add_distribution_value(key, value, tags)
end
def data_map_new do
_data_map_new()
end
def data_set_string(resource, key, value) do
_data_set_string(resource, key, value)
end
def data_set_string(resource, value) do
_data_set_string(resource, value)
end
def data_set_integer(resource, key, value) do
_data_set_integer(resource, key, value)
end
def data_set_integer(resource, value) do
_data_set_integer(resource, value)
end
def data_set_float(resource, key, value) do
_data_set_float(resource, key, value)
end
def data_set_float(resource, value) do
_data_set_float(resource, value)
end
def data_set_boolean(resource, key, value) do
_data_set_boolean(resource, key, value)
end
def data_set_boolean(resource, value) do
_data_set_boolean(resource, value)
end
def data_set_nil(resource, key) do
_data_set_nil(resource, key)
end
def data_set_nil(resource) do
_data_set_nil(resource)
end
def data_set_data(resource, key, value) do
_data_set_data(resource, key, value)
end
def data_set_data(resource, value) do
_data_set_data(resource, value)
end
def data_list_new do
_data_list_new()
end
def running_in_container? do
_running_in_container()
end
def loaded? do
_loaded()
end
if Mix.env() in [:test, :test_phoenix] do
def data_to_json(resource) do
_data_to_json(resource)
end
def transaction_to_json(resource) do
_transaction_to_json(resource)
end
end
def _env_put(_key, _value) do
:ok
end
def _env_get(_key) do
''
end
def _env_delete(_key) do
:ok
end
def _env_clear do
:ok
end
def _start do
:ok
end
def _stop do
:ok
end
def _diagnose do
:error
end
def _start_transaction(_id, _namespace) do
if System.otp_release() >= "20" do
{:ok, make_ref()}
else
{:ok, <<>>}
end
end
def _start_event(_transaction_resource) do
:ok
end
def _finish_event(_transaction_resource, _name, _title, _body, _body_format) do
:ok
end
def _finish_event_data(_transaction_resource, _name, _title, _body, _body_format) do
:ok
end
def _record_event(_transaction_resource, _name, _title, _body, _body_format, _duration) do
:ok
end
def _set_error(_transaction_resource, _error, _message, _backtrace) do
:ok
end
def _set_sample_data(_transaction_resource, _key, _payload) do
:ok
end
def _set_action(_transaction_resource, _action) do
:ok
end
def _set_namespace(_transaction_resource, _action) do
:ok
end
def _set_queue_start(_transaction_resource, _start) do
:ok
end
def _set_meta_data(_transaction_resource, _key, _value) do
:ok
end
def _finish(_transaction_resource) do
# Using `String.to_atom("no_sample") instead of `:no_sample` to trick
# Dialyzer into thinking this value isn't hardcoded.
String.to_atom("no_sample")
end
def _complete(_transaction_resource) do
:ok
end
def _set_gauge(_key, _value, _tags) do
:ok
end
def _increment_counter(_key, _count, _tags) do
:ok
end
def _add_distribution_value(_key, _value, _tags) do
:ok
end
def _data_map_new do
{:ok, nil}
end
def _data_set_string(resource, _key, _value) do
resource
end
def _data_set_string(resource, _value) do
resource
end
def _data_set_integer(resource, _key, _value) do
resource
end
def _data_set_integer(resource, _value) do
resource
end
def _data_set_float(resource, _key, _value) do
resource
end
def _data_set_float(resource, _value) do
resource
end
def _data_set_boolean(resource, _key, _value) do
resource
end
def _data_set_boolean(resource, _value) do
resource
end
def _data_set_nil(resource, _key) do
resource
end
def _data_set_nil(resource) do
resource
end
def _data_set_data(resource, _key, _value) do
resource
end
def _data_set_data(resource, _value) do
resource
end
def _data_list_new do
{:ok, nil}
end
def _running_in_container do
false
end
def _loaded do
false
end
if Mix.env() in [:test, :test_phoenix, :test_no_nif] do
def _data_to_json(resource) do
resource
end
def _transaction_to_json(resource) do
{:ok, resource}
end
end
end