appsignal 2.5.0.alpha.1-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +33 -0
- data/.rspec +4 -0
- data/.rubocop.yml +66 -0
- data/.rubocop_todo.yml +124 -0
- data/.travis.yml +72 -0
- data/.yardopts +8 -0
- data/CHANGELOG.md +639 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +264 -0
- data/Rakefile +214 -0
- data/appsignal.gemspec +42 -0
- data/benchmark.rake +77 -0
- data/bin/appsignal +13 -0
- data/ext/Rakefile +27 -0
- data/ext/agent.yml +64 -0
- data/ext/appsignal_extension.c +692 -0
- data/ext/base.rb +79 -0
- data/ext/extconf.rb +35 -0
- data/gemfiles/capistrano2.gemfile +7 -0
- data/gemfiles/capistrano3.gemfile +7 -0
- data/gemfiles/grape.gemfile +7 -0
- data/gemfiles/no_dependencies.gemfile +5 -0
- data/gemfiles/padrino.gemfile +7 -0
- data/gemfiles/que.gemfile +5 -0
- data/gemfiles/rails-3.2.gemfile +6 -0
- data/gemfiles/rails-4.0.gemfile +6 -0
- data/gemfiles/rails-4.1.gemfile +6 -0
- data/gemfiles/rails-4.2.gemfile +10 -0
- data/gemfiles/rails-5.0.gemfile +5 -0
- data/gemfiles/rails-5.1.gemfile +5 -0
- data/gemfiles/resque.gemfile +12 -0
- data/gemfiles/sequel-435.gemfile +11 -0
- data/gemfiles/sequel.gemfile +11 -0
- data/gemfiles/sinatra.gemfile +6 -0
- data/gemfiles/webmachine.gemfile +5 -0
- data/lib/appsignal.rb +804 -0
- data/lib/appsignal/auth_check.rb +65 -0
- data/lib/appsignal/capistrano.rb +10 -0
- data/lib/appsignal/cli.rb +108 -0
- data/lib/appsignal/cli/demo.rb +63 -0
- data/lib/appsignal/cli/diagnose.rb +500 -0
- data/lib/appsignal/cli/helpers.rb +72 -0
- data/lib/appsignal/cli/install.rb +277 -0
- data/lib/appsignal/cli/notify_of_deploy.rb +113 -0
- data/lib/appsignal/config.rb +287 -0
- data/lib/appsignal/demo.rb +107 -0
- data/lib/appsignal/event_formatter.rb +74 -0
- data/lib/appsignal/event_formatter/action_view/render_formatter.rb +24 -0
- data/lib/appsignal/event_formatter/active_record/instantiation_formatter.rb +14 -0
- data/lib/appsignal/event_formatter/active_record/sql_formatter.rb +14 -0
- data/lib/appsignal/event_formatter/elastic_search/search_formatter.rb +32 -0
- data/lib/appsignal/event_formatter/faraday/request_formatter.rb +19 -0
- data/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter.rb +89 -0
- data/lib/appsignal/event_formatter/moped/query_formatter.rb +80 -0
- data/lib/appsignal/extension.rb +63 -0
- data/lib/appsignal/extension/jruby.rb +460 -0
- data/lib/appsignal/garbage_collection_profiler.rb +48 -0
- data/lib/appsignal/hooks.rb +105 -0
- data/lib/appsignal/hooks/action_cable.rb +113 -0
- data/lib/appsignal/hooks/active_support_notifications.rb +52 -0
- data/lib/appsignal/hooks/celluloid.rb +30 -0
- data/lib/appsignal/hooks/data_mapper.rb +18 -0
- data/lib/appsignal/hooks/delayed_job.rb +19 -0
- data/lib/appsignal/hooks/mongo_ruby_driver.rb +21 -0
- data/lib/appsignal/hooks/net_http.rb +29 -0
- data/lib/appsignal/hooks/passenger.rb +22 -0
- data/lib/appsignal/hooks/puma.rb +35 -0
- data/lib/appsignal/hooks/que.rb +21 -0
- data/lib/appsignal/hooks/rake.rb +39 -0
- data/lib/appsignal/hooks/redis.rb +30 -0
- data/lib/appsignal/hooks/sequel.rb +60 -0
- data/lib/appsignal/hooks/shoryuken.rb +43 -0
- data/lib/appsignal/hooks/sidekiq.rb +144 -0
- data/lib/appsignal/hooks/unicorn.rb +40 -0
- data/lib/appsignal/hooks/webmachine.rb +23 -0
- data/lib/appsignal/integrations/capistrano/appsignal.cap +39 -0
- data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +52 -0
- data/lib/appsignal/integrations/data_mapper.rb +33 -0
- data/lib/appsignal/integrations/delayed_job_plugin.rb +54 -0
- data/lib/appsignal/integrations/grape.rb +53 -0
- data/lib/appsignal/integrations/mongo_ruby_driver.rb +55 -0
- data/lib/appsignal/integrations/object.rb +35 -0
- data/lib/appsignal/integrations/padrino.rb +84 -0
- data/lib/appsignal/integrations/que.rb +43 -0
- data/lib/appsignal/integrations/railtie.rb +41 -0
- data/lib/appsignal/integrations/rake.rb +2 -0
- data/lib/appsignal/integrations/resque.rb +20 -0
- data/lib/appsignal/integrations/resque_active_job.rb +30 -0
- data/lib/appsignal/integrations/sinatra.rb +17 -0
- data/lib/appsignal/integrations/webmachine.rb +38 -0
- data/lib/appsignal/js_exception_transaction.rb +54 -0
- data/lib/appsignal/marker.rb +63 -0
- data/lib/appsignal/minutely.rb +42 -0
- data/lib/appsignal/rack/generic_instrumentation.rb +49 -0
- data/lib/appsignal/rack/js_exception_catcher.rb +70 -0
- data/lib/appsignal/rack/rails_instrumentation.rb +51 -0
- data/lib/appsignal/rack/sinatra_instrumentation.rb +99 -0
- data/lib/appsignal/rack/streaming_listener.rb +73 -0
- data/lib/appsignal/system.rb +81 -0
- data/lib/appsignal/transaction.rb +498 -0
- data/lib/appsignal/transmitter.rb +107 -0
- data/lib/appsignal/utils.rb +127 -0
- data/lib/appsignal/utils/params_sanitizer.rb +59 -0
- data/lib/appsignal/utils/query_params_sanitizer.rb +55 -0
- data/lib/appsignal/version.rb +3 -0
- data/lib/sequel/extensions/appsignal_integration.rb +3 -0
- data/resources/appsignal.yml.erb +39 -0
- data/resources/cacert.pem +3866 -0
- data/spec/.rubocop.yml +7 -0
- data/spec/lib/appsignal/auth_check_spec.rb +80 -0
- data/spec/lib/appsignal/capistrano2_spec.rb +224 -0
- data/spec/lib/appsignal/capistrano3_spec.rb +237 -0
- data/spec/lib/appsignal/cli/demo_spec.rb +67 -0
- data/spec/lib/appsignal/cli/diagnose_spec.rb +988 -0
- data/spec/lib/appsignal/cli/helpers_spec.rb +171 -0
- data/spec/lib/appsignal/cli/install_spec.rb +632 -0
- data/spec/lib/appsignal/cli/notify_of_deploy_spec.rb +168 -0
- data/spec/lib/appsignal/cli_spec.rb +56 -0
- data/spec/lib/appsignal/config_spec.rb +637 -0
- data/spec/lib/appsignal/demo_spec.rb +87 -0
- data/spec/lib/appsignal/event_formatter/action_view/render_formatter_spec.rb +44 -0
- data/spec/lib/appsignal/event_formatter/active_record/instantiation_formatter_spec.rb +21 -0
- data/spec/lib/appsignal/event_formatter/active_record/sql_formatter_spec.rb +21 -0
- data/spec/lib/appsignal/event_formatter/elastic_search/search_formatter_spec.rb +52 -0
- data/spec/lib/appsignal/event_formatter/faraday/request_formatter_spec.rb +21 -0
- data/spec/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter_spec.rb +113 -0
- data/spec/lib/appsignal/event_formatter/moped/query_formatter_spec.rb +112 -0
- data/spec/lib/appsignal/event_formatter_spec.rb +100 -0
- data/spec/lib/appsignal/extension/jruby_spec.rb +43 -0
- data/spec/lib/appsignal/extension_spec.rb +137 -0
- data/spec/lib/appsignal/garbage_collection_profiler_spec.rb +66 -0
- data/spec/lib/appsignal/hooks/action_cable_spec.rb +370 -0
- data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +92 -0
- data/spec/lib/appsignal/hooks/celluloid_spec.rb +35 -0
- data/spec/lib/appsignal/hooks/data_mapper_spec.rb +39 -0
- data/spec/lib/appsignal/hooks/delayed_job_spec.rb +358 -0
- data/spec/lib/appsignal/hooks/mongo_ruby_driver_spec.rb +44 -0
- data/spec/lib/appsignal/hooks/net_http_spec.rb +53 -0
- data/spec/lib/appsignal/hooks/passenger_spec.rb +30 -0
- data/spec/lib/appsignal/hooks/puma_spec.rb +80 -0
- data/spec/lib/appsignal/hooks/que_spec.rb +19 -0
- data/spec/lib/appsignal/hooks/rake_spec.rb +73 -0
- data/spec/lib/appsignal/hooks/redis_spec.rb +55 -0
- data/spec/lib/appsignal/hooks/sequel_spec.rb +46 -0
- data/spec/lib/appsignal/hooks/shoryuken_spec.rb +192 -0
- data/spec/lib/appsignal/hooks/sidekiq_spec.rb +419 -0
- data/spec/lib/appsignal/hooks/unicorn_spec.rb +52 -0
- data/spec/lib/appsignal/hooks/webmachine_spec.rb +35 -0
- data/spec/lib/appsignal/hooks_spec.rb +195 -0
- data/spec/lib/appsignal/integrations/data_mapper_spec.rb +65 -0
- data/spec/lib/appsignal/integrations/grape_spec.rb +225 -0
- data/spec/lib/appsignal/integrations/mongo_ruby_driver_spec.rb +127 -0
- data/spec/lib/appsignal/integrations/object_spec.rb +249 -0
- data/spec/lib/appsignal/integrations/padrino_spec.rb +323 -0
- data/spec/lib/appsignal/integrations/que_spec.rb +174 -0
- data/spec/lib/appsignal/integrations/railtie_spec.rb +129 -0
- data/spec/lib/appsignal/integrations/resque_active_job_spec.rb +83 -0
- data/spec/lib/appsignal/integrations/resque_spec.rb +92 -0
- data/spec/lib/appsignal/integrations/sinatra_spec.rb +73 -0
- data/spec/lib/appsignal/integrations/webmachine_spec.rb +69 -0
- data/spec/lib/appsignal/js_exception_transaction_spec.rb +128 -0
- data/spec/lib/appsignal/marker_spec.rb +51 -0
- data/spec/lib/appsignal/minutely_spec.rb +50 -0
- data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +90 -0
- data/spec/lib/appsignal/rack/js_exception_catcher_spec.rb +147 -0
- data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +117 -0
- data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +213 -0
- data/spec/lib/appsignal/rack/streaming_listener_spec.rb +161 -0
- data/spec/lib/appsignal/system_spec.rb +131 -0
- data/spec/lib/appsignal/transaction_spec.rb +1146 -0
- data/spec/lib/appsignal/transmitter_spec.rb +152 -0
- data/spec/lib/appsignal/utils/params_sanitizer_spec.rb +136 -0
- data/spec/lib/appsignal/utils/query_params_sanitizer_spec.rb +192 -0
- data/spec/lib/appsignal/utils_spec.rb +150 -0
- data/spec/lib/appsignal_spec.rb +1049 -0
- data/spec/spec_helper.rb +116 -0
- data/spec/support/fixtures/containers/cgroups/docker +14 -0
- data/spec/support/fixtures/containers/cgroups/docker_systemd +8 -0
- data/spec/support/fixtures/containers/cgroups/lxc +10 -0
- data/spec/support/fixtures/containers/cgroups/no_permission +0 -0
- data/spec/support/fixtures/containers/cgroups/none +1 -0
- data/spec/support/fixtures/generated_config.yml +24 -0
- data/spec/support/fixtures/uploaded_file.txt +0 -0
- data/spec/support/helpers/api_request_helper.rb +19 -0
- data/spec/support/helpers/cli_helpers.rb +26 -0
- data/spec/support/helpers/config_helpers.rb +21 -0
- data/spec/support/helpers/dependency_helper.rb +73 -0
- data/spec/support/helpers/directory_helper.rb +27 -0
- data/spec/support/helpers/env_helpers.rb +33 -0
- data/spec/support/helpers/example_exception.rb +13 -0
- data/spec/support/helpers/example_standard_error.rb +13 -0
- data/spec/support/helpers/log_helpers.rb +22 -0
- data/spec/support/helpers/std_streams_helper.rb +66 -0
- data/spec/support/helpers/system_helpers.rb +8 -0
- data/spec/support/helpers/time_helpers.rb +11 -0
- data/spec/support/helpers/transaction_helpers.rb +37 -0
- data/spec/support/matchers/contains_log.rb +7 -0
- data/spec/support/mocks/fake_gc_profiler.rb +19 -0
- data/spec/support/mocks/mock_extension.rb +6 -0
- data/spec/support/project_fixture/config/application.rb +0 -0
- data/spec/support/project_fixture/config/appsignal.yml +32 -0
- data/spec/support/project_fixture/config/environments/development.rb +0 -0
- data/spec/support/project_fixture/config/environments/production.rb +0 -0
- data/spec/support/project_fixture/config/environments/test.rb +0 -0
- data/spec/support/project_fixture/log/.gitkeep +0 -0
- data/spec/support/rails/my_app.rb +6 -0
- data/spec/support/shared_examples/instrument.rb +43 -0
- data/spec/support/stubs/delayed_job.rb +0 -0
- metadata +483 -0
data/ext/base.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require "digest"
|
2
|
+
require "logger"
|
3
|
+
require "fileutils"
|
4
|
+
require "open-uri"
|
5
|
+
require "zlib"
|
6
|
+
require "yaml"
|
7
|
+
require "rubygems/package"
|
8
|
+
require File.expand_path("../../lib/appsignal/system.rb", __FILE__)
|
9
|
+
|
10
|
+
EXT_PATH = File.expand_path("..", __FILE__).freeze
|
11
|
+
AGENT_CONFIG = YAML.load(File.read(File.join(EXT_PATH, "agent.yml"))).freeze
|
12
|
+
|
13
|
+
PLATFORM = Appsignal::System.agent_platform
|
14
|
+
ARCH = "#{RbConfig::CONFIG["host_cpu"]}-#{PLATFORM}".freeze
|
15
|
+
CA_CERT_PATH = File.join(EXT_PATH, "../resources/cacert.pem").freeze
|
16
|
+
|
17
|
+
def ext_path(path)
|
18
|
+
File.join(EXT_PATH, path)
|
19
|
+
end
|
20
|
+
|
21
|
+
def logger
|
22
|
+
@logger ||= Logger.new(File.join(EXT_PATH, "install.log"))
|
23
|
+
end
|
24
|
+
|
25
|
+
def installation_failed(reason)
|
26
|
+
logger.error "Installation failed: #{reason}"
|
27
|
+
File.open(File.join(EXT_PATH, "Makefile"), "w") do |file|
|
28
|
+
file.write "default:\nclean:\ninstall:"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def write_agent_architecture
|
33
|
+
File.open(File.join(EXT_PATH, "appsignal.architecture"), "w") do |file|
|
34
|
+
file.write ARCH
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def check_architecture
|
39
|
+
if AGENT_CONFIG["triples"].keys.include?(ARCH)
|
40
|
+
true
|
41
|
+
else
|
42
|
+
installation_failed(
|
43
|
+
"AppSignal currently does not support your system architecture (#{ARCH})." \
|
44
|
+
"Please let us know at support@appsignal.com, we aim to support everything our customers run."
|
45
|
+
)
|
46
|
+
false
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def download_archive(arch_config, type)
|
51
|
+
logger.info "Downloading agent release from #{arch_config[type]["download_url"]}"
|
52
|
+
open(arch_config[type]["download_url"], :ssl_ca_cert => CA_CERT_PATH)
|
53
|
+
end
|
54
|
+
|
55
|
+
def verify_archive(archive, arch_config, type)
|
56
|
+
if Digest::SHA256.hexdigest(archive.read) == arch_config[type]["checksum"]
|
57
|
+
logger.info "Checksum of downloaded archive verified, extracting archive"
|
58
|
+
true
|
59
|
+
else
|
60
|
+
installation_failed(
|
61
|
+
"Aborting installation, checksum of downloaded archive could not be verified: " \
|
62
|
+
"Expected '#{arch_config[type]["checksum"]}', got '#{checksum}'."
|
63
|
+
)
|
64
|
+
false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def unarchive(archive)
|
69
|
+
Gem::Package::TarReader.new(Zlib::GzipReader.open(archive)) do |tar|
|
70
|
+
tar.each do |entry|
|
71
|
+
next unless entry.file?
|
72
|
+
|
73
|
+
File.open(ext_path(entry.full_name), "wb") do |f|
|
74
|
+
f.write(entry.read)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
FileUtils.chmod(0o755, ext_path("appsignal-agent"))
|
79
|
+
end
|
data/ext/extconf.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.expand_path("../../lib/appsignal/version.rb", __FILE__)
|
2
|
+
require File.expand_path("../base.rb", __FILE__)
|
3
|
+
|
4
|
+
def install
|
5
|
+
logger.info "Installing appsignal agent #{Appsignal::VERSION} for Ruby #{RUBY_VERSION} on #{RUBY_PLATFORM}"
|
6
|
+
write_agent_architecture
|
7
|
+
return unless check_architecture
|
8
|
+
arch_config = AGENT_CONFIG["triples"][ARCH]
|
9
|
+
|
10
|
+
unless File.exist?(ext_path("appsignal-agent")) &&
|
11
|
+
File.exist?(ext_path("libappsignal.a")) &&
|
12
|
+
File.exist?(ext_path("appsignal.h"))
|
13
|
+
archive = download_archive(arch_config, "static")
|
14
|
+
return unless verify_archive(archive, arch_config, "static")
|
15
|
+
unarchive(archive)
|
16
|
+
end
|
17
|
+
|
18
|
+
logger.info "Creating makefile"
|
19
|
+
require "mkmf"
|
20
|
+
if !have_library("appsignal", "appsignal_start", "appsignal.h")
|
21
|
+
installation_failed "Aborting installation, libappsignal.a or appsignal.h not found"
|
22
|
+
elsif !find_executable("appsignal-agent", EXT_PATH)
|
23
|
+
installation_failed "Aborting installation, appsignal-agent not found"
|
24
|
+
else
|
25
|
+
create_makefile "appsignal_extension"
|
26
|
+
logger.info "Successfully created Makefile for appsignal extension"
|
27
|
+
end
|
28
|
+
rescue => ex
|
29
|
+
installation_failed "Exception while installing: #{ex}"
|
30
|
+
ex.backtrace.each do |line|
|
31
|
+
logger.error line
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
install
|
data/lib/appsignal.rb
ADDED
@@ -0,0 +1,804 @@
|
|
1
|
+
require "json"
|
2
|
+
require "logger"
|
3
|
+
require "securerandom"
|
4
|
+
|
5
|
+
# AppSignal for Ruby gem's main module.
|
6
|
+
#
|
7
|
+
# Provides method to control the AppSignal instrumentation and the system agent.
|
8
|
+
# Also provides instrumentation helpers for ease of use.
|
9
|
+
module Appsignal
|
10
|
+
class << self
|
11
|
+
extend Gem::Deprecate
|
12
|
+
|
13
|
+
# Accessor for the AppSignal configuration.
|
14
|
+
# Return the current AppSignal configuration.
|
15
|
+
#
|
16
|
+
# Can return `nil` if no configuration has been set or automatically loaded
|
17
|
+
# by an automatic integration or by calling {.start}.
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
# Appsignal.config
|
21
|
+
#
|
22
|
+
# @example Setting the configuration
|
23
|
+
# Appsignal.config = Appsignal::Config.new(Dir.pwd, "production")
|
24
|
+
#
|
25
|
+
# @return [Config, nil]
|
26
|
+
# @see Config
|
27
|
+
attr_accessor :config
|
28
|
+
# Accessor for toggle if the AppSignal C-extension is loaded.
|
29
|
+
#
|
30
|
+
# Can be `nil` if extension has not been loaded yet. See
|
31
|
+
# {.extension_loaded?} for a boolean return value.
|
32
|
+
#
|
33
|
+
# @api private
|
34
|
+
# @return [Boolean, nil]
|
35
|
+
# @see Extension
|
36
|
+
# @see extension_loaded?
|
37
|
+
attr_accessor :extension_loaded
|
38
|
+
# @!attribute [rw] logger
|
39
|
+
# Accessor for the AppSignal logger.
|
40
|
+
#
|
41
|
+
# If no logger has been set, it will return a "in memory logger", using
|
42
|
+
# `in_memory_log`. Once AppSignal is started (using {.start}) the
|
43
|
+
# contents of the "in memory logger" is written to the new logger.
|
44
|
+
#
|
45
|
+
# @note some classes may have options to set custom loggers. Their
|
46
|
+
# defaults are pointed to this attribute.
|
47
|
+
# @api private
|
48
|
+
# @return [Logger]
|
49
|
+
# @see start_logger
|
50
|
+
attr_writer :logger
|
51
|
+
|
52
|
+
# @api private
|
53
|
+
def extensions
|
54
|
+
@extensions ||= []
|
55
|
+
end
|
56
|
+
|
57
|
+
# @api private
|
58
|
+
def initialize_extensions
|
59
|
+
Appsignal.logger.debug("Initializing extensions")
|
60
|
+
extensions.each do |extension|
|
61
|
+
Appsignal.logger.debug("Initializing #{extension}")
|
62
|
+
extension.initializer
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# @api private
|
67
|
+
def testing?
|
68
|
+
false
|
69
|
+
end
|
70
|
+
|
71
|
+
# Start the AppSignal integration.
|
72
|
+
#
|
73
|
+
# Starts AppSignal with the given configuration. If no configuration is set
|
74
|
+
# yet it will try to automatically load the configuration using the
|
75
|
+
# environment loaded from environment variables and the currently working
|
76
|
+
# directory.
|
77
|
+
#
|
78
|
+
# This is not required for the automatic integrations AppSignal offers, but
|
79
|
+
# this is required for all non-automatic integrations and pure Ruby
|
80
|
+
# applications. For more information, see our [integrations
|
81
|
+
# list](http://docs.appsignal.com/ruby/integrations/) and our [Integrating
|
82
|
+
# AppSignal](http://docs.appsignal.com/ruby/instrumentation/integrating-appsignal.html)
|
83
|
+
# guide.
|
84
|
+
#
|
85
|
+
# To start the logger see {.start_logger}.
|
86
|
+
#
|
87
|
+
# @example
|
88
|
+
# Appsignal.start
|
89
|
+
#
|
90
|
+
# @example with custom loaded configuration
|
91
|
+
# Appsignal.config = Appsignal::Config.new(Dir.pwd, "production")
|
92
|
+
# Appsignal.start
|
93
|
+
#
|
94
|
+
# @return [void]
|
95
|
+
# @since 0.7.0
|
96
|
+
def start # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
97
|
+
unless extension_loaded?
|
98
|
+
logger.info("Not starting appsignal, extension is not loaded")
|
99
|
+
return
|
100
|
+
end
|
101
|
+
|
102
|
+
logger.debug("Starting appsignal")
|
103
|
+
|
104
|
+
unless @config
|
105
|
+
@config = Config.new(
|
106
|
+
Dir.pwd,
|
107
|
+
ENV["APPSIGNAL_APP_ENV"] || ENV["RAILS_ENV"] || ENV["RACK_ENV"]
|
108
|
+
)
|
109
|
+
end
|
110
|
+
|
111
|
+
if config.valid?
|
112
|
+
logger.level =
|
113
|
+
if config[:debug]
|
114
|
+
Logger::DEBUG
|
115
|
+
else
|
116
|
+
Logger::INFO
|
117
|
+
end
|
118
|
+
if config.active?
|
119
|
+
logger.info "Starting AppSignal #{Appsignal::VERSION} "\
|
120
|
+
"(#{$PROGRAM_NAME}, Ruby #{RUBY_VERSION}, #{RUBY_PLATFORM})"
|
121
|
+
config.write_to_environment
|
122
|
+
Appsignal::Extension.start
|
123
|
+
Appsignal::Hooks.load_hooks
|
124
|
+
Appsignal::EventFormatter.initialize_formatters
|
125
|
+
initialize_extensions
|
126
|
+
|
127
|
+
if config[:enable_allocation_tracking] && !Appsignal::System.jruby?
|
128
|
+
Appsignal::Extension.install_allocation_event_hook
|
129
|
+
end
|
130
|
+
|
131
|
+
if config[:enable_gc_instrumentation]
|
132
|
+
GC::Profiler.enable
|
133
|
+
Appsignal::Minutely.add_gc_probe
|
134
|
+
end
|
135
|
+
|
136
|
+
Appsignal::Minutely.start if config[:enable_minutely_probes]
|
137
|
+
else
|
138
|
+
logger.info("Not starting, not active for #{config.env}")
|
139
|
+
end
|
140
|
+
else
|
141
|
+
logger.error("Not starting, no valid config for this environment")
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# Stop AppSignal's agent.
|
146
|
+
#
|
147
|
+
# Stops the AppSignal agent. Call this before the end of your program to
|
148
|
+
# make sure the agent is stopped as well.
|
149
|
+
#
|
150
|
+
# @example
|
151
|
+
# Appsignal.start
|
152
|
+
# # Run your application
|
153
|
+
# Appsignal.stop
|
154
|
+
#
|
155
|
+
# @param called_by [String] Name of the thing that requested the agent to
|
156
|
+
# be stopped. Will be used in the AppSignal log file.
|
157
|
+
# @return [void]
|
158
|
+
# @since 1.0.0
|
159
|
+
def stop(called_by = nil)
|
160
|
+
if called_by
|
161
|
+
logger.debug("Stopping appsignal (#{called_by})")
|
162
|
+
else
|
163
|
+
logger.debug("Stopping appsignal")
|
164
|
+
end
|
165
|
+
Appsignal::Extension.stop
|
166
|
+
end
|
167
|
+
|
168
|
+
def forked
|
169
|
+
return unless active?
|
170
|
+
Appsignal.start_logger
|
171
|
+
logger.debug("Forked process, resubscribing and restarting extension")
|
172
|
+
Appsignal::Extension.start
|
173
|
+
end
|
174
|
+
|
175
|
+
def get_server_state(key)
|
176
|
+
Appsignal::Extension.get_server_state(key)
|
177
|
+
end
|
178
|
+
|
179
|
+
# Creates an AppSignal transaction for the given block.
|
180
|
+
#
|
181
|
+
# If AppSignal is not {.active?} it will still execute the block, but not
|
182
|
+
# create a transaction for it.
|
183
|
+
#
|
184
|
+
# A event is created for this transaction with the name given in the `name`
|
185
|
+
# argument. The event name must start with either `perform_job` or
|
186
|
+
# `process_action` to differentiate between the "web" and "background"
|
187
|
+
# namespace. Custom namespaces are not supported by this helper method.
|
188
|
+
#
|
189
|
+
# This helper method also captures any exception that occurs in the given
|
190
|
+
# block.
|
191
|
+
#
|
192
|
+
# The other (request) `env` argument hash keys, not listed here, can be
|
193
|
+
# found on the {Appsignal::Transaction::ENV_METHODS} array.
|
194
|
+
# Each of these keys are available as keys in the `env` hash argument.
|
195
|
+
#
|
196
|
+
# @example
|
197
|
+
# Appsignal.monitor_transaction("perform_job.nightly_update") do
|
198
|
+
# # your code
|
199
|
+
# end
|
200
|
+
#
|
201
|
+
# @example with an environment
|
202
|
+
# Appsignal.monitor_transaction(
|
203
|
+
# "perform_job.nightly_update",
|
204
|
+
# :metadata => { "user_id" => 1 }
|
205
|
+
# ) do
|
206
|
+
# # your code
|
207
|
+
# end
|
208
|
+
#
|
209
|
+
# @param name [String] main event name.
|
210
|
+
# @param env [Hash<Symbol, Object>]
|
211
|
+
# @option env [Hash<Symbol/String, Object>] :params Params for the
|
212
|
+
# monitored request/job, see {Appsignal::Transaction#params=} for more
|
213
|
+
# information.
|
214
|
+
# @option env [String] :controller name of the controller in which the
|
215
|
+
# transaction was recorded.
|
216
|
+
# @option env [String] :class name of the Ruby class in which the
|
217
|
+
# transaction was recorded. If `:controller` is also given, `:controller`
|
218
|
+
# is used instead.
|
219
|
+
# @option env [String] :action name of the controller action in which the
|
220
|
+
# transaction was recorded.
|
221
|
+
# @option env [String] :method name of the Ruby method in which the
|
222
|
+
# transaction was recorded. If `:action` is also given, `:action`
|
223
|
+
# is used instead.
|
224
|
+
# @option env [Integer] :queue_start the moment the request/job was queued.
|
225
|
+
# Used to track how long requests/jobs were queued before being executed.
|
226
|
+
# @option env [Hash<Symbol/String, String/Fixnum>] :metadata Additional
|
227
|
+
# metadata for the transaction, see {Appsignal::Transaction#set_metadata}
|
228
|
+
# for more information.
|
229
|
+
# @yield the block to monitor.
|
230
|
+
# @raise [Exception] any exception that occurs within the given block is re-raised by
|
231
|
+
# this method.
|
232
|
+
# @return [Object] the value of the given block is returned.
|
233
|
+
# @since 0.10.0
|
234
|
+
def monitor_transaction(name, env = {})
|
235
|
+
unless active?
|
236
|
+
return yield
|
237
|
+
end
|
238
|
+
|
239
|
+
if name.start_with?("perform_job".freeze)
|
240
|
+
namespace = Appsignal::Transaction::BACKGROUND_JOB
|
241
|
+
request = Appsignal::Transaction::GenericRequest.new(env)
|
242
|
+
elsif name.start_with?("process_action".freeze)
|
243
|
+
namespace = Appsignal::Transaction::HTTP_REQUEST
|
244
|
+
request = ::Rack::Request.new(env)
|
245
|
+
else
|
246
|
+
logger.error("Unrecognized name '#{name}'")
|
247
|
+
return
|
248
|
+
end
|
249
|
+
transaction = Appsignal::Transaction.create(
|
250
|
+
SecureRandom.uuid,
|
251
|
+
namespace,
|
252
|
+
request
|
253
|
+
)
|
254
|
+
begin
|
255
|
+
Appsignal.instrument(name) do
|
256
|
+
yield
|
257
|
+
end
|
258
|
+
rescue Exception => error # rubocop:disable Lint/RescueException
|
259
|
+
transaction.set_error(error)
|
260
|
+
raise error
|
261
|
+
ensure
|
262
|
+
transaction.set_http_or_background_action(request.env)
|
263
|
+
transaction.set_http_or_background_queue_start
|
264
|
+
Appsignal::Transaction.complete_current!
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
# Monitor a transaction, stop AppSignal and wait for this single
|
269
|
+
# transaction to be flushed.
|
270
|
+
#
|
271
|
+
# Useful for cases such as Rake tasks and Resque-like systems where a
|
272
|
+
# process is forked and immediately exits after the transaction finishes.
|
273
|
+
#
|
274
|
+
# @see monitor_transaction
|
275
|
+
def monitor_single_transaction(name, env = {}, &block)
|
276
|
+
monitor_transaction(name, env, &block)
|
277
|
+
ensure
|
278
|
+
stop("monitor_single_transaction")
|
279
|
+
end
|
280
|
+
|
281
|
+
# Listen for an error to occur and send it to AppSignal.
|
282
|
+
#
|
283
|
+
# Uses {.send_error} to directly send the error in a separate transaction.
|
284
|
+
# Does not add the error to the current transaction.
|
285
|
+
#
|
286
|
+
# Make sure that AppSignal is integrated in your application beforehand.
|
287
|
+
# AppSignal won't record errors unless {Config#active?} is `true`.
|
288
|
+
#
|
289
|
+
# @example
|
290
|
+
# # my_app.rb
|
291
|
+
# # setup AppSignal beforehand
|
292
|
+
#
|
293
|
+
# Appsignal.listen_for_error do
|
294
|
+
# # my code
|
295
|
+
# raise "foo"
|
296
|
+
# end
|
297
|
+
#
|
298
|
+
# @see Transaction.set_tags
|
299
|
+
# @see Transaction.set_namespace
|
300
|
+
# @see .send_error
|
301
|
+
# @see https://docs.appsignal.com/ruby/instrumentation/integrating-appsignal.html
|
302
|
+
# AppSignal integration guide
|
303
|
+
#
|
304
|
+
# @param tags [Hash, nil]
|
305
|
+
# @param namespace [String] the namespace for this error.
|
306
|
+
# @yield yields the given block.
|
307
|
+
# @return [Object] returns the return value of the given block.
|
308
|
+
def listen_for_error(tags = nil, namespace = Appsignal::Transaction::HTTP_REQUEST)
|
309
|
+
yield
|
310
|
+
rescue Exception => error # rubocop:disable Lint/RescueException
|
311
|
+
send_error(error, tags, namespace)
|
312
|
+
raise error
|
313
|
+
end
|
314
|
+
alias :listen_for_exception :listen_for_error
|
315
|
+
|
316
|
+
# Send an error to AppSignal regardless of the context.
|
317
|
+
#
|
318
|
+
# Records and send the exception to AppSignal.
|
319
|
+
#
|
320
|
+
# This instrumentation helper does not require a transaction to be active,
|
321
|
+
# it starts a new transaction by itself.
|
322
|
+
#
|
323
|
+
# Use {.set_error} if your want to add an exception to the current
|
324
|
+
# transaction.
|
325
|
+
#
|
326
|
+
# **Note**: Does not do anything if AppSignal is not active or when the
|
327
|
+
# "error" is not a class extended from Ruby's Exception class.
|
328
|
+
#
|
329
|
+
# @example Send an exception
|
330
|
+
# begin
|
331
|
+
# raise "oh no!"
|
332
|
+
# rescue => e
|
333
|
+
# Appsignal.send_error(e)
|
334
|
+
# end
|
335
|
+
#
|
336
|
+
# @example Send an exception with tags
|
337
|
+
# begin
|
338
|
+
# raise "oh no!"
|
339
|
+
# rescue => e
|
340
|
+
# Appsignal.send_error(e, :key => "value")
|
341
|
+
# end
|
342
|
+
#
|
343
|
+
# @param error [Exception] The error to send to AppSignal.
|
344
|
+
# @param tags [Hash{String, Symbol => String, Symbol, Integer}] Additional
|
345
|
+
# tags to add to the error. See also {.tag_request}.
|
346
|
+
# @param namespace [String] The namespace in which the error occurred.
|
347
|
+
# See also {.set_namespace}.
|
348
|
+
# @return [void]
|
349
|
+
#
|
350
|
+
# @see http://docs.appsignal.com/ruby/instrumentation/exception-handling.html
|
351
|
+
# Exception handling guide
|
352
|
+
# @see http://docs.appsignal.com/ruby/instrumentation/tagging.html
|
353
|
+
# Tagging guide
|
354
|
+
# @since 0.6.0
|
355
|
+
def send_error(error, tags = nil, namespace = Appsignal::Transaction::HTTP_REQUEST)
|
356
|
+
return unless active?
|
357
|
+
unless error.is_a?(Exception)
|
358
|
+
logger.error("Can't send error, given value is not an exception")
|
359
|
+
return
|
360
|
+
end
|
361
|
+
transaction = Appsignal::Transaction.new(
|
362
|
+
SecureRandom.uuid,
|
363
|
+
namespace,
|
364
|
+
Appsignal::Transaction::GenericRequest.new({})
|
365
|
+
)
|
366
|
+
transaction.set_tags(tags) if tags
|
367
|
+
transaction.set_error(error)
|
368
|
+
transaction.complete
|
369
|
+
end
|
370
|
+
alias :send_exception :send_error
|
371
|
+
|
372
|
+
# Set an error on the current transaction.
|
373
|
+
#
|
374
|
+
# **Note**: Does not do anything if AppSignal is not active, no transaction
|
375
|
+
# is currently active or when the "error" is not a class extended from
|
376
|
+
# Ruby's Exception class.
|
377
|
+
#
|
378
|
+
# @example Manual instrumentation of set_error.
|
379
|
+
# # Manually starting AppSignal here
|
380
|
+
# # Manually starting a transaction here.
|
381
|
+
# begin
|
382
|
+
# raise "oh no!"
|
383
|
+
# rescue => e
|
384
|
+
# Appsignal.set_error(error)
|
385
|
+
# end
|
386
|
+
# # Manually completing the transaction here.
|
387
|
+
# # Manually stopping AppSignal here
|
388
|
+
#
|
389
|
+
# @example In a Rails application
|
390
|
+
# class SomeController < ApplicationController
|
391
|
+
# # The AppSignal transaction is created by our integration for you.
|
392
|
+
# def create
|
393
|
+
# # Do something that breaks
|
394
|
+
# rescue => e
|
395
|
+
# Appsignal.set_error(e)
|
396
|
+
# end
|
397
|
+
# end
|
398
|
+
#
|
399
|
+
# @param exception [Exception] The error to add to the current transaction.
|
400
|
+
# @param tags [Hash{String, Symbol => String, Symbol, Integer}] Additional
|
401
|
+
# tags to add to the error. See also {.tag_request}.
|
402
|
+
# @param namespace [String] The namespace in which the error occurred.
|
403
|
+
# See also {.set_namespace}.
|
404
|
+
# @return [void]
|
405
|
+
#
|
406
|
+
# @see Transaction#set_error
|
407
|
+
# @see http://docs.appsignal.com/ruby/instrumentation/exception-handling.html
|
408
|
+
# Exception handling guide
|
409
|
+
# @since 0.6.6
|
410
|
+
def set_error(exception, tags = nil, namespace = nil)
|
411
|
+
return if !active? ||
|
412
|
+
Appsignal::Transaction.current.nil? ||
|
413
|
+
exception.nil?
|
414
|
+
transaction = Appsignal::Transaction.current
|
415
|
+
transaction.set_error(exception)
|
416
|
+
transaction.set_tags(tags) if tags
|
417
|
+
transaction.set_namespace(namespace) if namespace
|
418
|
+
end
|
419
|
+
alias :set_exception :set_error
|
420
|
+
alias :add_exception :set_error
|
421
|
+
|
422
|
+
# Set a custom action name for the current transaction.
|
423
|
+
#
|
424
|
+
# When using an integration such as the Rails or Sinatra AppSignal will try
|
425
|
+
# to find the action name from the controller or endpoint for you.
|
426
|
+
#
|
427
|
+
# If you want to customize the action name as it appears on AppSignal.com
|
428
|
+
# you can use this method. This overrides the action name AppSignal
|
429
|
+
# generates in an integration.
|
430
|
+
#
|
431
|
+
# @example in a Rails controller
|
432
|
+
# class SomeController < ApplicationController
|
433
|
+
# before_action :set_appsignal_action
|
434
|
+
#
|
435
|
+
# def set_appsignal_action
|
436
|
+
# Appsignal.set_action("DynamicController#dynamic_method")
|
437
|
+
# end
|
438
|
+
# end
|
439
|
+
#
|
440
|
+
# @param action [String]
|
441
|
+
# @return [void]
|
442
|
+
# @see Transaction#set_action
|
443
|
+
# @since 2.2.0
|
444
|
+
def set_action(action)
|
445
|
+
return if !active? ||
|
446
|
+
Appsignal::Transaction.current.nil? ||
|
447
|
+
action.nil?
|
448
|
+
Appsignal::Transaction.current.set_action(action)
|
449
|
+
end
|
450
|
+
|
451
|
+
# Set a custom namespace for the current transaction.
|
452
|
+
#
|
453
|
+
# When using an integration such as Rails or Sidekiq AppSignal will try to
|
454
|
+
# find a appropriate namespace for the transaction.
|
455
|
+
#
|
456
|
+
# A Rails controller will be automatically put in the "http_request"
|
457
|
+
# namespace, while a Sidekiq background job is put in the "background_job"
|
458
|
+
# namespace.
|
459
|
+
#
|
460
|
+
# Note: The "http_request" namespace gets transformed on AppSignal.com to
|
461
|
+
# "Web" and "background_job" gets transformed to "Background".
|
462
|
+
#
|
463
|
+
# If you want to customize the namespace in which transactions appear you
|
464
|
+
# can use this method. This overrides the namespace AppSignal uses by
|
465
|
+
# default.
|
466
|
+
#
|
467
|
+
# A common request we've seen is to split the administration panel from the
|
468
|
+
# main application.
|
469
|
+
#
|
470
|
+
# @example create a custom admin namespace
|
471
|
+
# class AdminController < ApplicationController
|
472
|
+
# before_action :set_appsignal_namespace
|
473
|
+
#
|
474
|
+
# def set_appsignal_namespace
|
475
|
+
# Appsignal.set_namespace("admin")
|
476
|
+
# end
|
477
|
+
# end
|
478
|
+
#
|
479
|
+
# @param namespace [String]
|
480
|
+
# @return [void]
|
481
|
+
# @see Transaction#set_namespace
|
482
|
+
# @since 2.2.0
|
483
|
+
def set_namespace(namespace)
|
484
|
+
return if !active? ||
|
485
|
+
Appsignal::Transaction.current.nil? ||
|
486
|
+
namespace.nil?
|
487
|
+
Appsignal::Transaction.current.set_namespace(namespace)
|
488
|
+
end
|
489
|
+
|
490
|
+
# Set tags on the current transaction.
|
491
|
+
#
|
492
|
+
# Tags are extra bits of information that are added to transaction and
|
493
|
+
# appear on sample details pages on AppSignal.com.
|
494
|
+
#
|
495
|
+
# @example
|
496
|
+
# Appsignal.tag_request(:locale => "en")
|
497
|
+
# Appsignal.tag_request("locale" => "en")
|
498
|
+
# Appsignal.tag_request("user_id" => 1)
|
499
|
+
#
|
500
|
+
# @example Nested hashes are not supported
|
501
|
+
# # Bad
|
502
|
+
# Appsignal.tag_request(:user => { :locale => "en" })
|
503
|
+
#
|
504
|
+
# @example in a Rails controller
|
505
|
+
# class SomeController < ApplicationController
|
506
|
+
# before_action :set_appsignal_tags
|
507
|
+
#
|
508
|
+
# def set_appsignal_tags
|
509
|
+
# Appsignal.tag_request(:locale => I18n.locale)
|
510
|
+
# end
|
511
|
+
# end
|
512
|
+
#
|
513
|
+
# @param tags [Hash] Collection of tags.
|
514
|
+
# @option tags [String, Symbol, Integer] :any
|
515
|
+
# The name of the tag as a Symbol.
|
516
|
+
# @option tags [String, Symbol, Integer] "any"
|
517
|
+
# The name of the tag as a String.
|
518
|
+
# @return [void]
|
519
|
+
#
|
520
|
+
# @see Transaction.set_tags
|
521
|
+
# @see http://docs.appsignal.com/ruby/instrumentation/tagging.html
|
522
|
+
# Tagging guide
|
523
|
+
def tag_request(tags = {})
|
524
|
+
return unless active?
|
525
|
+
transaction = Appsignal::Transaction.current
|
526
|
+
return false unless transaction
|
527
|
+
transaction.set_tags(tags)
|
528
|
+
end
|
529
|
+
alias :tag_job :tag_request
|
530
|
+
|
531
|
+
# Instrument helper for AppSignal.
|
532
|
+
#
|
533
|
+
# For more help, read our custom instrumentation guide, listed under "See
|
534
|
+
# also".
|
535
|
+
#
|
536
|
+
# @example Simple instrumentation
|
537
|
+
# Appsignal.instrument("fetch.issue_fetcher") do
|
538
|
+
# # To be instrumented code
|
539
|
+
# end
|
540
|
+
#
|
541
|
+
# @example Instrumentation with title and body
|
542
|
+
# Appsignal.instrument(
|
543
|
+
# "fetch.issue_fetcher",
|
544
|
+
# "Fetching issue",
|
545
|
+
# "GitHub API"
|
546
|
+
# ) do
|
547
|
+
# # To be instrumented code
|
548
|
+
# end
|
549
|
+
#
|
550
|
+
# @param name [String] Name of the instrumented event. Read our event
|
551
|
+
# naming guide listed under "See also".
|
552
|
+
# @param title [String, nil] Human readable name of the event.
|
553
|
+
# @param body [String, nil] Value of importance for the event, such as the
|
554
|
+
# server against an API call is made.
|
555
|
+
# @param body_format [Integer] Enum for the type of event that is
|
556
|
+
# instrumented. Accepted values are {EventFormatter::DEFAULT} and
|
557
|
+
# {EventFormatter::SQL_BODY_FORMAT}, but we recommend you use
|
558
|
+
# {.instrument_sql} instead of {EventFormatter::SQL_BODY_FORMAT}.
|
559
|
+
# @yield yields the given block of code instrumented in an AppSignal
|
560
|
+
# event.
|
561
|
+
# @return [Object] Returns the block's return value.
|
562
|
+
#
|
563
|
+
# @see Appsignal::Transaction#instrument
|
564
|
+
# @see .instrument_sql
|
565
|
+
# @see http://docs.appsignal.com/ruby/instrumentation/instrumentation.html
|
566
|
+
# AppSignal custom instrumentation guide
|
567
|
+
# @see http://docs.appsignal.com/api/event-names.html
|
568
|
+
# AppSignal event naming guide
|
569
|
+
# @since 1.3.0
|
570
|
+
def instrument(name, title = nil, body = nil, body_format = Appsignal::EventFormatter::DEFAULT)
|
571
|
+
Appsignal::Transaction.current.start_event
|
572
|
+
yield if block_given?
|
573
|
+
ensure
|
574
|
+
Appsignal::Transaction.current.finish_event(name, title, body, body_format)
|
575
|
+
end
|
576
|
+
|
577
|
+
# Instrumentation helper for SQL queries.
|
578
|
+
#
|
579
|
+
# This helper filters out values from SQL queries so you don't have to.
|
580
|
+
#
|
581
|
+
# @example SQL query instrumentation
|
582
|
+
# Appsignal.instrument_sql("perform.query", nil, "SELECT * FROM ...") do
|
583
|
+
# # To be instrumented code
|
584
|
+
# end
|
585
|
+
#
|
586
|
+
# @example SQL query instrumentation
|
587
|
+
# Appsignal.instrument_sql("perform.query", nil, "WHERE email = 'foo@..'") do
|
588
|
+
# # query value will replace 'foo..' with a question mark `?`.
|
589
|
+
# end
|
590
|
+
#
|
591
|
+
# @param name [String] Name of the instrumented event. Read our event
|
592
|
+
# naming guide listed under "See also".
|
593
|
+
# @param title [String, nil] Human readable name of the event.
|
594
|
+
# @param body [String, nil] SQL query that's being executed.
|
595
|
+
# @yield yields the given block of code instrumented in an AppSignal event.
|
596
|
+
# @return [Object] Returns the block's return value.
|
597
|
+
#
|
598
|
+
# @see .instrument
|
599
|
+
# @see http://docs.appsignal.com/ruby/instrumentation/instrumentation.html
|
600
|
+
# AppSignal custom instrumentation guide
|
601
|
+
# @see http://docs.appsignal.com/api/event-names.html
|
602
|
+
# AppSignal event naming guide
|
603
|
+
# @since 2.0.0
|
604
|
+
def instrument_sql(name, title = nil, body = nil, &block)
|
605
|
+
instrument(name, title, body, Appsignal::EventFormatter::SQL_BODY_FORMAT, &block)
|
606
|
+
end
|
607
|
+
|
608
|
+
def set_gauge(key, value)
|
609
|
+
Appsignal::Extension.set_gauge(key.to_s, value.to_f)
|
610
|
+
rescue RangeError
|
611
|
+
Appsignal.logger.warn("Gauge value #{value} for key '#{key}' is too big")
|
612
|
+
end
|
613
|
+
|
614
|
+
def set_host_gauge(key, value)
|
615
|
+
Appsignal::Extension.set_host_gauge(key.to_s, value.to_f)
|
616
|
+
rescue RangeError
|
617
|
+
Appsignal.logger.warn("Host gauge value #{value} for key '#{key}' is too big")
|
618
|
+
end
|
619
|
+
|
620
|
+
def set_process_gauge(key, value)
|
621
|
+
Appsignal::Extension.set_process_gauge(key.to_s, value.to_f)
|
622
|
+
rescue RangeError
|
623
|
+
Appsignal.logger.warn("Process gauge value #{value} for key '#{key}' is too big")
|
624
|
+
end
|
625
|
+
|
626
|
+
def increment_counter(key, value = 1)
|
627
|
+
Appsignal::Extension.increment_counter(key.to_s, value)
|
628
|
+
rescue RangeError
|
629
|
+
Appsignal.logger.warn("Counter value #{value} for key '#{key}' is too big")
|
630
|
+
end
|
631
|
+
|
632
|
+
def add_distribution_value(key, value)
|
633
|
+
Appsignal::Extension.add_distribution_value(key.to_s, value.to_f)
|
634
|
+
rescue RangeError
|
635
|
+
Appsignal.logger.warn("Distribution value #{value} for key '#{key}' is too big")
|
636
|
+
end
|
637
|
+
|
638
|
+
# In memory logger used before any logger is started with {.start_logger}.
|
639
|
+
#
|
640
|
+
# The contents of this logger are flushed to the logger in {.start_logger}.
|
641
|
+
#
|
642
|
+
# @api private
|
643
|
+
# @return [StringIO]
|
644
|
+
def in_memory_log
|
645
|
+
if defined?(@in_memory_log) && @in_memory_log
|
646
|
+
@in_memory_log
|
647
|
+
else
|
648
|
+
@in_memory_log = StringIO.new
|
649
|
+
end
|
650
|
+
end
|
651
|
+
|
652
|
+
def logger
|
653
|
+
@logger ||= Logger.new(in_memory_log).tap do |l|
|
654
|
+
l.level = Logger::INFO
|
655
|
+
l.formatter = log_formatter("appsignal")
|
656
|
+
end
|
657
|
+
end
|
658
|
+
|
659
|
+
# @api private
|
660
|
+
def log_formatter(prefix = nil)
|
661
|
+
pre = "#{prefix}: " if prefix
|
662
|
+
proc do |severity, datetime, _progname, msg|
|
663
|
+
"[#{datetime.strftime("%Y-%m-%dT%H:%M:%S")} (process) "\
|
664
|
+
"##{Process.pid}][#{severity}] #{pre}#{msg}\n"
|
665
|
+
end
|
666
|
+
end
|
667
|
+
|
668
|
+
# Start the AppSignal logger.
|
669
|
+
#
|
670
|
+
# Sets the log level and sets the logger. Uses a file-based logger or the
|
671
|
+
# STDOUT-based logger. See the `:log` configuration option.
|
672
|
+
#
|
673
|
+
# @param path_arg [nil] Deprecated param. Use the `:log_path`
|
674
|
+
# configuration option instead.
|
675
|
+
# @return [void]
|
676
|
+
# @since 0.7.0
|
677
|
+
def start_logger(path_arg = nil)
|
678
|
+
if config && config[:log] == "file" && config.log_file_path
|
679
|
+
start_file_logger(config.log_file_path)
|
680
|
+
else
|
681
|
+
start_stdout_logger
|
682
|
+
end
|
683
|
+
|
684
|
+
logger.level =
|
685
|
+
if config && config[:debug]
|
686
|
+
Logger::DEBUG
|
687
|
+
else
|
688
|
+
Logger::INFO
|
689
|
+
end
|
690
|
+
|
691
|
+
if in_memory_log
|
692
|
+
logger << in_memory_log.string
|
693
|
+
end
|
694
|
+
|
695
|
+
if path_arg
|
696
|
+
logger.info("Setting the path in start_logger has no effect anymore, set it in the config instead")
|
697
|
+
end
|
698
|
+
end
|
699
|
+
|
700
|
+
# Returns if the C-extension was loaded properly.
|
701
|
+
#
|
702
|
+
# @return [Boolean]
|
703
|
+
# @see Extension
|
704
|
+
# @since 1.0.0
|
705
|
+
def extension_loaded?
|
706
|
+
!!extension_loaded
|
707
|
+
end
|
708
|
+
|
709
|
+
# Returns the active state of the AppSignal integration.
|
710
|
+
#
|
711
|
+
# Conditions apply for AppSignal to be marked as active:
|
712
|
+
#
|
713
|
+
# - There is a config set on the {.config} attribute.
|
714
|
+
# - The set config is active {Config.active?}.
|
715
|
+
# - The AppSignal Extension is loaded {.extension_loaded?}.
|
716
|
+
#
|
717
|
+
# This logic is used within instrument helper such as {.instrument} so it's
|
718
|
+
# not necessary to wrap {.instrument} calls with this method.
|
719
|
+
#
|
720
|
+
# @example Do this
|
721
|
+
# Appsignal.instrument(..) do
|
722
|
+
# # Do this
|
723
|
+
# end
|
724
|
+
#
|
725
|
+
# @example Don't do this
|
726
|
+
# if Appsignal.active?
|
727
|
+
# Appsignal.instrument(..) do
|
728
|
+
# # Don't do this
|
729
|
+
# end
|
730
|
+
# end
|
731
|
+
#
|
732
|
+
# @return [Boolean]
|
733
|
+
# @since 0.2.7
|
734
|
+
def active?
|
735
|
+
config && config.active? && extension_loaded?
|
736
|
+
end
|
737
|
+
|
738
|
+
# @deprecated No replacement
|
739
|
+
def is_ignored_error?(error) # rubocop:disable Style/PredicateName
|
740
|
+
Appsignal.config[:ignore_errors].include?(error.class.name)
|
741
|
+
end
|
742
|
+
alias :is_ignored_exception? :is_ignored_error?
|
743
|
+
deprecate :is_ignored_error?, :none, 2017, 3
|
744
|
+
|
745
|
+
# @deprecated No replacement
|
746
|
+
def is_ignored_action?(action) # rubocop:disable Style/PredicateName
|
747
|
+
Appsignal.config[:ignore_actions].include?(action)
|
748
|
+
end
|
749
|
+
deprecate :is_ignored_action?, :none, 2017, 3
|
750
|
+
|
751
|
+
# Convenience method for skipping instrumentations around a block of code.
|
752
|
+
#
|
753
|
+
# @example
|
754
|
+
# Appsignal.without_instrumentation do
|
755
|
+
# # Complex code here
|
756
|
+
# end
|
757
|
+
#
|
758
|
+
# @yield block of code that shouldn't be instrumented.
|
759
|
+
# @return [Object] Returns the return value of the block.
|
760
|
+
# @since 0.8.7
|
761
|
+
def without_instrumentation
|
762
|
+
Appsignal::Transaction.current.pause! if Appsignal::Transaction.current
|
763
|
+
yield
|
764
|
+
ensure
|
765
|
+
Appsignal::Transaction.current.resume! if Appsignal::Transaction.current
|
766
|
+
end
|
767
|
+
|
768
|
+
private
|
769
|
+
|
770
|
+
def start_stdout_logger
|
771
|
+
@logger = Logger.new($stdout)
|
772
|
+
logger.formatter = log_formatter("appsignal")
|
773
|
+
end
|
774
|
+
|
775
|
+
def start_file_logger(path)
|
776
|
+
@logger = Logger.new(path)
|
777
|
+
logger.formatter = log_formatter
|
778
|
+
rescue SystemCallError => error
|
779
|
+
start_stdout_logger
|
780
|
+
logger.warn "Unable to start logger with log path '#{path}'."
|
781
|
+
logger.warn error
|
782
|
+
end
|
783
|
+
end
|
784
|
+
end
|
785
|
+
|
786
|
+
require "appsignal/system"
|
787
|
+
require "appsignal/utils"
|
788
|
+
require "appsignal/extension"
|
789
|
+
require "appsignal/auth_check"
|
790
|
+
require "appsignal/config"
|
791
|
+
require "appsignal/event_formatter"
|
792
|
+
require "appsignal/hooks"
|
793
|
+
require "appsignal/marker"
|
794
|
+
require "appsignal/minutely"
|
795
|
+
require "appsignal/garbage_collection_profiler"
|
796
|
+
require "appsignal/integrations/railtie" if defined?(::Rails)
|
797
|
+
require "appsignal/integrations/resque"
|
798
|
+
require "appsignal/integrations/resque_active_job"
|
799
|
+
require "appsignal/transaction"
|
800
|
+
require "appsignal/version"
|
801
|
+
require "appsignal/rack/generic_instrumentation"
|
802
|
+
require "appsignal/rack/js_exception_catcher"
|
803
|
+
require "appsignal/js_exception_transaction"
|
804
|
+
require "appsignal/transmitter"
|