appsignal 0.11.18 → 0.12.beta.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|