prometheus-client-tracer 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 11dbb55ad9c5ce0135dd4376dff72e95b1f6e5ae378e1e4c6de2ce23a4ddc915
4
- data.tar.gz: 762b4e6b78aaa60c82c97470a9cf1df136b0e3fe685396df117beee3671c7012
3
+ metadata.gz: 79f6efb3f1967459a218c40e8cd89854231995138ed238d3d323e901d7a52922
4
+ data.tar.gz: 3253ed69867af1140f9390944692d32ccecb22766342d81409be0185a10f2f19
5
5
  SHA512:
6
- metadata.gz: 6291fbf2dcb56141208005a94df27e22531cd3e7c012551a809ab3287602702d91d8a499a3cea580b3b2b8ef07c677898abdb7c5f0a06296b923652a94e60b66
7
- data.tar.gz: ec047172d19516f20a24996adf32ceabb651e03627923e30b2e1ef90e096107f0f123e263cb2ff6325a5cbabfc86a4044a681046c54ebcfcd440c726a76817ea
6
+ metadata.gz: ec656afeb632da0716cbba505b9fb0074fb068ce041ae08fcbf9c5392351e2ba766e63e9690a7a53b163fa8688c8dc614dee73deb48f3921755c2330c254b04f
7
+ data.tar.gz: acaa90edcd32797f96ce46f0550ec785eddf9516792f2e4f40471eb949e39cfcfa8356723e69ec9c4da297e8f95e5969964524220c790cbcdd43f431b2cb5a66
@@ -0,0 +1 @@
1
+ /prometheus-client-tracer-*.gem
@@ -5,6 +5,9 @@ inherit_gem:
5
5
  AllCops:
6
6
  TargetRubyVersion: 2.4
7
7
 
8
+ Style/ParallelAssignment:
9
+ Enabled: false
10
+
8
11
  Metrics/MethodLength:
9
12
  Max: 15
10
13
 
@@ -2,7 +2,7 @@ PATH
2
2
  remote: .
3
3
  specs:
4
4
  prometheus-client-tracer (1.0.0)
