appsignal 0.11.18 → 0.12.beta.0
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.
- data/.gitignore +6 -0
- data/CHANGELOG.md +4 -38
- data/Rakefile +14 -6
- data/appsignal.gemspec +3 -1
- data/benchmark.rake +12 -16
- data/ext/appsignal_extension.c +183 -0
- data/ext/extconf.rb +39 -0
- data/gemfiles/capistrano2.gemfile +0 -1
- data/gemfiles/capistrano3.gemfile +0 -1
- data/gemfiles/rails-4.2.gemfile +1 -1
- data/lib/appsignal.rb +23 -61
- data/lib/appsignal/capistrano.rb +1 -2
- data/lib/appsignal/config.rb +13 -1
- data/lib/appsignal/event_formatter.rb +67 -0
- data/lib/appsignal/event_formatter/action_view/render_formatter.rb +23 -0
- data/lib/appsignal/event_formatter/active_record/sql_formatter.rb +74 -0
- data/lib/appsignal/event_formatter/moped/query_formatter.rb +80 -0
- data/lib/appsignal/event_formatter/net_http/request_formatter.rb +13 -0
- data/lib/appsignal/instrumentations/net_http.rb +6 -4
- data/lib/appsignal/integrations/resque.rb +2 -10
- data/lib/appsignal/integrations/sidekiq.rb +2 -2
- data/lib/appsignal/integrations/sinatra.rb +1 -0
- data/lib/appsignal/js_exception_transaction.rb +44 -28
- data/lib/appsignal/marker.rb +11 -13
- data/lib/appsignal/params_sanitizer.rb +5 -8
- data/lib/appsignal/rack/instrumentation.rb +2 -0
- data/lib/appsignal/rack/js_exception_catcher.rb +1 -0
- data/lib/appsignal/rack/listener.rb +1 -1
- data/lib/appsignal/rack/sinatra_instrumentation.rb +2 -12
- data/lib/appsignal/subscriber.rb +59 -0
- data/lib/appsignal/transaction.rb +117 -174
- data/lib/appsignal/transmitter.rb +8 -37
- data/lib/appsignal/version.rb +2 -1
- data/spec/lib/appsignal/config_spec.rb +25 -4
- data/spec/lib/appsignal/event_formatter/action_view/render_formatter_spec.rb +42 -0
- data/spec/lib/appsignal/{aggregator/middleware/active_record_sanitizer_spec.rb → event_formatter/active_record/sql_formatter_spec.rb} +61 -61
- data/spec/lib/appsignal/{event/moped_event_spec.rb → event_formatter/moped/query_formatter_spec.rb} +32 -78
- data/spec/lib/appsignal/event_formatter/net_http/request_formatter_spec.rb +26 -0
- data/spec/lib/appsignal/event_formatter_spec.rb +102 -0
- data/spec/lib/appsignal/extension_spec.rb +75 -0
- data/spec/lib/appsignal/instrumentations/net_http_spec.rb +20 -4
- data/spec/lib/appsignal/integrations/delayed_job_spec.rb +3 -2
- data/spec/lib/appsignal/integrations/rails_spec.rb +0 -7
- data/spec/lib/appsignal/integrations/resque_spec.rb +51 -55
- data/spec/lib/appsignal/integrations/sequel_spec.rb +8 -3
- data/spec/lib/appsignal/integrations/sidekiq_spec.rb +4 -21
- data/spec/lib/appsignal/integrations/sinatra_spec.rb +0 -6
- data/spec/lib/appsignal/js_exception_transaction_spec.rb +57 -60
- data/spec/lib/appsignal/params_sanitizer_spec.rb +11 -27
- data/spec/lib/appsignal/rack/listener_spec.rb +6 -6
- data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +2 -43
- data/spec/lib/appsignal/subscriber_spec.rb +162 -0
- data/spec/lib/appsignal/transaction_spec.rb +283 -615
- data/spec/lib/appsignal/transmitter_spec.rb +3 -32
- data/spec/lib/appsignal_spec.rb +41 -90
- data/spec/lib/generators/appsignal/appsignal_generator_spec.rb +0 -17
- data/spec/spec_helper.rb +18 -22
- data/spec/support/helpers/notification_helpers.rb +1 -1
- data/spec/support/helpers/time_helpers.rb +11 -0
- data/spec/support/helpers/transaction_helpers.rb +6 -18
- data/spec/support/project_fixture/config/appsignal.yml +1 -2
- metadata +68 -78
- checksums.yaml +0 -7
- data/gemfiles/padrino-0.13.gemfile +0 -7
- data/gemfiles/resque.gemfile +0 -5
- data/lib/appsignal/agent.rb +0 -217
- data/lib/appsignal/aggregator.rb +0 -67
- data/lib/appsignal/aggregator/middleware.rb +0 -4
- data/lib/appsignal/aggregator/middleware/action_view_sanitizer.rb +0 -23
- data/lib/appsignal/aggregator/middleware/active_record_sanitizer.rb +0 -65
- data/lib/appsignal/aggregator/middleware/chain.rb +0 -101
- data/lib/appsignal/aggregator/middleware/delete_blanks.rb +0 -16
- data/lib/appsignal/aggregator/post_processor.rb +0 -32
- data/lib/appsignal/event.rb +0 -20
- data/lib/appsignal/event/moped_event.rb +0 -90
- data/lib/appsignal/integrations/padrino.rb +0 -64
- data/lib/appsignal/integrations/passenger.rb +0 -13
- data/lib/appsignal/integrations/rake.rb +0 -29
- data/lib/appsignal/integrations/unicorn.rb +0 -25
- data/lib/appsignal/ipc.rb +0 -68
- data/lib/appsignal/transaction/formatter.rb +0 -85
- data/lib/appsignal/transaction/params_sanitizer.rb +0 -4
- data/lib/appsignal/zipped_payload.rb +0 -37
- data/spec/lib/appsignal/agent_spec.rb +0 -592
- data/spec/lib/appsignal/aggregator/middleware/action_view_sanitizer_spec.rb +0 -44
- data/spec/lib/appsignal/aggregator/middleware/chain_spec.rb +0 -168
- data/spec/lib/appsignal/aggregator/middleware/delete_blanks_spec.rb +0 -37
- data/spec/lib/appsignal/aggregator/post_processor_spec.rb +0 -99
- data/spec/lib/appsignal/aggregator_spec.rb +0 -186
- data/spec/lib/appsignal/event_spec.rb +0 -48
- data/spec/lib/appsignal/integrations/padrino_spec.rb +0 -171
- data/spec/lib/appsignal/integrations/passenger_spec.rb +0 -22
- data/spec/lib/appsignal/integrations/rake_spec.rb +0 -92
- data/spec/lib/appsignal/integrations/unicorn_spec.rb +0 -48
- data/spec/lib/appsignal/ipc_spec.rb +0 -128
- data/spec/lib/appsignal/transaction/formatter_spec.rb +0 -247
- data/spec/lib/appsignal/zipped_payload_spec.rb +0 -42
data/lib/appsignal.rb
CHANGED
@@ -1,22 +1,19 @@
|
|
1
1
|
require 'logger'
|
2
|
-
require 'rack'
|
3
|
-
require 'thread_safe'
|
4
2
|
require 'securerandom'
|
5
3
|
|
6
4
|
begin
|
7
5
|
require 'active_support/notifications'
|
8
|
-
|
6
|
+
ActiveSupport::Notifications::Fanout::Subscribers::Timed # See it it's recent enough
|
7
|
+
rescue LoadError, NameError
|
9
8
|
require 'vendor/active_support/notifications'
|
10
9
|
end
|
11
10
|
|
12
11
|
module Appsignal
|
13
12
|
class << self
|
14
|
-
attr_accessor :config, :logger, :agent, :in_memory_log
|
13
|
+
attr_accessor :config, :subscriber, :logger, :agent, :in_memory_log
|
15
14
|
|
16
15
|
def load_integrations
|
17
16
|
require 'appsignal/integrations/delayed_job'
|
18
|
-
require 'appsignal/integrations/passenger'
|
19
|
-
require 'appsignal/integrations/unicorn'
|
20
17
|
require 'appsignal/integrations/sidekiq'
|
21
18
|
require 'appsignal/integrations/resque'
|
22
19
|
require 'appsignal/integrations/sequel'
|
@@ -47,14 +44,13 @@ module Appsignal
|
|
47
44
|
end
|
48
45
|
if config.active?
|
49
46
|
logger.info("Starting AppSignal #{Appsignal::VERSION} on #{RUBY_VERSION}/#{RUBY_PLATFORM}")
|
47
|
+
config.write_to_environment
|
48
|
+
Appsignal::Extension.start
|
50
49
|
load_integrations
|
51
50
|
load_instrumentations
|
51
|
+
Appsignal::EventFormatter.initialize_formatters
|
52
52
|
initialize_extensions
|
53
|
-
@
|
54
|
-
at_exit do
|
55
|
-
logger.debug('Running at_exit block')
|
56
|
-
@agent.send_queue
|
57
|
-
end
|
53
|
+
@subscriber = Appsignal::Subscriber.new
|
58
54
|
else
|
59
55
|
logger.info("Not starting, not active for #{config.env}")
|
60
56
|
end
|
@@ -63,17 +59,6 @@ module Appsignal
|
|
63
59
|
end
|
64
60
|
end
|
65
61
|
|
66
|
-
# Convenience method for adding a transaction to the queue. This queue is
|
67
|
-
# managed and is periodically pushed to Appsignal.
|
68
|
-
#
|
69
|
-
# @return [ true ] True.
|
70
|
-
#
|
71
|
-
# @since 0.5.0
|
72
|
-
def enqueue(transaction)
|
73
|
-
return unless active?
|
74
|
-
agent.enqueue(transaction)
|
75
|
-
end
|
76
|
-
|
77
62
|
def monitor_transaction(name, payload={})
|
78
63
|
unless active?
|
79
64
|
yield
|
@@ -81,12 +66,12 @@ module Appsignal
|
|
81
66
|
end
|
82
67
|
|
83
68
|
begin
|
84
|
-
Appsignal::Transaction.create(SecureRandom.uuid, ENV)
|
69
|
+
Appsignal::Transaction.create(SecureRandom.uuid, ENV.to_hash)
|
85
70
|
ActiveSupport::Notifications.instrument(name, payload) do
|
86
71
|
yield
|
87
72
|
end
|
88
|
-
rescue
|
89
|
-
Appsignal.
|
73
|
+
rescue => exception
|
74
|
+
Appsignal.set_exception(exception)
|
90
75
|
raise exception
|
91
76
|
ensure
|
92
77
|
Appsignal::Transaction.complete_current!
|
@@ -102,23 +87,18 @@ module Appsignal
|
|
102
87
|
|
103
88
|
def send_exception(exception, tags=nil)
|
104
89
|
return if !active? || is_ignored_exception?(exception)
|
105
|
-
|
106
|
-
logger.error('Can\'t send exception, given value is not an exception')
|
107
|
-
return
|
108
|
-
end
|
109
|
-
transaction = Appsignal::Transaction.create(SecureRandom.uuid, nil)
|
110
|
-
transaction.add_exception(exception)
|
90
|
+
transaction = Appsignal::Transaction.create(SecureRandom.uuid, ENV.to_hash)
|
111
91
|
transaction.set_tags(tags) if tags
|
112
|
-
transaction.
|
113
|
-
Appsignal.
|
92
|
+
transaction.set_error(exception)
|
93
|
+
Appsignal::Transaction.complete_current!
|
114
94
|
end
|
115
95
|
|
116
|
-
def
|
96
|
+
def set_exception(exception)
|
117
97
|
return if !active? ||
|
118
98
|
Appsignal::Transaction.current.nil? ||
|
119
99
|
exception.nil? ||
|
120
100
|
is_ignored_exception?(exception)
|
121
|
-
Appsignal::Transaction.current.
|
101
|
+
Appsignal::Transaction.current.set_error(exception)
|
122
102
|
end
|
123
103
|
|
124
104
|
def tag_request(params={})
|
@@ -129,10 +109,6 @@ module Appsignal
|
|
129
109
|
end
|
130
110
|
alias :tag_job :tag_request
|
131
111
|
|
132
|
-
def transactions
|
133
|
-
@transactions ||= {}
|
134
|
-
end
|
135
|
-
|
136
112
|
def logger
|
137
113
|
@in_memory_log = StringIO.new unless @in_memory_log
|
138
114
|
@logger ||= Logger.new(@in_memory_log).tap do |l|
|
@@ -157,15 +133,8 @@ module Appsignal
|
|
157
133
|
@logger << @in_memory_log.string if @in_memory_log
|
158
134
|
end
|
159
135
|
|
160
|
-
def post_processing_middleware
|
161
|
-
@post_processing_chain ||= Appsignal::Aggregator::PostProcessor.default_middleware
|
162
|
-
yield @post_processing_chain if block_given?
|
163
|
-
@post_processing_chain
|
164
|
-
end
|
165
|
-
|
166
136
|
def active?
|
167
|
-
config && config.active?
|
168
|
-
agent && agent.active?
|
137
|
+
config && config.active?
|
169
138
|
end
|
170
139
|
|
171
140
|
def is_ignored_exception?(exception)
|
@@ -188,25 +157,18 @@ module Appsignal
|
|
188
157
|
end
|
189
158
|
end
|
190
159
|
|
191
|
-
require '
|
192
|
-
require 'appsignal/event'
|
193
|
-
require 'appsignal/aggregator'
|
194
|
-
require 'appsignal/aggregator/post_processor'
|
195
|
-
require 'appsignal/aggregator/middleware'
|
160
|
+
require 'appsignal_extension'
|
196
161
|
require 'appsignal/auth_check'
|
197
162
|
require 'appsignal/config'
|
163
|
+
require 'appsignal/event_formatter'
|
198
164
|
require 'appsignal/marker'
|
199
|
-
require 'appsignal/rack/listener'
|
200
|
-
require 'appsignal/rack/instrumentation'
|
201
|
-
require 'appsignal/rack/sinatra_instrumentation'
|
202
|
-
require 'appsignal/rack/js_exception_catcher'
|
203
165
|
require 'appsignal/params_sanitizer'
|
166
|
+
require 'appsignal/subscriber'
|
204
167
|
require 'appsignal/transaction'
|
205
|
-
require 'appsignal/transaction/formatter'
|
206
|
-
require 'appsignal/transaction/params_sanitizer'
|
207
|
-
require 'appsignal/transmitter'
|
208
|
-
require 'appsignal/zipped_payload'
|
209
|
-
require 'appsignal/ipc'
|
210
168
|
require 'appsignal/version'
|
169
|
+
require 'appsignal/rack/js_exception_catcher'
|
170
|
+
require 'appsignal/rack/listener'
|
171
|
+
require 'appsignal/rack/instrumentation'
|
211
172
|
require 'appsignal/integrations/rails'
|
212
173
|
require 'appsignal/js_exception_transaction'
|
174
|
+
require 'appsignal/transmitter'
|
data/lib/appsignal/capistrano.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'appsignal'
|
2
|
-
require 'capistrano/version'
|
3
2
|
|
4
|
-
if defined?(Capistrano::VERSION)
|
3
|
+
if defined?(Capistrano::VERSION)
|
5
4
|
# Capistrano 3+
|
6
5
|
load File.expand_path('../integrations/capistrano/appsignal.cap', __FILE__)
|
7
6
|
else
|
data/lib/appsignal/config.rb
CHANGED
@@ -10,7 +10,7 @@ module Appsignal
|
|
10
10
|
:ignore_exceptions => [],
|
11
11
|
:ignore_actions => [],
|
12
12
|
:send_params => true,
|
13
|
-
:endpoint => 'https://push.appsignal.com
|
13
|
+
:endpoint => 'https://push.appsignal.com',
|
14
14
|
:slow_request_threshold => 200,
|
15
15
|
:instrument_net_http => true,
|
16
16
|
:skip_session_data => false,
|
@@ -67,6 +67,18 @@ module Appsignal
|
|
67
67
|
!! self[:active]
|
68
68
|
end
|
69
69
|
|
70
|
+
def write_to_environment
|
71
|
+
ENV['APPSIGNAL_ACTIVE'] = active?.to_s
|
72
|
+
ENV['APPSIGNAL_APP_PATH'] = root_path.to_s
|
73
|
+
ENV['APPSIGNAL_AGENT_PATH'] = File.expand_path('../../../ext', __FILE__).to_s
|
74
|
+
ENV['APPSIGNAL_LOG_PATH'] = File.join(root_path, 'log')
|
75
|
+
ENV['APPSIGNAL_PUSH_API_ENDPOINT'] = config_hash[:endpoint]
|
76
|
+
ENV['APPSIGNAL_PUSH_API_KEY'] = config_hash[:push_api_key]
|
77
|
+
ENV['APPSIGNAL_APP_NAME'] = config_hash[:name]
|
78
|
+
ENV['APPSIGNAL_ENVIRONMENT'] = env
|
79
|
+
ENV['APPSIGNAL_AGENT_VERSION'] = Appsignal::AGENT_VERSION
|
80
|
+
end
|
81
|
+
|
70
82
|
protected
|
71
83
|
|
72
84
|
def config_file
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Appsignal
|
2
|
+
# Keeps track of formatters for types event that we can use to get
|
3
|
+
# the title and body of an event. Formatters should inherit from this class
|
4
|
+
# and implement a format(payload) method which returns an array with the title
|
5
|
+
# and body.
|
6
|
+
#
|
7
|
+
# When implementing a formatter remember that it cannot keep separate state per
|
8
|
+
# event, the same object will be called intermittently in a threaded environment.
|
9
|
+
# So only keep global configuration as state and pass the payload around as an
|
10
|
+
# argument if you need to use helper methods.
|
11
|
+
class EventFormatter
|
12
|
+
class << self
|
13
|
+
def formatters
|
14
|
+
@@formatters ||= {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def formatter_classes
|
18
|
+
@@formatter_classes ||= {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def register(name, formatter=self)
|
22
|
+
formatter_classes[name] = formatter
|
23
|
+
end
|
24
|
+
|
25
|
+
def unregister(name, formatter=self)
|
26
|
+
if formatter_classes[name] == formatter
|
27
|
+
formatter_classes.delete(name)
|
28
|
+
formatters.delete(name)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def registered?(name, klass=nil)
|
33
|
+
if klass
|
34
|
+
formatter_classes[name] == klass
|
35
|
+
else
|
36
|
+
formatter_classes.include?(name)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialize_formatters
|
41
|
+
formatter_classes.each do |name, formatter|
|
42
|
+
begin
|
43
|
+
format_method = formatter.instance_method(:format)
|
44
|
+
if format_method && format_method.arity == 1
|
45
|
+
formatters[name] = formatter.new
|
46
|
+
else
|
47
|
+
raise "#{f} does not have a format(payload) method"
|
48
|
+
end
|
49
|
+
rescue Exception => ex
|
50
|
+
formatter_classes.delete(name)
|
51
|
+
formatters.delete(name)
|
52
|
+
Appsignal.logger.debug("'#{ex.message}' when initializing #{name} event formatter")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def format(name, payload)
|
58
|
+
formatter = formatters[name]
|
59
|
+
formatter.format(payload) unless formatter.nil?
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
Dir.glob(File.expand_path('../event_formatter/**/*.rb', __FILE__)).each do |file|
|
66
|
+
require file
|
67
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Appsignal
|
2
|
+
class EventFormatter
|
3
|
+
module ActionView
|
4
|
+
class RenderFormatter < Appsignal::EventFormatter
|
5
|
+
register 'render_partial.action_view'
|
6
|
+
register 'render_template.action_view'
|
7
|
+
|
8
|
+
BLANK = ''.freeze
|
9
|
+
|
10
|
+
attr_reader :root_path
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@root_path = "#{Rails.root.to_s}/".freeze
|
14
|
+
end
|
15
|
+
|
16
|
+
def format(payload)
|
17
|
+
return nil unless payload[:identifier]
|
18
|
+
[payload[:identifier].sub(root_path, BLANK), nil]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Appsignal
|
2
|
+
class EventFormatter
|
3
|
+
module ActiveRecord
|
4
|
+
class SqlFormatter < Appsignal::EventFormatter
|
5
|
+
register 'sql.active_record'
|
6
|
+
|
7
|
+
SINGLE_QUOTE = /\\'/.freeze
|
8
|
+
DOUBLE_QUOTE = /\\"/.freeze
|
9
|
+
QUOTED_DATA = /(?:"[^"]+"|'[^']+')/.freeze
|
10
|
+
SINGLE_QUOTED_DATA = /(?:'[^']+')/.freeze
|
11
|
+
IN_ARRAY = /(IN \()[^\)]+(\))/.freeze
|
12
|
+
NUMERIC_DATA = /\b\d+\b/.freeze
|
13
|
+
SANITIZED_VALUE = '\1?\2'.freeze
|
14
|
+
|
15
|
+
attr_reader :adapter_uses_double_quoted_table_names, :adapter_uses_prepared_statements
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@connection_config = connection_config
|
19
|
+
@adapter_uses_prepared_statements = adapter_uses_prepared_statements?
|
20
|
+
@adapter_uses_double_quoted_table_names = adapter_uses_double_quoted_table_names?
|
21
|
+
rescue ::ActiveRecord::ConnectionNotEstablished
|
22
|
+
Appsignal::EventFormatter.unregister('sql.active_record', self.class)
|
23
|
+
Appsignal.logger.error('Error while getting ActiveRecord connection info, unregistering sql.active_record event formatter')
|
24
|
+
end
|
25
|
+
|
26
|
+
def format(payload)
|
27
|
+
return nil if schema_query?(payload) || !payload[:sql]
|
28
|
+
if adapter_uses_prepared_statements
|
29
|
+
[payload[:name], payload[:sql]]
|
30
|
+
else
|
31
|
+
sql_string = payload[:sql].dup
|
32
|
+
if adapter_uses_double_quoted_table_names
|
33
|
+
sql_string.gsub!(SINGLE_QUOTE, SANITIZED_VALUE)
|
34
|
+
sql_string.gsub!(SINGLE_QUOTED_DATA, SANITIZED_VALUE)
|
35
|
+
else
|
36
|
+
sql_string.gsub!(SINGLE_QUOTE, SANITIZED_VALUE)
|
37
|
+
sql_string.gsub!(DOUBLE_QUOTE, SANITIZED_VALUE)
|
38
|
+
sql_string.gsub!(QUOTED_DATA, SANITIZED_VALUE)
|
39
|
+
end
|
40
|
+
sql_string.gsub!(IN_ARRAY, SANITIZED_VALUE)
|
41
|
+
sql_string.gsub!(NUMERIC_DATA, SANITIZED_VALUE)
|
42
|
+
[payload[:name], sql_string]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
48
|
+
def schema_query?(payload)
|
49
|
+
payload[:name] == 'SCHEMA'
|
50
|
+
end
|
51
|
+
|
52
|
+
def connection_config
|
53
|
+
# TODO handle ActiveRecord::ConnectionNotEstablished
|
54
|
+
if ::ActiveRecord::Base.respond_to?(:connection_config)
|
55
|
+
::ActiveRecord::Base.connection_config
|
56
|
+
else
|
57
|
+
::ActiveRecord::Base.connection_pool.spec.config
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def adapter_uses_double_quoted_table_names?
|
62
|
+
adapter = @connection_config[:adapter]
|
63
|
+
adapter =~ /postgres/ || adapter =~ /sqlite/
|
64
|
+
end
|
65
|
+
|
66
|
+
def adapter_uses_prepared_statements?
|
67
|
+
return false unless adapter_uses_double_quoted_table_names?
|
68
|
+
return true if @connection_config[:prepared_statements].nil?
|
69
|
+
@connection_config[:prepared_statements]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Appsignal
|
2
|
+
class EventFormatter
|
3
|
+
module Moped
|
4
|
+
class QueryFormatter < Appsignal::EventFormatter
|
5
|
+
register 'query.moped'
|
6
|
+
|
7
|
+
def format(payload)
|
8
|
+
if payload[:ops] && payload[:ops].length > 0
|
9
|
+
op = payload[:ops].first
|
10
|
+
case op.class.to_s
|
11
|
+
when 'Moped::Protocol::Command'
|
12
|
+
return ['Command', {
|
13
|
+
:database => op.full_collection_name,
|
14
|
+
:selector => sanitize(op.selector)
|
15
|
+
}.inspect]
|
16
|
+
when 'Moped::Protocol::Query'
|
17
|
+
return ['Query', {
|
18
|
+
:database => op.full_collection_name,
|
19
|
+
:selector => sanitize(op.selector),
|
20
|
+
:flags => op.flags,
|
21
|
+
:limit => op.limit,
|
22
|
+
:skip => op.skip,
|
23
|
+
:fields => op.fields
|
24
|
+
}.inspect]
|
25
|
+
when 'Moped::Protocol::Delete'
|
26
|
+
return ['Delete', {
|
27
|
+
:database => op.full_collection_name,
|
28
|
+
:selector => sanitize(op.selector),
|
29
|
+
:flags => op.flags,
|
30
|
+
}.inspect]
|
31
|
+
when 'Moped::Protocol::Insert'
|
32
|
+
return ['Insert', {
|
33
|
+
:database => op.full_collection_name,
|
34
|
+
:documents => sanitize(op.documents),
|
35
|
+
:flags => op.flags,
|
36
|
+
}.inspect]
|
37
|
+
when 'Moped::Protocol::Update'
|
38
|
+
return ['Update', {
|
39
|
+
:database => op.full_collection_name,
|
40
|
+
:selector => sanitize(op.selector),
|
41
|
+
:update => sanitize(op.update),
|
42
|
+
:flags => op.flags,
|
43
|
+
}.inspect]
|
44
|
+
when 'Moped::Protocol::KillCursors'
|
45
|
+
return ['KillCursors', {
|
46
|
+
:number_of_cursor_ids => op.number_of_cursor_ids
|
47
|
+
}.inspect]
|
48
|
+
else
|
49
|
+
return [op.class.to_s.sub('Moped::Protocol::', ''), {
|
50
|
+
:database => op.full_collection_name
|
51
|
+
}.inspect]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
|
58
|
+
def sanitize(params)
|
59
|
+
if params.is_a?(Hash)
|
60
|
+
{}.tap do |hsh|
|
61
|
+
params.each do |key, val|
|
62
|
+
hsh[key] = sanitize(val)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
elsif params.is_a?(Array)
|
66
|
+
if params.first.is_a?(String)
|
67
|
+
['?']
|
68
|
+
else
|
69
|
+
params.map do |item|
|
70
|
+
sanitize(item)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
else
|
74
|
+
'?'
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|