appsignal 3.0.13-java → 3.0.17-java

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.
@@ -143,7 +143,7 @@ module Appsignal
143
143
  def transmit_report_to_appsignal
144
144
  puts " Transmitting diagnostics report"
145
145
  transmitter = Transmitter.new(
146
- DIAGNOSE_ENDPOINT,
146
+ ENV.fetch("APPSIGNAL_DIAGNOSE_ENDPOINT", DIAGNOSE_ENDPOINT),
147
147
  Appsignal.config
148
148
  )
149
149
  response = transmitter.transmit(:diagnose => data)
@@ -171,11 +171,18 @@ module Appsignal
171
171
  puts_value label, value
172
172
  end
173
173
 
174
+ # Prints values as given. Does no formatting on the value
174
175
  def puts_value(label, value, options = {})
175
176
  options[:level] ||= 1
176
177
  puts "#{" " * options[:level]}#{label}: #{value}"
177
178
  end
178
179
 
180
+ # Print values as inspected.
181
+ # Surrounds Strings in quotes.
182
+ def puts_format(label, value, options = {})
183
+ puts_value label, value.inspect, options
184
+ end
185
+
179
186
  def configure_appsignal(options)
180
187
  current_path = Dir.pwd
181
188
  initial_config = {}
@@ -327,9 +334,18 @@ module Appsignal
327
334
  data_section :library do
328
335
  save :language, "ruby"
329
336
  puts_value "Language", "Ruby"
330
- puts_and_save :package_version, "Gem version", Appsignal::VERSION
331
- puts_and_save :agent_version, "Agent version", Appsignal::Extension.agent_version
332
- puts_and_save :extension_loaded, "Extension loaded", Appsignal.extension_loaded
337
+
338
+ package_version = Appsignal::VERSION
339
+ save :package_version, package_version
340
+ puts_format "Gem version", package_version
341
+
342
+ agent_version = Appsignal::Extension.agent_version
343
+ save :agent_version, agent_version
344
+ puts_format "Agent version", agent_version
345
+
346
+ extension_loaded = Appsignal.extension_loaded
347
+ save :extension_loaded, extension_loaded
348
+ puts_format "Extension loaded", extension_loaded
333
349
  end
334
350
  end
335
351
 
@@ -381,29 +397,29 @@ module Appsignal
381
397
  def print_installation_language_report(report)
382
398
  report = report.fetch("language", {})
383
399
  puts " Language details"
384
- puts " Implementation: #{report["implementation"]}"
385
- puts " Ruby version: #{report["version"]}"
400
+ puts_format "Implementation", report["implementation"], :level => 2
401
+ puts_format "Ruby version", report["version"], :level => 2
386
402
  end
387
403
 
388
404
  def print_installation_download_report(report)
389
405
  report = report.fetch("download", {})
390
406
  puts " Download details"
391
- puts " Download URL: #{report["download_url"]}"
392
- puts " Checksum: #{report["checksum"]}"
407
+ puts_format "Download URL", report["download_url"], :level => 2
408
+ puts_format "Checksum", report["checksum"], :level => 2
393
409
  end
394
410
 
395
411
  def print_installation_build_report(report)
396
412
  report = report.fetch("build", {})
397
413
  puts " Build details"
398
- puts " Install time: #{report["time"]}"
399
- puts " Architecture: #{report["architecture"]}"
400
- puts " Target: #{report["target"]}"
401
- puts " Musl override: #{report["musl_override"]}"
402
- puts " Linux ARM override: #{report["linux_arm_override"]}"
403
- puts " Library type: #{report["library_type"]}"
404
- puts " Source: #{report["source"]}" if report["source"] != "remote"
405
- puts " Dependencies: #{report["dependencies"]}"
406
- puts " Flags: #{report["flags"]}"
414
+ puts_format "Install time", report["time"].to_s, :level => 2
415
+ puts_format "Architecture", report["architecture"], :level => 2
416
+ puts_format "Target", report["target"], :level => 2
417
+ puts_format "Musl override", report["musl_override"], :level => 2
418
+ puts_format "Linux ARM override", report["linux_arm_override"], :level => 2
419
+ puts_format "Library type", report["library_type"], :level => 2
420
+ puts_format "Source", report["source"], :level => 2 if report["source"] != "remote"
421
+ puts_format "Dependencies", report["dependencies"], :level => 2
422
+ puts_format "Flags", report["flags"], :level => 2
407
423
  end
