atatus 1.3.0 → 1.4.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 (147) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/Gemfile +72 -22
  4. data/LICENSE +1 -1
  5. data/atatus.gemspec +2 -2
  6. data/lib/atatus.rb +76 -16
  7. data/lib/atatus/agent.rb +78 -29
  8. data/lib/atatus/central_config.rb +72 -27
  9. data/lib/atatus/central_config/cache_control.rb +18 -1
  10. data/lib/atatus/child_durations.rb +64 -0
  11. data/lib/atatus/collector/base.rb +61 -29
  12. data/lib/atatus/collector/builder.rb +46 -2
  13. data/lib/atatus/collector/hist.rb +54 -0
  14. data/lib/atatus/collector/transport.rb +41 -11
  15. data/lib/atatus/config.rb +129 -28
  16. data/lib/atatus/config/bytes.rb +17 -0
  17. data/lib/atatus/config/duration.rb +17 -0
  18. data/lib/atatus/config/options.rb +29 -9
  19. data/lib/atatus/config/regexp_list.rb +17 -0
  20. data/lib/atatus/config/wildcard_pattern_list.rb +64 -0
  21. data/lib/atatus/context.rb +32 -1
  22. data/lib/atatus/context/request.rb +17 -0
  23. data/lib/atatus/context/request/socket.rb +18 -1
  24. data/lib/atatus/context/request/url.rb +17 -0
  25. data/lib/atatus/context/response.rb +27 -2
  26. data/lib/atatus/context/user.rb +17 -0
  27. data/lib/atatus/context_builder.rb +19 -4
  28. data/lib/atatus/deprecations.rb +17 -0
  29. data/lib/atatus/error.rb +27 -0
  30. data/lib/atatus/error/exception.rb +24 -0
  31. data/lib/atatus/error/log.rb +17 -0
  32. data/lib/atatus/error_builder.rb +17 -2
  33. data/lib/atatus/grape.rb +62 -0
  34. data/lib/atatus/graphql.rb +91 -0
  35. data/lib/atatus/grpc.rb +99 -0
  36. data/lib/atatus/instrumenter.rb +135 -30
  37. data/lib/atatus/internal_error.rb +17 -0
  38. data/lib/atatus/logging.rb +17 -2
  39. data/lib/atatus/metadata.rb +17 -0
  40. data/lib/atatus/metadata/process_info.rb +17 -0
  41. data/lib/atatus/metadata/service_info.rb +21 -6
  42. data/lib/atatus/metadata/system_info.rb +22 -3
  43. data/lib/atatus/metadata/system_info/container_info.rb +49 -10
  44. data/lib/atatus/metadata/system_info/hw_info.rb +1 -1
  45. data/lib/atatus/metrics.rb +69 -27
  46. data/lib/atatus/metrics/breakdown_set.rb +31 -0
  47. data/lib/atatus/metrics/{cpu_mem.rb → cpu_mem_set.rb} +110 -63
  48. data/lib/atatus/metrics/metric.rb +140 -0
  49. data/lib/atatus/metrics/set.rb +123 -0
  50. data/lib/atatus/metrics/span_scoped_set.rb +56 -0
  51. data/lib/atatus/metrics/transaction_set.rb +26 -0
  52. data/lib/atatus/metrics/vm_set.rb +58 -0
  53. data/lib/atatus/metricset.rb +48 -4
  54. data/lib/atatus/middleware.rb +28 -8
  55. data/lib/atatus/naively_hashable.rb +17 -0
  56. data/lib/atatus/normalizers.rb +23 -9
  57. data/lib/atatus/normalizers/grape.rb +22 -0
  58. data/lib/atatus/normalizers/grape/endpoint_run.rb +65 -0
  59. data/lib/atatus/normalizers/rails.rb +27 -0
  60. data/lib/atatus/normalizers/rails/action_controller.rb +44 -0
  61. data/lib/atatus/normalizers/rails/action_mailer.rb +43 -0
  62. data/lib/atatus/normalizers/{action_view.rb → rails/action_view.rb} +17 -0
  63. data/lib/atatus/normalizers/rails/active_record.rb +80 -0
  64. data/lib/atatus/opentracing.rb +75 -42
  65. data/lib/atatus/rails.rb +29 -13
  66. data/lib/atatus/railtie.rb +19 -6
  67. data/lib/atatus/resque.rb +29 -0
  68. data/lib/atatus/sinatra.rb +53 -0
  69. data/lib/atatus/span.rb +44 -15
  70. data/lib/atatus/span/context.rb +43 -28
  71. data/lib/atatus/span/context/db.rb +43 -0
  72. data/lib/atatus/span/context/destination.rb +77 -0
  73. data/lib/atatus/span/context/http.rb +43 -0
  74. data/lib/atatus/span_helpers.rb +18 -1
  75. data/lib/atatus/spies.rb +33 -15
  76. data/lib/atatus/spies/action_dispatch.rb +27 -6
  77. data/lib/atatus/spies/delayed_job.rb +26 -5
  78. data/lib/atatus/spies/dynamo_db.rb +62 -0
  79. data/lib/atatus/spies/elasticsearch.rb +53 -7
  80. data/lib/atatus/spies/faraday.rb +54 -20
  81. data/lib/atatus/spies/http.rb +36 -6
  82. data/lib/atatus/spies/json.rb +18 -0
  83. data/lib/atatus/spies/mongo.rb +41 -10
  84. data/lib/atatus/spies/net_http.rb +52 -11
  85. data/lib/atatus/spies/rake.rb +42 -23
  86. data/lib/atatus/spies/redis.rb +17 -0
  87. data/lib/atatus/spies/resque.rb +57 -0
  88. data/lib/atatus/spies/sequel.rb +54 -17
  89. data/lib/atatus/spies/shoryuken.rb +69 -0
  90. data/lib/atatus/spies/sidekiq.rb +46 -25
  91. data/lib/atatus/spies/sinatra.rb +20 -4
  92. data/lib/atatus/spies/sneakers.rb +74 -0
  93. data/lib/atatus/spies/sucker_punch.rb +58 -0
  94. data/lib/atatus/spies/tilt.rb +20 -1
  95. data/lib/atatus/sql.rb +36 -0
  96. data/lib/atatus/sql/signature.rb +169 -0
  97. data/lib/atatus/sql/tokenizer.rb +264 -0
  98. data/lib/atatus/sql/tokens.rb +63 -0
  99. data/lib/atatus/sql_summarizer.rb +24 -6
  100. data/lib/atatus/stacktrace.rb +17 -0
  101. data/lib/atatus/stacktrace/frame.rb +17 -3
  102. data/lib/atatus/stacktrace_builder.rb +23 -3
  103. data/lib/atatus/subscriber.rb +23 -4
  104. data/lib/atatus/trace_context.rb +84 -51
  105. data/lib/atatus/trace_context/traceparent.rb +111 -0
  106. data/lib/atatus/trace_context/tracestate.rb +148 -0
  107. data/lib/atatus/transaction.rb +74 -18
  108. data/lib/atatus/transport/base.rb +44 -27
  109. data/lib/atatus/transport/connection.rb +28 -72
  110. data/lib/atatus/transport/connection/http.rb +58 -35
  111. data/lib/atatus/transport/connection/proxy_pipe.rb +24 -5
  112. data/lib/atatus/transport/filters.rb +18 -1
  113. data/lib/atatus/transport/filters/hash_sanitizer.rb +77 -0
  114. data/lib/atatus/transport/filters/secrets_filter.rb +30 -55
  115. data/lib/atatus/transport/headers.rb +83 -0
  116. data/lib/atatus/transport/serializers.rb +17 -5
  117. data/lib/atatus/transport/serializers/context_serializer.rb +30 -3
  118. data/lib/atatus/transport/serializers/error_serializer.rb +17 -2
  119. data/lib/atatus/transport/serializers/metadata_serializer.rb +44 -22
  120. data/lib/atatus/transport/serializers/metricset_serializer.rb +34 -6
  121. data/lib/atatus/transport/serializers/span_serializer.rb +47 -12
  122. data/lib/atatus/transport/serializers/transaction_serializer.rb +18 -2
  123. data/lib/atatus/transport/user_agent.rb +48 -0
  124. data/lib/atatus/transport/worker.rb +31 -7
  125. data/lib/atatus/util.rb +18 -1
  126. data/lib/atatus/util/inflector.rb +17 -0
  127. data/lib/atatus/util/lru_cache.rb +17 -0
  128. data/lib/atatus/util/throttle.rb +17 -0
  129. data/lib/atatus/version.rb +19 -1
  130. metadata +46 -26
  131. data/Rakefile +0 -19
  132. data/bench/.gitignore +0 -2
  133. data/bench/app.rb +0 -53
  134. data/bench/benchmark.rb +0 -36
  135. data/bench/report.rb +0 -55
  136. data/bench/rubyprof.rb +0 -39
  137. data/bench/stackprof.rb +0 -23
  138. data/bin/build_docs +0 -5
  139. data/bin/console +0 -15
  140. data/bin/setup +0 -8
  141. data/bin/with_framework +0 -7
  142. data/lib/atatus/metrics/vm.rb +0 -60
  143. data/lib/atatus/normalizers/action_controller.rb +0 -27
  144. data/lib/atatus/normalizers/action_mailer.rb +0 -26
  145. data/lib/atatus/normalizers/active_record.rb +0 -45
  146. data/lib/atatus/util/prefixed_logger.rb +0 -18
  147. data/vendor/.gitkeep +0 -0
