appsignal 1.4.0.alpha.2 → 1.4.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +3 -1
  3. data/.travis.yml +3 -1
  4. data/CHANGELOG.md +38 -1
  5. data/Rakefile +29 -12
  6. data/benchmark.rake +3 -7
  7. data/ext/agent.yml +11 -11
  8. data/ext/appsignal_extension.c +364 -72
  9. data/ext/extconf.rb +2 -4
  10. data/gemfiles/resque.gemfile +1 -0
  11. data/lib/appsignal.rb +40 -30
  12. data/lib/appsignal/auth_check.rb +1 -1
  13. data/lib/appsignal/cli/diagnose.rb +4 -3
  14. data/lib/appsignal/cli/install.rb +16 -15
  15. data/lib/appsignal/config.rb +31 -31
  16. data/lib/appsignal/event_formatter.rb +1 -1
  17. data/lib/appsignal/extension.rb +6 -0
  18. data/lib/appsignal/garbage_collection_profiler.rb +47 -0
  19. data/lib/appsignal/hooks.rb +1 -0
  20. data/lib/appsignal/hooks/active_support_notifications.rb +43 -0
  21. data/lib/appsignal/integrations/capistrano/appsignal.cap +1 -1
  22. data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +2 -2
  23. data/lib/appsignal/integrations/mongo_ruby_driver.rb +1 -1
  24. data/lib/appsignal/integrations/object.rb +4 -4
  25. data/lib/appsignal/integrations/padrino.rb +1 -1
  26. data/lib/appsignal/integrations/sinatra.rb +1 -1
  27. data/lib/appsignal/integrations/webmachine.rb +2 -2
  28. data/lib/appsignal/js_exception_transaction.rb +7 -10
  29. data/lib/appsignal/marker.rb +3 -2
  30. data/lib/appsignal/rack/generic_instrumentation.rb +1 -1
  31. data/lib/appsignal/rack/sinatra_instrumentation.rb +13 -6
  32. data/lib/appsignal/rack/streaming_listener.rb +5 -3
  33. data/lib/appsignal/system.rb +36 -0
  34. data/lib/appsignal/transaction.rb +20 -20
  35. data/lib/appsignal/transmitter.rb +11 -7
  36. data/lib/appsignal/utils.rb +76 -2
  37. data/lib/appsignal/version.rb +1 -1
  38. data/spec/lib/appsignal/auth_check_spec.rb +0 -2
  39. data/spec/lib/appsignal/capistrano2_spec.rb +99 -79
  40. data/spec/lib/appsignal/capistrano3_spec.rb +57 -78
  41. data/spec/lib/appsignal/cli/diagnose_spec.rb +17 -15
  42. data/spec/lib/appsignal/cli/install_spec.rb +38 -20
  43. data/spec/lib/appsignal/cli/notify_of_deploy_spec.rb +2 -5
  44. data/spec/lib/appsignal/cli_spec.rb +2 -5
  45. data/spec/lib/appsignal/config_spec.rb +385 -158
  46. data/spec/lib/appsignal/event_formatter/action_view/render_formatter_spec.rb +1 -3
  47. data/spec/lib/appsignal/event_formatter/active_record/instantiation_formatter_spec.rb +0 -2
  48. data/spec/lib/appsignal/event_formatter/active_record/sql_formatter_spec.rb +0 -2
  49. data/spec/lib/appsignal/event_formatter/elastic_search/search_formatter_spec.rb +0 -2
  50. data/spec/lib/appsignal/event_formatter/faraday/request_formatter_spec.rb +0 -2
  51. data/spec/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter_spec.rb +0 -2
  52. data/spec/lib/appsignal/event_formatter/moped/query_formatter_spec.rb +0 -2
  53. data/spec/lib/appsignal/event_formatter_spec.rb +0 -2
  54. data/spec/lib/appsignal/extension_spec.rb +7 -8
  55. data/spec/lib/appsignal/garbage_collection_profiler_spec.rb +71 -0
  56. data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +42 -0
  57. data/spec/lib/appsignal/hooks/celluloid_spec.rb +0 -2
  58. data/spec/lib/appsignal/hooks/data_mapper_spec.rb +0 -2
  59. data/spec/lib/appsignal/hooks/delayed_job_spec.rb +0 -2
  60. data/spec/lib/appsignal/hooks/mongo_ruby_driver_spec.rb +0 -2
  61. data/spec/lib/appsignal/hooks/net_http_spec.rb +0 -2
  62. data/spec/lib/appsignal/hooks/passenger_spec.rb +0 -2
  63. data/spec/lib/appsignal/hooks/puma_spec.rb +0 -2
  64. data/spec/lib/appsignal/hooks/rake_spec.rb +1 -2
  65. data/spec/lib/appsignal/hooks/redis_spec.rb +0 -2
  66. data/spec/lib/appsignal/hooks/sequel_spec.rb +19 -21
  67. data/spec/lib/appsignal/hooks/shoryuken_spec.rb +1 -4
  68. data/spec/lib/appsignal/hooks/sidekiq_spec.rb +2 -3
  69. data/spec/lib/appsignal/hooks/unicorn_spec.rb +0 -2
  70. data/spec/lib/appsignal/hooks/webmachine_spec.rb +4 -11
  71. data/spec/lib/appsignal/hooks_spec.rb +0 -2
  72. data/spec/lib/appsignal/integrations/data_mapper_spec.rb +0 -1
  73. data/spec/lib/appsignal/integrations/grape_spec.rb +1 -3
  74. data/spec/lib/appsignal/integrations/mongo_ruby_driver_spec.rb +1 -2
  75. data/spec/lib/appsignal/integrations/object_spec.rb +32 -3
  76. data/spec/lib/appsignal/integrations/padrino_spec.rb +4 -11
  77. data/spec/lib/appsignal/integrations/railtie_spec.rb +1 -3
  78. data/spec/lib/appsignal/integrations/resque_active_job_spec.rb +1 -3
  79. data/spec/lib/appsignal/integrations/resque_spec.rb +2 -4
  80. data/spec/lib/appsignal/integrations/sinatra_spec.rb +33 -8
  81. data/spec/lib/appsignal/integrations/webmachine_spec.rb +6 -15
  82. data/spec/lib/appsignal/js_exception_transaction_spec.rb +3 -5
  83. data/spec/lib/appsignal/marker_spec.rb +35 -48
  84. data/spec/lib/appsignal/minutely_spec.rb +0 -2
  85. data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +0 -2
  86. data/spec/lib/appsignal/rack/js_exception_catcher_spec.rb +0 -2
  87. data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +3 -5
  88. data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +47 -11
  89. data/spec/lib/appsignal/rack/streaming_listener_spec.rb +6 -7
  90. data/spec/lib/appsignal/system/container_spec.rb +67 -0
  91. data/spec/lib/appsignal/system_spec.rb +49 -0
  92. data/spec/lib/appsignal/transaction_spec.rb +30 -13
  93. data/spec/lib/appsignal/transmitter_spec.rb +53 -20
  94. data/spec/lib/appsignal/utils/gzip_spec.rb +10 -0
  95. data/spec/lib/appsignal/utils/params_sanitizer_spec.rb +0 -2
  96. data/spec/lib/appsignal/utils/query_params_sanitizer_spec.rb +0 -2
  97. data/spec/lib/appsignal/utils_spec.rb +59 -3
  98. data/spec/lib/appsignal_spec.rb +132 -58
  99. data/spec/spec_helper.rb +24 -116
  100. data/spec/support/fixtures/containers/cgroups/docker +14 -0
  101. data/spec/support/fixtures/containers/cgroups/docker_systemd +8 -0
  102. data/spec/support/fixtures/containers/cgroups/lxc +10 -0
  103. data/spec/support/fixtures/containers/cgroups/no_permission +0 -0
  104. data/spec/support/fixtures/containers/cgroups/none +1 -0
  105. data/spec/support/helpers/api_request_helper.rb +22 -0
  106. data/spec/support/helpers/dependency_helper.rb +61 -0
  107. data/spec/support/helpers/directory_helper.rb +27 -0
  108. data/spec/support/helpers/std_streams_helper.rb +35 -0
  109. data/spec/support/helpers/system_helpers.rb +24 -0
  110. data/spec/support/helpers/transaction_helpers.rb +7 -64
  111. data/spec/support/helpers/very_specific_error.rb +8 -0
  112. data/spec/support/mocks/fake_gc_profiler.rb +19 -0
  113. data/spec/support/project_fixture/config/appsignal.yml +10 -1
  114. metadata +60 -35
  115. data/circle.yml +0 -12
  116. data/lib/appsignal/subscriber.rb +0 -55
  117. data/lib/appsignal/update_active_support.rb +0 -20
  118. data/lib/vendor/active_support/notifications.rb +0 -212
  119. data/lib/vendor/active_support/notifications/fanout.rb +0 -157
  120. data/lib/vendor/active_support/notifications/instrumenter.rb +0 -73
  121. data/lib/vendor/active_support/per_thread_registry.rb +0 -53
  122. data/spec/lib/appsignal/subscriber_spec.rb +0 -160
  123. data/spec/lib/appsignal/update_active_support_spec.rb +0 -17
  124. data/spec/support/helpers/notification_helpers.rb +0 -14