408
424
 
409
425
  def print_installation_host_report(report)
@@ -417,24 +433,31 @@ module Appsignal
417
433
  rbconfig = RbConfig::CONFIG
418
434
  puts "Host information"
419
435
  data_section :host do
420
- puts_and_save :architecture, "Architecture", Appsignal::System.agent_architecture
436
+ agent_architecture = Appsignal::System.agent_architecture
437
+ save :architecture, agent_architecture
438
+ puts_format "Architecture", agent_architecture
421
439
 
422
- os_label = os = rbconfig["host_os"]
423
- os_label = "#{os} (Microsoft Windows is not supported.)" if Gem.win_platform?
440
+ os = rbconfig["host_os"]
441
+ os_label = os.inspect
442
+ os_label = "#{os_label} (Microsoft Windows is not supported.)" if Gem.win_platform?
424
443
  save :os, os
425
444
  puts_value "Operating System", os_label
426
445
 
427
- puts_and_save :language_version, "Ruby version",
428
- "#{rbconfig["ruby_version"]}-p#{rbconfig["PATCHLEVEL"]}"
446
+ language_version = "#{rbconfig["ruby_version"]}-p#{rbconfig["PATCHLEVEL"]}"
447
+ save :language_version, language_version
448
+ puts_format "Ruby version", language_version
429
449
 
430
- puts_value "Heroku", "true" if Appsignal::System.heroku?
431
- save :heroku, Appsignal::System.heroku?
450
+ heroku = Appsignal::System.heroku?
451
+ save :heroku, heroku
452
+ puts_format "Heroku", true if Appsignal::System.heroku?
432
453
 
433
- save :root, Process.uid.zero?
434
- puts_value "Root user",
435
- Process.uid.zero? ? "true (not recommended)" : "false"
436
- puts_and_save :running_in_container, "Running in container",
437
- Appsignal::Extension.running_in_container?
454
+ root = Process.uid.zero?
455
+ save :root, root
456
+ puts_value "Root user", root ? "true (not recommended)" : "false"
457
+
458
+ running_in_container = Appsignal::Extension.running_in_container?
459
+ save :running_in_container, running_in_container
460
+ puts_format "Running in container", running_in_container
438
461
  end
439
462
  end
440
463
 
@@ -451,7 +474,6 @@ module Appsignal
451
474
  :env => config.env_config
452
475
  }
453
476
  }
454
- print_environment(config)
455
477
  print_config_options(config)
456
478
  end
457
479
 
@@ -460,7 +482,7 @@ module Appsignal
460
482
  option = :env
461
483
  option_sources = sources_for_option(option)
462
484
  sources_label = config_sources_label(option, option_sources)
463
- print " Environment: #{format_config_option(env)}"
485
+ print " environment: #{format_config_option(env)}"
464
486
 
465
487
  if env == ""
466
488
  message = " Warning: No environment set, no config loaded!\n" \
@@ -474,10 +496,22 @@ module Appsignal
474
496
  end
475
497
 
476
498
  def print_config_options(config)
477
- config.config_hash.each do |key, value|
499
+ # We add the nullified "environment" key to print it ordered
500
+ # instead of adding it at the top of the list.
501
+ ordered_config_options = config
502
+ .config_hash
503
+ .merge(:environment => nil)
504
+ .sort
505
+
506
+ ordered_config_options.each do |key, value|
478
507
  option_sources = sources_for_option(key)
479
508
  sources_label = config_sources_label(key, option_sources)
480
- puts " #{key}: #{format_config_option(value)}#{sources_label}"
509
+
510
+ if key == :environment
511
+ print_environment(config)
512
+ else
513
+ puts " #{key}: #{format_config_option(value)}#{sources_label}"
514
+ end
481
515
  end
482
516
 
