appsignal 2.4.3 → 2.5.0.alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +14 -5
  3. data/.rubocop_todo.yml +3 -0
  4. data/.travis.yml +3 -4
  5. data/CHANGELOG.md +3 -0
  6. data/Rakefile +21 -6
  7. data/appsignal.gemspec +12 -5
  8. data/ext/Rakefile +27 -0
  9. data/ext/agent.yml +52 -21
  10. data/ext/base.rb +79 -0
  11. data/ext/extconf.rb +5 -76
  12. data/gemfiles/sequel-435.gemfile +5 -1
  13. data/gemfiles/sequel.gemfile +5 -1
  14. data/lib/appsignal.rb +11 -6
  15. data/lib/appsignal/cli.rb +1 -2
  16. data/lib/appsignal/cli/install.rb +3 -3
  17. data/lib/appsignal/config.rb +56 -37
  18. data/lib/appsignal/extension.rb +28 -4
  19. data/lib/appsignal/extension/jruby.rb +460 -0
  20. data/lib/appsignal/hooks/sidekiq.rb +4 -4
  21. data/lib/appsignal/integrations/capistrano/appsignal.cap +7 -2
  22. data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +8 -3
  23. data/lib/appsignal/system.rb +16 -1
  24. data/lib/appsignal/transaction.rb +2 -2
  25. data/lib/appsignal/utils.rb +3 -1
  26. data/lib/appsignal/version.rb +1 -3
  27. data/spec/.rubocop.yml +3 -0
  28. data/spec/lib/appsignal/capistrano2_spec.rb +55 -41
  29. data/spec/lib/appsignal/capistrano3_spec.rb +87 -61
  30. data/spec/lib/appsignal/cli/diagnose_spec.rb +3 -3
  31. data/spec/lib/appsignal/cli/notify_of_deploy_spec.rb +4 -4
  32. data/spec/lib/appsignal/config_spec.rb +54 -21
  33. data/spec/lib/appsignal/extension/jruby_spec.rb +43 -0
  34. data/spec/lib/appsignal/extension_spec.rb +28 -12
  35. data/spec/lib/appsignal/hooks/sequel_spec.rb +7 -1
  36. data/spec/lib/appsignal/integrations/que_spec.rb +5 -5
  37. data/spec/lib/appsignal/system_spec.rb +5 -4
  38. data/spec/lib/appsignal/transaction_spec.rb +8 -8
  39. data/spec/lib/appsignal/utils/params_sanitizer_spec.rb +4 -4
  40. data/spec/lib/appsignal/utils/query_params_sanitizer_spec.rb +3 -3
  41. data/spec/lib/appsignal_spec.rb +5 -3
  42. data/spec/spec_helper.rb +29 -8
  43. data/spec/support/helpers/config_helpers.rb +3 -2
  44. metadata +12 -7
@@ -22,10 +22,10 @@ module Appsignal
22
22
  class SidekiqPlugin
23
23
  include Appsignal::Hooks::Helpers
24
24
 
25
- JOB_KEYS = %w(
25
+ JOB_KEYS = %w[
26
26
  args backtrace class created_at enqueued_at error_backtrace error_class
27
27
  error_message failed_at jid retried_at retry wrapped
28
- ).freeze
28
+ ].freeze
29
29
 
30
30
  def call(_worker, item, _queue)
31
31
  transaction = Appsignal::Transaction.create(
@@ -90,7 +90,7 @@ module Appsignal
90
90
  end
91
91
  when "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper"
92
92
  job_class = job["wrapped"] || args[0]
93
- if "ActionMailer::DeliveryJob" == job_class
93
+ if job_class == "ActionMailer::DeliveryJob"
94
94
  # MailerClass#mailer_method
95
95
  args[0]["arguments"][0..1].join("#")
96
96
  else
@@ -112,7 +112,7 @@ module Appsignal
112
112
  when "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper"
113
113
  is_wrapped = job["wrapped"]
114
114
  job_args = is_wrapped ? args[0]["arguments"] : []
115
- if "ActionMailer::DeliveryJob" == (is_wrapped || args[0])
115
+ if (is_wrapped || args[0]) == "ActionMailer::DeliveryJob"
116
116
  # Remove MailerClass, mailer_method and "deliver_now"
117
117
  job_args.drop(3)
118
118
  else
@@ -7,9 +7,14 @@ namespace :appsignal do
7
7
  appsignal_config = Appsignal::Config.new(
8
8
  ENV["PWD"],
9
9
  appsignal_env,
10
- fetch(:appsignal_config, {}),
10
+ {},
11
11
  Logger.new(StringIO.new)
12
- )
12
+ ).tap do |c|
13
+ fetch(:appsignal_config, {}).each do |key, value|
14
+ c[key] = value
15
+ end
16
+ c.validate
17
+ end
13
18
 