@@ -1,73 +0,0 @@
1
- require 'securerandom'
2
-
3
- module ActiveSupport
4
- module Notifications
5
- # Instrumenters are stored in a thread local.
6
- class Instrumenter
7
- attr_reader :id
8
-
9
- def initialize(notifier)
10
- @id = unique_id
11
- @notifier = notifier
12
- end
13
-
14
- # Instrument the given block by measuring the time taken to execute it
15
- # and publish it. Notice that events get sent even if an error occurs
16
- # in the passed-in block.
17
- def instrument(name, payload={})
18
- start name, payload
19
- begin
20
- yield payload
21
- rescue Exception => e
22
- payload[:exception] = [e.class.name, e.message]
23
- raise e
24
- ensure
25
- finish name, payload
26
- end
27
- end
28
-
29
- # Send a start notification with +name+ and +payload+.
30
- def start(name, payload)
31
- @notifier.start name, @id, payload
32
- end
33
-
34
- # Send a finish notification with +name+ and +payload+.
35
- def finish(name, payload)
36
- @notifier.finish name, @id, payload
37
- end
38
-
39
- private
40
-
41
- def unique_id
42
- SecureRandom.hex(10)
43
- end
44
- end
45
-
46
- class Event
47
- attr_reader :name, :time, :transaction_id, :payload, :children
48
- attr_accessor :end
49
-
50
- def initialize(name, start, ending, transaction_id, payload)
51
- @name = name
52
- @payload = payload.dup
53
- @time = start
54
- @transaction_id = transaction_id
55
- @end = ending
56
- @children = []
57
- @duration = nil
58
- end
59
-
60
- def duration
61
- @duration ||= 1000.0 * (self.end - time)
62
- end
63
-
64
- def <<(event)
65
- @children << event
66
- end
67
-
68
- def parent_of?(event)
69
- @children.include? event
70
- end
71
- end
72
- end
73
- end
@@ -1,53 +0,0 @@
1
- module ActiveSupport
2
- # This module is used to encapsulate access to thread local variables.
3
- #
4
- # Instead of polluting the thread locals namespace:
5
- #
6
- # Thread.current[:connection_handler]
7
- #
8
- # you define a class that extends this module:
9
- #
10
- # module ActiveRecord
11
- # class RuntimeRegistry
12
- # extend ActiveSupport::PerThreadRegistry
13
- #
14
- # attr_accessor :connection_handler
15
- # end
16
- # end
17
- #
18
- # and invoke the declared instance accessors as class methods. So
19
- #
20
- # ActiveRecord::RuntimeRegistry.connection_handler = connection_handler
21
- #
22
- # sets a connection handler local to the current thread, and
23
- #
24
- # ActiveRecord::RuntimeRegistry.connection_handler
25
- #
26
- # returns a connection handler local to the current thread.
27
- #
28
- # This feature is accomplished by instantiating the class and storing the
29
- # instance as a thread local keyed by the class name. In the example above
30
- # a key "ActiveRecord::RuntimeRegistry" is stored in <tt>Thread.current</tt>.
31
- # The class methods proxy to said thread local instance.
32
- #
33
- # If the class has an initializer, it must accept no arguments.
34
- module PerThreadRegistry
35
- def self.extended(object)
36
- object.instance_variable_set '@per_thread_registry_key', object.name.freeze
37
- end
38
-
39
- def instance
40
- Thread.current[@per_thread_registry_key] ||= new
41
- end
42
-
43
- protected
44
- def method_missing(name, *args, &block) # :nodoc:
45
- # Caches the method definition as a singleton method of the receiver.
46
- define_singleton_method(name) do |*a, &b|
47
- instance.public_send(name, *a, &b)
48
- end
49
-
50
- send(name, *args, &block)
51
- end
52
- end
53
- end
@@ -1,160 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Appsignal::Subscriber do
4
- before :all do
5
- start_agent
6
- end
7
-
8
- before do
9
- ActiveSupport::Notifications.notifier.instance_variable_get(:@subscribers).clear
10
- Thread.current[:appsignal_transaction] = nil
11
- end
12
-
13
- let(:subscriber) { Appsignal::Subscriber.new }
14
- subject { subscriber }
15
-
16
- context "initialization" do
17
- before do
18
- subject
19
- end
20
-
21
- it "should be in the subscriber list" do
22
- ActiveSupport::Notifications.notifier.instance_variable_get(:@subscribers).select do |s|
23
- s.instance_variable_get(:@delegate).is_a?(Appsignal::Subscriber)
24
- end.count.should eq 1
25
- end
26
- end
27
-
28
- context "subscriptions" do
29
- describe "subscribe" do
30
- it "should subscribe" do
31
- subject.subscribe
32
- subject.as_subscriber.should_not be_nil
33
-
34
- ActiveSupport::Notifications.notifier.instance_variable_get(:@subscribers).select do |s|
35
- s.instance_variable_get(:@delegate).is_a?(Appsignal::Subscriber)
36
- end.count.should eq 2
37
- end
38
- end
39
-
40
- describe "#unsubscribe" do
41
- it "should unsubscribe" do
42
- subject.unsubscribe
43
- subject.as_subscriber.should be_nil
44
-
45
- ActiveSupport::Notifications.notifier.instance_variable_get(:@subscribers).select do |s|
46
- s.instance_variable_get(:@delegate).is_a?(Appsignal::Subscriber)
47
- end.count.should eq 0
48
- end
49
- end
50
-
51
- describe "#resubscribe" do
52
- it "should unsubscribe and subscribe" do
53
- subject.resubscribe
54
- subject.as_subscriber.should_not be_nil
55
-
56
- ActiveSupport::Notifications.notifier.instance_variable_get(:@subscribers).select do |s|
57
- s.instance_variable_get(:@delegate).is_a?(Appsignal::Subscriber)
58
- end.count.should eq 1
59
- end
60
- end
61
- end
62
-
63
- describe "#publish" do
64
- it "should exist" do
65
- lambda {
66
- subject.publish('name', '')
67
- }.should_not raise_error
68
- end
69
- end
70
-
71
- context "handling events using #start and #finish" do
72
- before do
73
- subscriber
74
- end
75
-
76
- it "should should not listen to events that start with a bang" do
77
- subject.should_not_receive(:start)
78
- subject.should_not_receive(:finish)
79
-
80
- ActiveSupport::Notifications.instrument '!render_template'
81
- end
82
-
83
- it "should not record events when there is no current transaction" do
84
- Appsignal::Extension.should_not_receive(:start_event)
85
- Appsignal::Extension.should_not_receive(:finish_event)
86
-
87
- lambda {
88
- ActiveSupport::Notifications.instrument 'something'
89
- }.should_not raise_error
90
- end
91
-
92
- context "with a current transaction" do
93
- let(:transaction) { Appsignal::Transaction.current }
94
-
95
- before do
96
- Appsignal::Transaction.create('request-id', Appsignal::Transaction::HTTP_REQUEST, {})
97
- end
98
-
99
- it "should call native start and finish event for every event" do
100
- transaction.should_receive(:start_event).exactly(4).times
101
- transaction.should_receive(:finish_event).with('one', nil, nil, nil).once
102
- transaction.should_receive(:finish_event).with('two', nil, nil, nil).once
103
- transaction.should_receive(:finish_event).with('two.three', nil, nil, nil).once
104
- transaction.should_receive(:finish_event).with('one.three', nil, nil, nil).once
105
-
106
- ActiveSupport::Notifications.instrument('one') do
107
- ActiveSupport::Notifications.instrument('two') do
108
- ActiveSupport::Notifications.instrument('one.three') do
109
- end
110
- ActiveSupport::Notifications.instrument('two.three') do
111
- end
112
- end
113
- end
114
- end
115
-
116
- it "should call finish with title and body if there is a formatter" do
117
- transaction.should_receive(:start_event).once
118
- transaction.should_receive(:finish_event).with(
119
- 'request.faraday',
120
- 'GET http://www.google.com',
121
- 'GET http://www.google.com',
122
- nil
123
- ).once
124
-
125
- ActiveSupport::Notifications.instrument(
126
- 'request.faraday',
127
- :method => 'get',
128
- :url => URI('http://www.google.com')
129
- )
130
- end
131
-
132
- it "should call finish with title, body and body format if there is a formatter that returns it" do
133
- transaction.should_receive(:start_event).once
134
- transaction.should_receive(:finish_event).with(
135
- 'sql.active_record',
136
- 'Something load',
137
- 'SELECT * FROM something',
138
- 1
139
- ).once
140
-
141
- ActiveSupport::Notifications.instrument(
142
- 'sql.active_record',
143
- :name => 'Something load',
144
- :sql => 'SELECT * FROM something'
145
- )
146
- end
147
-
148
- context "when paused" do
149
- before { transaction.pause! }
150
-
151
- it "should add no events" do
152
- Appsignal::Extension.should_not_receive(:start_event)
153
- Appsignal::Extension.should_not_receive(:finish_event)
154
-
155
- ActiveSupport::Notifications.instrument 'sql.active_record'
156
- end
157
- end
158
- end
159
- end
160
- end
@@ -1,17 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'Appsignal::UpdateActiveSupport', :if => (
4
- Gem.loaded_specs['rails'] &&
5
- Gem.loaded_specs['rails'].version < Gem::Version.create('4.0')
6
- ) do
7
- require 'appsignal/update_active_support'
8
- let(:pattern) { 'foo' }
9
- let(:delegate) { double }
10
- before { ActiveSupport::Notifications.subscribe(pattern, delegate) }
11
-
12
- it "should transfer old subscriptions to the new version" do
13
- expect( ActiveSupport::Notifications ).to receive(:subscribe).with(pattern, delegate)
14
- end
15
-
16
- after { Appsignal::UpdateActiveSupport.run }
17
- end
@@ -1,14 +0,0 @@
1
- module NotificationHelpers
2
- def notification_event(args={})
3
- args = {
4
- :name => 'process_action.action_controller',
5
- :start => fixed_time,
6
- :ending => fixed_time + 0.1,
7
- :tid => '1',
8
- :payload => http_request_env_with_data
9
- }.merge(args)
10
- ActiveSupport::Notifications::Event.new(
11
- args[:name], args[:start], args[:ending], args[:tid], args[:payload]
12
- )
13
- end
14
- end