483
517
  puts "\nRead more about how the diagnose config output is rendered\n"\
@@ -543,7 +577,7 @@ module Appsignal
543
577
  when "401"
544
578
  ["invalid", :red]
545
579
  else
546
- ["Failed with status #{status}\n#{error.inspect}", :red]
580
+ ["Failed to validate: status #{status}\n#{error.inspect}", :red]
547
581
  end
548
582
  data[:validation][:push_api_key] = result
549
583
  puts_value "Validating Push API key", colorize(result, color)
@@ -563,6 +597,7 @@ module Appsignal
563
597
 
564
598
  unless path[:exists]
565
599
  puts_value "Exists?", path[:exists], :level => 2
600
+ print_empty_line
566
601
  return
567
602
  end
568
603
 
@@ -11,15 +11,25 @@ module Appsignal
11
11
  include Appsignal::Utils::DeprecationMessage
12
12
 
13
13
  DEFAULT_CONFIG = {
14
+ :ca_file_path => File.expand_path(File.join("../../../resources/cacert.pem"), __FILE__),
14
15
  :debug => false,
15
- :log => "file",
16
+ :dns_servers => [],
17
+ :enable_allocation_tracking => true,
18
+ :enable_gc_instrumentation => false,
19
+ :enable_host_metrics => true,
20
+ :enable_minutely_probes => true,
21
+ :enable_statsd => true,
22
+ :endpoint => "https://push.appsignal.com",
23
+ :files_world_accessible => true,
24
+ :filter_parameters => [],
25
+ :filter_session_data => [],
16
26
  :ignore_actions => [],
17
27
  :ignore_errors => [],
18
28
  :ignore_namespaces => [],
19
- :filter_parameters => [],
20
- :filter_session_data => [],
21
- :send_environment_metadata => true,
22
- :send_params => true,
29
+ :instrument_net_http => true,
30
+ :instrument_redis => true,
31
+ :instrument_sequel => true,
32
+ :log => "file",
23
33
  :request_headers => %w[
24
34
  HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING
25
35
  HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_CONNECTION
@@ -27,54 +37,61 @@ module Appsignal
27
37
  REQUEST_METHOD REQUEST_URI SERVER_NAME SERVER_PORT
28
38
  SERVER_PROTOCOL
29
39
  ],
30
- :endpoint => "https://push.appsignal.com",
31
- :instrument_net_http => true,
32
- :instrument_redis => true,
33
- :instrument_sequel => true,
40
+ :send_environment_metadata => true,
41
+ :send_params => true,
34
42
  :skip_session_data => false,
35
- :enable_allocation_tracking => true,
36
- :enable_gc_instrumentation => false,
37
- :enable_host_metrics => true,
38
- :enable_minutely_probes => true,
39
- :ca_file_path => File.expand_path(File.join("../../../resources/cacert.pem"), __FILE__),
40
- :dns_servers => [],
41
- :files_world_accessible => true,
42
43
  :transaction_debug_mode => false
43
44
  }.freeze
44
45
 