14
19
  if appsignal_config && appsignal_config.active?
15
20
  marker_data = {
@@ -3,7 +3,7 @@ module Appsignal
3
3
  # @api private
4
4
  class Capistrano
5
5
  def self.tasks(config)
6
- config.load do
6
+ config.load do # rubocop:disable Metrics/BlockLength
7
7
  after "deploy", "appsignal:deploy"
8
8
  after "deploy:migrations", "appsignal:deploy"
9
9
 
@@ -16,9 +16,14 @@ module Appsignal
16
16
  appsignal_config = Appsignal::Config.new(
17
17
  ENV["PWD"],
18
18
  env,
19
- fetch(:appsignal_config, {}),
19
+ {},
20
20
  Logger.new(StringIO.new)
21
- )
21
+ ).tap do |c|
22
+ fetch(:appsignal_config, {}).each do |key, value|
23
+ c[key] = value
24
+ end
25
+ c.validate
26
+ end
22
27
 
23
28
  if appsignal_config && appsignal_config.active?
24
29
  marker_data = {
@@ -40,7 +40,18 @@ module Appsignal
40
40
  def self.agent_platform
41
41
  return MUSL_TARGET if ENV["APPSIGNAL_BUILD_FOR_MUSL"]
42
42
 
43
- local_os = Gem::Platform.local.os
43
+ host_os = RbConfig::CONFIG["host_os"].downcase
44
+ local_os =
45
+ case host_os
46
+ when /linux/
47
+ "linux"
48
+ when /darwin/
49
+ "darwin"
50
+ when /freebsd/
51
+ "freebsd"
52
+ else
53
+ host_os
54
+ end
44
55
  if local_os =~ /linux/
45
56
  ldd_output = ldd_version_output
46
57
  return MUSL_TARGET if ldd_output.include? "musl"
@@ -62,5 +73,9 @@ module Appsignal
62
73
  def self.ldd_version_output
63
74
  `ldd --version 2>&1`
64
75
  end
76
+
77
+ def self.jruby?
78
+ RUBY_PLATFORM == "java"
79
+ end
65
80
  end
66
81
  end
@@ -9,7 +9,7 @@ module Appsignal
9
9
  BLANK = "".freeze
10
10
 
11
11
  # Based on what Rails uses + some variables we'd like to show
12
- ENV_METHODS = %w(
12
+ ENV_METHODS = %w[
13
13
  CONTENT_LENGTH AUTH_TYPE GATEWAY_INTERFACE
14
14
  PATH_TRANSLATED REMOTE_HOST REMOTE_IDENT REMOTE_USER REMOTE_ADDR
15
15
  REQUEST_METHOD SERVER_NAME SERVER_PORT SERVER_PROTOCOL REQUEST_URI
@@ -21,7 +21,7 @@ module Appsignal
21
21
  HTTP_CACHE_CONTROL HTTP_CONNECTION HTTP_USER_AGENT HTTP_FROM
22
22
  HTTP_NEGOTIATE HTTP_PRAGMA HTTP_REFERER HTTP_X_FORWARDED_FOR
23
23
  HTTP_CLIENT_IP HTTP_RANGE
24
- ).freeze
24
+ ].freeze
25
25
 
26
26
  class << self
27
27
  def create(id, namespace, request, options = {})
@@ -104,7 +104,9 @@ module Appsignal
104
104
  when Numeric, NilClass, TrueClass, FalseClass
105
105
  value
106
106
  when Hash
107
- Hash[value.map { |k, v| [jsonify(k), jsonify(v)] }]
107
+ value.each_with_object({}) do |(k, v), hash|
108
+ hash[jsonify(k)] = jsonify(v)
109
+ end
108
110
  when Array
109
111
  value.map { |v| jsonify(v) }
110
112
  else
@@ -1,5 +1,3 @@
1
- require "yaml"
2
-
3
1
  module Appsignal
4
- VERSION = "2.4.3".freeze
2
+ VERSION = "2.5.0.alpha.1".freeze
5
3
  end
@@ -1,4 +1,7 @@
1
1
  inherit_from: ../.rubocop.yml
2
2
 
3
+ Metrics/BlockLength:
4
+ Enabled: false
5
+
3
6
  # Metrics/LineLength:
4
7
  # Max: 100
@@ -25,7 +25,7 @@ if DependencyHelper.capistrano2_present?
25
25
  end
26
26
  end
27
27
 
28
- it "should have a deploy task" do
28
+ it "has a deploy task" do
29
29
  expect(capistrano_config.find_task("appsignal:deploy")).to_not be_nil
30
30
  end
31
31
 
@@ -40,27 +40,25 @@ if DependencyHelper.capistrano2_present?
40
40
  capistrano_config.dry_run = true
41
41
  end
42
42
 
43
- it "should be instantiated with the right params" do
44
- expect(Appsignal::Config).to receive(:new).with(
45
- project_fixture_path,
46
- "production",
47
- {},
48
- kind_of(Logger)
49
- )
50
- end
51
-
52
43
  context "when appsignal_config is available" do
53
44
  before do
54
- capistrano_config.set(:appsignal_config, :name => "AppName")
45
+ capistrano_config.set(
46
+ :appsignal_config,
47
+ :name => "AppName",
48
+ :active => true,
49
+ :push_api_key => "abc"
50
+ )
55
51
  end
56
52
 
57
- it "should be instantiated with the right params" do
58
- expect(Appsignal::Config).to receive(:new).with(
59
- project_fixture_path,
60
- "production",
61
- { :name => "AppName" },
62
- kind_of(Logger)
63
- )
53
+ it "overrides the default config with the custom appsignal_config" do
54
+ original_new = Appsignal::Marker.method(:new)
55
+
56
+ expect(Appsignal::Marker).to receive(:new) do |data, given_config|
57
+ expect(given_config[:name]).to eq("AppName")
58
+ original_new.call(data, given_config)
59
+ end
60
+
61
+ run
64
62
  end
65
63
 
66
64
  context "when rack_env is used instead of rails_env" do
@@ -69,13 +67,15 @@ if DependencyHelper.capistrano2_present?
69
67
  capistrano_config.set(:rack_env, "rack_production")
70
68
  end
71
69
 
72
- it "should be instantiated with the right params" do
73
- expect(Appsignal::Config).to receive(:new).with(
74
- project_fixture_path,
75
- "rack_production",
76
- { :name => "AppName" },
77
- kind_of(Logger)
78
- )
70
+ it "uses the rack_env as the env" do
71
+ original_new = Appsignal::Marker.method(:new)
72
+
73
+ expect(Appsignal::Marker).to receive(:new) do |data, given_config|
74
+ expect(given_config.env).to eq("rack_production")
75
+ original_new.call(data, given_config)
76
+ end
77
+
78
+ run
79
79
  end
80
80
  end
81
81
 
@@ -85,13 +85,15 @@ if DependencyHelper.capistrano2_present?
85
85
  capistrano_config.set(:stage, "stage_production")
86
86
  end
87
87
 
88
- it "should be instantiated with the right params" do
89
- expect(Appsignal::Config).to receive(:new).with(
90
- project_fixture_path,
91
- "stage_production",
92
- { :name => "AppName" },
93
- kind_of(Logger)
94
- )
88
+ it "uses the stage as the env" do
89
+ original_new = Appsignal::Marker.method(:new)
90
+
91
+ expect(Appsignal::Marker).to receive(:new) do |data, given_config|
92
+ expect(given_config.env).to eq("stage_production")
93
+ original_new.call(data, given_config)
94
+ end
95
+
96
+ run
95
97
  end
96
98
  end
97
99
 
@@ -102,18 +104,30 @@ if DependencyHelper.capistrano2_present?
102
104
  capistrano_config.set(:appsignal_env, "appsignal_production")
103
105
  end
104
106
 
105
- it "should prefer the appsignal_env rather than stage, rails_env and rack_env" do
106
- expect(Appsignal::Config).to receive(:new).with(
107
- project_fixture_path,
108
- "appsignal_production",
109
- { :name => "AppName" },
110
- kind_of(Logger)
111
- )
107
+ it "uses the appsignal_env as the env" do
108
+ original_new = Appsignal::Marker.method(:new)
109
+
110
+ expect(Appsignal::Marker).to receive(:new) do |data, given_config|
111
+ expect(given_config.env).to eq("appsignal_production")
112
+ original_new.call(data, given_config)
113
+ end
114
+
115
+ run
112
116
  end
113
117
  end
114
- end
115
118
 
116
- after { run }
119
+ context "with invalid config" do
120
+ before do
121
+ capistrano_config.set(:appsignal_config, :push_api_key => nil)
122
+ end
123
+
124
+ it "does not continue with invalid config" do
125
+ run
126
+ expect(output).to include \
127
+ "Not notifying of deploy, config is not active for environment: production"
128
+ end
129
+ end
130
+ end
117
131
  end
118
132
 
119
133
  describe "markers" do
@@ -21,6 +21,12 @@ if DependencyHelper.capistrano3_present?
21
21
  c.set(:current_revision, "503ce0923ed177a3ce000005")
22
22
  end
23
23
  end
24
+ let(:marker_data) do
25
+ {
26
+ :revision => "503ce0923ed177a3ce000005",
27
+ :user => "batman"
28
+ }
29
+ end
24
30
  before { Rake::Task["appsignal:deploy"].reenable }
25
31
 
26
32
  def run
@@ -40,94 +46,110 @@ if DependencyHelper.capistrano3_present?
40
46
  end
41
47
 
42
48
  context "config" do
43
- it "should be instantiated with the right params" do
44
- expect(Appsignal::Config).to receive(:new).with(
45
- project_fixture_path,
46
- "production",
47
- {},
48
- kind_of(Logger)
49
+ let(:env) { "production" }
50
+ before do
51
+ capistrano_config.set(
52
+ :appsignal_config,
53
+ :name => "AppName",
54
+ :active => true,
55
+ :push_api_key => "abc"
49
56
  )
57
+ config[:name] = "AppName"
58
+ config.instance_variable_set(:@env, env)
59
+ stub_marker_request.to_return(:status => 200)
50
60
  end
51
61
 
52
- context "when appsignal_config is available" do
62
+ context "when rack_env is the only env set" do
63
+ let(:env) { "rack_production" }
53
64
  before do
54
- capistrano_config.set(:appsignal_config, :name => "AppName")
65
+ capistrano_config.delete(:rails_env)
66
+ capistrano_config.set(:rack_env, env)
55
67
  end
56
68
 
57
- it "should be instantiated with the right params" do
58
- expect(Appsignal::Config).to receive(:new).with(
59
- project_fixture_path,
60
- "production",
61
- { :name => "AppName" },
62
- kind_of(Logger)
63
- )
64
- end
69
+ it "uses the rack_env as the env" do
70
+ original_new = Appsignal::Marker.method(:new)
65
71
 
66
- context "when rack_env is the only env set" do
67
- before do
68
- capistrano_config.delete(:rails_env)
69
- capistrano_config.set(:rack_env, "rack_production")
72
+ expect(Appsignal::Marker).to receive(:new) do |data, given_config|
73
+ expect(given_config.env).to eq("rack_production")
74
+ original_new.call(data, given_config)
70
75
  end
71
76
 
72
- it "should be instantiated with the rack env" do
73
- expect(Appsignal::Config).to receive(:new).with(
74
- project_fixture_path,
75
- "rack_production",
76
- { :name => "AppName" },
77
- kind_of(Logger)
78
- )
79
- end
77
+ run
80
78
  end
79
+ end
81
80
 
82
- context "when stage is set" do
83
- before do
84
- capistrano_config.set(:rack_env, "rack_production")
85
- capistrano_config.set(:stage, "stage_production")
81
+ context "when stage is set" do
82
+ let(:env) { "stage_production" }
83
+ before do
84
+ capistrano_config.set(:rack_env, "rack_production")
85
+ capistrano_config.set(:stage, env)
86
+ end
87
+
88
+ it "prefers the Capistrano stage rather than rails_env and rack_env" do
89
+ original_new = Appsignal::Marker.method(:new)
90
+
91
+ expect(Appsignal::Marker).to receive(:new) do |data, given_config|
92
+ expect(given_config.env).to eq("stage_production")
93
+ original_new.call(data, given_config)
86
94
  end
87
95
 
88
- it "should prefer the stage rather than rails_env and rack_env" do
89
- expect(Appsignal::Config).to receive(:new).with(
90
- project_fixture_path,
91
- "stage_production",
92
- { :name => "AppName" },
93
- kind_of(Logger)
94
- )
96
+ run
97
+ end
98
+ end
99
+
100
+ context "when `appsignal_config` is set" do
101
+ before do
102
+ ENV["APPSIGNAL_APP_NAME"] = "EnvName"
103
+ capistrano_config.set(:appsignal_config, :name => "AppName")
104
+ config[:name] = "AppName"
105
+ end
106
+
107
+ it "overrides the default config with the custom appsignal_config" do
108
+ original_new = Appsignal::Marker.method(:new)
109
+
110
+ expect(Appsignal::Marker).to receive(:new) do |data, given_config|
111
+ expect(given_config[:name]).to eq("AppName")
112
+ original_new.call(data, given_config)
95
113
  end
114
+
115
+ run
96
116
  end
97
117
 
98
- context "when appsignal_env is set" do
118
+ context "with invalid config" do
99
119
  before do
100
- capistrano_config.set(:rack_env, "rack_production")
101
- capistrano_config.set(:stage, "stage_production")
102
- capistrano_config.set(:appsignal_env, "appsignal_production")
120
+ capistrano_config.set(:appsignal_config, :push_api_key => nil)
103
121
  end
104
122
 
105
- it "should prefer the appsignal_env rather than stage, rails_env and rack_env" do
106
- expect(Appsignal::Config).to receive(:new).with(
107
- project_fixture_path,
108
- "appsignal_production",
109
- { :name => "AppName" },
110
- kind_of(Logger)
111
- )
123
+ it "does not continue with invalid config" do
124
+ run
125
+ expect(output).to include \
126
+ "Not notifying of deploy, config is not active for environment: production"
112
127
  end
113
128
  end
114
129
  end
115
130
 
116
- after { run }
117
- end
131
+ context "when `appsignal_env` is set" do
132
+ let(:env) { "appsignal_production" }
133
+ before do
134
+ capistrano_config.set(:rack_env, "rack_production")
135
+ capistrano_config.set(:stage, "stage_production")
136
+ capistrano_config.set(:appsignal_env, env)
137
+ end
118
138
 
119
- describe "markers" do
120
- def stub_marker_request(data = {})
121
- stub_api_request config, "markers", marker_data.merge(data)
122
- end
139
+ it "prefers the appsignal_env rather than stage, rails_env and rack_env" do
140
+ original_new = Appsignal::Marker.method(:new)
141
+
142
+ expect(Appsignal::Marker).to receive(:new) do |data, given_config|
143
+ expect(given_config.env).to eq("appsignal_production")
144
+ original_new.call(data, given_config)
145
+ end
123
146
 
124
- let(:marker_data) do
125
- {
126
- :revision => "503ce0923ed177a3ce000005",
127
- :user => "batman"
128
- }
147
+ run
148
+ end
129
149
  end
150
+ end
130
151
 
152
+ describe "markers" do
131
153
  context "when active for this environment" do
132
154
  it "transmits marker" do
133
155
  stub_marker_request.to_return(:status => 200)
@@ -208,4 +230,8 @@ if DependencyHelper.capistrano3_present?
208
230
  end
209
231
  end
210
232
  end
233
+
234
+ def stub_marker_request(data = {})
235
+ stub_api_request config, "markers", marker_data.merge(data)
236
+ end
211
237
  end