Packages
appsignal
1.7.0-beta.1
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.install.ex
defmodule Mix.Tasks.Appsignal.Install do
use Mix.Task
alias Appsignal.{Utils.PushApiKeyValidator, Config}
@demo Application.get_env(:appsignal, :appsignal_demo, Appsignal.Demo)
def run([]) do
header()
IO.puts "We're missing an AppSignal Push API key and cannot continue."
IO.puts "Please supply one as an argument to this command.\n"
IO.puts " mix appsignal.install push_api_key\n"
IO.puts "You can find your push_api_key on https://appsignal.com/accounts under 'Add app'"
IO.puts "Contact us at support@appsignal.com if you're stuck."
end
def run([push_api_key]) do
config = %{active: true, push_api_key: push_api_key, request_headers: []}
Application.put_env(:appsignal, :config, config)
Config.initialize
header()
validate_push_api_key()
config = Map.put(config, :name, ask_for_app_name())
case ask_kind_of_configuration() do
:file ->
write_config_file(config)
link_config_file()
activate_config_for_env("dev")
activate_config_for_env("stag")
activate_config_for_env("prod")
:env ->
output_config_environment_variables(config)
end
if Appsignal.phoenix? do
output_phoenix_instructions()
end
IO.puts "\nAppSignal installed! 🎉"
# Start AppSignal so that we can send demo samples
Application.put_env(:appsignal, :config, config)
{:ok, _} = Application.ensure_all_started(:appsignal)
run_demo()
end
defp header do
IO.puts "AppSignal install"
IO.puts String.duplicate("=", 80)
IO.puts "Website: https://appsignal.com"
IO.puts "Documentation: http://docs.appsignal.com"
IO.puts "Support: support@appsignal.com"
IO.puts String.duplicate("=", 80)
IO.puts "\nWelcome to AppSignal!\n"
IO.puts "This installer will guide you through setting up AppSignal in your application."
IO.puts "We will perform some checks on your system and ask how you like AppSignal to be "
IO.puts "configured.\n"
IO.puts String.duplicate("=", 80)
IO.puts ""
end
defp validate_push_api_key do
IO.write "Validating Push API key: "
config = Application.get_env(:appsignal, :config)
case PushApiKeyValidator.validate(config) do
:ok -> IO.puts "Valid! 🎉"
{:error, :invalid} ->
IO.puts "Invalid"
IO.puts " Please make sure you're using the correct push api key from appsignal.com"
IO.puts " Contact us at support@appsignal.com if you're stuck."
exit :shutdown
{:error, reason} ->
IO.puts reason
exit :shutdown
end
end
defp ask_for_app_name, do: ask_for_input("What is your application's name?")
defp ask_kind_of_configuration do
IO.puts "\nThere are two methods of configuring AppSignal in your application."
IO.puts " Option 1: Using a \"config/appsignal.exs\" file. (1)"
IO.puts " Option 2: Using system environment variables. (2)"
case ask_for_input("What is your preferred configuration method? (1/2)") do
"1" -> :file
"2" -> :env
_ ->
IO.puts "I'm sorry, I didn't quite get that."
ask_kind_of_configuration()
end
end
defp output_config_environment_variables(config) do
IO.puts "Configuring with environment variables."
IO.puts "Please put the following variables in your environment to configure AppSignal.\n"
IO.puts ~s( export APPSIGNAL_APP_NAME="#{config[:name]}")
IO.puts ~s( export APPSIGNAL_APP_ENV="production")
IO.puts ~s( export APPSIGNAL_PUSH_API_KEY="#{config[:push_api_key]}")
end
defp write_config_file(config) do
IO.write "Writing config file config/appsignal.exs: "
case File.open appsignal_config_file_path(), [:write] do
{:ok, file} ->
case IO.binwrite(file, appsignal_config_file_contents(config)) do
:ok -> IO.puts "Success!"
{:error, reason} ->
IO.puts "Failure! #{reason}"
exit :shutdown
end
File.close(file)
{:error, reason} ->
IO.puts "Failure! #{reason}"
exit :shutdown
end
end
# Link the config/appsignal.exs config file to the config/config.exs file.
# If already linked, it's ignored.
defp link_config_file do
IO.write "Linking config to config/config.exs: "
config_file = Path.join("config", "config.exs")
active_content = "\nimport_config \"#{appsignal_config_filename()}\"\n"
if appsignal_config_linked?() do
IO.puts "Success! (Already linked?)"
else
case append_to_file(config_file, active_content) do
:ok -> IO.puts "Success!"
{:error, reason} ->
IO.puts "Failure! #{reason}"
exit :shutdown
end
end
end
defp config_file_path, do: Path.join("config", "config.exs")
defp appsignal_config_filename, do: "appsignal.exs"
defp appsignal_config_file_path, do: Path.join("config", appsignal_config_filename())
# Checks if AppSignal was already linked in the main config/config.exs file.
defp appsignal_config_linked? do
case File.read(config_file_path()) do
{:ok, contents} ->
String.contains?(contents, ~s(import_config "#{appsignal_config_filename()})) ||
String.contains?(contents, "import_config '#{appsignal_config_filename()}")
{:error, reason} ->
IO.puts "Failure! #{reason}"
exit :shutdown
end
end
# Contents for the config/appsignal.exs file.
defp appsignal_config_file_contents(config) do
options = [
~s( name: "#{config[:name]}",),
~s( push_api_key: "#{config[:push_api_key]}",),
~s( env: Mix.env)
]
options_with_active = case has_environment_configuration_files?() do
false -> [~s( active: true,)] ++ options
true -> options
end
"use Mix.Config\n\n" <>
"config :appsignal, :config,\n" <>
Enum.join(options_with_active, "\n") <>
"\n"
end
# Append a line to Mix configuration environment files which activate
# AppSignal. This is done for development, staging and production
# environments if they are present.
defp activate_config_for_env(env) do
env_file = config_path_for_env(env)
if File.exists? env_file do
IO.write "Activating #{env} environment: "
active_content = "\nconfig :appsignal, :config, active: true\n"
case file_contains?(env_file, active_content) do
:ok -> IO.puts "Success! (Already active?)"
{:error, :not_found} ->
case append_to_file(env_file, active_content) do
:ok -> IO.puts "Success!"
{:error, reason} ->
IO.puts "Failure! #{reason}"
exit :shutdown
end
{:error, reason} ->
IO.puts "Failure! #{reason}"
exit :shutdown
end
end
end
defp file_contains?(path, contents) do
case File.read(path) do
{:ok, file_contents} ->
case String.contains?(file_contents, contents) do
true -> :ok
_ -> {:error, :not_found}
end
{:error, reason} -> {:error, reason}
end
end
defp append_to_file(path, contents) do
case File.open path, [:append] do
{:ok, file} ->
result = IO.binwrite(file, contents)
File.close(file)
result
{:error, reason} -> {:error, reason}
end
end
defp output_phoenix_instructions do
IO.puts "\nAppSignal detected a Phoenix app"
IO.puts " Please follow the following guide to integrate AppSignal in your"
IO.puts " Phoenix application."
IO.puts " http://docs.appsignal.com/elixir/integrations/phoenix.html"
end
defp ask_for_input(prompt) do
input = String.trim(IO.gets("#{prompt}: "))
if String.length(input) <= 0 do
IO.puts "I'm sorry, I didn't quite get that."
ask_for_input(prompt)
else
input
end
end
defp run_demo do
{:ok, _} = Application.ensure_all_started(:appsignal)
@demo.create_transaction_performance_request
@demo.create_transaction_error_request
Appsignal.stop(nil)
IO.puts "Demonstration sample data sent!"
IO.puts "It may take about a minute for the data to appear on https://appsignal.com/accounts"
end
defp has_environment_configuration_files? do
"dev" |> config_path_for_env |> File.exists? or
"stag" |> config_path_for_env |> File.exists? or
"prod" |> config_path_for_env |> File.exists?
end
defp config_path_for_env(env) do
Path.join("config", "#{env}.exs")
end
end