5
- prometheus-client (~> 0.10.0.alpha)
5
+ prometheus-client (~> 1.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
@@ -18,7 +18,7 @@ GEM
18
18
  parallel (1.17.0)
19
19
  parser (2.6.3.0)
20
20
  ast (~> 2.4.0)
21
- prometheus-client (0.10.0.pre.alpha.2)
21
+ prometheus-client (1.0.0)
22
22
  pry (0.12.2)
23
23
  coderay (~> 1.1.0)
24
24
  method_source (~> 0.9.0)
@@ -45,6 +45,7 @@ GEM
45
45
  unicode-display_width (>= 1.4.0, < 1.7)
46
46
  rubocop-rspec (1.33.0)
47
47
  rubocop (>= 0.60.0)
48
+ ruby-prof (0.18.0)
48
49
  ruby-progressbar (1.10.1)
49
50
  unicode-display_width (1.6.0)
50
51
 
@@ -56,6 +57,7 @@ DEPENDENCIES
56
57
  prometheus-client-tracer!
57
58
  pry (~> 0.10)
58
59
  rspec (~> 3.8)
60
+ ruby-prof (~> 0.18)
59
61
 
60
62
  BUNDLED WITH
61
63
  2.0.1
data/README.md CHANGED
@@ -1,13 +1,16 @@
1
1
  # prometheus-client-tracer-ruby [![CircleCI](https://circleci.com/gh/lawrencejones/prometheus-client-tracer-ruby.svg?style=svg)](https://circleci.com/gh/lawrencejones/prometheus-client-tracer-ruby)
2
2
 
3
+ https://blog.lawrencejones.dev/incremental-measurement/
4
+
3
5
  This gem provides an interface for tracing long-running duration measurements
4
6
  using the Prometheus client. By updating the associated metric as part of the
5
7
  Prometheus /metrics endpoint, the increment is spread evenly over the scrapes
6
- that occur while the operation is in process, instead of applying one massive
8
+ that occur while the operation is in process, instead of applying one large
7
9
  increment at the end.
8
10
 
9
- This means you can trust your metrics will be accurate, even if the operations
10
- you're measuring far exceed your scrape duration.
11
+ If you find this useful and would prefer it to live within the official
12
+ Prometheus Ruby client, please drop your feedback as a comment here:
13
+ https://github.com/prometheus/client_ruby/pull/135
11
14
 
12
15
  ## Why?
13
16
 
@@ -30,8 +33,21 @@ value only after the task has finished. Graphs visualising how time is spent
30
33
  will show no activity while the task was running and then an impossible burst
31
34
  just as things finish.
32
35
 
33
- To avoid this time of measurement bias, this commit introduces a metric tracer
34
- that manages updating metrics associated with long-running tasks. Users will
36
+ When jobs run quickly, your graphs will look reasonable. An example with ten
37
+ workers constantly working small jobs, each worker reports one second of work
38
+ per second, as the world should be.
39
+
40
+ ![Work per worker with small jobs](res/bias-0_1-1_0.png)
41
+
42
+ As soon as job duration increases, the bias becomes significant, and the graph
43
+ starts departing from reality:
44
+
45
+ ![Work per worker with long-running jobs](res/bias-0_1-30_0.png)
46
+
47
+ ## How?
48
+
49
+ To avoid this time of measurement bias, this gem provides a metric tracer
50
+ that manages updating metrics associated with long-running tasks. Users will
35
51
  begin a trace, do work, and while the work is on-going any calls to the tracer
36
52
  collect method will incrementally update the associated metric with elapsed
37
53
  time.
@@ -42,9 +58,9 @@ tracer is thread safe and designed to be as lightweight as possible- it should
42
58
  hopefully provide no performance hit and be preferable for tracing durations of
43
59
  most lengths, provided you don't exceed hundreds of on-going traces.
44
60
 
45
- For easy use, the Prometheus client initialises a global tracer in the same vein
46
- as the global registry. Most users are going to want to use a tracer without
47
- initialising a handle in their own code, and can do so like this:
61
+ For easy use, we patch the Prometheus client with a global tracer, following the
62
+ example of the global registry. Most users will want to use tracers without
63
+ initialising one in their own code, and can do so like this:
48
64
 
49
65
  ```ruby
50
66
  def run
@@ -54,9 +70,10 @@ def run
54
70
  end
55
71
  ```
56
72
 
57
- By default, users who do this will see their metrics update just as frequently
58
- as the original implementation. For the incremental measurement to work, they
59
- must use a TraceCollector to trigger a collection just prior to serving metrics:
73
+ Without any additional configuration, users who do this will see their metrics
74
+ update just as frequently as the naive implementation. For the incremental
75
+ measurement to work, they must use a `TraceCollector` to trigger a collection
76
+ just prior to serving metrics:
60
77
 
61
78
  ```ruby
62
79
  # By default, collect the global tracer
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file can be used to validate the performance of the tracer is not incomparable to a
4
+ # naive tracing implementation. The performance will degrade linearly with the number of
5
+ # on-going traces, however a modern i7 can achieve trace throughput:
6
+ #
7
+ # naive: 333k/s
8
+ # trace, 0 on-going: 233k/s
9
+ # trace, 5 on-going: 216k/s
10
+ # trace, 25 on-going: 155k/s
11
+ # trace, 100 on-going: 84k/s
12
+ #
13
+ # While this seems more than reasonable performance for almost any use case, consider
14
+ # using multiple tracers if this does become a problem.
15
+
16
+ require "benchmark"
17
+
18
+ require "prometheus/client"
19
+ require "prometheus/client/tracer"
20
+
21
+ counter = Prometheus::Client::Counter.new(
22
+ :counter, docstring: "example", labels: %i[worker]
23
+ )
24
+ another_counter = Prometheus::Client::Counter.new(
25
+ :counter_another, docstring: "another example", labels: %i[]
26
+ )
27
+
28
+ def trace(metric, labels = {})
29
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
30
+ yield
31
+ ensure
32
+ metric.increment(
33
+ by: Process.clock_gettime(Process::CLOCK_MONOTONIC) - start,
34
+ labels: labels,
35
+ )
36
+ end
37
+
38
+ n_string, n_concurrent_traces_string, = ARGV
39
+ n, n_concurrent_traces = [n_string.to_i, n_concurrent_traces_string.to_i]
40
+
41
+ n_concurrent_traces.times do
42
+ Prometheus::Client.tracer.send(:start, another_counter, {})
43
+ end
44
+
45
+ Benchmark.bm(7) do |x|
46
+ x.report("naive:") { n.times { trace(counter, worker: 1) { nil } } }
47
+ x.report("trace:") do
48
+ n.times { Prometheus::Client.tracer.trace(counter, worker: 1) { nil } }
49
+ end
50
+ end
@@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "prometheus-client-tracer"
8
- spec.version = "1.0.0"
8
+ spec.version = "1.1.0"
9
9
  spec.summary = "Tracer for accurate duration tracking with Prometheus metrics"
10
10
  spec.authors = %w[me@lawrencejones.dev]
11
11
  spec.homepage = "https://github.com/lawrencejones/prometheus-client-tracer"
@@ -18,9 +18,10 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^spec/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency "prometheus-client", "~> 0.10.0.alpha"
21
+ spec.add_dependency "prometheus-client", "~> 1.0"
22
22
 
23
23
  spec.add_development_dependency "gc_ruboconfig", "= 2.4.0"
24
24
  spec.add_development_dependency "pry", "~> 0.10"
25
25
  spec.add_development_dependency "rspec", "~> 3.8"
26
+ spec.add_development_dependency "ruby-prof", "~> 0.18"
26
27
  end
Binary file
Binary file
@@ -21,7 +21,7 @@ describe Prometheus::Client::Tracer do
21
21
  # The tracer is normally passed a block that manipulates @now.
22
22
  subject(:trace) { tracer.trace(metric, labels, &trace_block) }
23
23
 
24
- let(:labels) { { worker: 1 } }
24
+ let(:labels) { { worker: "1" } }
25
25
  let(:trace_block) { -> { @now += 1.0 } }
26
26
 
27
27
  before do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prometheus-client-tracer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - me@lawrencejones.dev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-06 00:00:00.000000000 Z
11
+ date: 2020-01-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: prometheus-client
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.10.0.alpha
19
+ version: '1.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.10.0.alpha
26
+ version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: gc_ruboconfig
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '3.8'
69
+ - !ruby/object:Gem::Dependency
70
+ name: ruby-prof
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.18'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.18'
69
83
  description:
70
84
  email:
71
85
  - me@lawrencejones.dev
@@ -74,15 +88,19 @@ extensions: []
74
88
  extra_rdoc_files: []
75
89
  files:
76
90
  - ".circleci/config.yml"
91
+ - ".gitignore"
77
92
  - ".rspec"
78
93
  - ".rubocop.yml"
79
94
  - ".ruby-version"
80
95
  - Gemfile
81
96
  - Gemfile.lock
82
97
  - README.md
98
+ - exe/benchmark_tracer.rb
83
99
  - lib/prometheus/client/tracer.rb
84
100
  - lib/prometheus/middleware/trace_collector.rb
85
101
  - prometheus-client-tracer.gemspec
102
+ - res/bias-0_1-1_0.png
103
+ - res/bias-0_1-30_0.png
86
104
  - spec/prometheus/client/tracer_spec.rb
87
105
  - spec/prometheus/middleware/trace_collector_spec.rb
88
106
  - spec/spec_helper.rb