prometheus-client-tracer 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.circleci/config.yml +42 -0
- data/.rspec +1 -0
- data/.rubocop.yml +25 -0
- data/.ruby-version +1 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +61 -0
- data/README.md +64 -0
- data/lib/prometheus/client/tracer.rb +79 -0
- data/lib/prometheus/middleware/trace_collector.rb +22 -0
- data/prometheus-client-tracer.gemspec +26 -0
- data/spec/prometheus/client/tracer_spec.rb +82 -0
- data/spec/prometheus/middleware/trace_collector_spec.rb +22 -0
- data/spec/spec_helper.rb +5 -0
- metadata +115 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 11dbb55ad9c5ce0135dd4376dff72e95b1f6e5ae378e1e4c6de2ce23a4ddc915
|
4
|
+
data.tar.gz: 762b4e6b78aaa60c82c97470a9cf1df136b0e3fe685396df117beee3671c7012
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6291fbf2dcb56141208005a94df27e22531cd3e7c012551a809ab3287602702d91d8a499a3cea580b3b2b8ef07c677898abdb7c5f0a06296b923652a94e60b66
|
7
|
+
data.tar.gz: ec047172d19516f20a24996adf32ceabb651e03627923e30b2e1ef90e096107f0f123e263cb2ff6325a5cbabfc86a4044a681046c54ebcfcd440c726a76817ea
|
@@ -0,0 +1,42 @@
|
|
1
|
+
---
|
2
|
+
version: 2
|
3
|
+
|
4
|
+
references:
|
5
|
+
steps: &steps
|
6
|
+
- checkout
|
7
|
+
|
8
|
+
- type: cache-restore
|
9
|
+
key: prometheus-client-tracer-bundler-{{ checksum "prometheus-client-tracer.gemspec" }}
|
10
|
+
|
11
|
+
- run: gem install bundler -v 2.0.1
|
12
|
+
- run: bundle install --path vendor/bundle
|
13
|
+
|
14
|
+
- type: cache-save
|
15
|
+
key: prometheus-client-tracer-bundler-{{ checksum "prometheus-client-tracer.gemspec" }}
|
16
|
+
paths:
|
17
|
+
- vendor/bundle
|
18
|
+
|
19
|
+
- run: bundle exec rubocop
|
20
|
+
- run: bundle exec rspec
|
21
|
+
|
22
|
+
jobs:
|
23
|
+
build-ruby24:
|
24
|
+
docker:
|
25
|
+
- image: ruby:2.4
|
26
|
+
steps: *steps
|
27
|
+
build-ruby25:
|
28
|
+
docker:
|
29
|
+
- image: ruby:2.5
|
30
|
+
steps: *steps
|
31
|
+
build-ruby26:
|
32
|
+
docker:
|
33
|
+
- image: ruby:2.6
|
34
|
+
steps: *steps
|
35
|
+
|
36
|
+
workflows:
|
37
|
+
version: 2
|
38
|
+
tests:
|
39
|
+
jobs:
|
40
|
+
- build-ruby24
|
41
|
+
- build-ruby25
|
42
|
+
- build-ruby26
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require ./spec/spec_helper.rb --color
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
---
|
2
|
+
inherit_gem:
|
3
|
+
gc_ruboconfig: rubocop.yml
|
4
|
+
|
5
|
+
AllCops:
|
6
|
+
TargetRubyVersion: 2.4
|
7
|
+
|
8
|
+
Metrics/MethodLength:
|
9
|
+
Max: 15
|
10
|
+
|
11
|
+
RSpec/MultipleExpectations:
|
12
|
+
Max: 3
|
13
|
+
|
14
|
+
Style/RescueStandardError:
|
15
|
+
Exclude:
|
16
|
+
- "*/**/*_spec.rb"
|
17
|
+
|
18
|
+
Naming/UncommunicativeMethodParamName:
|
19
|
+
AllowedNames:
|
20
|
+
# These are the default allowed names, set by Rubocop
|
21
|
+
- io
|
22
|
+
- id
|
23
|
+
# These are some custom names that we want to allow, since they aren't
|
24
|
+
# uncommunicative - they're actually rather meaningful!
|
25
|
+
- as
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.6.2
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
prometheus-client-tracer (1.0.0)
|
5
|
+
prometheus-client (~> 0.10.0.alpha)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
ast (2.4.0)
|
11
|
+
coderay (1.1.2)
|
12
|
+
diff-lcs (1.3)
|
13
|
+
gc_ruboconfig (2.4.0)
|
14
|
+
rubocop (>= 0.70)
|
15
|
+
rubocop-rspec (>= 1.33.0)
|
16
|
+
jaro_winkler (1.5.3)
|
17
|
+
method_source (0.9.2)
|
18
|
+
parallel (1.17.0)
|
19
|
+
parser (2.6.3.0)
|
20
|
+
ast (~> 2.4.0)
|
21
|
+
prometheus-client (0.10.0.pre.alpha.2)
|
22
|
+
pry (0.12.2)
|
23
|
+
coderay (~> 1.1.0)
|
24
|
+
method_source (~> 0.9.0)
|
25
|
+
rainbow (3.0.0)
|
26
|
+
rspec (3.8.0)
|
27
|
+
rspec-core (~> 3.8.0)
|
28
|
+
rspec-expectations (~> 3.8.0)
|
29
|
+
rspec-mocks (~> 3.8.0)
|
30
|
+
rspec-core (3.8.2)
|
31
|
+
rspec-support (~> 3.8.0)
|
32
|
+
rspec-expectations (3.8.4)
|
33
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
34
|
+
rspec-support (~> 3.8.0)
|
35
|
+
rspec-mocks (3.8.1)
|
36
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
37
|
+
rspec-support (~> 3.8.0)
|
38
|
+
rspec-support (3.8.2)
|
39
|
+
rubocop (0.72.0)
|
40
|
+
jaro_winkler (~> 1.5.1)
|
41
|
+
parallel (~> 1.10)
|
42
|
+
parser (>= 2.6)
|
43
|
+
rainbow (>= 2.2.2, < 4.0)
|
44
|
+
ruby-progressbar (~> 1.7)
|
45
|
+
unicode-display_width (>= 1.4.0, < 1.7)
|
46
|
+
rubocop-rspec (1.33.0)
|
47
|
+
rubocop (>= 0.60.0)
|
48
|
+
ruby-progressbar (1.10.1)
|
49
|
+
unicode-display_width (1.6.0)
|
50
|
+
|
51
|
+
PLATFORMS
|
52
|
+
ruby
|
53
|
+
|
54
|
+
DEPENDENCIES
|
55
|
+
gc_ruboconfig (= 2.4.0)
|
56
|
+
prometheus-client-tracer!
|
57
|
+
pry (~> 0.10)
|
58
|
+
rspec (~> 3.8)
|
59
|
+
|
60
|
+
BUNDLED WITH
|
61
|
+
2.0.1
|
data/README.md
ADDED
@@ -0,0 +1,64 @@
|
|
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
|
+
|
3
|
+
This gem provides an interface for tracing long-running duration measurements
|
4
|
+
using the Prometheus client. By updating the associated metric as part of the
|
5
|
+
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
|
7
|
+
increment at the end.
|
8
|
+
|
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
|
+
|
12
|
+
## Why?
|
13
|
+
|
14
|
+
One of the most common observability requirements is to trace the amount of time
|
15
|
+
spent running a job or task. This information is useful in the context of when
|
16
|
+
this time was spent. The typical implementation of such a measurement might be:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
def run
|
20
|
+
start = Time.now
|
21
|
+
long_running_task
|
22
|
+
metric.increment(by: start - Time.now)
|
23
|
+
end
|
24
|
+
```
|
25
|
+
|
26
|
+
The metric tracking duration is incremented only once the task has finished. If
|
27
|
+
the task took > Prometheus scrape interval, perhaps by a significant factor (say
|
28
|
+
1hr vs the normal 15s scrape interval), then the metric is incremented by a huge
|
29
|
+
value only after the task has finished. Graphs visualising how time is spent
|
30
|
+
will show no activity while the task was running and then an impossible burst
|
31
|
+
just as things finish.
|
32
|
+
|
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
|
35
|
+
begin a trace, do work, and while the work is on-going any calls to the tracer
|
36
|
+
collect method will incrementally update the associated metric with elapsed
|
37
|
+
time.
|
38
|
+
|
39
|
+
This is a game-changer in terms of making metrics usable, removing a huge source
|
40
|
+
of uncertainty when interpreting metric measurements. The implementation of the
|
41
|
+
tracer is thread safe and designed to be as lightweight as possible- it should
|
42
|
+
hopefully provide no performance hit and be preferable for tracing durations of
|
43
|
+
most lengths, provided you don't exceed hundreds of on-going traces.
|
44
|
+
|
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:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
def run
|
51
|
+
Prometheus::Client.trace(metric, { worker: 1 }) do
|
52
|
+
long_running_task
|
53
|
+
end
|
54
|
+
end
|
55
|
+
```
|
56
|
+
|
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:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
# By default, collect the global tracer
|
63
|
+
use Prometheus::Middleware::TraceCollector
|
64
|
+
```
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Prometheus
|
4
|
+
module Client
|
5
|
+
# Most people will want to use a global tracer instead of building their own, similar
|
6
|
+
# to how most will use the global metrics registry.
|
7
|
+
def self.tracer
|
8
|
+
@tracer ||= Tracer.new
|
9
|
+
end
|
10
|
+
|
11
|
+
# Delegate to the Tracer.
|
12
|
+
def self.trace(metric, labels = {}, &block)
|
13
|
+
tracer.trace(metric, labels, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
# For metrics that track durations over the course of long-running tasks, we need to
|
17
|
+
# ensure the metric is updated gradually while they execute instead of right at the
|
18
|
+
# end. This class is used to track on-going 'traces', records of tasks starting and
|
19
|
+
# stopping, and exposes a method `collect` that will update the associated metric with
|
20
|
+
# the time elapsed since the last `collect`.
|
21
|
+
class Tracer
|
22
|
+
Trace = Struct.new(:metric, :labels, :time)
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
@lock = Mutex.new
|
26
|
+
@traces = []
|
27
|
+
end
|
28
|
+
|
29
|
+
# Start and manage the life of a trace. Pass a long-running block to this method to
|
30
|
+
# ensure the associated metric is updated gradually throughout the execution.
|
31
|
+
def trace(metric, labels = {})
|
32
|
+
start(metric, labels)
|
33
|
+
yield
|
34
|
+
ensure
|
35
|
+
stop(metric, labels)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Update currently traced metrics- this will increment all on-going traces with the
|
39
|
+
# delta of time between the last update and now. This should be called just before
|
40
|
+
# serving a /metrics request.
|
41
|
+
def collect(traces = @traces)
|
42
|
+
@lock.synchronize do
|
43
|
+
now = monotonic_now
|
44
|
+
traces.each do |trace|
|
45
|
+
time_since = [now - trace.time, 0].max
|
46
|
+
trace.time = now
|
47
|
+
trace.metric.increment(
|
48
|
+
by: time_since,
|
49
|
+
labels: trace.labels,
|
50
|
+
)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def start(metric, labels = {})
|
58
|
+
@lock.synchronize { @traces << Trace.new(metric, labels, monotonic_now) }
|
59
|
+
end
|
60
|
+
|
61
|
+
def stop(metric, labels = {})
|
62
|
+
matching = nil
|
63
|
+
@lock.synchronize do
|
64
|
+
matching, @traces = @traces.partition do |trace|
|
65
|
+
trace.metric == metric && trace.labels == labels
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
collect(matching)
|
70
|
+
end
|
71
|
+
|
72
|
+
# We're doing duration arithmetic which should make use of monotonic clocks, to
|
73
|
+
# avoid changes to the system time from affecting our metrics.
|
74
|
+
def monotonic_now
|
75
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "prometheus/client"
|
4
|
+
|
5
|
+
module Prometheus
|
6
|
+
module Middleware
|
7
|
+
# This class integrates with a Prometheus::Client::Tracer to update associated metric
|
8
|
+
# traces just prior to serving metrics. By default, this will collect traces on the
|
9
|
+
# global Client tracer.
|
10
|
+
class TraceCollector
|
11
|
+
def initialize(app, options = {})
|
12
|
+
@app = app
|
13
|
+
@tracer = options[:tracer] || Client.tracer
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
@tracer.collect
|
18
|
+
@app.call(env)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path("lib", __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "prometheus-client-tracer"
|
8
|
+
spec.version = "1.0.0"
|
9
|
+
spec.summary = "Tracer for accurate duration tracking with Prometheus metrics"
|
10
|
+
spec.authors = %w[me@lawrencejones.dev]
|
11
|
+
spec.homepage = "https://github.com/lawrencejones/prometheus-client-tracer"
|
12
|
+
spec.email = %w[me@lawrencejones.dev]
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.required_ruby_version = ">= 2.4"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0")
|
18
|
+
spec.test_files = spec.files.grep(%r{^spec/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "prometheus-client", "~> 0.10.0.alpha"
|
22
|
+
|
23
|
+
spec.add_development_dependency "gc_ruboconfig", "= 2.4.0"
|
24
|
+
spec.add_development_dependency "pry", "~> 0.10"
|
25
|
+
spec.add_development_dependency "rspec", "~> 3.8"
|
26
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "timeout"
|
4
|
+
|
5
|
+
# rubocop:disable RSpec/InstanceVariable
|
6
|
+
describe Prometheus::Client::Tracer do
|
7
|
+
subject(:tracer) { described_class.new }
|
8
|
+
|
9
|
+
let(:metric) do
|
10
|
+
Prometheus::Client::Counter.new(:counter, docstring: "example", labels: %i[worker])
|
11
|
+
end
|
12
|
+
|
13
|
+
describe ".trace" do
|
14
|
+
# These tests try stubbing timing logic. Instead of using let's, we use a test
|
15
|
+
# instance variable @now to represent the current time, as returned by a monotonic
|
16
|
+
# clock system call.
|
17
|
+
#
|
18
|
+
# The #monotonic_now method of the tracer is stubbed to always return the current
|
19
|
+
# value of @now, and tests can manipulate time by advancing that instance variable.
|
20
|
+
#
|
21
|
+
# The tracer is normally passed a block that manipulates @now.
|
22
|
+
subject(:trace) { tracer.trace(metric, labels, &trace_block) }
|
23
|
+
|
24
|
+
let(:labels) { { worker: 1 } }
|
25
|
+
let(:trace_block) { -> { @now += 1.0 } }
|
26
|
+
|
27
|
+
before do
|
28
|
+
@now = 0.0 # set initial time
|
29
|
+
allow(tracer).to receive(:monotonic_now) { @now }
|
30
|
+
end
|
31
|
+
|
32
|
+
it "increments metric with elapsed duration" do
|
33
|
+
expect { trace }.to change { metric.values[labels] }.by(1.0)
|
34
|
+
end
|
35
|
+
|
36
|
+
context "when .collect is called during a trace" do
|
37
|
+
let(:latch) { Mutex.new }
|
38
|
+
let(:trace_block) do
|
39
|
+
-> { latch.synchronize { @now += 1.0 } }
|
40
|
+
end
|
41
|
+
|
42
|
+
# rubocop:disable RSpec/ExampleLength
|
43
|
+
it "increments metric with incremental duration" do
|
44
|
+
latch.lock # acquire the lock, trace should now block
|
45
|
+
trace_thread = Thread.new do
|
46
|
+
trace # will block until latch is released
|
47
|
+
end
|
48
|
+
|
49
|
+
# We need to block until the trace_thread has actually begun, otherwise we'll
|
50
|
+
# never be able to guarantee the trace was started at now = 0.0, even if this
|
51
|
+
# should happen almost immediately.
|
52
|
+
Timeout.timeout(1) { sleep(0.01) until tracer.collect.any? }
|
53
|
+
|
54
|
+
# Advance the clock by 0.5s
|
55
|
+
@now += 0.5
|
56
|
+
|
57
|
+
# If we now collect, the metric should be incremented by the elapsed time (0.5s)
|
58
|
+
expect { tracer.collect }.to change { metric.values[labels] }.by(0.5)
|
59
|
+
|
60
|
+
# Collect once more should leave the metric unchanged, as no time has passed since
|
61
|
+
# the last collect
|
62
|
+
expect { tracer.collect }.to change { metric.values[labels] }.by(0.0)
|
63
|
+
|
64
|
+
# Unlocking the latch and allowing the trace thread to complete will execute the
|
65
|
+
# final part of a trace, which should update the metric with time elapsed. The
|
66
|
+
# trace thread advances time by 1s right before it ends, so we expect to update
|
67
|
+
# the metric by 1s.
|
68
|
+
#
|
69
|
+
# A bug would be if we incremented the metric by the time since our trace started
|
70
|
+
# and when it ended, which in total is 1.5s. This would suggest we never reset the
|
71
|
+
# trace clock when calling collect.
|
72
|
+
expect do
|
73
|
+
latch.unlock
|
74
|
+
trace_thread.join(1)
|
75
|
+
trace_thread.kill # in case thread misbehaves
|
76
|
+
end.to change { metric.values[labels] }.by(1.0)
|
77
|
+
end
|
78
|
+
# rubocop:enable RSpec/ExampleLength
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
# rubocop:enable RSpec/InstanceVariable
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe Prometheus::Middleware::TraceCollector do
|
4
|
+
subject(:collector) { described_class.new(app, options) }
|
5
|
+
|
6
|
+
let(:app) { instance_double(Proc, call: []) }
|
7
|
+
let(:options) { { tracer: tracer } }
|
8
|
+
let(:tracer) { Prometheus::Client::Tracer.new }
|
9
|
+
|
10
|
+
describe ".call" do
|
11
|
+
subject(:call) { collector.call({}) }
|
12
|
+
|
13
|
+
# The most basic of tests, just verifying the tracer is invoked. We rely on the tests
|
14
|
+
# for the tracer to validate #collect works correctly.
|
15
|
+
it "calls tracer.collect, then the original app" do
|
16
|
+
expect(tracer).to receive(:collect).and_call_original
|
17
|
+
expect(app).to receive(:call)
|
18
|
+
|
19
|
+
call
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: prometheus-client-tracer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- me@lawrencejones.dev
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-07-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: prometheus-client
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.10.0.alpha
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.10.0.alpha
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: gc_ruboconfig
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.4.0
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.4.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.10'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.10'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.8'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.8'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- me@lawrencejones.dev
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".circleci/config.yml"
|
77
|
+
- ".rspec"
|
78
|
+
- ".rubocop.yml"
|
79
|
+
- ".ruby-version"
|
80
|
+
- Gemfile
|
81
|
+
- Gemfile.lock
|
82
|
+
- README.md
|
83
|
+
- lib/prometheus/client/tracer.rb
|
84
|
+
- lib/prometheus/middleware/trace_collector.rb
|
85
|
+
- prometheus-client-tracer.gemspec
|
86
|
+
- spec/prometheus/client/tracer_spec.rb
|
87
|
+
- spec/prometheus/middleware/trace_collector_spec.rb
|
88
|
+
- spec/spec_helper.rb
|
89
|
+
homepage: https://github.com/lawrencejones/prometheus-client-tracer
|
90
|
+
licenses:
|
91
|
+
- MIT
|
92
|
+
metadata: {}
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options: []
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '2.4'
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubygems_version: 3.0.3
|
109
|
+
signing_key:
|
110
|
+
specification_version: 4
|
111
|
+
summary: Tracer for accurate duration tracking with Prometheus metrics
|
112
|
+
test_files:
|
113
|
+
- spec/prometheus/client/tracer_spec.rb
|
114
|
+
- spec/prometheus/middleware/trace_collector_spec.rb
|
115
|
+
- spec/spec_helper.rb
|