data/Rakefile DELETED
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/gem_tasks'
4
-
5
- Rake::Task[:release].enhance do
6
- `git checkout 2.x &&
7
- git rebase master &&
8
- git push origin 2.x &&
9
- git checkout master`
10
- end
11
-
12
- require 'rspec/core/rake_task'
13
- RSpec::Core::RakeTask.new(:spec)
14
-
15
- require 'yard'
16
- YARD::Rake::YardocTask.new
17
- task docs: :yard
18
-
19
- task default: :spec
@@ -1,2 +0,0 @@
1
- tmp/*
2
- db/*
@@ -1,53 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
5
- require 'active_record'
6
- require 'action_controller/railtie'
7
- require 'atatus'
8
- require 'atatus/railtie'
9
-
10
- $log = Logger.new('/tmp/bench.log')
11
-
12
- ActiveRecord::Base.logger = $log
13
-
14
- ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: '/tmp/bench.sqlite3')
15
-
16
- ActiveRecord::Schema.define do
17
- create_table :posts, force: true do |t|
18
- t.string :title
19
- t.timestamps
20
- end
21
- end
22
-
23
- class Post < ActiveRecord::Base
24
- end
25
-
26
- 10.times { |i| Post.create! title: "Post #{i}" }
27
-
28
- class ApplicationController < ActionController::Base
29
- def index
30
- render inline: '<%= Post.pluck(:title).join(", ") %>'
31
- end
32
-
33
- def favicon
34
- render nothing: true
35
- end
36
- end
37
-
38
- class App < Rails::Application
39
- config.secret_key_base = '__secret'
40
- config.logger = $log
41
- config.eager_load = false
42
-
43
- config.atatus.disable_send = true
44
- config.atatus.logger = $log
45
- config.atatus.log_level = Logger::DEBUG
46
- end
47
-
48
- App.initialize!
49
-
50
- App.routes.draw do
51
- get '/favicon.ico', to: 'application#favicon'
52
- root to: 'application#index'
53
- end
@@ -1,36 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- ENV['RAILS_ENV'] = 'production'
5
-
6
- require 'bundler'
7
- require 'bundler/setup'
8
-
9
- require 'benchmark'
10
- include Benchmark
11
- require 'rack/test'
12
-
13
- require './bench/app'
14
-
15
- def app
16
- App
17
- end
18
-
19
- include Rack::Test::Methods
20
-
21
- def perform
22
- 10_000.times do
23
- get '/'
24
- end
25
- end
26
-
27
- bench = Benchmark.benchmark(CAPTION, 15, FORMAT) do |b|
28
- perform # warm up
29
-
30
- b.report('with agent:') { perform }
31
-
32
- Atatus.stop
33
- perform # warm up
34
-
35
- b.report('without agent:') { perform }
36
- end
@@ -1,55 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require 'time'
5
- require 'json'
6
-
7
- input = STDIN.read.split("\n")
8
-
9
- git_sha, git_msg = `git log -n 1 --pretty="format:%H|||%s"`.split('|||')
10
- git_date = `git log -n 1 --pretty="format:%ai"`
11
- platform = Gem::Platform.local
12
-
13
- def doc(payload)
14
- puts({ index: { _index: "benchmark-ruby", _type: "_doc" } }.to_json)
15
- puts(payload.to_json)
16
- end
17
-
18
- meta = {
19
- executed_at: Time.new.iso8601,
20
- 'git.commit' => git_sha,
21
- 'git.date' => String(git_date).strip != '' && Time.parse(git_date).iso8601,
22
- 'git.subject' => git_msg,
23
- hostname: `hostname`.chomp,
24
- engine: RUBY_ENGINE,
25
- arch: platform.cpu,
26
- os: platform.os,
27
- ruby_version: "#{RUBY_ENGINE == 'jruby' ? 'j' : ''}#{RUBY_VERSION}"
28
- }
29
-
30
- results =
31
- input
32
- .grep(/^with/)
33
- .map do |line|
34
- title = line.match(/^(.*):/) { |m| m[1] }
35
- user, system, total, real = line.scan(/[0-9\.]+/).map(&:to_f)
36
- meta.merge(
37
- title: title,
38
- user: user,
39
- system: system,
40
- total: total,
41
- real: real,
42
- )
43
- end
44
-
45
- results.each { |result| doc result }
46
-
47
- overhead =
48
- (results[0][:total] - results[1][:total]) *
49
- 1000 / # milliseconds
50
- 10_000 # transactions
51
-
52
- doc meta.merge(
53
- title: 'overhead',
54
- overhead: overhead
55
- )
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'ruby-prof'
4
- require 'rack/test'
5
-
6
- $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
7
- require 'atatus'
8
-
9
- require './bench/app'
10
- include App::Helpers
11
-
12
- def perform(app, count: 1000)
13
- app.start
14
-
15
- transactions = count.times.map do |i|
16
- Atatus.transaction "Transaction##{i}",
17
- context: Atatus.build_context(app.mock_env) do
18
- Atatus.span('Number one') { 'ok 1' }
19
- Atatus.span('Number two') { 'ok 2' }
20
- Atatus.span('Number three') { 'ok 3' }
21
- end
22
- end
23
-
24
- app.stop
25
- end
26
-
27
- def do_bench(transaction_count: 1000, **config)
28
- with_app(config) do |app|
29
- profile = RubyProf::Profile.new
30
- profile.exclude_common_methods!
31
- profile.start
32
- perform(app, count: transaction_count)
33
- profile.stop
34
- printer = RubyProf::GraphHtmlPrinter.new(profile)
35
- printer.print(File.open('bench/tmp/out.html', 'w'))
36
- end
37
- end
38
-
39
- do_bench(transaction_count: 10_000)
@@ -1,23 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require 'stackprof'
5
- require 'rack/test'
6
-
7
- require './bench/app'
8
-
9
- def app
10
- App
11
- end
12
-
13
- include Rack::Test::Methods
14
-
15
- puts 'Running '
16
- profile = StackProf.run(mode: :cpu) do
17
- 10_000.times do
18
- get '/'
19
- end
20
- end
21
- puts ''
22
-
23
- StackProf::Report.new(profile).print_text
@@ -1,5 +0,0 @@
1
- #!/bin/bash
2
- set -ex
3
-
4
- # Requires atatus/docs to be checked out at ../docs
5
- ../docs/build_docs.pl --doc docs/index.asciidoc --chunk 1
@@ -1,15 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require 'bundler/setup'
5
- require 'atatus'
6
-
7
- # You can add fixtures and/or initialization code here to make experimenting
8
- # with your gem easier. You can also use a different console, if you like.
9
-
10
- # (If you use this, don't forget to add pry to your Gemfile!)
11
- # require "pry"
12
- # Pry.start
13
-
14
- require 'irb'
15
- IRB.start(__FILE__)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
@@ -1,7 +0,0 @@
1
- #!/bin/bash -x
2
- set -e
3
-
4
- framework=$1
5
-
6
- FRAMEWORK=$framework bundle update
7
- FRAMEWORK=$framework ${@:2}
@@ -1,60 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Atatus
4
- module Metrics
5
- # @api private
6
- class VM
7
- include Logging
8
-
9
- def initialize(config)
10
- @config = config
11
- @total_time = 0
12
- @disabled = false
13
- end
14
-
15
- attr_reader :config
16
- attr_writer :disabled
17
-
18
- # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
19
- # rubocop:disable Metrics/CyclomaticComplexity
20
- def collect
21
- return if disabled?
22
-
23
- stat = GC.stat
24
- thread_count = Thread.list.count
25
-
26
- sample = {
27
- 'ruby.gc.count': stat[:count],
28
- 'ruby.threads': thread_count
29
- }
30
-
31
- (live_slots = stat[:heap_live_slots]) &&
32
- sample[:'ruby.heap.slots.live'] = live_slots
33
- (heap_slots = stat[:heap_free_slots]) &&
34
- sample[:'ruby.heap.slots.free'] = heap_slots
35
- (allocated = stat[:total_allocated_objects]) &&
36
- sample[:'ruby.heap.allocations.total'] = allocated
37
-
38
- return sample unless GC::Profiler.enabled?
39
-
40
- @total_time += GC::Profiler.total_time
41
- GC::Profiler.clear
42
- sample[:'ruby.gc.time'] = @total_time
43
-
44
- sample
45
- rescue TypeError => e
46
- error 'VM metrics encountered error: %s', e
47
- debug('Backtrace:') { e.backtrace.join("\n") }
48
-
49
- @disabled = true
50
- nil
51
- end
52
- # rubocop:enable Metrics/CyclomaticComplexity
53
- # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
54
-
55
- def disabled?
56
- @disabled
57
- end
58
- end
59
- end
60
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Atatus
4
- module Normalizers
5
- module ActionController
6
- # @api private
7
- class ProcessActionNormalizer < Normalizer
8
- register 'process_action.action_controller'
9
-
10
- TYPE = 'app'
11
- SUBTYPE = 'controller'
12
- ACTION = 'action'
13
-
14
- def normalize(transaction, _name, payload)
15
- transaction.name = endpoint(payload)
16
- [transaction.name, TYPE, SUBTYPE, ACTION, nil]
17
- end
18
-
19
- private
20
-
21
- def endpoint(payload)
22
- "#{payload[:controller]}##{payload[:action]}"
23
- end
24
- end
25
- end
26
- end
27
- end
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Atatus
4
- module Normalizers
5
- module ActionMailer
6
- # @api private
7
- class ProcessActionNormalizer < Normalizer
8
- register 'process.action_mailer'
9
-
10
- TYPE = 'app'
11
- SUBTYPE = 'mailer'
12
- ACTION = 'action'
13
-
14
- def normalize(_transaction, _name, payload)
15
- [endpoint(payload), TYPE, SUBTYPE, ACTION, nil]
16
- end
17
-
18
- private
19
-
20
- def endpoint(payload)
21
- "#{payload[:mailer]}##{payload[:action]}"
22
- end
23
- end
24
- end
25
- end
26
- end
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'atatus/sql_summarizer'
4
-
5
- module Atatus
6
- module Normalizers
7
- module ActiveRecord
8
- # @api private
9
- class SqlNormalizer < Normalizer
10
- register 'sql.active_record'
11
-
12
- TYPE = 'db'
13
- ACTION = 'sql'
14
-
15
- def initialize(*args)
16
- super
17
-
18
- @subtype = lookup_adapter || 'unknown'
19
- @summarizer = SqlSummarizer.new
20
- end
21
-
22
- def normalize(_transaction, _name, payload)
23
- return :skip if %w[SCHEMA CACHE].include?(payload[:name])
24
-
25
- name = summarize(payload[:sql]) || payload[:name]
26
- context =
27
- Span::Context.new(db: { statement: payload[:sql], type: 'sql' })
28
- [name, TYPE, @subtype, ACTION, context]
29
- end
30
-
31
- private
32
-
33
- def summarize(sql)
34
- @summarizer.summarize(sql)
35
- end
36
-
37
- def lookup_adapter
38
- ::ActiveRecord::Base.connection.adapter_name.downcase
39
- rescue StandardError
40
- nil
41
- end
42
- end
43
- end
44
- end
45
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Atatus
4
- # @api private
5
- class PrefixedLogger < Logger
6
- def initialize(logdev, prefix: '', **args)
7
- super(logdev, **args)
8
-
9
- @prefix = prefix
10
- end
11
-
12
- attr_reader :prefix
13
-
14
- def add(severity, message = nil, progname = nil, &block)
15
- super(severity, message, format('%s%s', prefix, progname), &block)
16
- end
17
- end
18
- end