46
+ # @api private
47
+ DEFAULT_LOG_LEVEL = Logger::INFO
48
+ # Map from the `log_level` config option to Ruby's Logger level value.
49
+ #
50
+ # The trace level doesn't exist in the Ruby logger so it's mapped to debug.
51
+ # @api private
52
+ LOG_LEVEL_MAP = {
53
+ "error" => Logger::ERROR,
54
+ "warn" => Logger::WARN,
55
+ "info" => Logger::INFO,
56
+ "debug" => Logger::DEBUG,
57
+ "trace" => Logger::DEBUG
58
+ }.freeze
59
+
45
60
  ENV_TO_KEY_MAPPING = {
46
61
  "APPSIGNAL_ACTIVE" => :active,
47
- "APPSIGNAL_PUSH_API_KEY" => :push_api_key,
48
62
  "APPSIGNAL_APP_NAME" => :name,
49
- "APPSIGNAL_PUSH_API_ENDPOINT" => :endpoint,
63
+ "APPSIGNAL_CA_FILE_PATH" => :ca_file_path,
50
64
  "APPSIGNAL_DEBUG" => :debug,
51
- "APPSIGNAL_LOG" => :log,
52
- "APPSIGNAL_LOG_PATH" => :log_path,
53
- "APPSIGNAL_INSTRUMENT_NET_HTTP" => :instrument_net_http,
54
- "APPSIGNAL_INSTRUMENT_REDIS" => :instrument_redis,
55
- "APPSIGNAL_INSTRUMENT_SEQUEL" => :instrument_sequel,
56
- "APPSIGNAL_SKIP_SESSION_DATA" => :skip_session_data,
57
- "APPSIGNAL_IGNORE_ACTIONS" => :ignore_actions,
58
- "APPSIGNAL_IGNORE_ERRORS" => :ignore_errors,
59
- "APPSIGNAL_IGNORE_NAMESPACES" => :ignore_namespaces,
60
- "APPSIGNAL_FILTER_PARAMETERS" => :filter_parameters,
61
- "APPSIGNAL_FILTER_SESSION_DATA" => :filter_session_data,
62
- "APPSIGNAL_SEND_ENVIRONMENT_METADATA" => :send_environment_metadata,
63
- "APPSIGNAL_SEND_PARAMS" => :send_params,
64
- "APPSIGNAL_HTTP_PROXY" => :http_proxy,
65
+ "APPSIGNAL_DNS_SERVERS" => :dns_servers,
65
66
  "APPSIGNAL_ENABLE_ALLOCATION_TRACKING" => :enable_allocation_tracking,
66
67
  "APPSIGNAL_ENABLE_GC_INSTRUMENTATION" => :enable_gc_instrumentation,
67
- "APPSIGNAL_RUNNING_IN_CONTAINER" => :running_in_container,
68
- "APPSIGNAL_WORKING_DIR_PATH" => :working_dir_path,
69
- "APPSIGNAL_WORKING_DIRECTORY_PATH" => :working_directory_path,
70
68
  "APPSIGNAL_ENABLE_HOST_METRICS" => :enable_host_metrics,
71
69
  "APPSIGNAL_ENABLE_MINUTELY_PROBES" => :enable_minutely_probes,
72
- "APPSIGNAL_HOSTNAME" => :hostname,
73
- "APPSIGNAL_CA_FILE_PATH" => :ca_file_path,
74
- "APPSIGNAL_DNS_SERVERS" => :dns_servers,
70
+ "APPSIGNAL_ENABLE_STATSD" => :enable_statsd,
75
71
  "APPSIGNAL_FILES_WORLD_ACCESSIBLE" => :files_world_accessible,
72
+ "APPSIGNAL_FILTER_PARAMETERS" => :filter_parameters,
73
+ "APPSIGNAL_FILTER_SESSION_DATA" => :filter_session_data,
74
+ "APPSIGNAL_HOSTNAME" => :hostname,
75
+ "APPSIGNAL_HTTP_PROXY" => :http_proxy,
76
+ "APPSIGNAL_IGNORE_ACTIONS" => :ignore_actions,
77
+ "APPSIGNAL_IGNORE_ERRORS" => :ignore_errors,
78
+ "APPSIGNAL_IGNORE_NAMESPACES" => :ignore_namespaces,
79
+ "APPSIGNAL_INSTRUMENT_NET_HTTP" => :instrument_net_http,
80
+ "APPSIGNAL_INSTRUMENT_REDIS" => :instrument_redis,
81
+ "APPSIGNAL_INSTRUMENT_SEQUEL" => :instrument_sequel,
82
+ "APPSIGNAL_LOG" => :log,
83
+ "APPSIGNAL_LOG_LEVEL" => :log_level,
84
+ "APPSIGNAL_LOG_PATH" => :log_path,
85
+ "APPSIGNAL_PUSH_API_ENDPOINT" => :endpoint,
86
+ "APPSIGNAL_PUSH_API_KEY" => :push_api_key,
76
87
  "APPSIGNAL_REQUEST_HEADERS" => :request_headers,
88
+ "APPSIGNAL_RUNNING_IN_CONTAINER" => :running_in_container,
89
+ "APPSIGNAL_SEND_ENVIRONMENT_METADATA" => :send_environment_metadata,
90
+ "APPSIGNAL_SEND_PARAMS" => :send_params,
91
+ "APPSIGNAL_SKIP_SESSION_DATA" => :skip_session_data,
77
92
  "APPSIGNAL_TRANSACTION_DEBUG_MODE" => :transaction_debug_mode,
93
+ "APPSIGNAL_WORKING_DIRECTORY_PATH" => :working_directory_path,
94
+ "APPSIGNAL_WORKING_DIR_PATH" => :working_dir_path,
78
95
  "APP_REVISION" => :revision
79
96
  }.freeze
