appsignal 3.0.13-java → 3.0.17-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -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"