solarwinds_apm 5.0.0

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.
Files changed (142) hide show
  1. checksums.yaml +7 -0
  2. data/.dockerignore +5 -0
  3. data/.github/ISSUE_TEMPLATE/bug-or-feature-request.md +16 -0
  4. data/.github/workflows/build_and_release_gem.yml +112 -0
  5. data/.github/workflows/build_for_packagecloud.yml +70 -0
  6. data/.github/workflows/docker-images.yml +47 -0
  7. data/.github/workflows/run_cpluplus_tests.yml +73 -0
  8. data/.github/workflows/run_tests.yml +155 -0
  9. data/.github/workflows/scripts/test_install.rb +23 -0
  10. data/.github/workflows/swig/swig-v4.0.2.tar.gz +0 -0
  11. data/.github/workflows/test_on_4_linux.yml +161 -0
  12. data/.gitignore +39 -0
  13. data/.rubocop.yml +29 -0
  14. data/.yardopts +7 -0
  15. data/CHANGELOG.md +769 -0
  16. data/CONFIG.md +31 -0
  17. data/Gemfile +14 -0
  18. data/LICENSE +202 -0
  19. data/README.md +383 -0
  20. data/bin/solarwinds_apm_config +15 -0
  21. data/examples/prepend.rb +13 -0
  22. data/examples/sdk_examples.rb +158 -0
  23. data/ext/oboe_metal/README.md +69 -0
  24. data/ext/oboe_metal/extconf.rb +141 -0
  25. data/ext/oboe_metal/extconf_local.rb +75 -0
  26. data/ext/oboe_metal/lib/.keep +0 -0
  27. data/ext/oboe_metal/lib/liboboe-1.0-alpine-x86_64.so.0.0.0.sha256 +1 -0
  28. data/ext/oboe_metal/lib/liboboe-1.0-x86_64.so.0.0.0.sha256 +1 -0
  29. data/ext/oboe_metal/noop/noop.c +8 -0
  30. data/ext/oboe_metal/src/README.md +6 -0
  31. data/ext/oboe_metal/src/VERSION +2 -0
  32. data/ext/oboe_metal/src/bson/bson.h +220 -0
  33. data/ext/oboe_metal/src/bson/platform_hacks.h +91 -0
  34. data/ext/oboe_metal/src/frames.cc +247 -0
  35. data/ext/oboe_metal/src/frames.h +40 -0
  36. data/ext/oboe_metal/src/init_solarwinds_apm.cc +21 -0
  37. data/ext/oboe_metal/src/logging.cc +95 -0
  38. data/ext/oboe_metal/src/logging.h +35 -0
  39. data/ext/oboe_metal/src/oboe.h +1169 -0
  40. data/ext/oboe_metal/src/oboe_api.cpp +658 -0
  41. data/ext/oboe_metal/src/oboe_api.hpp +433 -0
  42. data/ext/oboe_metal/src/oboe_debug.h +59 -0
  43. data/ext/oboe_metal/src/oboe_swig_wrap.cc +7562 -0
  44. data/ext/oboe_metal/src/profiling.cc +435 -0
  45. data/ext/oboe_metal/src/profiling.h +78 -0
  46. data/ext/oboe_metal/test/CMakeLists.txt +53 -0
  47. data/ext/oboe_metal/test/FindGMock.cmake +43 -0
  48. data/ext/oboe_metal/test/README.md +56 -0
  49. data/ext/oboe_metal/test/frames_test.cc +164 -0
  50. data/ext/oboe_metal/test/profiling_test.cc +93 -0
  51. data/ext/oboe_metal/test/ruby_inc_dir.rb +8 -0
  52. data/ext/oboe_metal/test/ruby_prefix.rb +8 -0
  53. data/ext/oboe_metal/test/ruby_test_helper.rb +67 -0
  54. data/ext/oboe_metal/test/test.h +11 -0
  55. data/ext/oboe_metal/test/test_main.cc +32 -0
  56. data/init.rb +4 -0
  57. data/lib/oboe.rb +7 -0
  58. data/lib/oboe_metal.rb +172 -0
  59. data/lib/rails/generators/solarwinds_apm/install_generator.rb +47 -0
  60. data/lib/rails/generators/solarwinds_apm/templates/solarwinds_apm_initializer.rb +424 -0
  61. data/lib/solarwinds_apm/api/layerinit.rb +41 -0
  62. data/lib/solarwinds_apm/api/logging.rb +356 -0
  63. data/lib/solarwinds_apm/api/memcache.rb +37 -0
  64. data/lib/solarwinds_apm/api/metrics.rb +63 -0
  65. data/lib/solarwinds_apm/api/util.rb +98 -0
  66. data/lib/solarwinds_apm/api.rb +21 -0
  67. data/lib/solarwinds_apm/base.rb +160 -0
  68. data/lib/solarwinds_apm/config.rb +301 -0
  69. data/lib/solarwinds_apm/frameworks/grape.rb +96 -0
  70. data/lib/solarwinds_apm/frameworks/padrino.rb +78 -0
  71. data/lib/solarwinds_apm/frameworks/rails/inst/action_controller.rb +100 -0
  72. data/lib/solarwinds_apm/frameworks/rails/inst/action_controller5.rb +50 -0
  73. data/lib/solarwinds_apm/frameworks/rails/inst/action_controller_api.rb +50 -0
  74. data/lib/solarwinds_apm/frameworks/rails/inst/action_view.rb +88 -0
  75. data/lib/solarwinds_apm/frameworks/rails/inst/active_record.rb +26 -0
  76. data/lib/solarwinds_apm/frameworks/rails/inst/connection_adapters/mysql2.rb +29 -0
  77. data/lib/solarwinds_apm/frameworks/rails/inst/connection_adapters/postgresql.rb +22 -0
  78. data/lib/solarwinds_apm/frameworks/rails/inst/connection_adapters/utils5x.rb +103 -0
  79. data/lib/solarwinds_apm/frameworks/rails/inst/logger_formatters.rb +14 -0
  80. data/lib/solarwinds_apm/frameworks/rails.rb +100 -0
  81. data/lib/solarwinds_apm/frameworks/sinatra.rb +96 -0
  82. data/lib/solarwinds_apm/inst/bunny-client.rb +157 -0
  83. data/lib/solarwinds_apm/inst/bunny-consumer.rb +102 -0
  84. data/lib/solarwinds_apm/inst/curb.rb +288 -0
  85. data/lib/solarwinds_apm/inst/dalli.rb +89 -0
  86. data/lib/solarwinds_apm/inst/delayed_job.rb +100 -0
  87. data/lib/solarwinds_apm/inst/excon.rb +113 -0
  88. data/lib/solarwinds_apm/inst/faraday.rb +96 -0
  89. data/lib/solarwinds_apm/inst/graphql.rb +206 -0
  90. data/lib/solarwinds_apm/inst/grpc_client.rb +147 -0
  91. data/lib/solarwinds_apm/inst/grpc_server.rb +119 -0
  92. data/lib/solarwinds_apm/inst/httpclient.rb +181 -0
  93. data/lib/solarwinds_apm/inst/logger_formatter.rb +46 -0
  94. data/lib/solarwinds_apm/inst/logging_log_event.rb +24 -0
  95. data/lib/solarwinds_apm/inst/lumberjack_formatter.rb +9 -0
  96. data/lib/solarwinds_apm/inst/memcached.rb +86 -0
  97. data/lib/solarwinds_apm/inst/mongo.rb +246 -0
  98. data/lib/solarwinds_apm/inst/mongo2.rb +225 -0
  99. data/lib/solarwinds_apm/inst/moped.rb +466 -0
  100. data/lib/solarwinds_apm/inst/net_http.rb +60 -0
  101. data/lib/solarwinds_apm/inst/rack.rb +217 -0
  102. data/lib/solarwinds_apm/inst/rack_cache.rb +35 -0
  103. data/lib/solarwinds_apm/inst/redis.rb +273 -0
  104. data/lib/solarwinds_apm/inst/resque.rb +129 -0
  105. data/lib/solarwinds_apm/inst/rest-client.rb +43 -0
  106. data/lib/solarwinds_apm/inst/sequel.rb +241 -0
  107. data/lib/solarwinds_apm/inst/sidekiq-client.rb +63 -0
  108. data/lib/solarwinds_apm/inst/sidekiq-worker.rb +64 -0
  109. data/lib/solarwinds_apm/inst/typhoeus.rb +90 -0
  110. data/lib/solarwinds_apm/instrumentation.rb +22 -0
  111. data/lib/solarwinds_apm/loading.rb +65 -0
  112. data/lib/solarwinds_apm/logger.rb +14 -0
  113. data/lib/solarwinds_apm/noop/README.md +9 -0
  114. data/lib/solarwinds_apm/noop/context.rb +26 -0
  115. data/lib/solarwinds_apm/noop/metadata.rb +25 -0
  116. data/lib/solarwinds_apm/noop/profiling.rb +21 -0
  117. data/lib/solarwinds_apm/oboe_init_options.rb +191 -0
  118. data/lib/solarwinds_apm/ruby.rb +35 -0
  119. data/lib/solarwinds_apm/sdk/current_trace_info.rb +123 -0
  120. data/lib/solarwinds_apm/sdk/custom_metrics.rb +94 -0
  121. data/lib/solarwinds_apm/sdk/logging.rb +37 -0
  122. data/lib/solarwinds_apm/sdk/trace_context_headers.rb +69 -0
  123. data/lib/solarwinds_apm/sdk/tracing.rb +432 -0
  124. data/lib/solarwinds_apm/support/profiling.rb +22 -0
  125. data/lib/solarwinds_apm/support/trace_context.rb +53 -0
  126. data/lib/solarwinds_apm/support/trace_state.rb +69 -0
  127. data/lib/solarwinds_apm/support/trace_string.rb +89 -0
  128. data/lib/solarwinds_apm/support/transaction_metrics.rb +67 -0
  129. data/lib/solarwinds_apm/support/transaction_settings.rb +233 -0
  130. data/lib/solarwinds_apm/support/x_trace_options.rb +113 -0
  131. data/lib/solarwinds_apm/support.rb +12 -0
  132. data/lib/solarwinds_apm/support_report.rb +113 -0
  133. data/lib/solarwinds_apm/test.rb +165 -0
  134. data/lib/solarwinds_apm/thread_local.rb +26 -0
  135. data/lib/solarwinds_apm/util.rb +334 -0
  136. data/lib/solarwinds_apm/version.rb +17 -0
  137. data/lib/solarwinds_apm.rb +72 -0
  138. data/log/.keep +0 -0
  139. data/log/postgresql/.keep +0 -0
  140. data/solarwinds_apm.gemspec +52 -0
  141. data/yardoc_frontpage.md +24 -0
  142. metadata +228 -0