80
97
  # @api private
@@ -84,6 +101,7 @@ module Appsignal
84
101
  APPSIGNAL_HOSTNAME
85
102
  APPSIGNAL_HTTP_PROXY
86
103
  APPSIGNAL_LOG
104
+ APPSIGNAL_LOG_LEVEL
87
105
  APPSIGNAL_LOG_PATH
88
106
  APPSIGNAL_PUSH_API_ENDPOINT
89
107
  APPSIGNAL_PUSH_API_KEY
@@ -99,6 +117,7 @@ module Appsignal
99
117
  APPSIGNAL_ENABLE_GC_INSTRUMENTATION
100
118
  APPSIGNAL_ENABLE_HOST_METRICS
101
119
  APPSIGNAL_ENABLE_MINUTELY_PROBES
120
+ APPSIGNAL_ENABLE_STATSD
102
121
  APPSIGNAL_FILES_WORLD_ACCESSIBLE
103
122
  APPSIGNAL_INSTRUMENT_NET_HTTP
104
123
  APPSIGNAL_INSTRUMENT_REDIS
@@ -236,6 +255,18 @@ module Appsignal
236
255
  config_hash[key] = value
237
256
  end
238
257
 
258
+ def log_level
259
+ if config_hash[:debug] || config_hash[:transaction_debug_mode]
260
+ level = Logger::DEBUG
261
+ end
262
+ option = config_hash[:log_level]
263
+ if option
264
+ log_level_option = LOG_LEVEL_MAP[option]
265
+ level = log_level_option if log_level_option
266
+ end
267
+ level.nil? ? Appsignal::Config::DEFAULT_LOG_LEVEL : level
268
+ end
269
+
239
270
  def log_file_path
240
271
  path = config_hash[:log_path] || root_path && File.join(root_path, "log")
241
272
  if path && File.writable?(path)
@@ -265,32 +296,35 @@ module Appsignal
265
296
 
266
297
  def write_to_environment # rubocop:disable Metrics/AbcSize
267
298
  ENV["_APPSIGNAL_ACTIVE"] = active?.to_s
268
- ENV["_APPSIGNAL_APP_PATH"] = root_path.to_s
269
299
  ENV["_APPSIGNAL_AGENT_PATH"] = File.expand_path("../../../ext", __FILE__).to_s
300
+ ENV["_APPSIGNAL_APP_NAME"] = config_hash[:name]
301
+ ENV["_APPSIGNAL_APP_PATH"] = root_path.to_s
302
+ ENV["_APPSIGNAL_CA_FILE_PATH"] = config_hash[:ca_file_path].to_s
303
+ ENV["_APPSIGNAL_DEBUG_LOGGING"] = config_hash[:debug].to_s
304
+ ENV["_APPSIGNAL_DNS_SERVERS"] = config_hash[:dns_servers].join(",")
305
+ ENV["_APPSIGNAL_ENABLE_HOST_METRICS"] = config_hash[:enable_host_metrics].to_s
306
+ ENV["_APPSIGNAL_ENABLE_STATSD"] = config_hash[:enable_statsd].to_s
270
307
  ENV["_APPSIGNAL_ENVIRONMENT"] = env
