influx_reporter 1.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 (103) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +51 -0
  5. data/.travis.yml +42 -0
  6. data/.yardopts +3 -0
  7. data/Dockerfile +9 -0
  8. data/Gemfile +7 -0
  9. data/HISTORY.md +1 -0
  10. data/LICENSE +14 -0
  11. data/README.md +189 -0
  12. data/Rakefile +27 -0
  13. data/gemfiles/Gemfile.base +29 -0
  14. data/gemfiles/Gemfile.rails-3.2.x +4 -0
  15. data/gemfiles/Gemfile.rails-4.0.x +4 -0
  16. data/gemfiles/Gemfile.rails-4.1.x +4 -0
  17. data/gemfiles/Gemfile.rails-4.2.x +5 -0
  18. data/gemfiles/Gemfile.rails-5.0.x +5 -0
  19. data/gemfiles/Gemfile.rails-HEAD +7 -0
  20. data/influx_reporter.gemspec +26 -0
  21. data/lib/influx_reporter.rb +142 -0
  22. data/lib/influx_reporter/client.rb +306 -0
  23. data/lib/influx_reporter/configuration.rb +88 -0
  24. data/lib/influx_reporter/data_builders.rb +18 -0
  25. data/lib/influx_reporter/data_builders/error.rb +52 -0
  26. data/lib/influx_reporter/data_builders/transactions.rb +120 -0
  27. data/lib/influx_reporter/error.rb +7 -0
  28. data/lib/influx_reporter/error_message.rb +85 -0
  29. data/lib/influx_reporter/error_message/exception.rb +14 -0
  30. data/lib/influx_reporter/error_message/http.rb +73 -0
  31. data/lib/influx_reporter/error_message/stacktrace.rb +76 -0
  32. data/lib/influx_reporter/error_message/user.rb +25 -0
  33. data/lib/influx_reporter/filter.rb +66 -0
  34. data/lib/influx_reporter/http_client.rb +140 -0
  35. data/lib/influx_reporter/influx_db_client.rb +74 -0
  36. data/lib/influx_reporter/injections.rb +89 -0
  37. data/lib/influx_reporter/injections/json.rb +21 -0
  38. data/lib/influx_reporter/injections/net_http.rb +50 -0
  39. data/lib/influx_reporter/injections/redis.rb +25 -0
  40. data/lib/influx_reporter/injections/sequel.rb +37 -0
  41. data/lib/influx_reporter/injections/sinatra.rb +59 -0
  42. data/lib/influx_reporter/integration/delayed_job.rb +30 -0
  43. data/lib/influx_reporter/integration/rails/inject_exceptions_catcher.rb +25 -0
  44. data/lib/influx_reporter/integration/railtie.rb +56 -0
  45. data/lib/influx_reporter/integration/resque.rb +18 -0
  46. data/lib/influx_reporter/integration/sidekiq.rb +130 -0
  47. data/lib/influx_reporter/line_cache.rb +21 -0
  48. data/lib/influx_reporter/logging.rb +39 -0
  49. data/lib/influx_reporter/middleware.rb +63 -0
  50. data/lib/influx_reporter/normalizers.rb +65 -0
  51. data/lib/influx_reporter/normalizers/action_controller.rb +34 -0
  52. data/lib/influx_reporter/normalizers/action_view.rb +72 -0
  53. data/lib/influx_reporter/normalizers/active_record.rb +45 -0
  54. data/lib/influx_reporter/sql_summarizer.rb +31 -0
  55. data/lib/influx_reporter/subscriber.rb +80 -0
  56. data/lib/influx_reporter/tasks.rb +28 -0
  57. data/lib/influx_reporter/trace.rb +48 -0
  58. data/lib/influx_reporter/trace_helpers.rb +31 -0
  59. data/lib/influx_reporter/transaction.rb +114 -0
  60. data/lib/influx_reporter/util.rb +18 -0
  61. data/lib/influx_reporter/util/constantize.rb +56 -0
  62. data/lib/influx_reporter/util/inspector.rb +72 -0
  63. data/lib/influx_reporter/util/timestamp.rb +11 -0
  64. data/lib/influx_reporter/version.rb +5 -0
  65. data/lib/influx_reporter/worker.rb +56 -0
  66. data/spec/influx_reporter/client_spec.rb +264 -0
  67. data/spec/influx_reporter/configuration_spec.rb +42 -0
  68. data/spec/influx_reporter/data_builders/error_spec.rb +40 -0
  69. data/spec/influx_reporter/data_builders/transactions_spec.rb +48 -0
  70. data/spec/influx_reporter/error_message/exception_spec.rb +22 -0
  71. data/spec/influx_reporter/error_message/http_spec.rb +55 -0
  72. data/spec/influx_reporter/error_message/stacktrace_spec.rb +56 -0
  73. data/spec/influx_reporter/error_message/user_spec.rb +26 -0
  74. data/spec/influx_reporter/error_message_spec.rb +102 -0
  75. data/spec/influx_reporter/filter_spec.rb +33 -0
  76. data/spec/influx_reporter/injections/net_http_spec.rb +35 -0
  77. data/spec/influx_reporter/injections/sequel_spec.rb +33 -0
  78. data/spec/influx_reporter/injections/sinatra_spec.rb +13 -0
  79. data/spec/influx_reporter/injections_spec.rb +50 -0
  80. data/spec/influx_reporter/integration/delayed_job_spec.rb +37 -0
  81. data/spec/influx_reporter/integration/json_spec.rb +41 -0
  82. data/spec/influx_reporter/integration/rails_spec.rb +92 -0
  83. data/spec/influx_reporter/integration/redis_spec.rb +20 -0
  84. data/spec/influx_reporter/integration/resque_spec.rb +42 -0
  85. data/spec/influx_reporter/integration/sidekiq_spec.rb +40 -0
  86. data/spec/influx_reporter/integration/sinatra_spec.rb +99 -0
  87. data/spec/influx_reporter/line_cache_spec.rb +38 -0
  88. data/spec/influx_reporter/logging_spec.rb +49 -0
  89. data/spec/influx_reporter/middleware_spec.rb +32 -0
  90. data/spec/influx_reporter/normalizers/action_controller_spec.rb +37 -0
  91. data/spec/influx_reporter/normalizers/action_view_spec.rb +78 -0
  92. data/spec/influx_reporter/normalizers/active_record_spec.rb +70 -0
  93. data/spec/influx_reporter/normalizers_spec.rb +16 -0
  94. data/spec/influx_reporter/sql_summarizer_spec.rb +35 -0
  95. data/spec/influx_reporter/subscriber_spec.rb +83 -0
  96. data/spec/influx_reporter/trace_spec.rb +43 -0
  97. data/spec/influx_reporter/transaction_spec.rb +98 -0
  98. data/spec/influx_reporter/util/inspector_spec.rb +41 -0
  99. data/spec/influx_reporter/util_spec.rb +20 -0
  100. data/spec/influx_reporter/worker_spec.rb +54 -0
  101. data/spec/influx_reporter_spec.rb +50 -0
  102. data/spec/spec_helper.rb +86 -0
  103. metadata +188 -0
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ module InfluxReporter
6
+ RSpec.describe Normalizers do
7
+ let(:config) { Configuration.new }
8
+
9
+ describe Normalizers::Default do
10
+ it 'skips' do
11
+ normalizer = Normalizers::Default.new config
12
+ expect(normalizer.normalize(1, 2, 3)).to eq :skip
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ module InfluxReporter
6
+ RSpec.describe SqlSummarizer do
7
+ let(:config) { Configuration.new }
8
+
9
+ subject { SqlSummarizer.new(config) }
10
+
11
+ it 'summarizes selects' do
12
+ expect(subject.signature_for("SELECT CAST(SERVERPROPERTY('ProductVersion') AS varchar)")).to eq('SQL')
13
+ end
14
+
15
+ it 'summarizes selects from table' do
16
+ expect(subject.signature_for('SELECT * FROM table')).to eq('SELECT FROM table')
17
+ end
18
+
19
+ it 'summarizes selects from table with columns' do
20
+ expect(subject.signature_for('SELECT a, b FROM table')).to eq('SELECT FROM table')
21
+ end
22
+
23
+ it 'summarizes inserts' do
24
+ expect(subject.signature_for("INSERT INTO table (a, b) VALUES ('A','B')")).to eq('INSERT INTO table')
25
+ end
26
+
27
+ it 'summarizes updates' do
28
+ expect(subject.signature_for("UPDATE table SET a = 'B' WHERE b = 'B'")).to eq('UPDATE table')
29
+ end
30
+
31
+ it 'summarizes deletes' do
32
+ expect(subject.signature_for("DELETE FROM table WHERE b = 'B'")).to eq('DELETE FROM table')
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ module InfluxReporter
6
+ RSpec.describe Subscriber do
7
+ let(:config) { Configuration.new }
8
+ let(:client) { Client.new config }
9
+
10
+ subject do
11
+ Subscriber.new config, client
12
+ end
13
+
14
+ describe '#register!' do
15
+ it 'subscribes to ActiveSupport::Notifications' do
16
+ expect(ActiveSupport::Notifications).to receive(:subscribe)
17
+ subject.register!
18
+ end
19
+ it 'unregisters first if already registered' do
20
+ subject.register!
21
+ expect(subject).to receive(:unregister!)
22
+ expect(ActiveSupport::Notifications).to receive(:subscribe)
23
+ subject.register!
24
+ end
25
+ end
26
+
27
+ describe '#unregister' do
28
+ it 'unsubscribes to AS::Notifications' do
29
+ expect(ActiveSupport::Notifications).to receive(:unsubscribe)
30
+ subject.register!
31
+ subject.unregister!
32
+ end
33
+ end
34
+
35
+ describe 'ActiveSupport::Notifications API', start_without_worker: true do
36
+ let(:message_args) do
37
+ [
38
+ 'process_action.action_controller',
39
+ nil,
40
+ { controller: 'Controller', action: 'index' }
41
+ ]
42
+ end
43
+ describe '#start' do
44
+ it 'adds a new notification to current transaction' do
45
+ transaction = InfluxReporter.transaction 'Test'
46
+
47
+ expect do
48
+ subject.start(*message_args)
49
+ end.to change(transaction.notifications, :length).by 1
50
+
51
+ transaction.release
52
+ end
53
+ end
54
+
55
+ describe '#finish' do
56
+ it 'adds a trace to current transaction' do
57
+ transaction = InfluxReporter.transaction 'Test'
58
+
59
+ expect do
60
+ subject.start(*message_args)
61
+ subject.finish(*message_args)
62
+ end.to change(transaction.traces, :length).by 1
63
+
64
+ transaction.release
65
+ end
66
+ it 'adds a stack of parents', mock_time: true do
67
+ transaction = InfluxReporter.transaction 'Rack' do
68
+ subject.start(*message_args)
69
+ travel 100
70
+ InfluxReporter.trace('thing-1') do
71
+ travel 100
72
+ end
73
+ travel 100
74
+ subject.finish(*message_args)
75
+ end.done(200)
76
+
77
+ expect(transaction.traces.length).to eq 3
78
+ expect(transaction.traces.last.parents.map(&:signature)).to eq ['transaction', 'Controller#index']
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ module InfluxReporter
6
+ describe Trace, mock_time: true do
7
+ describe '#initialize' do
8
+ it 'has a timestamp' do
9
+ trace = Trace.new nil, 'test'
10
+ expect(trace.timestamp).to eq (Time.now.utc.to_i * 1_000_000_000 + Time.now.utc.nsec)
11
+ end
12
+ end
13
+
14
+ describe '#start' do
15
+ it 'has a relative and absolute start time with a transaction' do
16
+ transaction = Transaction.new(nil, 'Test')
17
+ travel 400
18
+ trace = transaction.trace 'test-1' do
19
+ travel 100
20
+ transaction.trace 'test-2' do |t|
21
+ travel 100
22
+ t
23
+ end
24
+ end
25
+
26
+ expect(trace.signature).to eq 'test-2'
27
+ expect(trace.relative_start).to eq 100_000_000
28
+ end
29
+ end
30
+
31
+ describe '#done' do
32
+ it 'sets duration' do
33
+ transaction = Transaction.new nil, 'Test'
34
+ trace = Trace.new(transaction, 'test').start transaction.start_time
35
+ travel 100
36
+ trace.done
37
+
38
+ expect(trace.duration).to eq 100_000_000
39
+ expect(trace).to be_done
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'influx_reporter'
5
+
6
+ module InfluxReporter
7
+ describe Transaction, mock_time: true do
8
+ describe '#initialize' do
9
+ it 'has a root trace, timestamp and start time' do
10
+ transaction = Transaction.new nil, 'Test'
11
+ expect(transaction.traces.length).to be 1
12
+ expect(transaction.timestamp).to eq 694_224_000_000_000_000
13
+ expect(transaction.start_time).to eq 694_224_000_000_000_000
14
+ end
15
+ end
16
+
17
+ describe '#release' do
18
+ it 'sets clients current transaction to nil' do
19
+ client = Struct.new(:current_transaction).new(1)
20
+ transaction = Transaction.new client, 'Test'
21
+ transaction.release
22
+ expect(client.current_transaction).to be_nil
23
+ end
24
+ end
25
+
26
+ describe '#done' do
27
+ it 'it sets result, durations and ends root trace' do
28
+ transaction = Transaction.new nil, 'Test'
29
+
30
+ travel 100
31
+ transaction.done(200)
32
+
33
+ expect(transaction.result).to be 200
34
+ expect(transaction.traces.first).to be_done
35
+ expect(transaction.duration).to eq 100_000_000
36
+ end
37
+ end
38
+
39
+ describe '#submit' do
40
+ it 'ends transaction and submits it to the client' do
41
+ client = double('client', submit_transaction: true, :current_transaction= => true)
42
+ transaction = Transaction.new client, 'Test'
43
+
44
+ travel 100
45
+ transaction.submit 200
46
+
47
+ expect(transaction.result).to be 200
48
+ expect(transaction).to be_done
49
+ expect(client).to have_received(:current_transaction=)
50
+ expect(client).to have_received(:submit_transaction).with transaction
51
+ end
52
+ end
53
+
54
+ describe '#running_traces' do
55
+ it 'returns running traces' do
56
+ transaction = Transaction.new nil, 'Test'
57
+
58
+ transaction.trace 'test' do
59
+ travel 100
60
+ end
61
+
62
+ running_trace = transaction.trace 'test2'
63
+ travel 100
64
+
65
+ expect(transaction.running_traces).to eq [transaction.root_trace, running_trace]
66
+ end
67
+ end
68
+
69
+ describe '#trace' do
70
+ subject do
71
+ transaction = Transaction.new nil, 'Test'
72
+
73
+ travel 100
74
+
75
+ transaction.trace 'test' do
76
+ travel 100
77
+ end
78
+
79
+ transaction.done
80
+ end
81
+ it 'creates a new trace' do
82
+ expect(subject.traces.length).to be 2
83
+ end
84
+ it 'has root as a parent' do
85
+ expect(subject.traces.last.parents).to eq [subject.traces.first]
86
+ end
87
+ it 'has a duration' do
88
+ expect(subject.traces.last.duration).to eq 100_000_000
89
+ end
90
+ it 'has a relative start' do
91
+ expect(subject.traces.last.relative_start).to eq 100_000_000
92
+ end
93
+ it 'has a total duration' do
94
+ expect(subject.duration).to eq 200_000_000
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ module InfluxReporter
6
+ RSpec.describe Util::Inspector, start_without_worker: true, mock_time: true do
7
+ let(:transaction) do
8
+ InfluxReporter.transaction 'Test' do |transaction|
9
+ travel 10
10
+ InfluxReporter.trace('test 1', 'trace.test') do
11
+ travel 100
12
+ InfluxReporter.trace('test 2', 'trace.test') { travel 150 }
13
+ travel 50
14
+ end
15
+ travel 50
16
+ InfluxReporter.trace('test 3', 'trace.test') do
17
+ travel 100
18
+ end
19
+ travel 1
20
+
21
+ transaction
22
+ end
23
+ end
24
+ subject do
25
+ Util::Inspector.new.transaction(transaction, include_parents: true)
26
+ end
27
+
28
+ it "doesn't explode" do
29
+ expect { subject }.to_not raise_error
30
+ end
31
+
32
+ it "doesn't exceed it's length" do
33
+ expect(subject.split("\n").map(&:length).find { |l| l < 100 })
34
+ end
35
+
36
+ # preview
37
+ it 'is beautiful' do
38
+ puts subject
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ module InfluxReporter
6
+ RSpec.describe Util do
7
+ describe '#nearest_minute', mock_time: true do
8
+ it 'normalizes to nearest minute' do
9
+ travel 125_000 # two minutes five secs
10
+ expect(Util.nearest_minute).to eq Time.utc(1992, 1, 1, 0, 2, 0)
11
+ end
12
+ end
13
+
14
+ describe '#ms', mock_time: true do
15
+ it 'returns current ms since unix epoch' do
16
+ expect(Util.nanos).to eq 694_224_000_000_000_000
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ module InfluxReporter
6
+ RSpec.describe Worker do
7
+ before do
8
+ @queue = Queue.new
9
+ end
10
+
11
+ let :worker do
12
+ config = build_config
13
+ Worker.new config, @queue, InfluxDBClient.new(config)
14
+ end
15
+
16
+ describe '#run' do
17
+ context 'during a loop' do
18
+ before { allow(worker).to receive(:loop).and_yield }
19
+
20
+ subject { Thread.new { worker.run }.join 0.05 }
21
+
22
+ it 'does nothing with an empty queue' do
23
+ subject
24
+ expect(WebMock).to_not have_requested(:any, /.*/)
25
+ end
26
+
27
+ it 'pops the queue' do
28
+ @queue << Worker::PostRequest.new('/errors/', { series: 'test', values: { id: 1 }, timestamp: 0})
29
+ @queue << Worker::PostRequest.new('/errors/', { series: 'test', values: { id: 1 }, timestamp: 1})
30
+
31
+ subject
32
+
33
+ expect(WebMock).to have_requested(:post, %r{/write}).with(body: 'test id=1i 0')
34
+ expect(WebMock).to have_requested(:post, %r{/write}).with(body: 'test id=1i 1')
35
+ end
36
+ end
37
+
38
+ context 'can be stopped by sending a message' do
39
+ it 'loops until stopped' do
40
+ thread = Thread.new do
41
+ worker.run
42
+ end
43
+
44
+ @queue << Worker::StopMessage.new
45
+
46
+ thread.join
47
+
48
+ expect(thread).to_not be_alive
49
+ expect(@queue).to be_empty
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe InfluxReporter do
6
+ it { should_not be_started }
7
+
8
+ describe 'self.start!' do
9
+ it 'delegates to client' do
10
+ conf = InfluxReporter::Configuration.new database: 'test'
11
+ expect(InfluxReporter::Client).to receive(:start!).with(conf) { true }
12
+ InfluxReporter.start! conf
13
+ end
14
+ end
15
+
16
+ it { should delegate :stop!, to: InfluxReporter }
17
+
18
+ describe 'when InfluxReporter is started', start: true do
19
+ it { should be_started }
20
+
21
+ it { should delegate :transaction, to: InfluxReporter::Client.inst, args: ['Test', nil, nil] }
22
+ it { should delegate :trace, to: InfluxReporter::Client.inst, args: ['test', nil, {}] }
23
+ it { should delegate :report, to: InfluxReporter::Client.inst, args: [Exception.new, nil] }
24
+ it { should delegate :set_context, to: InfluxReporter::Client.inst, args: [{}] }
25
+ it { should delegate :with_context, to: InfluxReporter::Client.inst, args: [{}] }
26
+ it { should delegate :report_message, to: InfluxReporter::Client.inst, args: ['My message', nil] }
27
+ it { should delegate :capture, to: InfluxReporter::Client.inst }
28
+
29
+ describe 'a block example', mock_time: true do
30
+ it 'is done' do
31
+ transaction = InfluxReporter.transaction 'Test' do
32
+ travel 100
33
+ InfluxReporter.trace 'test1' do
34
+ travel 100
35
+ InfluxReporter.trace 'test1-1' do
36
+ travel 100
37
+ end
38
+ InfluxReporter.trace 'test1-2' do
39
+ travel 100
40
+ end
41
+ travel 100
42
+ end
43
+ end.done(true)
44
+
45
+ expect(transaction).to be_done
46
+ expect(transaction.duration).to eq 500_000_000
47
+ end
48
+ end
49
+ end
50
+ end