appsignal 2.4.3 → 2.5.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
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