308
+ ENV["_APPSIGNAL_FILES_WORLD_ACCESSIBLE"] = config_hash[:files_world_accessible].to_s
309
+ ENV["_APPSIGNAL_FILTER_PARAMETERS"] = config_hash[:filter_parameters].join(",")
310
+ ENV["_APPSIGNAL_FILTER_SESSION_DATA"] = config_hash[:filter_session_data].join(",")
311
+ ENV["_APPSIGNAL_HOSTNAME"] = config_hash[:hostname].to_s
312
+ ENV["_APPSIGNAL_HTTP_PROXY"] = config_hash[:http_proxy]
313
+ ENV["_APPSIGNAL_IGNORE_ACTIONS"] = config_hash[:ignore_actions].join(",")
314
+ ENV["_APPSIGNAL_IGNORE_ERRORS"] = config_hash[:ignore_errors].join(",")
315
+ ENV["_APPSIGNAL_IGNORE_NAMESPACES"] = config_hash[:ignore_namespaces].join(",")
271
316
  ENV["_APPSIGNAL_LANGUAGE_INTEGRATION_VERSION"] = "ruby-#{Appsignal::VERSION}"
272
- ENV["_APPSIGNAL_DEBUG_LOGGING"] = config_hash[:debug].to_s
273
317
  ENV["_APPSIGNAL_LOG"] = config_hash[:log]
318
+ ENV["_APPSIGNAL_LOG_LEVEL"] = config_hash[:log_level]
274
319
  ENV["_APPSIGNAL_LOG_FILE_PATH"] = log_file_path.to_s if log_file_path
320
+ ENV["_APPSIGNAL_PROCESS_NAME"] = $PROGRAM_NAME
275
321
  ENV["_APPSIGNAL_PUSH_API_ENDPOINT"] = config_hash[:endpoint]
276
322
  ENV["_APPSIGNAL_PUSH_API_KEY"] = config_hash[:push_api_key]
277
- ENV["_APPSIGNAL_APP_NAME"] = config_hash[:name]
278
- ENV["_APPSIGNAL_HTTP_PROXY"] = config_hash[:http_proxy]
279
- ENV["_APPSIGNAL_IGNORE_ACTIONS"] = config_hash[:ignore_actions].join(",")
280
- ENV["_APPSIGNAL_IGNORE_ERRORS"] = config_hash[:ignore_errors].join(",")
281
- ENV["_APPSIGNAL_IGNORE_NAMESPACES"] = config_hash[:ignore_namespaces].join(",")
282
323
  ENV["_APPSIGNAL_RUNNING_IN_CONTAINER"] = config_hash[:running_in_container].to_s
283
- ENV["_APPSIGNAL_WORKING_DIR_PATH"] = config_hash[:working_dir_path] if config_hash[:working_dir_path]
284
- ENV["_APPSIGNAL_WORKING_DIRECTORY_PATH"] = config_hash[:working_directory_path] if config_hash[:working_directory_path]
285
- ENV["_APPSIGNAL_ENABLE_HOST_METRICS"] = config_hash[:enable_host_metrics].to_s
286
- ENV["_APPSIGNAL_HOSTNAME"] = config_hash[:hostname].to_s
287
- ENV["_APPSIGNAL_PROCESS_NAME"] = $PROGRAM_NAME
288
- ENV["_APPSIGNAL_CA_FILE_PATH"] = config_hash[:ca_file_path].to_s
289
- ENV["_APPSIGNAL_DNS_SERVERS"] = config_hash[:dns_servers].join(",")
290
- ENV["_APPSIGNAL_FILES_WORLD_ACCESSIBLE"] = config_hash[:files_world_accessible].to_s
291
- ENV["_APPSIGNAL_TRANSACTION_DEBUG_MODE"] = config_hash[:transaction_debug_mode].to_s
292
324
  ENV["_APPSIGNAL_SEND_ENVIRONMENT_METADATA"] = config_hash[:send_environment_metadata].to_s
293
- ENV["_APPSIGNAL_ENABLE_STATSD"] = "true"
325
+ ENV["_APPSIGNAL_TRANSACTION_DEBUG_MODE"] = config_hash[:transaction_debug_mode].to_s
326
+ ENV["_APPSIGNAL_WORKING_DIRECTORY_PATH"] = config_hash[:working_directory_path] if config_hash[:working_directory_path]
327
+ ENV["_APPSIGNAL_WORKING_DIR_PATH"] = config_hash[:working_dir_path] if config_hash[:working_dir_path]
294
328
  ENV["_APP_REVISION"] = config_hash[:revision].to_s
