appsignal 2.8.4 → 2.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.rubocop_todo.yml +7 -16
- data/.travis.yml +4 -1
- data/CHANGELOG.md +16 -0
- data/README.md +23 -0
- data/Rakefile +10 -7
- data/appsignal.gemspec +3 -0
- data/build_matrix.yml +5 -1
- data/ext/Rakefile +23 -16
- data/ext/agent.yml +37 -37
- data/ext/base.rb +86 -24
- data/ext/extconf.rb +33 -26
- data/gemfiles/rails-6.0.gemfile +5 -0
- data/lib/appsignal.rb +14 -489
- data/lib/appsignal/cli/diagnose.rb +84 -4
- data/lib/appsignal/cli/diagnose/paths.rb +0 -5
- data/lib/appsignal/cli/diagnose/utils.rb +17 -0
- data/lib/appsignal/cli/helpers.rb +6 -0
- data/lib/appsignal/cli/install.rb +13 -7
- data/lib/appsignal/config.rb +1 -2
- data/lib/appsignal/event_formatter.rb +4 -5
- data/lib/appsignal/event_formatter/moped/query_formatter.rb +60 -59
- data/lib/appsignal/extension.rb +2 -2
- data/lib/appsignal/helpers/instrumentation.rb +485 -0
- data/lib/appsignal/helpers/metrics.rb +55 -0
- data/lib/appsignal/hooks.rb +9 -8
- data/lib/appsignal/hooks/puma.rb +65 -9
- data/lib/appsignal/hooks/sidekiq.rb +90 -0
- data/lib/appsignal/integrations/mongo_ruby_driver.rb +7 -0
- data/lib/appsignal/integrations/railtie.rb +2 -1
- data/lib/appsignal/marker.rb +2 -3
- data/lib/appsignal/minutely.rb +164 -14
- data/lib/appsignal/rack/sinatra_instrumentation.rb +1 -1
- data/lib/appsignal/system.rb +16 -18
- data/lib/appsignal/utils/rails_helper.rb +16 -0
- data/lib/appsignal/version.rb +1 -1
- data/spec/lib/appsignal/cli/diagnose_spec.rb +129 -22
- data/spec/lib/appsignal/cli/install_spec.rb +6 -1
- data/spec/lib/appsignal/config_spec.rb +3 -3
- data/spec/lib/appsignal/event_formatter/moped/query_formatter_spec.rb +6 -0
- data/spec/lib/appsignal/event_formatter_spec.rb +168 -69
- data/spec/lib/appsignal/hooks/puma_spec.rb +129 -0
- data/spec/lib/appsignal/hooks/sidekiq_spec.rb +147 -0
- data/spec/lib/appsignal/integrations/mongo_ruby_driver_spec.rb +24 -1
- data/spec/lib/appsignal/minutely_spec.rb +251 -21
- data/spec/lib/appsignal/system_spec.rb +0 -35
- data/spec/lib/appsignal/utils/hash_sanitizer_spec.rb +39 -31
- data/spec/lib/appsignal/utils/json_spec.rb +7 -3
- data/spec/lib/appsignal_spec.rb +27 -2
- data/spec/spec_helper.rb +13 -0
- data/spec/support/helpers/log_helpers.rb +6 -0
- data/spec/support/project_fixture/config/appsignal.yml +1 -0
- data/spec/support/stubs/sidekiq/api.rb +4 -0
- metadata +8 -2
data/ext/extconf.rb
CHANGED
@@ -1,18 +1,24 @@
|
|
1
|
-
require File.expand_path("../../lib/appsignal/version.rb", __FILE__)
|
2
1
|
require File.expand_path("../base.rb", __FILE__)
|
3
2
|
|
4
|
-
def
|
5
|
-
|
6
|
-
|
3
|
+
def local_build?
|
4
|
+
File.exist?(ext_path("appsignal-agent")) &&
|
5
|
+
File.exist?(ext_path("libappsignal.a")) &&
|
6
|
+
File.exist?(ext_path("appsignal.h"))
|
7
|
+
end
|
8
|
+
|
9
|
+
def install
|
10
|
+
library_type = "static"
|
11
|
+
report["language"]["implementation"] = "ruby"
|
12
|
+
report["build"]["library_type"] = library_type
|
7
13
|
return unless check_architecture
|
8
14
|
arch_config = AGENT_CONFIG["triples"][ARCH]
|
9
15
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
archive = download_archive(arch_config,
|
16
|
+
if local_build?
|
17
|
+
report["build"]["source"] = "local"
|
18
|
+
else
|
19
|
+
archive = download_archive(arch_config, library_type)
|
14
20
|
return unless archive
|
15
|
-
return unless verify_archive(archive, arch_config,
|
21
|
+
return unless verify_archive(archive, arch_config, library_type)
|
16
22
|
unarchive(archive)
|
17
23
|
end
|
18
24
|
|
@@ -21,15 +27,13 @@ def install # rubocop:disable Metrics/CyclomaticComplexity
|
|
21
27
|
Appsignal::System::MUSL_TARGET
|
22
28
|
].include?(PLATFORM)
|
23
29
|
|
24
|
-
logger.info "Creating makefile"
|
25
30
|
require "mkmf"
|
26
|
-
|
27
31
|
link_libraries if is_linux_system
|
28
32
|
|
29
33
|
if !have_library("appsignal", "appsignal_start", "appsignal.h")
|
30
|
-
|
34
|
+
abort_installation("Library libappsignal.a or appsignal.h not found")
|
31
35
|
elsif !find_executable("appsignal-agent", EXT_PATH)
|
32
|
-
|
36
|
+
abort_installation("File appsignal-agent not found")
|
33
37
|
else
|
34
38
|
if is_linux_system
|
35
39
|
# Statically link libgcc and libgcc_s libraries.
|
@@ -38,15 +42,16 @@ def install # rubocop:disable Metrics/CyclomaticComplexity
|
|
38
42
|
# run on one that isn't the missing libraries will cause the extension
|
39
43
|
# to fail on start.
|
40
44
|
$LDFLAGS += " -static-libgcc" # rubocop:disable Style/GlobalVars
|
45
|
+
report["build"]["flags"]["LDFLAGS"] = $LDFLAGS # rubocop:disable Style/GlobalVars
|
41
46
|
end
|
42
47
|
create_makefile "appsignal_extension"
|
43
|
-
|
44
|
-
end
|
45
|
-
rescue => ex
|
46
|
-
installation_failed "Exception while installing: #{ex}"
|
47
|
-
ex.backtrace.each do |line|
|
48
|
-
logger.error line
|
48
|
+
successful_installation
|
49
49
|
end
|
50
|
+
rescue => error
|
51
|
+
fail_installation_with_error(error)
|
52
|
+
ensure
|
53
|
+
create_dummy_makefile unless installation_succeeded?
|
54
|
+
write_report
|
50
55
|
end
|
51
56
|
|
52
57
|
# Ruby 2.6 requires us to statically link more libraries we use in our
|
@@ -54,26 +59,28 @@ end
|
|
54
59
|
# and musl builds.
|
55
60
|
def link_libraries
|
56
61
|
if RbConfig::CONFIG["THREAD_MODEL"] == "pthread"
|
57
|
-
logger.info "Linking extension against 'pthread' library"
|
58
62
|
# Link gem extension against pthread library
|
59
63
|
have_library "pthread"
|
60
|
-
have_required_function "pthread_create"
|
64
|
+
have_required_function "pthread", "pthread_create"
|
61
65
|
end
|
62
66
|
|
63
67
|
# Links gem extension against the `dl` library. This is needed when Ruby is
|
64
68
|
# not linked against `dl` itself, so link it on the gem extension.
|
65
|
-
logger.info "Linking extension against 'dl' library"
|
66
69
|
have_library "dl"
|
67
70
|
# Check if functions are available now from the linked library
|
68
71
|
%w[dlopen dlclose dlsym].each do |func|
|
69
|
-
have_required_function func
|
72
|
+
have_required_function "dl", func
|
70
73
|
end
|
71
74
|
end
|
72
75
|
|
73
|
-
def have_required_function(func) # rubocop:disable Naming/PredicateName
|
74
|
-
|
76
|
+
def have_required_function(library, func) # rubocop:disable Naming/PredicateName
|
77
|
+
if have_func(func)
|
78
|
+
report["build"]["dependencies"][library] = "linked"
|
79
|
+
return
|
80
|
+
end
|
75
81
|
|
76
|
-
|
82
|
+
report["build"]["dependencies"][library] = "not linked"
|
83
|
+
abort_installation("Missing function '#{func}'")
|
77
84
|
# Exit with true/0/success because the AppSignal installation should never
|
78
85
|
# break a build
|
79
86
|
exit
|
data/lib/appsignal.rb
CHANGED
@@ -4,13 +4,20 @@ require "json"
|
|
4
4
|
require "logger"
|
5
5
|
require "securerandom"
|
6
6
|
|
7
|
+
require "appsignal/helpers/instrumentation"
|
8
|
+
require "appsignal/helpers/metrics"
|
9
|
+
|
7
10
|
# AppSignal for Ruby gem's main module.
|
8
11
|
#
|
9
|
-
# Provides method to control the AppSignal instrumentation and the system
|
10
|
-
# Also provides
|
12
|
+
# Provides method to control the AppSignal instrumentation and the system
|
13
|
+
# agent. Also provides direct access to instrumentation helpers (from
|
14
|
+
# {Appsignal::Helpers::Instrumentation}) and metrics helpers (from
|
15
|
+
# {Appsignal::Helpers::Metrics}) for ease of use.
|
11
16
|
module Appsignal
|
12
17
|
class << self
|
13
18
|
extend Gem::Deprecate
|
19
|
+
include Helpers::Instrumentation
|
20
|
+
include Helpers::Metrics
|
14
21
|
|
15
22
|
# Accessor for the AppSignal configuration.
|
16
23
|
# Return the current AppSignal configuration.
|
@@ -130,7 +137,7 @@ module Appsignal
|
|
130
137
|
|
131
138
|
if config[:enable_gc_instrumentation]
|
132
139
|
GC::Profiler.enable
|
133
|
-
Appsignal::Minutely.
|
140
|
+
Appsignal::Minutely.register_garbage_collection_probe
|
134
141
|
end
|
135
142
|
|
136
143
|
Appsignal::Minutely.start if config[:enable_minutely_probes]
|
@@ -176,471 +183,6 @@ module Appsignal
|
|
176
183
|
Appsignal::Extension.get_server_state(key)
|
177
184
|
end
|
178
185
|
|
179
|
-
# Creates an AppSignal transaction for the given block.
|
180
|
-
#
|
181
|
-
# If AppSignal is not {.active?} it will still execute the block, but not
|
182
|
-
# create a transaction for it.
|
183
|
-
#
|
184
|
-
# A event is created for this transaction with the name given in the `name`
|
185
|
-
# argument. The event name must start with either `perform_job` or
|
186
|
-
# `process_action` to differentiate between the "web" and "background"
|
187
|
-
# namespace. Custom namespaces are not supported by this helper method.
|
188
|
-
#
|
189
|
-
# This helper method also captures any exception that occurs in the given
|
190
|
-
# block.
|
191
|
-
#
|
192
|
-
# @example
|
193
|
-
# Appsignal.monitor_transaction("perform_job.nightly_update") do
|
194
|
-
# # your code
|
195
|
-
# end
|
196
|
-
#
|
197
|
-
# @example with an environment
|
198
|
-
# Appsignal.monitor_transaction(
|
199
|
-
# "perform_job.nightly_update",
|
200
|
-
# :metadata => { "user_id" => 1 }
|
201
|
-
# ) do
|
202
|
-
# # your code
|
203
|
-
# end
|
204
|
-
#
|
205
|
-
# @param name [String] main event name.
|
206
|
-
# @param env [Hash<Symbol, Object>]
|
207
|
-
# @option env [Hash<Symbol/String, Object>] :params Params for the
|
208
|
-
# monitored request/job, see {Appsignal::Transaction#params=} for more
|
209
|
-
# information.
|
210
|
-
# @option env [String] :controller name of the controller in which the
|
211
|
-
# transaction was recorded.
|
212
|
-
# @option env [String] :class name of the Ruby class in which the
|
213
|
-
# transaction was recorded. If `:controller` is also given, `:controller`
|
214
|
-
# is used instead.
|
215
|
-
# @option env [String] :action name of the controller action in which the
|
216
|
-
# transaction was recorded.
|
217
|
-
# @option env [String] :method name of the Ruby method in which the
|
218
|
-
# transaction was recorded. If `:action` is also given, `:action`
|
219
|
-
# is used instead.
|
220
|
-
# @option env [Integer] :queue_start the moment the request/job was queued.
|
221
|
-
# Used to track how long requests/jobs were queued before being executed.
|
222
|
-
# @option env [Hash<Symbol/String, String/Fixnum>] :metadata Additional
|
223
|
-
# metadata for the transaction, see {Appsignal::Transaction#set_metadata}
|
224
|
-
# for more information.
|
225
|
-
# @yield the block to monitor.
|
226
|
-
# @raise [Exception] any exception that occurs within the given block is re-raised by
|
227
|
-
# this method.
|
228
|
-
# @return [Object] the value of the given block is returned.
|
229
|
-
# @since 0.10.0
|
230
|
-
def monitor_transaction(name, env = {})
|
231
|
-
return yield unless active?
|
232
|
-
|
233
|
-
if name.start_with?("perform_job".freeze)
|
234
|
-
namespace = Appsignal::Transaction::BACKGROUND_JOB
|
235
|
-
request = Appsignal::Transaction::GenericRequest.new(env)
|
236
|
-
elsif name.start_with?("process_action".freeze)
|
237
|
-
namespace = Appsignal::Transaction::HTTP_REQUEST
|
238
|
-
request = ::Rack::Request.new(env)
|
239
|
-
else
|
240
|
-
logger.error("Unrecognized name '#{name}'")
|
241
|
-
return
|
242
|
-
end
|
243
|
-
transaction = Appsignal::Transaction.create(
|
244
|
-
SecureRandom.uuid,
|
245
|
-
namespace,
|
246
|
-
request
|
247
|
-
)
|
248
|
-
begin
|
249
|
-
Appsignal.instrument(name) do
|
250
|
-
yield
|
251
|
-
end
|
252
|
-
rescue Exception => error # rubocop:disable Lint/RescueException
|
253
|
-
transaction.set_error(error)
|
254
|
-
raise error
|
255
|
-
ensure
|
256
|
-
transaction.set_http_or_background_action(request.env)
|
257
|
-
transaction.set_http_or_background_queue_start
|
258
|
-
Appsignal::Transaction.complete_current!
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
# Monitor a transaction, stop AppSignal and wait for this single
|
263
|
-
# transaction to be flushed.
|
264
|
-
#
|
265
|
-
# Useful for cases such as Rake tasks and Resque-like systems where a
|
266
|
-
# process is forked and immediately exits after the transaction finishes.
|
267
|
-
#
|
268
|
-
# @see monitor_transaction
|
269
|
-
def monitor_single_transaction(name, env = {}, &block)
|
270
|
-
monitor_transaction(name, env, &block)
|
271
|
-
ensure
|
272
|
-
stop("monitor_single_transaction")
|
273
|
-
end
|
274
|
-
|
275
|
-
# Listen for an error to occur and send it to AppSignal.
|
276
|
-
#
|
277
|
-
# Uses {.send_error} to directly send the error in a separate transaction.
|
278
|
-
# Does not add the error to the current transaction.
|
279
|
-
#
|
280
|
-
# Make sure that AppSignal is integrated in your application beforehand.
|
281
|
-
# AppSignal won't record errors unless {Config#active?} is `true`.
|
282
|
-
#
|
283
|
-
# @example
|
284
|
-
# # my_app.rb
|
285
|
-
# # setup AppSignal beforehand
|
286
|
-
#
|
287
|
-
# Appsignal.listen_for_error do
|
288
|
-
# # my code
|
289
|
-
# raise "foo"
|
290
|
-
# end
|
291
|
-
#
|
292
|
-
# @see Transaction.set_tags
|
293
|
-
# @see Transaction.set_namespace
|
294
|
-
# @see .send_error
|
295
|
-
# @see https://docs.appsignal.com/ruby/instrumentation/integrating-appsignal.html
|
296
|
-
# AppSignal integration guide
|
297
|
-
#
|
298
|
-
# @param tags [Hash, nil]
|
299
|
-
# @param namespace [String] the namespace for this error.
|
300
|
-
# @yield yields the given block.
|
301
|
-
# @return [Object] returns the return value of the given block.
|
302
|
-
def listen_for_error(tags = nil, namespace = Appsignal::Transaction::HTTP_REQUEST)
|
303
|
-
yield
|
304
|
-
rescue Exception => error # rubocop:disable Lint/RescueException
|
305
|
-
send_error(error, tags, namespace)
|
306
|
-
raise error
|
307
|
-
end
|
308
|
-
alias :listen_for_exception :listen_for_error
|
309
|
-
|
310
|
-
# Send an error to AppSignal regardless of the context.
|
311
|
-
#
|
312
|
-
# Records and send the exception to AppSignal.
|
313
|
-
#
|
314
|
-
# This instrumentation helper does not require a transaction to be active,
|
315
|
-
# it starts a new transaction by itself.
|
316
|
-
#
|
317
|
-
# Use {.set_error} if your want to add an exception to the current
|
318
|
-
# transaction.
|
319
|
-
#
|
320
|
-
# **Note**: Does not do anything if AppSignal is not active or when the
|
321
|
-
# "error" is not a class extended from Ruby's Exception class.
|
322
|
-
#
|
323
|
-
# @example Send an exception
|
324
|
-
# begin
|
325
|
-
# raise "oh no!"
|
326
|
-
# rescue => e
|
327
|
-
# Appsignal.send_error(e)
|
328
|
-
# end
|
329
|
-
#
|
330
|
-
# @example Send an exception with tags
|
331
|
-
# begin
|
332
|
-
# raise "oh no!"
|
333
|
-
# rescue => e
|
334
|
-
# Appsignal.send_error(e, :key => "value")
|
335
|
-
# end
|
336
|
-
#
|
337
|
-
# @param error [Exception] The error to send to AppSignal.
|
338
|
-
# @param tags [Hash{String, Symbol => String, Symbol, Integer}] Additional
|
339
|
-
# tags to add to the error. See also {.tag_request}.
|
340
|
-
# @param namespace [String] The namespace in which the error occurred.
|
341
|
-
# See also {.set_namespace}.
|
342
|
-
# @return [void]
|
343
|
-
#
|
344
|
-
# @see http://docs.appsignal.com/ruby/instrumentation/exception-handling.html
|
345
|
-
# Exception handling guide
|
346
|
-
# @see http://docs.appsignal.com/ruby/instrumentation/tagging.html
|
347
|
-
# Tagging guide
|
348
|
-
# @since 0.6.0
|
349
|
-
def send_error(error, tags = nil, namespace = Appsignal::Transaction::HTTP_REQUEST)
|
350
|
-
return unless active?
|
351
|
-
unless error.is_a?(Exception)
|
352
|
-
logger.error("Can't send error, given value is not an exception")
|
353
|
-
return
|
354
|
-
end
|
355
|
-
transaction = Appsignal::Transaction.new(
|
356
|
-
SecureRandom.uuid,
|
357
|
-
namespace,
|
358
|
-
Appsignal::Transaction::GenericRequest.new({})
|
359
|
-
)
|
360
|
-
transaction.set_tags(tags) if tags
|
361
|
-
transaction.set_error(error)
|
362
|
-
transaction.complete
|
363
|
-
end
|
364
|
-
alias :send_exception :send_error
|
365
|
-
|
366
|
-
# Set an error on the current transaction.
|
367
|
-
#
|
368
|
-
# **Note**: Does not do anything if AppSignal is not active, no transaction
|
369
|
-
# is currently active or when the "error" is not a class extended from
|
370
|
-
# Ruby's Exception class.
|
371
|
-
#
|
372
|
-
# @example Manual instrumentation of set_error.
|
373
|
-
# # Manually starting AppSignal here
|
374
|
-
# # Manually starting a transaction here.
|
375
|
-
# begin
|
376
|
-
# raise "oh no!"
|
377
|
-
# rescue => e
|
378
|
-
# Appsignal.set_error(error)
|
379
|
-
# end
|
380
|
-
# # Manually completing the transaction here.
|
381
|
-
# # Manually stopping AppSignal here
|
382
|
-
#
|
383
|
-
# @example In a Rails application
|
384
|
-
# class SomeController < ApplicationController
|
385
|
-
# # The AppSignal transaction is created by our integration for you.
|
386
|
-
# def create
|
387
|
-
# # Do something that breaks
|
388
|
-
# rescue => e
|
389
|
-
# Appsignal.set_error(e)
|
390
|
-
# end
|
391
|
-
# end
|
392
|
-
#
|
393
|
-
# @param exception [Exception] The error to add to the current transaction.
|
394
|
-
# @param tags [Hash{String, Symbol => String, Symbol, Integer}] Additional
|
395
|
-
# tags to add to the error. See also {.tag_request}.
|
396
|
-
# @param namespace [String] The namespace in which the error occurred.
|
397
|
-
# See also {.set_namespace}.
|
398
|
-
# @return [void]
|
399
|
-
#
|
400
|
-
# @see Transaction#set_error
|
401
|
-
# @see http://docs.appsignal.com/ruby/instrumentation/exception-handling.html
|
402
|
-
# Exception handling guide
|
403
|
-
# @since 0.6.6
|
404
|
-
def set_error(exception, tags = nil, namespace = nil)
|
405
|
-
return if !active? ||
|
406
|
-
Appsignal::Transaction.current.nil? ||
|
407
|
-
exception.nil?
|
408
|
-
transaction = Appsignal::Transaction.current
|
409
|
-
transaction.set_error(exception)
|
410
|
-
transaction.set_tags(tags) if tags
|
411
|
-
transaction.set_namespace(namespace) if namespace
|
412
|
-
end
|
413
|
-
alias :set_exception :set_error
|
414
|
-
alias :add_exception :set_error
|
415
|
-
|
416
|
-
# Set a custom action name for the current transaction.
|
417
|
-
#
|
418
|
-
# When using an integration such as the Rails or Sinatra AppSignal will try
|
419
|
-
# to find the action name from the controller or endpoint for you.
|
420
|
-
#
|
421
|
-
# If you want to customize the action name as it appears on AppSignal.com
|
422
|
-
# you can use this method. This overrides the action name AppSignal
|
423
|
-
# generates in an integration.
|
424
|
-
#
|
425
|
-
# @example in a Rails controller
|
426
|
-
# class SomeController < ApplicationController
|
427
|
-
# before_action :set_appsignal_action
|
428
|
-
#
|
429
|
-
# def set_appsignal_action
|
430
|
-
# Appsignal.set_action("DynamicController#dynamic_method")
|
431
|
-
# end
|
432
|
-
# end
|
433
|
-
#
|
434
|
-
# @param action [String]
|
435
|
-
# @return [void]
|
436
|
-
# @see Transaction#set_action
|
437
|
-
# @since 2.2.0
|
438
|
-
def set_action(action)
|
439
|
-
return if !active? ||
|
440
|
-
Appsignal::Transaction.current.nil? ||
|
441
|
-
action.nil?
|
442
|
-
Appsignal::Transaction.current.set_action(action)
|
443
|
-
end
|
444
|
-
|
445
|
-
# Set a custom namespace for the current transaction.
|
446
|
-
#
|
447
|
-
# When using an integration such as Rails or Sidekiq AppSignal will try to
|
448
|
-
# find a appropriate namespace for the transaction.
|
449
|
-
#
|
450
|
-
# A Rails controller will be automatically put in the "http_request"
|
451
|
-
# namespace, while a Sidekiq background job is put in the "background_job"
|
452
|
-
# namespace.
|
453
|
-
#
|
454
|
-
# Note: The "http_request" namespace gets transformed on AppSignal.com to
|
455
|
-
# "Web" and "background_job" gets transformed to "Background".
|
456
|
-
#
|
457
|
-
# If you want to customize the namespace in which transactions appear you
|
458
|
-
# can use this method. This overrides the namespace AppSignal uses by
|
459
|
-
# default.
|
460
|
-
#
|
461
|
-
# A common request we've seen is to split the administration panel from the
|
462
|
-
# main application.
|
463
|
-
#
|
464
|
-
# @example create a custom admin namespace
|
465
|
-
# class AdminController < ApplicationController
|
466
|
-
# before_action :set_appsignal_namespace
|
467
|
-
#
|
468
|
-
# def set_appsignal_namespace
|
469
|
-
# Appsignal.set_namespace("admin")
|
470
|
-
# end
|
471
|
-
# end
|
472
|
-
#
|
473
|
-
# @param namespace [String]
|
474
|
-
# @return [void]
|
475
|
-
# @see Transaction#set_namespace
|
476
|
-
# @since 2.2.0
|
477
|
-
def set_namespace(namespace)
|
478
|
-
return if !active? ||
|
479
|
-
Appsignal::Transaction.current.nil? ||
|
480
|
-
namespace.nil?
|
481
|
-
Appsignal::Transaction.current.set_namespace(namespace)
|
482
|
-
end
|
483
|
-
|
484
|
-
# Set tags on the current transaction.
|
485
|
-
#
|
486
|
-
# Tags are extra bits of information that are added to transaction and
|
487
|
-
# appear on sample details pages on AppSignal.com.
|
488
|
-
#
|
489
|
-
# @example
|
490
|
-
# Appsignal.tag_request(:locale => "en")
|
491
|
-
# Appsignal.tag_request("locale" => "en")
|
492
|
-
# Appsignal.tag_request("user_id" => 1)
|
493
|
-
#
|
494
|
-
# @example Nested hashes are not supported
|
495
|
-
# # Bad
|
496
|
-
# Appsignal.tag_request(:user => { :locale => "en" })
|
497
|
-
#
|
498
|
-
# @example in a Rails controller
|
499
|
-
# class SomeController < ApplicationController
|
500
|
-
# before_action :set_appsignal_tags
|
501
|
-
#
|
502
|
-
# def set_appsignal_tags
|
503
|
-
# Appsignal.tag_request(:locale => I18n.locale)
|
504
|
-
# end
|
505
|
-
# end
|
506
|
-
#
|
507
|
-
# @param tags [Hash] Collection of tags.
|
508
|
-
# @option tags [String, Symbol, Integer] :any
|
509
|
-
# The name of the tag as a Symbol.
|
510
|
-
# @option tags [String, Symbol, Integer] "any"
|
511
|
-
# The name of the tag as a String.
|
512
|
-
# @return [void]
|
513
|
-
#
|
514
|
-
# @see Transaction.set_tags
|
515
|
-
# @see http://docs.appsignal.com/ruby/instrumentation/tagging.html
|
516
|
-
# Tagging guide
|
517
|
-
def tag_request(tags = {})
|
518
|
-
return unless active?
|
519
|
-
transaction = Appsignal::Transaction.current
|
520
|
-
return false unless transaction
|
521
|
-
transaction.set_tags(tags)
|
522
|
-
end
|
523
|
-
alias :tag_job :tag_request
|
524
|
-
|
525
|
-
# Instrument helper for AppSignal.
|
526
|
-
#
|
527
|
-
# For more help, read our custom instrumentation guide, listed under "See
|
528
|
-
# also".
|
529
|
-
#
|
530
|
-
# @example Simple instrumentation
|
531
|
-
# Appsignal.instrument("fetch.issue_fetcher") do
|
532
|
-
# # To be instrumented code
|
533
|
-
# end
|
534
|
-
#
|
535
|
-
# @example Instrumentation with title and body
|
536
|
-
# Appsignal.instrument(
|
537
|
-
# "fetch.issue_fetcher",
|
538
|
-
# "Fetching issue",
|
539
|
-
# "GitHub API"
|
540
|
-
# ) do
|
541
|
-
# # To be instrumented code
|
542
|
-
# end
|
543
|
-
#
|
544
|
-
# @param name [String] Name of the instrumented event. Read our event
|
545
|
-
# naming guide listed under "See also".
|
546
|
-
# @param title [String, nil] Human readable name of the event.
|
547
|
-
# @param body [String, nil] Value of importance for the event, such as the
|
548
|
-
# server against an API call is made.
|
549
|
-
# @param body_format [Integer] Enum for the type of event that is
|
550
|
-
# instrumented. Accepted values are {EventFormatter::DEFAULT} and
|
551
|
-
# {EventFormatter::SQL_BODY_FORMAT}, but we recommend you use
|
552
|
-
# {.instrument_sql} instead of {EventFormatter::SQL_BODY_FORMAT}.
|
553
|
-
# @yield yields the given block of code instrumented in an AppSignal
|
554
|
-
# event.
|
555
|
-
# @return [Object] Returns the block's return value.
|
556
|
-
#
|
557
|
-
# @see Appsignal::Transaction#instrument
|
558
|
-
# @see .instrument_sql
|
559
|
-
# @see http://docs.appsignal.com/ruby/instrumentation/instrumentation.html
|
560
|
-
# AppSignal custom instrumentation guide
|
561
|
-
# @see http://docs.appsignal.com/api/event-names.html
|
562
|
-
# AppSignal event naming guide
|
563
|
-
# @since 1.3.0
|
564
|
-
def instrument(name, title = nil, body = nil, body_format = Appsignal::EventFormatter::DEFAULT)
|
565
|
-
Appsignal::Transaction.current.start_event
|
566
|
-
yield if block_given?
|
567
|
-
ensure
|
568
|
-
Appsignal::Transaction.current.finish_event(name, title, body, body_format)
|
569
|
-
end
|
570
|
-
|
571
|
-
# Instrumentation helper for SQL queries.
|
572
|
-
#
|
573
|
-
# This helper filters out values from SQL queries so you don't have to.
|
574
|
-
#
|
575
|
-
# @example SQL query instrumentation
|
576
|
-
# Appsignal.instrument_sql("perform.query", nil, "SELECT * FROM ...") do
|
577
|
-
# # To be instrumented code
|
578
|
-
# end
|
579
|
-
#
|
580
|
-
# @example SQL query instrumentation
|
581
|
-
# Appsignal.instrument_sql("perform.query", nil, "WHERE email = 'foo@..'") do
|
582
|
-
# # query value will replace 'foo..' with a question mark `?`.
|
583
|
-
# end
|
584
|
-
#
|
585
|
-
# @param name [String] Name of the instrumented event. Read our event
|
586
|
-
# naming guide listed under "See also".
|
587
|
-
# @param title [String, nil] Human readable name of the event.
|
588
|
-
# @param body [String, nil] SQL query that's being executed.
|
589
|
-
# @yield yields the given block of code instrumented in an AppSignal event.
|
590
|
-
# @return [Object] Returns the block's return value.
|
591
|
-
#
|
592
|
-
# @see .instrument
|
593
|
-
# @see http://docs.appsignal.com/ruby/instrumentation/instrumentation.html
|
594
|
-
# AppSignal custom instrumentation guide
|
595
|
-
# @see http://docs.appsignal.com/api/event-names.html
|
596
|
-
# AppSignal event naming guide
|
597
|
-
# @since 2.0.0
|
598
|
-
def instrument_sql(name, title = nil, body = nil, &block)
|
599
|
-
instrument(name, title, body, Appsignal::EventFormatter::SQL_BODY_FORMAT, &block)
|
600
|
-
end
|
601
|
-
|
602
|
-
def set_gauge(key, value, tags = {})
|
603
|
-
Appsignal::Extension.set_gauge(
|
604
|
-
key.to_s,
|
605
|
-
value.to_f,
|
606
|
-
Appsignal::Utils::Data.generate(tags)
|
607
|
-
)
|
608
|
-
rescue RangeError
|
609
|
-
Appsignal.logger.warn("Gauge value #{value} for key '#{key}' is too big")
|
610
|
-
end
|
611
|
-
|
612
|
-
def set_host_gauge(key, value)
|
613
|
-
Appsignal::Extension.set_host_gauge(key.to_s, value.to_f)
|
614
|
-
rescue RangeError
|
615
|
-
Appsignal.logger.warn("Host gauge value #{value} for key '#{key}' is too big")
|
616
|
-
end
|
617
|
-
|
618
|
-
def set_process_gauge(key, value)
|
619
|
-
Appsignal::Extension.set_process_gauge(key.to_s, value.to_f)
|
620
|
-
rescue RangeError
|
621
|
-
Appsignal.logger.warn("Process gauge value #{value} for key '#{key}' is too big")
|
622
|
-
end
|
623
|
-
|
624
|
-
def increment_counter(key, value = 1.0, tags = {})
|
625
|
-
Appsignal::Extension.increment_counter(
|
626
|
-
key.to_s,
|
627
|
-
value.to_f,
|
628
|
-
Appsignal::Utils::Data.generate(tags)
|
629
|
-
)
|
630
|
-
rescue RangeError
|
631
|
-
Appsignal.logger.warn("Counter value #{value} for key '#{key}' is too big")
|
632
|
-
end
|
633
|
-
|
634
|
-
def add_distribution_value(key, value, tags = {})
|
635
|
-
Appsignal::Extension.add_distribution_value(
|
636
|
-
key.to_s,
|
637
|
-
value.to_f,
|
638
|
-
Appsignal::Utils::Data.generate(tags)
|
639
|
-
)
|
640
|
-
rescue RangeError
|
641
|
-
Appsignal.logger.warn("Distribution value #{value} for key '#{key}' is too big")
|
642
|
-
end
|
643
|
-
|
644
186
|
# In memory logger used before any logger is started with {.start_logger}.
|
645
187
|
#
|
646
188
|
# The contents of this logger are flushed to the logger in {.start_logger}.
|
@@ -681,6 +223,10 @@ module Appsignal
|
|
681
223
|
# @return [void]
|
682
224
|
# @since 0.7.0
|
683
225
|
def start_logger(path_arg = nil)
|
226
|
+
if path_arg
|
227
|
+
logger.info("Setting the path in start_logger has no effect anymore, set it in the config instead")
|
228
|
+
end
|
229
|
+
|
684
230
|
if config && config[:log] == "file" && config.log_file_path
|
685
231
|
start_file_logger(config.log_file_path)
|
686
232
|
else
|
@@ -695,10 +241,6 @@ module Appsignal
|
|
695
241
|
end
|
696
242
|
|
697
243
|
logger << @in_memory_log.string if @in_memory_log
|
698
|
-
|
699
|
-
if path_arg
|
700
|
-
logger.info("Setting the path in start_logger has no effect anymore, set it in the config instead")
|
701
|
-
end
|
702
244
|
end
|
703
245
|
|
704
246
|
# Returns if the C-extension was loaded properly.
|
@@ -752,23 +294,6 @@ module Appsignal
|
|
752
294
|
end
|
753
295
|
deprecate :is_ignored_action?, :none, 2017, 3
|
754
296
|
|
755
|
-
# Convenience method for skipping instrumentation around a block of code.
|
756
|
-
#
|
757
|
-
# @example
|
758
|
-
# Appsignal.without_instrumentation do
|
759
|
-
# # Complex code here
|
760
|
-
# end
|
761
|
-
#
|
762
|
-
# @yield block of code that shouldn't be instrumented.
|
763
|
-
# @return [Object] Returns the return value of the block.
|
764
|
-
# @since 0.8.7
|
765
|
-
def without_instrumentation
|
766
|
-
Appsignal::Transaction.current.pause! if Appsignal::Transaction.current
|
767
|
-
yield
|
768
|
-
ensure
|
769
|
-
Appsignal::Transaction.current.resume! if Appsignal::Transaction.current
|
770
|
-
end
|
771
|
-
|
772
297
|
private
|
773
298
|
|
774
299
|
def start_stdout_logger
|