Packages

appsignal

1.5.0
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 mix_helpers.exs
Raw

mix_helpers.exs

{_, _} = Code.eval_file("agent.exs")
defmodule Mix.Appsignal.Helper do
@moduledoc """
Helper functions for downloading and compiling the AppSignal agent library.
"""
@os Application.get_env(:appsignal, :os, :os)
require Logger
@max_retries 5
def verify_system_architecture() do
input_arch = :erlang.system_info(:system_architecture)
map_arch(input_arch, agent_platform())
end
def ensure_downloaded(arch) do
arch_config = Appsignal.Agent.triples[arch]
System.put_env("LIB_DIR", priv_dir())
if has_local_release_files?() do
IO.puts "AppSignal: Using local agent release."
File.rm_rf!(priv_dir())
File.mkdir_p!(priv_dir())
Enum.each(["appsignal.h", "appsignal-agent", "appsignal.version", "libappsignal.a"], fn(file) ->
File.cp(project_ext_path(file), priv_path(file))
end)
else
if has_files?() and has_correct_agent_version?() do
:ok
else
if is_nil(arch_config) do
raise Mix.Error, message: """
No config found for architecture '#{arch}'.
Please check http://docs.appsignal.com/support/operating-systems.html
And inform us about this error at support@appsignal.com
"""
end
version = Appsignal.Agent.version
File.rm_rf!(priv_dir())
File.mkdir_p!(priv_dir())
try do
download_and_extract(arch_config[:download_url], version, arch_config[:checksum])
catch
{:checksum_mismatch, filename, _, _} ->
File.rm!(filename)
try do
download_and_extract(arch_config[:download_url], version, arch_config[:checksum])
catch
{:checksum_mismatch, filename, calculated, expected} ->
raise Mix.Error, message: """
Checksum verification of #{filename} failed!
Calculated: #{calculated}
Expected: #{expected}
"""
end
end
end
end
end
def store_architecture(arch) do
File.mkdir_p!(priv_dir())
case File.open priv_path("appsignal.architecture"), [:write] do
{:ok, file} ->
result = IO.binwrite(file, arch)
File.close(file)
result
{:error, reason} -> {:error, reason}
end
end
defp download_and_extract(url, version, checksum) do
download_file(url, version)
|> verify_checksum(checksum)
|> extract
end
defp download_file(url, version) do
filename = Path.join(tmp_dir(), "appsignal-agent-#{version}.tar.gz")
case File.exists?(filename) do
true ->
filename
false ->
Logger.info "Downloading agent release from #{url}"
case System.find_executable("curl") do
nil ->
raise Mix.Error, message: """
Could not find the curl executable. Please make sure curl is
installed on this system as it is needed to download the AppSignal
extension and agent.
"""
_ ->
case System.cmd("curl", ["-s", "-S", "--retry", Integer.to_string(@max_retries), "-f", "-o", filename, url], stderr_to_stdout: true) do
{_, 0} ->
filename
{result, exitcode} ->
IO.binwrite(result)
raise Mix.Error, message: """
Download failed with code #{exitcode}
"""
end
end
end
end
defp verify_checksum(filename, expected) do
data = File.read!(filename)
calculated = :crypto.hash(:sha256, data) |> Base.encode16(case: :lower)
if calculated != expected do
throw {:checksum_mismatch, filename, calculated, expected}
end
filename
end
defp extract(filename) do
case System.cmd("tar", ["zxf", filename, "--no-same-owner"], stderr_to_stdout: true, cd: priv_dir()) do
{_, 0} ->
:ok
{result, _exitcode} ->
IO.binwrite(result)
raise Mix.Error, message: """
Extracting of #{filename} failed!
"""
end
end
def compile do
{result, error_code} = System.cmd("make", make_args(to_string(Mix.env)))
IO.binwrite(result)
if error_code != 0 do
raise Mix.Error, message: """
Could not run `make`. Please check if `make` and either `clang` or `gcc` are installed
"""
end
:ok
end
defp make_args("test" <> _), do: ["-e", "CFLAGS_ADD=-DTEST"]
defp make_args(_), do: []
if Mix.env != :test_no_nif do
defp map_arch('i386-' ++ _, platform), do: build_for("i686", platform)
defp map_arch('i686-' ++ _, platform), do: build_for("i686", platform)
defp map_arch('x86-' ++ _, platform), do: build_for("i686", platform)
defp map_arch('amd64-' ++ _, platform), do: build_for("x86_64", platform)
defp map_arch('x86_64-' ++ _, platform), do: build_for("x86_64", platform)
end
defp map_arch(arch, platform), do: {:error, {:unknown, {arch, platform}}}
defp build_for(bit, platform) do
arch = "#{bit}-#{platform}"
case Map.has_key?(Appsignal.Agent.triples, arch) do
true -> {:ok, arch}
false -> {:error, {:unsupported, arch}}
end
end
defp tmp_dir do
default_tmp_dir = "/tmp"
case {File.dir?(default_tmp_dir), File.stat(default_tmp_dir)} do
{true, {:ok, %{access: :write}}} -> default_tmp_dir
{true, {:ok, %{access: :read_write}}} -> default_tmp_dir
_ -> System.tmp_dir!
end
end
defp priv_path(filename) do
Path.join(priv_dir(), filename)
end
defp project_ext_path(filename) do
Path.join([__DIR__, "c_src", filename])
end
defp has_file(filename) do
filename |> priv_path |> File.exists?
end
defp has_local_ext_file(filename) do
filename |> project_ext_path |> File.exists?
end
defp has_files? do
has_file("appsignal-agent") and
has_file("appsignal.h") and
has_file("appsignal_extension.so")
end
defp has_local_release_files? do
has_local_ext_file("appsignal-agent") and
has_local_ext_file("appsignal.h") and
has_local_ext_file("libappsignal.a")
end
defp has_correct_agent_version? do
path = priv_path("appsignal.version")
File.read(path) == {:ok, "#{Appsignal.Agent.version}\n"}
end
def agent_platform do
case force_musl_build?() do
true -> "linux-musl"
false ->
case @os.type do
{:unix, :linux} ->
agent_platform_by_ldd_version()
{_, os} ->
to_string(os)
end
end
end
def priv_dir() do
case :code.priv_dir(:appsignal) do
{:error, :bad_name} ->
# This happens on initial compilation
Mix.Tasks.Compile.Erlang.manifests
|> List.first
|> Path.dirname
|> String.trim_trailing(".mix")
|> Path.join("priv")
path ->
path
|> List.to_string
end
end
defp agent_platform_by_ldd_version do
try do
{output, _} = System.cmd("ldd", ["--version"], stderr_to_stdout: true)
case String.contains?(output, "musl") do
true -> "linux-musl"
false ->
ldd_version = List.first(Regex.run(~r/\d+\.\d+/, output))
case Version.compare("#{ldd_version}.0", "2.15.0") do
:lt -> "linux-musl"
_ -> "linux"
end
end
rescue
_ -> "linux"
end
end
defp force_musl_build? do
!is_nil(System.get_env("APPSIGNAL_BUILD_FOR_MUSL"))
end
end