295
329
  end
296
330
 
@@ -131,6 +131,65 @@ module Appsignal
131
131
  [:pointer],
132
132
  :appsignal_string
133
133
 
134
+ # Span methods
135
+ attach_function :appsignal_create_root_span,
136
+ [:appsignal_string],
137
+ :pointer
138
+ attach_function :appsignal_create_root_span_with_timestamp,
139
+ [:appsignal_string, :int64, :int64],
140
+ :pointer
141
+ attach_function :appsignal_create_child_span,
142
+ [:pointer],
143
+ :pointer
144
+ attach_function :appsignal_create_child_span_with_timestamp,
145
+ [:pointer, :int64, :int64],
146
+ :pointer
147
+ attach_function :appsignal_create_span_from_traceparent,
148
+ [:appsignal_string],
149
+ :pointer
150
+ attach_function :appsignal_span_id,
151
+ [:pointer],
152
+ :appsignal_string
153
+ attach_function :appsignal_span_to_json,
154
+ [:pointer],
155
+ :appsignal_string
156
+ attach_function :appsignal_set_span_name,
157
+ [:pointer, :appsignal_string],
158
+ :void
159
+ attach_function :appsignal_set_span_namespace,
160
+ [:pointer, :appsignal_string],
161
+ :void
162
+ attach_function :appsignal_add_span_error,
163
+ [:pointer, :appsignal_string, :appsignal_string, :pointer],
164
+ :void
165
+ attach_function :appsignal_set_span_sample_data,
166
+ [:pointer, :appsignal_string, :pointer],
167
+ :void
168
+ attach_function :appsignal_set_span_attribute_string,
169
+ [:pointer, :appsignal_string, :appsignal_string],
170
+ :void
171
+ attach_function :appsignal_set_span_attribute_sql_string,
172
+ [:pointer, :appsignal_string, :appsignal_string],
173
+ :void
174
+ attach_function :appsignal_set_span_attribute_int,
175
+ [:pointer, :appsignal_string, :int64],
176
+ :void
177
+ attach_function :appsignal_set_span_attribute_bool,
178
+ [:pointer, :appsignal_string, :bool],
179
+ :void
180
+ attach_function :appsignal_set_span_attribute_double,
181
+ [:pointer, :appsignal_string, :double],
182
+ :void
183
+ attach_function :appsignal_close_span,
184
+ [:pointer],
185
+ :void
186
+ attach_function :appsignal_close_span_with_timestamp,
187
+ [:pointer, :int64, :int64],
188
+ :void
189
+ attach_function :appsignal_free_span,
190
+ [:pointer],
191
+ :void
192
+
134
193
  # Data struct methods
135
194
  attach_function :appsignal_free_data, [], :void
136
195
  attach_function :appsignal_data_map_new, [], :pointer
@@ -375,6 +434,94 @@ module Appsignal
375
434
  end
376
435
  end
377
436
 