@@ -0,0 +1,165 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module SolarWindsAPM
5
+ module Test
6
+ class << self
7
+ ##
8
+ # load_extras
9
+ #
10
+ # This method simply loads all the extras needed to run
11
+ # tests such as models, jobs etc...
12
+ #
13
+ def load_extras
14
+ # If we're using the libraries gemfile (with sidekiq and resque)
15
+ if SolarWindsAPM::Test.gemfile?(:libraries)
16
+ # Load all of the test workers
17
+ pattern = File.join(File.dirname(__FILE__), '../../test/jobs/**/', '*.rb')
18
+ Dir.glob(pattern) do |f|
19
+ SolarWindsAPM.logger.debug "[solarwinds_apm/test] Loading test job file: #{File.basename(f)}"
20
+ require f
21
+ end
22
+ end
23
+ end
24
+
25
+ ##
26
+ # gemfile?
27
+ #
28
+ # Method used to determine under which gemfile we're running.
29
+ # Pass <tt>name</tt> as the gemfile name only (without the
30
+ # .gemfile extension)
31
+ #
32
+ # returns true or fase depending on result
33
+ #
34
+ def gemfile?(name)
35
+ File.basename(ENV['BUNDLE_GEMFILE']) == (name.to_s + '.gemfile')
36
+ end
37
+
38
+ ##
39
+ # gemfile
40
+ #
41
+ # Used to determine under which gemfile we are running. This
42
+ # method will return the name of the active gemfile
43
+ #
44
+ def gemfile
45
+ File.basename(ENV['BUNDLE_GEMFILE']).split('.').first
46
+ end
47
+
48
+ ##
49
+ # set_postgresql_env
50
+ #
51
+ # Used to set the postgresql specific DATABASE_URL env based
52
+ # on various conditions
53
+ def set_postgresql_env
54
+ if ENV.key?('TRAVIS_PSQL_PASS')
55
+ ENV['DATABASE_URL'] = "postgresql://postgres:#{ENV['TRAVIS_PSQL_PASS']}@127.0.0.1:5432/test_db"
56
+ elsif ENV.key?('POSTGRES_USER')
57
+ port = ENV.key?('POSTGRES_PORT') ? ENV['POSTGRES_PORT'] : 5432
58
+ ENV['DATABASE_URL'] = "postgresql://#{ENV['POSTGRES_PASSWORD']}:#{ENV['POSTGRES_USER']}@#{ENV['POSTGRES_HOST']}:#{port}/test_db"
59
+ else
60
+ ENV['DATABASE_URL'] = 'postgresql://postgres@127.0.0.1:5432/test_db'
61
+ end
62
+ end
63
+
64
+ ##
65
+ # To configure Rails to enable or disable prepared statements
66
+ # we need to do it using the database.yml file
67
+ # there is no method exposed (afaik) to set prepared_statements
68
+ # interactively
69
+ def set_postgresql_rails_config
70
+ # need to use string keys otherwise the output is not readable by Rails 5
71
+ config = {
72
+ 'adapter' => "postgresql",
73
+ 'username' => ENV.key?('POSTGRES_USER') ? ENV['POSTGRES_USER'] : "postgres",
74
+ 'password' => ENV.key?('POSTGRES_PASSWORD') ? ENV['POSTGRES_PASSWORD'] : "postgres",
75
+ 'database' => "test_db",
76
+ 'host' => ENV.key?('POSTGRES_HOST') ? ENV['POSTGRES_HOST'] : '127.0.0.1',
77
+ 'port' => ENV.key?('POSTGRES_PORT') ? ENV['POSTGRES_PORT'] : 5432,
78
+ 'statement_limit' => 5
79
+ }
80
+
81
+ if ENV.key?('TEST_PREPARED_STATEMENT')
82
+ config['prepared_statements'] = ENV['TEST_PREPARED_STATEMENT'] == 'true' ? true : false
83
+ else
84
+ config['prepared_statements'] = false
85
+ end
86
+
87
+ env_config = {
88
+ 'default' => config,
89
+ 'development' => config,
90
+ 'test' => config
91
+ }
92
+
93
+ FileUtils.mkdir_p('config')
94
+ File.open("config/database.yml","w") do |file|
95
+ file.write env_config.to_yaml
96
+ end
97
+ config
98
+ end
99
+ ##
100
+ # set_mysql_env
101
+ #
102
+ # Used to set the mysql specific DATABASE_URL env based
103
+ # on various conditions
104
+ def set_mysql_env
105
+ if ENV.key?('TRAVIS_MYSQL_PASS')
106
+ ENV['DATABASE_URL'] = "mysql://root:#{ENV['TRAVIS_MYSQL_PASS']}@127.0.0.1:3306/test_db"
107
+ elsif ENV.key?('DOCKER_MYSQL_PASS')
108
+ port = ENV.key?('MYSQL_PORT') ? ENV['MYSQL_PORT'] : 3306
109
+ ENV['DATABASE_URL'] = "mysql://root:#{ENV['DOCKER_MYSQL_PASS']}@#{ENV['MYSQL_HOST']}:#{port}/test_db"
110
+ else
111
+ ENV['DATABASE_URL'] = 'mysql://root@127.0.0.1:3306/test_db'
112
+ end
113
+ end
114
+
115
+ ##
116
+ # set_mysql2_env
117
+ #
118
+ # Used to set the mysql specific DATABASE_URL env based
119
+ # on various conditions
120
+ def set_mysql2_env
121
+ if ENV.key?('TRAVIS_MYSQL_PASS')
122
+ ENV['DATABASE_URL'] = "mysql2://root:#{ENV['TRAVIS_MYSQL_PASS']}@127.0.0.1:3306/test_db"
123
+ elsif ENV.key?('DOCKER_MYSQL_PASS')
124
+ ENV['DATABASE_URL'] = "mysql2://root:#{ENV['DOCKER_MYSQL_PASS']}@#{ENV['MYSQL_HOST']}:3306/test_db"
125
+ else
126
+ ENV['DATABASE_URL'] = 'mysql2://root@127.0.0.1:3306/test_db'
127
+ end
128
+ end
129
+
130
+ ##
131
+ # To configure Rails to enable or disable prepared statements
132
+ # we need to do it using the database.yml file
133
+ # there is no method exposed (afaik) to set prepared_statements
134
+ # interactively
135
+ def set_mysql2_rails_config
136
+ config = {
137
+ 'adapter' => "mysql2",
138
+ 'username' => "root",
139
+ 'database' => "test_db",
140
+ 'port' => 3306
141
+ }
142
+
143
+ config[:password] = ENV['DOCKER_MYSQL_PASS'] if ENV.key?('DOCKER_MYSQL_PASS')
144
+ config[:host] = ENV.key?('MYSQL_HOST') ? ENV['MYSQL_HOST'] : '127.0.0.1'
145
+
146
+ if ENV.key?('TEST_PREPARED_STATEMENT')
147
+ config['prepared_statements'] = ENV['TEST_PREPARED_STATEMENT'] == 'true' ? true : false
148
+ else
149
+ config['prepared_statements'] = false
150
+ end
151
+
152
+ env_config = {
153
+ 'default' => config,
154
+ 'test' => config
155
+ }
156
+
157
+ FileUtils.mkdir_p('config')
158
+ File.open("config/database.yml","w") do |file|
159
+ file.write env_config.to_yaml
160
+ end
161
+ config
162
+ end
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,26 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module SolarWindsAPM
5
+ ##
6
+ # Provides thread local storage for SolarWindsAPM.
7
+ #
8
+ # Example usage:
9
+ # module SolarWindsAPMBase
10
+ # extend SolarWindsAPM::ThreadLocal
11
+ # thread_local :layer_op
12
+ # end
13
+ module ThreadLocal
14
+ def thread_local(name)
15
+ key = "__#{self}_#{name}__".intern
16
+
17
+ define_method(name) do
18
+ Thread.current[key]
19
+ end
20
+
21
+ define_method(name.to_s + '=') do |value|
22
+ Thread.current[key] = value
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,334 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module SolarWindsAPM
5
+ ##
6
+ # Provides utility methods for use while in the business
7
+ # of instrumenting code
8
+ module Util
9
+ class << self
10
+ def contextual_name(cls)
11
+ # Attempt to infer a contextual name if not indicated
12
+ #
13
+ # For example:
14
+ # ::ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter.to_s.split(/::/).last
15
+ # => "AbstractMysqlAdapter"
16
+ #
17
+ cls.to_s.split(/::/).last
18
+ rescue
19
+ cls
20
+ end
21
+
22
+ ##
23
+ # method_alias
24
+ #
25
+ # Centralized utility method to alias a method on an arbitrary
26
+ # class or module.
27
+ #
28
+ def method_alias(cls, method, name = nil)
29
+ name ||= contextual_name(cls)
30
+
31
+ if cls.method_defined?(method.to_sym) || cls.private_method_defined?(method.to_sym)
32
+
33
+ # Strip '!' or '?' from method if present
34
+ safe_method_name = method.to_s.chop if method.to_s =~ /\?$|\!$/
35
+ safe_method_name ||= method
36
+
37
+ without_sw_apm = "#{safe_method_name}_without_sw_apm"
38
+ with_sw_apm = "#{safe_method_name}_with_sw_apm"
39
+
40
+ # Only alias if we haven't done so already
41
+ unless cls.method_defined?(without_sw_apm.to_sym) ||
42
+ cls.private_method_defined?(without_sw_apm.to_sym)
43
+
44
+ cls.class_eval do
45
+ alias_method without_sw_apm, method.to_s
46
+ alias_method method.to_s, with_sw_apm
47
+ end
48
+ end
49
+ else
50
+ SolarWindsAPM.logger.warn "[solarwinds_apm/loading] Couldn't properly instrument #{name}.#{method}. Partial traces may occur."
51
+ end
52
+ end
53
+
54
+ ##
55
+ # class_method_alias
56
+ #
57
+ # Centralized utility method to alias a class method on an arbitrary
58
+ # class or module
59
+ #
60
+ def class_method_alias(cls, method, name = nil)
61
+ name ||= contextual_name(cls)
62
+
63
+ if cls.singleton_methods.include? method.to_sym
64
+
65
+ # Strip '!' or '?' from method if present
66
+ safe_method_name = method.to_s.chop if method.to_s =~ /\?$|\!$/
67
+ safe_method_name ||= method
68
+
69
+ without_sw_apm = "#{safe_method_name}_without_sw_apm"
70
+ with_sw_apm = "#{safe_method_name}_with_sw_apm"
71
+
72
+ # Only alias if we haven't done so already
73
+ unless cls.singleton_methods.include? without_sw_apm.to_sym
74
+ cls.singleton_class.send(:alias_method, without_sw_apm, method.to_s)
75
+ cls.singleton_class.send(:alias_method, method.to_s, with_sw_apm)
76
+ end
77
+ else
78
+ SolarWindsAPM.logger.warn "[solarwinds_apm/loading] Couldn't properly instrument #{name}. Partial traces may occur."
79
+ end
80
+ end
81
+
82
+ ##
83
+ # send_extend
84
+ #
85
+ # Centralized utility method to send an extend call for an
86
+ # arbitrary class
87
+ def send_extend(target_cls, cls)
88
+ target_cls.send(:extend, cls) if defined?(target_cls)
89
+ end
90
+
91
+ ##
92
+ # send_include
93
+ #
94
+ # Centralized utility method to send a include call for an
95
+ # arbitrary class
96
+ def send_include(target_cls, cls)
97
+ target_cls.send(:include, cls) if defined?(target_cls)
98
+ end
99
+
100
+ ##
101
+ # prettify
102
+ #
103
+ # Even to my surprise, 'prettify' is a real word:
104
+ # transitive v. To make pretty or prettier, especially in a superficial or insubstantial way.
105
+ # from The American Heritage Dictionary of the English Language, 4th Edition
106
+ #
107
+ # This method makes things 'purty' for reporting.
108
+ def prettify(x)
109
+ if (x.to_s =~ /^#</) == 0
110
+ x.class.to_s
111
+ else
112
+ x.to_s
113
+ end
114
+ end
115
+
116
+ ##
117
+ # upcase
118
+ #
119
+ # Occasionally, we want to send some values in all caps. This is true
120
+ # for things like HTTP scheme or method. This takes anything and does
121
+ # it's best to safely convert it to a string (if needed) and convert it
122
+ # to all uppercase.
123
+ def upcase(o)
124
+ if o.is_a?(String) || o.respond_to?(:to_s)
125
+ o.to_s.upcase
126
+ else
127
+ SolarWindsAPM.logger.debug "[solarwinds_apm/debug] SolarWindsAPM::Util.upcase: could not convert #{o.class}"
128
+ 'UNKNOWN'
129
+ end
130
+ end
131
+
132
+ ##
133
+ # to_query
134
+ #
135
+ # Used to convert a hash into a URL # query.
136
+ #
137
+ def to_query(h)
138
+ return '' unless h.is_a?(Hash)
139
+
140
+ result = []
141
+
142
+ h.each { |k, v| result.push(k.to_s + '=' + v.to_s) }
143
+ result.sort.join('&')
144
+ end
145
+
146
+ ##
147
+ # sanitize_sql
148
+ #
149
+ # Remove query literals from SQL. Used by all
150
+ # DB adapter instrumentation.
151
+ #
152
+ # The regular expression passed to String.gsub is configurable
153
+ # via SolarWindsAPM::Config[:sanitize_sql_regexp] and
154
+ # SolarWindsAPM::Config[:sanitize_sql_opts].
155
+ #
156
+ def sanitize_sql(sql)
157
+ return sql unless SolarWindsAPM::Config[:sanitize_sql]
158
+
159
+ @@regexp ||= Regexp.new(SolarWindsAPM::Config[:sanitize_sql_regexp], SolarWindsAPM::Config[:sanitize_sql_opts]).freeze
160
+ sql.gsub(/\\\'/,'').gsub(@@regexp, '?')
161
+ end
162
+
163
+ ##
164
+ # remove_traceparent
165
+ #
166
+ # Remove trace context injection
167
+ #
168
+ def remove_traceparent(sql)
169
+ sql.gsub(SolarWindsAPM::SDK::CurrentTraceInfo::TraceInfo::SQL_REGEX, '')
170
+ end
171
+
172
+ ##
173
+ # deep_dup
174
+ #
175
+ # deep duplicate of array or hash
176
+ #
177
+ def deep_dup(obj)
178
+ if obj.is_a? Array
179
+ new_obj = []
180
+ obj.each do |v|
181
+ new_obj << deep_dup(v)
182
+ end
183
+ elsif obj.is_a? Hash
184
+ new_obj = {}
185
+ obj.each_pair do |key, value|
186
+ new_obj[key] = deep_dup(value)
187
+ end
188
+ end
189
+ end
190
+
191
+ ##
192
+ # legacy_build_init_report
193
+ #
194
+ # Internal: Build a hash of KVs that reports on the status of the
195
+ # running environment. This is used on stack boot in __Init reporting
196
+ # and for SolarWindsAPM.support_report.
197
+ #
198
+ # This legacy version of build_init_report is used for apps without Bundler.
199
+ #
200
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
201
+ #
202
+ # @deprecated Please use {#build_init_report} instead
203
+ def legacy_build_init_report
204
+ SolarWindsAPM.logger.warn '[solarwinds_apm/deprecated] Oboe::API will be deprecated in a future version.'
205
+ platform_info = {}
206
+
207
+ begin
208
+ # Report the framework in use
209
+ if defined?(::RailsLts::VERSION)
210
+ platform_info['Ruby.RailsLts.Version'] = "RailsLts-#{::RailsLts::VERSION}"
211
+ elsif defined?(::Rails.version)
212
+ platform_info['Ruby.Rails.Version'] = "Rails-#{::Rails.version}"
213
+ end
214
+ platform_info['Ruby.Grape.Version'] = "Grape-#{::Grape::VERSION}" if defined?(::Grape::VERSION)
215
+ platform_info['Ruby.Cramp.Version'] = "Cramp-#{::Cramp::VERSION}" if defined?(::Cramp::VERSION)
216
+
217
+ if defined?(::Padrino::VERSION)
218
+ platform_info['Ruby.Padrino.Version'] = "Padrino-#{::Padrino::VERSION}"
219
+ elsif defined?(::Sinatra::VERSION)
220
+ platform_info['Ruby.Sinatra.Version'] = "Sinatra-#{::Sinatra::VERSION}"
221
+ end
222
+
223
+ # Report the instrumented libraries
224
+ platform_info['Ruby.Curb.Version'] = "Curb-#{::Curl::VERSION}" if defined?(::Curl::VERSION)
225
+ platform_info['Ruby.Dalli.Version'] = "Dalli-#{::Dalli::VERSION}" if defined?(::Dalli::VERSION)
226
+ platform_info['Ruby.Excon.Version'] = "Excon-#{::Excon::VERSION}" if defined?(::Excon::VERSION)
227
+ platform_info['Ruby.Faraday.Version'] = "Faraday-#{::Faraday::VERSION}" if defined?(::Faraday::VERSION)
228
+ platform_info['Ruby.HTTPClient.Version'] = "HTTPClient-#{::HTTPClient::VERSION}" if defined?(::HTTPClient::VERSION)
229
+ platform_info['Ruby.Memcached.Version'] = "Memcached-#{::Memcached::VERSION}" if defined?(::Memcached::VERSION)
230
+ platform_info['Ruby.Moped.Version'] = "Moped-#{::Moped::VERSION}" if defined?(::Moped::VERSION)
231
+ platform_info['Ruby.Redis.Version'] = "Redis-#{::Redis::VERSION}" if defined?(::Redis::VERSION)
232
+ platform_info['Ruby.Resque.Version'] = "Resque-#{::Resque::VERSION}" if defined?(::Resque::VERSION)
233
+ platform_info['Ruby.RestClient.Version'] = "RestClient-#{::RestClient::VERSION}" if defined?(::RestClient::VERSION)
234
+ platform_info['Ruby.Sidekiq.Version'] = "Sidekiq-#{::Sidekiq::VERSION}" if defined?(::Sidekiq::VERSION)
235
+ platform_info['Ruby.Typhoeus.Version'] = "Typhoeus-#{::Typhoeus::VERSION}" if defined?(::Typhoeus::VERSION)
236
+
237
+ if Gem.loaded_specs.key?('delayed_job')
238
+ # Oddly, DelayedJob doesn't have an embedded version number so we get it from the loaded
239
+ # gem specs.
240
+ version = Gem.loaded_specs['delayed_job'].version.to_s
241
+ platform_info['Ruby.DelayedJob.Version'] = "DelayedJob-#{version}"
242
+ end
243
+
244
+ # Special case since the Mongo 1.x driver doesn't embed the version number in the gem directly
245
+ if ::Gem.loaded_specs.key?('mongo')
246
+ platform_info['Ruby.Mongo.Version'] = "Mongo-#{::Gem.loaded_specs['mongo'].version}"
247
+ end
248
+
249
+ # Report the DB adapter in use
250
+ platform_info['Ruby.Mysql.Version'] = Mysql::GemVersion::VERSION if defined?(Mysql::GemVersion::VERSION)
251
+ platform_info['Ruby.PG.Version'] = PG::VERSION if defined?(PG::VERSION)
252
+ platform_info['Ruby.Mysql2.Version'] = Mysql2::VERSION if defined?(Mysql2::VERSION)
253
+ platform_info['Ruby.Sequel.Version'] = ::Sequel::VERSION if defined?(::Sequel::VERSION)
254
+ rescue StandardError, ScriptError => e
255
+ # Also rescue ScriptError (aka SyntaxError) in case one of the expected
256
+ # version defines don't exist
257
+
258
+ platform_info['Error'] = "Error in legacy_build_init_report: #{e.message}"
259
+
260
+ SolarWindsAPM.logger.warn "[solarwinds_apm/legacy] Error in legacy_build_init_report: #{e.message}"
261
+ SolarWindsAPM.logger.debug e.backtrace
262
+ end
263
+ platform_info
264
+ end
265
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
266
+
267
+ ##
268
+ # build_init_report
269
+ #
270
+ # Internal: Build a hash of KVs that reports on the status of the
271
+ # running environment. This is used on stack boot in __Init reporting
272
+ # and for SolarWindsAPM.support_report.
273
+ #
274
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
275
+ def build_init_report
276
+ platform_info = { '__Init' => 1 }
277
+
278
+ begin
279
+ platform_info['Force'] = true
280
+ platform_info['Ruby.Platform.Version'] = RUBY_PLATFORM
281
+ platform_info['Ruby.Version'] = RUBY_VERSION
282
+ platform_info['Ruby.SolarWindsAPM.Version'] = SolarWindsAPM::Version::STRING
283
+
284
+ # oboe not loaded yet, can't use oboe_api function to read oboe VERSION
285
+ clib_version_file = File.join(Gem::Specification.find_by_name('solarwinds_apm').gem_dir, 'ext', 'oboe_metal', 'src', 'VERSION')
286
+ platform_info['Ruby.SolarWindsAPMExtension.Version'] = File.read(clib_version_file).strip
287
+ platform_info['RubyHeroku.SolarWindsAPM.Version'] = SolarWindsAPMHeroku::Version::STRING if defined?(SolarWindsAPMHeroku)
288
+ platform_info['Ruby.TraceMode.Version'] = SolarWindsAPM::Config[:tracing_mode]
289
+
290
+ # Collect up the loaded gems
291
+ if defined?(Gem) && Gem.respond_to?(:loaded_specs)
292
+ Gem.loaded_specs.each_pair { |k, v|
293
+ platform_info["Ruby.#{k}.Version"] = v.version.to_s
294
+ }
295
+ else
296
+ platform_info.merge!(legacy_build_init_report)
297
+ end
298
+
299
+ # Report the server in use (if possible)
300
+ if defined?(::Unicorn::Const::UNICORN_VERSION)
301
+ platform_info['Ruby.AppContainer.Version'] = "Unicorn-#{::Unicorn::Const::UNICORN_VERSION}"
302
+ elsif defined?(::Puma::Const::PUMA_VERSION)
303
+ platform_info['Ruby.AppContainer.Version'] = "Puma-#{::Puma::Const::PUMA_VERSION} (#{::Puma::Const::CODE_NAME})"
304
+ elsif defined?(::PhusionPassenger::PACKAGE_NAME)
305
+ platform_info['Ruby.AppContainer.Version'] = "#{::PhusionPassenger::PACKAGE_NAME}-#{::PhusionPassenger::VERSION_STRING}"
306
+ elsif defined?(::Thin::VERSION::STRING)
307
+ platform_info['Ruby.AppContainer.Version'] = "Thin-#{::Thin::VERSION::STRING} (#{::Thin::VERSION::CODENAME})"
308
+ elsif defined?(::Mongrel::Const::MONGREL_VERSION)
309
+ platform_info['Ruby.AppContainer.Version'] = "Mongrel-#{::Mongrel::Const::MONGREL_VERSION}"
310
+ elsif defined?(::Mongrel2::VERSION)
311
+ platform_info['Ruby.AppContainer.Version'] = "Mongrel2-#{::Mongrel2::VERSION}"
312
+ elsif defined?(::Trinidad::VERSION)
313
+ platform_info['Ruby.AppContainer.Version'] = "Trinidad-#{::Trinidad::VERSION}"
314
+ elsif defined?(::WEBrick::VERSION)
315
+ platform_info['Ruby.AppContainer.Version'] = "WEBrick-#{::WEBrick::VERSION}"
316
+ else
317
+ platform_info['Ruby.AppContainer.Version'] = File.basename($PROGRAM_NAME)
318
+ end
319
+
320
+ rescue StandardError, ScriptError => e
321
+ # Also rescue ScriptError (aka SyntaxError) in case one of the expected
322
+ # version defines don't exist
323
+
324
+ platform_info['Error'] = "Error in build_report: #{e.message}"
325
+
326
+ SolarWindsAPM.logger.warn "[solarwinds_apm/warn] Error in build_init_report: #{e.message}"
327
+ SolarWindsAPM.logger.debug e.backtrace
328
+ end
329
+ platform_info
330
+ end
331
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
332
+ end
333
+ end
334
+ end
@@ -0,0 +1,17 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module SolarWindsAPM
5
+ ##
6
+ # The current version of the gem. Used mainly by
7
+ # solarwinds_apm.gemspec during gem build process
8
+ module Version
9
+ MAJOR = 5 # breaking,
10
+ MINOR = 0 # feature,
11
+ PATCH = 0 # fix => BFF
12
+ PRE = nil # for pre-releases into packagecloud,
13
+ # set to nil for production releases into rubygems
14
+
15
+ STRING = [MAJOR, MINOR, PATCH, PRE].compact.join('.')
16
+ end
17
+ end
@@ -0,0 +1,72 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ begin
5
+ require 'openssl'
6
+ require 'solarwinds_apm/version'
7
+ require 'solarwinds_apm/thread_local'
8
+ require 'solarwinds_apm/logger'
9
+ require 'solarwinds_apm/util'
10
+ require 'solarwinds_apm/support_report'
11
+ require 'solarwinds_apm/base'
12
+ SolarWindsAPM.loaded = false
13
+
14
+ require 'solarwinds_apm/config'
15
+ SolarWindsAPM::Config.load_config_file
16
+
17
+ begin
18
+ if RUBY_PLATFORM =~ /linux/
19
+ require_relative './libsolarwinds_apm.so'
20
+ require 'solarwinds_apm/oboe_init_options'
21
+ require 'oboe_metal.rb' # sets SolarWindsAPM.loaded = true if successful
22
+ else
23
+ SolarWindsAPM.logger.warn '==================================================================='
24
+ SolarWindsAPM.logger.warn "SolarWindsAPM warning: Platform #{RUBY_PLATFORM} not yet supported."
25
+ SolarWindsAPM.logger.warn 'see: https://documentation.solarwinds.com/en/success_center/observability/default.htm#cshid=config-ruby-agent'
26
+ SolarWindsAPM.logger.warn 'Tracing disabled.'
27
+ SolarWindsAPM.logger.warn 'Contact technicalsupport@solarwinds.com if this is unexpected.'
28
+ SolarWindsAPM.logger.warn '==================================================================='
29
+ end
30
+ rescue LoadError => e
31
+ unless ENV['RAILS_GROUP'] == 'assets' or ENV['SW_APM_NO_LIBRARIES_WARNING']
32
+ SolarWindsAPM.logger.error '=============================================================='
33
+ SolarWindsAPM.logger.error 'Missing SolarWindsAPM libraries. Tracing disabled.'
34
+ SolarWindsAPM.logger.error "Error: #{e.message}"
35
+ SolarWindsAPM.logger.error 'See: https://documentation.solarwinds.com/en/success_center/observability/default.htm#cshid=config-ruby-agent'
36
+ SolarWindsAPM.logger.error '=============================================================='
37
+ end
38
+ end
39
+
40
+ # solarwinds_apm/loading can set SolarWindsAPM.loaded = false if the service key is not working
41
+ require 'solarwinds_apm/loading'
42
+
43
+ if SolarWindsAPM.loaded
44
+ require 'solarwinds_apm/instrumentation'
45
+ require 'solarwinds_apm/support'
46
+
47
+ # Frameworks
48
+ require 'solarwinds_apm/frameworks/rails'
49
+ require 'solarwinds_apm/frameworks/sinatra'
50
+ require 'solarwinds_apm/frameworks/padrino'
51
+ require 'solarwinds_apm/frameworks/grape'
52
+ else
53
+ SolarWindsAPM.logger.warn '=============================================================='
54
+ SolarWindsAPM.logger.warn 'SolarWindsAPM not loaded. Tracing disabled.'
55
+ SolarWindsAPM.logger.warn 'There may be a problem with the service key or other settings.'
56
+ SolarWindsAPM.logger.warn 'Please check previous log messages.'
57
+ SolarWindsAPM.logger.warn '=============================================================='
58
+ require 'solarwinds_apm/noop/context'
59
+ require 'solarwinds_apm/noop/metadata'
60
+ require 'solarwinds_apm/noop/profiling'
61
+ require 'solarwinds_apm/support/trace_string'
62
+ end
63
+
64
+ # Load Ruby module last. If there is no framework detected,
65
+ # it will load all of the Ruby instrumentation
66
+ require 'solarwinds_apm/ruby'
67
+
68
+ require 'solarwinds_apm/test' if ENV['SW_APM_GEM_TEST']
69
+ rescue => e
70
+ $stderr.puts "[solarwinds_apm/error] Problem loading: #{e.inspect}"
71
+ $stderr.puts e.backtrace
72
+ end
data/log/.keep ADDED
File without changes
File without changes
@@ -0,0 +1,52 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require "solarwinds_apm/version"
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = %q{solarwinds_apm}
6
+ s.version = SolarWindsAPM::Version::STRING
7
+ s.date = Time.now.strftime('%Y-%m-%d')
8
+
9
+ s.license = "Apache-2.0"
10
+
11
+ s.authors = ["Maia Engeli", "Peter Giacomo Lombardo", "Spiros Eliopoulos"]
12
+ s.email = %q{technicalsupport@solarwinds.com}
13
+ s.homepage = %q{https://cloud.solarwinds.com/}
14
+ s.summary = %q{SolarWindsAPM performance instrumentation gem for Ruby}
15
+ s.description = <<-EOF
16
+ Automatic tracing and metrics for Ruby applications. Get started at cloud.solarwinds.com
17
+ EOF
18
+
19
+ s.metadata = {
20
+ 'changelog_uri' => 'https://github.com/appoptics/appoptics-apm-ruby/releases',
21
+ 'documentation_uri' => 'https://documentation.solarwinds.com/en/success_center/observability/default.htm#cshid=config-ruby-agent',
22
+ 'homepage_uri' => 'https://cloud.solarwinds.com/',
23
+ 'source_code_uri' => 'https://github.com/appoptics/appoptics-apm-ruby',
24
+ }
25
+
26
+ s.extra_rdoc_files = ['LICENSE']
27
+ s.files = `git ls-files`.split("\n").reject { |f| f.match(%r{^(test|gemfiles)/}) }
28
+ s.files += ['ext/oboe_metal/src/oboe.h',
29
+ 'ext/oboe_metal/src/oboe_api.cpp',
30
+ 'ext/oboe_metal/src/oboe_api.hpp',
31
+ 'ext/oboe_metal/src/oboe_debug.h',
32
+ 'ext/oboe_metal/src/oboe_swig_wrap.cc',
33
+ 'ext/oboe_metal/src/bson/bson.h',
34
+ 'ext/oboe_metal/src/bson/platform_hacks.h',
35
+ 'ext/oboe_metal/src/VERSION',
36
+ 'ext/oboe_metal/lib/liboboe-1.0-alpine-x86_64.so.0.0.0.sha256',
37
+ 'ext/oboe_metal/lib/liboboe-1.0-x86_64.so.0.0.0.sha256'
38
+ ]
39
+ s.files -= ['build_gem.sh',
40
+ 'build_gem_upload_to_packagecloud.sh',
41
+ 'Rakefile']
42
+
43
+ s.extensions = ['ext/oboe_metal/extconf.rb']
44
+
45
+ # this still gives a warning, would have to be pinned to a minor version
46
+ # but that is not necessary and may restrict other gems
47
+ s.add_runtime_dependency('json', '~> 2.0')
48
+ s.add_runtime_dependency('no_proxy_fix', '~> 0.1.2', '>= 0.1.2')
49
+
50
+ s.required_ruby_version = '>= 2.5.0'
51
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
52
+ end