Packages

appsignal

1.8.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 lib mix tasks appsignal.diagnose.ex
Raw

lib/mix/tasks/appsignal.diagnose.ex

defmodule Mix.Tasks.Appsignal.Diagnose do
use Mix.Task
alias Appsignal.Config
alias Appsignal.Diagnose
@system Application.get_env(:appsignal, :appsignal_system, Appsignal.System)
@report Application.get_env(:appsignal, :appsignal_diagnose_report, Appsignal.Diagnose.Report)
@shortdoc "Starts and tests AppSignal while validating the configuration."
def run(_args) do
Application.load(:appsignal)
report = %{process: %{uid: @system.uid}}
configure_appsignal()
config = Application.get_env(:appsignal, :config)
header()
empty_line()
library_report = Diagnose.Library.info
report = Map.put(report, :library, library_report)
print_library_info(library_report)
empty_line()
host_report = Diagnose.Host.info
report = Map.put(report, :host, host_report)
print_host_information(host_report)
empty_line()
report =
case Diagnose.Agent.report do
{:ok, agent_report} ->
print_agent_diagnostics(agent_report)
Map.put(report, :agent, agent_report)
{:error, :nif_not_loaded} ->
IO.puts "Agent diagnostics"
IO.puts " Error: Nif not loaded, aborting.\n"
report
{:error, raw_report} ->
IO.puts "Agent diagnostics"
IO.puts " Error: Could not parse the agent report:"
IO.puts " Output: #{raw_report}\n"
Map.put(report, :agent, %{output: raw_report})
end
report = Map.put(report, :config, config)
print_configuration(config)
empty_line()
validation_report = Diagnose.Validation.validate(config)
report = Map.put(report, :validation, validation_report)
print_validation(validation_report)
empty_line()
path_report = Diagnose.Paths.info(config)
report = Map.put(report, :paths, path_report)
print_paths(path_report)
empty_line()
logs = Diagnose.Logs.info
report = Map.put(report, :logs, logs)
print_logs(logs)
send_report_to_appsignal_if_agreed_upon(config, report)
end
defp header do
IO.puts "AppSignal diagnose"
IO.puts String.duplicate("=", 80)
IO.puts "Use this information to debug your configuration."
IO.puts "More information is available on the documentation site."
IO.puts "http://docs.appsignal.com/"
IO.puts "Send this output to support@appsignal.com if you need help."
IO.puts String.duplicate("=", 80)
end
defp print_library_info(library_report) do
IO.puts "AppSignal agent"
IO.puts " Language: Elixir"
IO.puts " Package version: #{library_report[:package_version]}"
IO.puts " Agent version: #{library_report[:agent_version]}"
IO.puts " Agent architecture: #{library_report[:agent_architecture]}"
IO.puts " Nif loaded: #{yes_or_no(library_report[:extension_loaded])}"
end
defp print_host_information(host_report) do
IO.puts "Host information"
IO.puts " Architecture: #{host_report[:architecture]}"
IO.puts " Elixir version: #{host_report[:language_version]}"
IO.puts " OTP version: #{host_report[:otp_version]}"
root_user = if (host_report[:root]), do: "yes (not recommended)", else: "no"
IO.puts " root user: #{root_user}"
if host_report[:heroku] do
IO.puts " Heroku: yes"
end
IO.puts " Container: #{yes_or_no(host_report[:running_in_container])}"
end
defp configure_appsignal do
Config.initialize
Config.write_to_environment
end
defp print_agent_diagnostics(report) do
Diagnose.Agent.print(report)
end
defp print_configuration(config) do
IO.puts "Configuration"
Enum.each config, fn({key, value}) ->
IO.puts " #{key}: #{value}"
end
end
defp print_validation(validation_report) do
IO.puts "Validation"
IO.puts " Push API key: #{validation_report[:push_api_key]}"
end
defp print_paths(path_report) do
IO.puts "Paths"
Enum.each(path_report, fn(path) ->
print_path path
end)
end
defp print_logs(logs) do
IO.puts "Log files"
Enum.each(logs, fn({filename, log}) ->
IO.puts " #{filename}:"
IO.puts " Path: #{log[:path]}"
case log do
%{exists: false} -> IO.puts " File not found."
%{content: lines} ->
IO.puts " Contents:"
Enum.each(lines, &IO.puts/1)
end
empty_line()
end)
end
defp print_path({name, path}) do
IO.puts " #{name}: #{path[:path]}"
if path[:exists] do
IO.puts " - Writable?: #{yes_or_no(path[:writable])}"
file_uid = path[:ownership][:uid]
process_uid = @system.uid
IO.write " - Ownership?: #{yes_or_no(file_uid == process_uid)}"
IO.puts " (file: #{file_uid}, process: #{process_uid})"
else
IO.puts " - Exists?: no"
end
if path[:error], do: IO.puts " - Error: #{path[:error]}"
end
defp send_report_to_appsignal_if_agreed_upon(config, report) do
IO.puts "\nDiagnostics report"
IO.puts " Do you want to send this diagnostics report to AppSignal?"
IO.puts " If you share this diagnostics report you will be given\n" <>
" a support token you can use to refer to your diagnotics \n" <>
" report when you contact us at support@appsignal.com\n"
answer = yes_or_no?(" Send diagnostics report to AppSignal? (Y/n): ")
case answer do
true ->
IO.puts "\n Transmitting diagnostics report"
case @report.send(config, report) do
{:ok, support_token} ->
IO.puts " Your diagnostics report has been sent to AppSignal."
IO.puts " Your support token: #{support_token}"
{:error, %{status_code: 200, body: body}} ->
IO.puts " Error: Couldn't decode server response."
IO.puts " Response body: #{body}"
{:error, %{status_code: status_code, body: body}} ->
IO.puts " Error: Something went wrong while submitting the " <>
"report to AppSignal."
IO.puts " Response code: #{status_code}"
IO.puts " Response body: #{body}"
{:error, %{reason: reason}} ->
IO.puts " Error: Something went wrong while submitting the " <>
"report to AppSignal."
IO.puts reason
end
false ->
IO.puts " Not sending diagnostics report to AppSignal."
end
end
defp empty_line, do: IO.puts ""
defp yes_or_no(true), do: "yes"
defp yes_or_no(false), do: "no"
# Ask for a yes or no input from the user
defp yes_or_no?(prompt) do
case IO.gets(prompt) do
input when is_binary(input) ->
case String.downcase(String.trim(input)) do
input when input in ["y", "yes", ""] -> true
input when input in ["n", "no"] -> false
_ -> yes_or_no? prompt
end
:eof -> yes_or_no? prompt
{:error, reason} ->
IO.puts " Error while reading input: #{reason}"
yes_or_no? prompt
end
end
end