437
+ class Span
438
+ include StringHelpers
439
+ extend StringHelpers
440
+
441
+ attr_reader :pointer
442
+
443
+ def initialize(pointer)
444
+ @pointer = FFI::AutoPointer.new(
445
+ pointer,
446
+ Extension.method(:appsignal_free_span)
447
+ )
448
+ end
449
+
450
+ def self.root(namespace)
451
+ namespace = make_appsignal_string(namespace)
452
+ Span.new(Extension.appsignal_create_root_span(namespace))
453
+ end
454
+
455
+ def child
456
+ Span.new(Extension.appsignal_create_child_span(pointer))
457
+ end
458
+
459
+ def add_error(name, message, backtrace)
460
+ Extension.appsignal_add_span_error(
461
+ pointer,
462
+ make_appsignal_string(name),
463
+ make_appsignal_string(message),
464
+ backtrace.pointer
465
+ )
466
+ end
467
+
468
+ def set_sample_data(key, payload)
469
+ Extension.appsignal_set_span_sample_data(
470
+ pointer,
471
+ make_appsignal_string(key),
472
+ payload.pointer
473
+ )
474
+ end
475
+
476
+ def set_name(name) # rubocop:disable Naming/AccessorMethodName
477
+ Extension.appsignal_set_span_name(
478
+ pointer,
479
+ make_appsignal_string(name)
480
+ )
481
+ end
482
+
483
+ def set_attribute_string(key, value)
484
+ Extension.appsignal_set_span_attribute_string(
485
+ pointer,
486
+ make_appsignal_string(key),
487
+ make_appsignal_string(value)
488
+ )
489
+ end
490
+
491
+ def set_attribute_int(key, value)
492
+ Extension.appsignal_set_span_attribute_int(
493
+ pointer,
494
+ make_appsignal_string(key),
495
+ value
496
+ )
497
+ end
498
+
499
+ def set_attribute_bool(key, value)
500
+ Extension.appsignal_set_span_attribute_bool(
501
+ pointer,
502
+ make_appsignal_string(key),
503
+ value
504
+ )
505
+ end
506
+
507
+ def set_attribute_double(key, value)
508
+ Extension.appsignal_set_span_attribute_double(
509
+ pointer,
510
+ make_appsignal_string(key),
511
+ value
512
+ )
513
+ end
514
+
515
+ def to_json
516
+ json = Extension.appsignal_span_to_json(pointer)
517
+ make_ruby_string(json) if json[:len] > 0
518
+ end
519
+
520
+ def close
521
+ Extension.appsignal_close_span(pointer)
522
+ end
523
+ end
524
+
378
525
  class Data
379
526
  include StringHelpers
380
527
  attr_reader :pointer
@@ -60,6 +60,11 @@ module Appsignal
60
60
  # Makes sure the generated docs aren't always overwritten with the JRuby
61
61
  # version.
62
62
  Transaction = Jruby::Transaction
63
+ # Reassign Span class for JRuby extension usage.
64
+ #
65
+ # Makes sure the generated docs aren't always overwritten with the JRuby
66
+ # version.
67
+ Span = Jruby::Span
63
68
  # Reassign Data class for JRuby extension usage.
64
69
  #
65
70
  # Makes sure the generated docs aren't always overwritten with the JRuby
@@ -0,0 +1,16 @@
1
+ module Appsignal
2
+ class Hooks
3
+ # @api private
4
+ class MriHook < Appsignal::Hooks::Hook
5
+ register :mri
6
+
7
+ def dependencies_present?
8
+ defined?(::RubyVM)
9
+ end
10
+
11
+ def install
12
+ Appsignal::Minutely.probes.register :mri, Appsignal::Probes::MriProbe
13
+ end
14
+ end
15
+ end
16
+ end
@@ -94,6 +94,7 @@ require "appsignal/hooks/active_job"
94
94
  require "appsignal/hooks/active_support_notifications"
95
95
  require "appsignal/hooks/celluloid"
96
96
  require "appsignal/hooks/delayed_job"
97
+ require "appsignal/hooks/mri"
97
98
  require "appsignal/hooks/net_http"
98
99
  require "appsignal/hooks/passenger"
99
100
  require "appsignal/hooks/puma"
@@ -0,0 +1,26 @@
1
+ module Appsignal
2
+ module Probes
3
+ class MriProbe
4
+ # @api private
5
+ def self.dependencies_present?
6
+ defined?(::RubyVM) && ::RubyVM.respond_to?(:stat)
7
+ end
8
+
9
+ def initialize
10
+ Appsignal.logger.debug("Initializing VM probe")
11
+ end
12
+
13
+ # @api private
14
+ def call
15
+ stat = RubyVM.stat
16
+ [:class_serial, :global_constant_state].each do |metric|
17
+ Appsignal.add_distribution_value(
18
+ "ruby_vm",
19
+ stat[metric],
20
+ :metric => metric
21
+ )
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -3,4 +3,5 @@ module Appsignal
3
3
  end
4
4
  end
5
5
 
6
+ require "appsignal/probes/mri"
6
7
  require "appsignal/probes/sidekiq"