appoptics_apm 4.11.0 → 4.12.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +31 -21
- data/.travis.yml +29 -45
- data/Gemfile +31 -22
- data/LICENSE +202 -193
- data/README.md +4 -2
- data/appoptics_apm.gemspec +16 -15
- data/examples/sdk_examples.rb +142 -0
- data/ext/oboe_metal/README.md +2 -2
- data/ext/oboe_metal/extconf.rb +40 -9
- data/ext/oboe_metal/src/VERSION +1 -1
- data/ext/oboe_metal/src/init_appoptics_apm.cc +20 -0
- data/lib/appoptics_apm.rb +1 -1
- data/lib/appoptics_apm/api/metrics.rb +7 -2
- data/lib/appoptics_apm/config.rb +9 -8
- data/lib/appoptics_apm/frameworks/rails.rb +7 -1
- data/lib/appoptics_apm/frameworks/rails/inst/action_view.rb +64 -21
- data/lib/appoptics_apm/inst/graphql.rb +44 -19
- data/lib/appoptics_apm/inst/grpc_client.rb +1 -1
- data/lib/appoptics_apm/inst/http.rb +67 -59
- data/lib/appoptics_apm/inst/rack_cache.rb +35 -0
- data/lib/appoptics_apm/noop/context.rb +1 -3
- data/lib/appoptics_apm/oboe_init_options.rb +17 -3
- data/lib/appoptics_apm/sdk/current_trace.rb +5 -9
- data/lib/appoptics_apm/sdk/custom_metrics.rb +2 -2
- data/lib/appoptics_apm/support/transaction_metrics.rb +1 -1
- data/lib/appoptics_apm/support/transaction_settings.rb +1 -1
- data/lib/appoptics_apm/test.rb +3 -3
- data/lib/appoptics_apm/util.rb +4 -3
- data/lib/appoptics_apm/version.rb +5 -4
- data/lib/rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb +56 -20
- metadata +13 -94
- data/examples/SDK/01_basic_tracing.rb +0 -68
- data/examples/carrying_context.rb +0 -220
@@ -13,23 +13,23 @@
|
|
13
13
|
# ____ what is in the graphql gem and vice-versa
|
14
14
|
|
15
15
|
|
16
|
-
if defined?(GraphQL::Tracing)
|
16
|
+
if defined?(GraphQL::Tracing) && !(AppOpticsAPM::Config[:graphql][:enabled] == false)
|
17
17
|
module GraphQL
|
18
18
|
module Tracing
|
19
19
|
# AppOpticsTracing in the graphql gem may be a different version than the
|
20
20
|
# one defined here, we want to use the newer one
|
21
|
-
|
21
|
+
redefine = true
|
22
22
|
this_version = Gem::Version.new('1.0.0')
|
23
23
|
|
24
24
|
if defined?(GraphQL::Tracing::AppOpticsTracing)
|
25
25
|
if this_version > GraphQL::Tracing::AppOpticsTracing.version
|
26
26
|
send(:remove_const, :AppOpticsTracing)
|
27
27
|
else
|
28
|
-
|
28
|
+
redefine = false
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
|
32
|
+
if redefine
|
33
33
|
#-----------------------------------------------------------------------------#
|
34
34
|
#----- this class is duplicated in the graphql gem ---------------------------#
|
35
35
|
#-----------------------------------------------------------------------------#
|
@@ -84,7 +84,7 @@ if defined?(GraphQL::Tracing)
|
|
84
84
|
|
85
85
|
def transaction_name(query)
|
86
86
|
return if gql_config[:transaction_name] == false ||
|
87
|
-
|
87
|
+
::AppOpticsAPM::SDK.get_transaction_name
|
88
88
|
|
89
89
|
split_query = query.strip.split(/\W+/, 3)
|
90
90
|
split_query[0] = 'query' if split_query[0].empty?
|
@@ -95,7 +95,7 @@ if defined?(GraphQL::Tracing)
|
|
95
95
|
|
96
96
|
def multiplex_transaction_name(names)
|
97
97
|
return if gql_config[:transaction_name] == false ||
|
98
|
-
|
98
|
+
::AppOpticsAPM::SDK.get_transaction_name
|
99
99
|
|
100
100
|
name = "graphql.multiplex.#{names.join('.')}"
|
101
101
|
name = "#{name[0..251]}..." if name.length > 254
|
@@ -167,8 +167,8 @@ if defined?(GraphQL::Tracing)
|
|
167
167
|
|
168
168
|
# remove arguments
|
169
169
|
query.gsub(/"[^"]*"/, '"?"') # strings
|
170
|
-
|
171
|
-
|
170
|
+
.gsub(/-?[0-9]*\.?[0-9]+e?[0-9]*/, '?') # ints + floats
|
171
|
+
.gsub(/\[[^\]]*\]/, '[?]') # arrays
|
172
172
|
end
|
173
173
|
|
174
174
|
def remove_comments(query)
|
@@ -184,10 +184,16 @@ if defined?(GraphQL::Tracing)
|
|
184
184
|
|
185
185
|
module AppOpticsAPM
|
186
186
|
module GraphQLSchemaPrepend
|
187
|
-
def use(plugin, options
|
188
|
-
super unless GraphQL::Schema.plugins.find { |pl| pl[0].to_s == plugin.to_s }
|
187
|
+
def use(plugin, **options)
|
188
|
+
# super unless GraphQL::Schema.plugins.find { |pl| pl[0].to_s == plugin.to_s }
|
189
|
+
super unless self.plugins.find { |pl| pl[0].to_s == plugin.to_s }
|
189
190
|
|
190
|
-
|
191
|
+
self.plugins
|
192
|
+
end
|
193
|
+
|
194
|
+
def inherited(subclass)
|
195
|
+
subclass.use(GraphQL::Tracing::AppOpticsTracing)
|
196
|
+
super
|
191
197
|
end
|
192
198
|
end
|
193
199
|
|
@@ -200,16 +206,35 @@ if defined?(GraphQL::Tracing)
|
|
200
206
|
end
|
201
207
|
end
|
202
208
|
# rubocop:enable Style/RedundantSelf
|
203
|
-
end
|
204
209
|
|
205
|
-
|
206
|
-
|
207
|
-
|
210
|
+
# a different way of autoinstrumenting for graphql 1.7.4 - < 1.8.0
|
211
|
+
module GraphQLSchemaPrepend17
|
212
|
+
def initialize
|
213
|
+
super
|
214
|
+
unless tracers.find { |tr| tr.is_a? GraphQL::Tracing::AppOpticsTracing }
|
215
|
+
tracer = GraphQL::Tracing::AppOpticsTracing.new
|
216
|
+
tracers.push(tracer)
|
217
|
+
instrumenters[:field] << tracer
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
208
221
|
end
|
209
222
|
|
210
|
-
|
211
|
-
|
212
|
-
GraphQL::
|
223
|
+
if Gem.loaded_specs['graphql'] && Gem.loaded_specs['graphql'].version >= Gem::Version.new('1.8.0')
|
224
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting GraphQL' if AppOpticsAPM::Config[:verbose]
|
225
|
+
if defined?(GraphQL::Schema)
|
226
|
+
GraphQL::Schema.singleton_class.prepend(AppOpticsAPM::GraphQLSchemaPrepend)
|
227
|
+
end
|
228
|
+
|
229
|
+
# rubocop:disable Style/IfUnlessModifier
|
230
|
+
if defined?(GraphQL::Error)
|
231
|
+
GraphQL::Error.prepend(AppOpticsAPM::GraphQLErrorPrepend)
|
232
|
+
end
|
233
|
+
# rubocop:enable Style/IfUnlessModifier
|
234
|
+
elsif Gem.loaded_specs['graphql'] && Gem.loaded_specs['graphql'].version >= Gem::Version.new('1.7.4')
|
235
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting GraphQL' if AppOpticsAPM::Config[:verbose]
|
236
|
+
if defined?(GraphQL::Schema)
|
237
|
+
GraphQL::Schema.prepend(AppOpticsAPM::GraphQLSchemaPrepend17)
|
238
|
+
end
|
213
239
|
end
|
214
|
-
# rubocop:enable Style/IfUnlessModifier
|
215
240
|
end
|
@@ -4,70 +4,78 @@
|
|
4
4
|
require 'net/http'
|
5
5
|
|
6
6
|
if AppOpticsAPM::Config[:nethttp][:enabled]
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
# Collect KVs to report in the info event
|
30
|
-
if args.respond_to?(:first) && args.first
|
31
|
-
req = args.first
|
32
|
-
|
33
|
-
opts[:Spec] = 'rsc'
|
34
|
-
opts[:IsService] = 1
|
35
|
-
opts[:RemoteURL] = "#{use_ssl? ? 'https' : 'http'}://#{addr_port}"
|
36
|
-
opts[:RemoteURL] << (AppOpticsAPM::Config[:nethttp][:log_args] ? req.path : req.path.split('?').first)
|
37
|
-
opts[:HTTPMethod] = req.method
|
38
|
-
opts[:Blacklisted] = true if blacklisted
|
39
|
-
opts[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:nethttp][:collect_backtraces]
|
40
|
-
|
41
|
-
req['X-Trace'] = context unless blacklisted
|
42
|
-
end
|
43
|
-
|
44
|
-
begin
|
45
|
-
# The actual net::http call
|
46
|
-
resp = request_without_appoptics(*args, &block)
|
47
|
-
|
48
|
-
# Re-attach net::http edge unless blacklisted and is a valid X-Trace ID
|
49
|
-
unless blacklisted
|
50
|
-
xtrace = resp.get_fields('X-Trace')
|
51
|
-
xtrace = xtrace[0] if xtrace && xtrace.is_a?(Array)
|
52
|
-
|
53
|
-
AppOpticsAPM::XTrace.continue_service_context(context, xtrace)
|
7
|
+
module AppOpticsAPM
|
8
|
+
module Inst
|
9
|
+
module NetHttp
|
10
|
+
# Net::HTTP.class_eval do
|
11
|
+
# def request_with_appoptics(*args, &block)
|
12
|
+
def request(*args, &block)
|
13
|
+
# Avoid cross host tracing for blacklisted domains
|
14
|
+
blacklisted = AppOpticsAPM::API.blacklisted?(addr_port)
|
15
|
+
|
16
|
+
# If we're not tracing, just do a fast return. Since
|
17
|
+
# net/http.request calls itself, only trace
|
18
|
+
# once the http session has been started.
|
19
|
+
if !AppOpticsAPM.tracing? || !started?
|
20
|
+
if blacklisted # if the other site is blacklisted, we don't want to leak its X-trace
|
21
|
+
resp = super
|
22
|
+
resp.delete('X-Trace') # if resp['X-Trace']
|
23
|
+
return resp
|
24
|
+
else
|
25
|
+
xtrace = AppOpticsAPM::Context.toString
|
26
|
+
args[0]['X-Trace'] = xtrace if AppOpticsAPM::XTrace.valid?(xtrace)
|
27
|
+
return super
|
28
|
+
end
|
54
29
|
end
|
55
30
|
|
56
|
-
opts
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
31
|
+
opts = {}
|
32
|
+
AppOpticsAPM::API.trace(:'net-http', opts) do
|
33
|
+
context = AppOpticsAPM::Context.toString
|
34
|
+
|
35
|
+
# Collect KVs to report in the exit event
|
36
|
+
if args.respond_to?(:first) && args.first
|
37
|
+
req = args.first
|
38
|
+
|
39
|
+
opts[:Spec] = 'rsc'
|
40
|
+
opts[:IsService] = 1
|
41
|
+
opts[:RemoteURL] = "#{use_ssl? ? 'https' : 'http'}://#{addr_port}"
|
42
|
+
opts[:RemoteURL] << (AppOpticsAPM::Config[:nethttp][:log_args] ? req.path : req.path.split('?').first)
|
43
|
+
opts[:HTTPMethod] = req.method
|
44
|
+
opts[:Blacklisted] = true if blacklisted
|
45
|
+
opts[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:nethttp][:collect_backtraces]
|
46
|
+
|
47
|
+
req['X-Trace'] = context unless blacklisted
|
48
|
+
end
|
49
|
+
|
50
|
+
begin
|
51
|
+
# The actual net::http call
|
52
|
+
resp = super
|
53
|
+
# Re-attach net::http edge unless blacklisted and is a valid X-Trace ID
|
54
|
+
xtrace = resp.get_fields('X-Trace')
|
55
|
+
if blacklisted
|
56
|
+
# we don't want the x-trace if it is from a blacklisted address
|
57
|
+
resp.delete('X-Trace') # if xtrace
|
58
|
+
else
|
59
|
+
xtrace = xtrace[0] if xtrace && xtrace.is_a?(Array)
|
60
|
+
AppOpticsAPM::XTrace.continue_service_context(context, xtrace)
|
61
|
+
end
|
62
|
+
|
63
|
+
opts[:HTTPStatus] = resp.code
|
64
|
+
|
65
|
+
# If we get a redirect, report the location header
|
66
|
+
if ((300..308).to_a.include? resp.code.to_i) && resp.header["Location"]
|
67
|
+
opts[:Location] = resp.header["Location"]
|
68
|
+
end
|
69
|
+
|
70
|
+
next resp
|
71
|
+
end
|
61
72
|
end
|
62
|
-
|
63
|
-
next resp
|
64
73
|
end
|
74
|
+
|
65
75
|
end
|
66
76
|
end
|
67
|
-
|
68
|
-
alias request_without_appoptics request
|
69
|
-
alias request request_with_appoptics
|
70
|
-
|
71
|
-
AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting net/http' if AppOpticsAPM::Config[:verbose]
|
72
77
|
end
|
78
|
+
|
79
|
+
Net::HTTP.prepend(AppOpticsAPM::Inst::NetHttp)
|
80
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting net/http' if AppOpticsAPM::Config[:verbose]
|
73
81
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Copyright (c) 2020 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
module AppOpticsAPM
|
5
|
+
module RackCacheContext
|
6
|
+
|
7
|
+
###
|
8
|
+
# This adds a controller.action like transaction name for
|
9
|
+
# requests directly served from the cache without involving a controller.
|
10
|
+
# The resulting transaction name is `rack-cache.<cache-store>`,
|
11
|
+
# e.g. `rack-cache.memcached`
|
12
|
+
#
|
13
|
+
# It is not a full instrumentation, no span is added.
|
14
|
+
#
|
15
|
+
def call!(env)
|
16
|
+
metastore_type = begin
|
17
|
+
if options['rack-cache.metastore']
|
18
|
+
options['rack-cache.metastore'].match(/^([^\:]*)\:/)[1]
|
19
|
+
end || 'unknown_store'
|
20
|
+
rescue
|
21
|
+
'unknown_store'
|
22
|
+
end
|
23
|
+
|
24
|
+
env['appoptics_apm.action'] = metastore_type
|
25
|
+
env['appoptics_apm.controller'] = 'rack-cache'
|
26
|
+
|
27
|
+
super
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
if AppOpticsAPM::Config[:rack_cache][:transaction_name] && defined?(Rack::Cache::Context)
|
33
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting rack_cache' if AppOpticsAPM::Config[:verbose]
|
34
|
+
Rack::Cache::Context.send(:prepend, ::AppOpticsAPM::RackCacheContext)
|
35
|
+
end
|
@@ -10,8 +10,6 @@ module AppOpticsAPM
|
|
10
10
|
# noop version of :toString
|
11
11
|
# toString would return the current context (xtrace) as string
|
12
12
|
#
|
13
|
-
# the noop version returns an empty string
|
14
|
-
#
|
15
13
|
def self.toString
|
16
14
|
'2B0000000000000000000000000000000000000000000000000000000000'
|
17
15
|
end
|
@@ -23,4 +21,4 @@ module AppOpticsAPM
|
|
23
21
|
|
24
22
|
end
|
25
23
|
end
|
26
|
-
end
|
24
|
+
end
|
@@ -8,7 +8,7 @@ module AppOpticsAPM
|
|
8
8
|
class OboeInitOptions
|
9
9
|
include Singleton
|
10
10
|
|
11
|
-
attr_reader :reporter, :host, :service_name, :ec2_md_timeout # exposing these mainly for testing
|
11
|
+
attr_reader :reporter, :host, :service_name, :ec2_md_timeout, :grpc_proxy # exposing these mainly for testing
|
12
12
|
|
13
13
|
# TODO decide if these globals are useful when testing
|
14
14
|
# OBOE_HOSTNAME_ALIAS = 0
|
@@ -71,6 +71,7 @@ module AppOpticsAPM
|
|
71
71
|
@file_single = (ENV['APPOPTICS_REPORTER_FILE_SINGLE'].to_s.downcase == 'true') ? 1 : 0
|
72
72
|
# timeout for ec2 metadata
|
73
73
|
@ec2_md_timeout = read_and_validate_ec2_md_timeout
|
74
|
+
@grpc_proxy = read_and_validate_proxy
|
74
75
|
end
|
75
76
|
|
76
77
|
def re_init # for testing with changed ENV vars
|
@@ -97,7 +98,8 @@ module AppOpticsAPM
|
|
97
98
|
@token_bucket_capacity,
|
98
99
|
@token_bucket_rate,
|
99
100
|
@file_single,
|
100
|
-
@ec2_md_timeout
|
101
|
+
@ec2_md_timeout,
|
102
|
+
@grpc_proxy
|
101
103
|
]
|
102
104
|
end
|
103
105
|
|
@@ -183,11 +185,23 @@ module AppOpticsAPM
|
|
183
185
|
end
|
184
186
|
|
185
187
|
def read_and_validate_ec2_md_timeout
|
186
|
-
timeout =
|
188
|
+
timeout = ENV['APPOPTICS_EC2_METADATA_TIMEOUT'] || AppOpticsAPM::Config[:ec2_metadata_timeout]
|
187
189
|
return 1000 unless timeout.is_a?(Integer) || timeout =~ /^\d+$/
|
188
190
|
timeout = timeout.to_i
|
189
191
|
return timeout.between?(0, 3000) ? timeout : 1000
|
190
192
|
end
|
193
|
+
|
194
|
+
def read_and_validate_proxy
|
195
|
+
proxy = ENV['APPOPTICS_PROXY'] || AppOpticsAPM::Config[:http_proxy] || ''
|
196
|
+
return proxy if proxy == ''
|
197
|
+
|
198
|
+
unless proxy =~ /http:\/\/.*:\d+$/
|
199
|
+
AppOpticsAPM.logger.error "[appoptics_apm/oboe_options] APPOPTICS_PROXY/http_proxy doesn't start with 'http://', #{proxy}"
|
200
|
+
return '' # try without proxy, it may work, shouldn't crash but may not report
|
201
|
+
end
|
202
|
+
|
203
|
+
proxy
|
204
|
+
end
|
191
205
|
end
|
192
206
|
end
|
193
207
|
|
@@ -37,14 +37,10 @@ module AppOpticsAPM
|
|
37
37
|
attr_reader :id
|
38
38
|
|
39
39
|
def initialize
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
task_id = AppOpticsAPM::XTrace.task_id(@xtrace)
|
45
|
-
sampled = AppOpticsAPM::XTrace.sampled?(@xtrace)
|
46
|
-
@id = "#{task_id}-#{sampled ? 1 : 0}"
|
47
|
-
end
|
40
|
+
@xtrace = AppOpticsAPM::Context.toString
|
41
|
+
task_id = AppOpticsAPM::XTrace.task_id(@xtrace)
|
42
|
+
sampled = AppOpticsAPM::XTrace.sampled?(@xtrace)
|
43
|
+
@id = "#{task_id}-#{sampled ? 1 : 0}"
|
48
44
|
end
|
49
45
|
|
50
46
|
# for_log returns a string in the format 'traceId=<current_trace.id>' or ''.
|
@@ -78,4 +74,4 @@ module AppOpticsAPM
|
|
78
74
|
|
79
75
|
extend CurrentTrace
|
80
76
|
end
|
81
|
-
end
|
77
|
+
end
|
@@ -29,7 +29,7 @@ module AppOpticsAPM
|
|
29
29
|
# end
|
30
30
|
#
|
31
31
|
# === Returns:
|
32
|
-
# *
|
32
|
+
# * 0 on success, error code on failure
|
33
33
|
#
|
34
34
|
def increment_metric(name, count = 1, with_hostname = false, tags_kvs = {})
|
35
35
|
return true unless AppOpticsAPM.loaded
|
@@ -62,7 +62,7 @@ module AppOpticsAPM
|
|
62
62
|
# end
|
63
63
|
#
|
64
64
|
# === Returns:
|
65
|
-
# *
|
65
|
+
# * 0 on success, error code on failure
|
66
66
|
#
|
67
67
|
def summary_metric(name, value, count = 1, with_hostname = false, tags_kvs = {})
|
68
68
|
return true unless AppOpticsAPM.loaded
|
@@ -55,7 +55,7 @@ module AppOpticsAPM
|
|
55
55
|
args << options.timestamp
|
56
56
|
end
|
57
57
|
|
58
|
-
metrics, sample, @rate, @source, @type, @auth, @status_msg, @auth_msg, @status =
|
58
|
+
metrics, sample, @rate, @source, @bucket_rate, @bucket_cap, @type, @auth, @status_msg, @auth_msg, @status =
|
59
59
|
AppOpticsAPM::Context.getDecisions(*args)
|
60
60
|
|
61
61
|
if @status > AO_TRACING_DECISIONS_OK
|
data/lib/appoptics_apm/test.rb
CHANGED
@@ -53,13 +53,13 @@ module AppOpticsAPM
|
|
53
53
|
def set_postgresql_env
|
54
54
|
if ENV.key?('TRAVIS_PSQL_PASS')
|
55
55
|
ENV['DATABASE_URL'] = "postgresql://postgres:#{ENV['TRAVIS_PSQL_PASS']}@127.0.0.1:5432/travis_ci_test"
|
56
|
-
elsif ENV.key?('
|
57
|
-
ENV['DATABASE_URL'] = "postgresql
|
56
|
+
elsif ENV.key?('POSTGRES_USER')
|
57
|
+
ENV['DATABASE_URL'] = "postgresql://#{ENV['POSTGRES_PASSWORD']}:#{ENV['POSTGRES_USER']}@#{ENV['PSQL_HOST']}:5432/travis_ci_test"
|
58
|
+
# ENV['DATABASE_URL'] = "postgresql://postgres@#{ENV['PSQL_HOST']}:5432/travis_ci_test"
|
58
59
|
else
|
59
60
|
ENV['DATABASE_URL'] = 'postgresql://postgres@127.0.0.1:5432/travis_ci_test'
|
60
61
|
end
|
61
62
|
end
|
62
|
-
|
63
63
|
##
|
64
64
|
# set_mysql_env
|
65
65
|
#
|
data/lib/appoptics_apm/util.rb
CHANGED
@@ -271,12 +271,13 @@ module AppOpticsAPM
|
|
271
271
|
platform_info['Force'] = true
|
272
272
|
platform_info['Ruby.Platform.Version'] = RUBY_PLATFORM
|
273
273
|
platform_info['Ruby.Version'] = RUBY_VERSION
|
274
|
-
platform_info['Ruby.AppOptics.Version']
|
274
|
+
platform_info['Ruby.AppOptics.Version'] = AppOpticsAPM::Version::STRING
|
275
275
|
|
276
|
+
# oboe not loaded yet, can't use oboe_api function to read oboe VERSION
|
276
277
|
clib_version_file = File.join(Gem::Specification.find_by_name('appoptics_apm').gem_dir, 'ext', 'oboe_metal', 'src', 'VERSION')
|
277
|
-
platform_info['Ruby.
|
278
|
+
platform_info['Ruby.AppOpticsExtension.Version'] = File.read(clib_version_file).chomp
|
278
279
|
platform_info['RubyHeroku.AppOpticsAPM.Version'] = AppOpticsAPMHeroku::Version::STRING if defined?(AppOpticsAPMHeroku)
|
279
|
-
platform_info['Ruby.TraceMode.Version']
|
280
|
+
platform_info['Ruby.TraceMode.Version'] = AppOpticsAPM::Config[:tracing_mode]
|
280
281
|
|
281
282
|
# Collect up the loaded gems
|
282
283
|
if defined?(Gem) && Gem.respond_to?(:loaded_specs)
|