Packages
appsignal
1.3.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
Current section
Files
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 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) 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 " 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_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 endend