stoplight-statsd 0.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.
- checksums.yaml +7 -0
- data/README.md +95 -0
- data/lib/stoplight/statsd/subscription_group.rb +18 -0
- data/lib/stoplight/statsd/version.rb +7 -0
- data/lib/stoplight/statsd.rb +139 -0
- data/sig/stoplight/statsd.rbs +31 -0
- metadata +91 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 10b6fa4537afd4535b2f688c867e9696ca0e1e533493ce4eefdbb83ae693bee4
|
|
4
|
+
data.tar.gz: 62f42990dc70ce1b679bf4b8626d0225463277cbc67dd8f4a2dcc7502081fe21
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 4377451407e84fc48d17e5c9245871fc55cbbf1ea2f697aa7e3e6693bb7c4cac6b4a17afd1e68cc3c565aec5aca1bc339e90ce87ebeca42be0924360483472e9
|
|
7
|
+
data.tar.gz: 584de22665a30ee2076d71a184e684294eceaedbcbc0d85fc08a57fb568e2a04ff2dc31abf78177c4589a2d564ce0082426f139a6ce405c5d8ef288f5abf42da
|
data/README.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Stoplight::Statsd
|
|
2
|
+
|
|
3
|
+
A [DogStatsD] exporter for [Stoplight]'s telemetry bus.
|
|
4
|
+
|
|
5
|
+
[Stoplight] is a Ruby circuit breaker: you wrap a risky call (a flaky API, a slow database) in a
|
|
6
|
+
"light", and once it fails too often, the light turns red and stops making the call for a while,
|
|
7
|
+
giving the dependency time to recover. Stoplight already emits detailed telemetry about what its
|
|
8
|
+
lights are doing internally - this gem listens to that telemetry and forwards it to DogStatsD, so
|
|
9
|
+
those events show up as metrics and events in Datadog (or any other StatsD-compatible receiver)
|
|
10
|
+
without you having to wire that up yourself.
|
|
11
|
+
|
|
12
|
+
🚧 **Status: under development, not yet released.** Nothing in this README is installable yet.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
bundle add stoplight-statsd
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
Call `Stoplight::Statsd.subscribe` once, wherever you set up Stoplight, and pass it a DogStatsD
|
|
23
|
+
client:
|
|
24
|
+
|
|
25
|
+
```ruby
|
|
26
|
+
require "datadog/statsd"
|
|
27
|
+
require "stoplight/statsd"
|
|
28
|
+
|
|
29
|
+
statsd = Datadog::Statsd.new("localhost", 8125)
|
|
30
|
+
Stoplight::Statsd.subscribe(Stoplight.telemetry, statsd:)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
That's it - from then on, every light reports its runs, recovery attempts, and state changes to
|
|
34
|
+
`statsd` automatically. See [Events](#events) below for the full list of what gets sent.
|
|
35
|
+
|
|
36
|
+
`subscribe` returns a handle you can use to stop forwarding later, e.g. when tearing down in tests:
|
|
37
|
+
|
|
38
|
+
```ruby
|
|
39
|
+
subscription = Stoplight::Statsd.subscribe(Stoplight.telemetry, statsd:)
|
|
40
|
+
subscription.unsubscribe
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Sampling busy traffic
|
|
44
|
+
|
|
45
|
+
`Light#run` fires on every call made through a light, so on a busy fleet it can dominate metric
|
|
46
|
+
volume. Pass `sample_rate:` (`0.0`-`1.0`, default `1.0`) to forward only a fraction of
|
|
47
|
+
`stoplight.run.completed`/`stoplight.run.duration` - the only two metrics whose volume scales with
|
|
48
|
+
traffic (each sampled independently, so a `0.1` rate isn't guaranteed to keep the same runs in both
|
|
49
|
+
series, just the same average share). Everything else stays low-volume on its own, so it always
|
|
50
|
+
sends at full rate regardless of `sample_rate`.
|
|
51
|
+
|
|
52
|
+
```ruby
|
|
53
|
+
Stoplight::Statsd.subscribe(Stoplight.telemetry, statsd:, sample_rate: 0.1)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Events
|
|
57
|
+
|
|
58
|
+
"Count" metrics are plain counters; "histogram" metrics record a distribution of values (here,
|
|
59
|
+
milliseconds) so you can graph percentiles instead of just an average.
|
|
60
|
+
|
|
61
|
+
- `stoplight.run.completed` (count) - every call made through a light, tagged with the outcome
|
|
62
|
+
(`success`/`failure`/`blocked`). Respects `sample_rate`.
|
|
63
|
+
- `stoplight.run.duration` (histogram, ms) - how long that call took, when known. Respects
|
|
64
|
+
`sample_rate`.
|
|
65
|
+
- `stoplight.recovery_probe.completed` (count) - every recovery probe, i.e. the trial call
|
|
66
|
+
Stoplight makes while a light is yellow to decide whether it can go back to green. Always sent
|
|
67
|
+
at full rate.
|
|
68
|
+
- `stoplight.recovery_probe.duration` (histogram, ms) - how long that probe took, when known.
|
|
69
|
+
Always sent at full rate.
|
|
70
|
+
- `stoplight.state.transitioned` (count, plus a matching Datadog event) - a light trips to red, a
|
|
71
|
+
recovery attempt starts, succeeds, or fails, or a light gets locked/unlocked. Always sent at
|
|
72
|
+
full rate.
|
|
73
|
+
- `stoplight.light.registered` (count) - a light is registered for the first time. Always sent at
|
|
74
|
+
full rate.
|
|
75
|
+
|
|
76
|
+
## Development
|
|
77
|
+
|
|
78
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then run `rake spec` to run
|
|
79
|
+
the tests. `bin/console` gives you an interactive prompt.
|
|
80
|
+
|
|
81
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
|
82
|
+
|
|
83
|
+
## Contributing
|
|
84
|
+
|
|
85
|
+
Bug reports and pull requests are welcome on GitHub at
|
|
86
|
+
https://github.com/bolshakov/stoplight-statsd.
|
|
87
|
+
|
|
88
|
+
## License
|
|
89
|
+
|
|
90
|
+
The gem is available as open source under the terms of the
|
|
91
|
+
[MIT License](https://opensource.org/licenses/MIT).
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
[DogStatsD]: https://docs.datadoghq.com/developers/dogstatsd/
|
|
95
|
+
[Stoplight]: https://github.com/bolshakov/stoplight
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Stoplight
|
|
4
|
+
module Statsd
|
|
5
|
+
# Aggregates multiple bus subscriptions behind one caller-facing handle.
|
|
6
|
+
class SubscriptionGroup
|
|
7
|
+
def initialize(telemetry:, subscriptions:)
|
|
8
|
+
@telemetry = telemetry
|
|
9
|
+
@subscriptions = subscriptions
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def unsubscribe
|
|
13
|
+
@subscriptions.each { |subscription| @telemetry.unsubscribe(subscription) }
|
|
14
|
+
nil
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "stoplight"
|
|
4
|
+
require "zeitwerk"
|
|
5
|
+
|
|
6
|
+
# steep:ignore:start
|
|
7
|
+
loader = Zeitwerk::Loader.for_gem_extension(Stoplight)
|
|
8
|
+
loader.setup
|
|
9
|
+
# steep:ignore:end
|
|
10
|
+
|
|
11
|
+
module Stoplight
|
|
12
|
+
module Statsd
|
|
13
|
+
class Error < StandardError; end
|
|
14
|
+
|
|
15
|
+
def self.subscribe(telemetry, statsd:, sample_rate: 1.0)
|
|
16
|
+
unless (0.0..1.0).cover?(sample_rate)
|
|
17
|
+
raise Error, "sample_rate must be between 0.0 and 1.0, got #{sample_rate.inspect}"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
subscriptions = [subscribe_run_completed(telemetry, statsd: statsd, sample_rate:),
|
|
21
|
+
subscribe_recovery_probe_completed(telemetry, statsd: statsd),
|
|
22
|
+
subscribe_state_transitioned(telemetry, statsd: statsd), subscribe_light_registered(telemetry, statsd: statsd)]
|
|
23
|
+
SubscriptionGroup.new(telemetry:, subscriptions:)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.envelope_tags(envelope)
|
|
27
|
+
["system_name:#{envelope.system_name}", "light_name:#{envelope.light_name}"]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.subscribe_run_completed(telemetry, statsd:, sample_rate:)
|
|
31
|
+
telemetry.subscribe(Stoplight::Telemetry::RunCompleted) do |envelope|
|
|
32
|
+
record_run_completed(envelope, statsd: statsd, sample_rate: sample_rate)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.record_run_completed(envelope, statsd:, sample_rate:)
|
|
37
|
+
identity_tags = envelope_tags(envelope)
|
|
38
|
+
outcome_tag = "outcome:#{envelope.payload.outcome}"
|
|
39
|
+
|
|
40
|
+
statsd.increment("stoplight.run.completed", tags: [
|
|
41
|
+
*identity_tags, outcome_tag,
|
|
42
|
+
"color:#{envelope.payload.color}",
|
|
43
|
+
"fallback_used:#{envelope.payload.fallback_used}"
|
|
44
|
+
], sample_rate:)
|
|
45
|
+
return unless envelope.payload.duration_ms
|
|
46
|
+
|
|
47
|
+
statsd.histogram("stoplight.run.duration", envelope.payload.duration_ms,
|
|
48
|
+
tags: [*identity_tags, outcome_tag], sample_rate:)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def self.subscribe_recovery_probe_completed(telemetry, statsd:)
|
|
52
|
+
telemetry.subscribe(Stoplight::Telemetry::RecoveryProbeCompleted) do |envelope|
|
|
53
|
+
identity_tags = envelope_tags(envelope)
|
|
54
|
+
outcome_tag = "outcome:#{envelope.payload.outcome}"
|
|
55
|
+
|
|
56
|
+
statsd.increment("stoplight.recovery_probe.completed", tags: [*identity_tags, outcome_tag], sample_rate: 1.0)
|
|
57
|
+
statsd.histogram("stoplight.recovery_probe.duration", envelope.payload.duration_ms,
|
|
58
|
+
tags: [*identity_tags, outcome_tag], sample_rate: 1.0)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# The event's text is always the color transition, never the failure's exception message - that
|
|
63
|
+
# message is the host application's own text, written for its own logs, and can carry data (a
|
|
64
|
+
# failed URL, a DB value, echoed user input) never meant to leave the process to a third-party
|
|
65
|
+
# service. state_transitioned_variant_tags already exposes the bounded, developer-controlled
|
|
66
|
+
# exception_class as a tag, which is safe to export.
|
|
67
|
+
def self.subscribe_state_transitioned(telemetry, statsd:)
|
|
68
|
+
telemetry.subscribe(Stoplight::Telemetry::StateTransitioned) do |envelope|
|
|
69
|
+
record_state_transitioned(envelope, statsd: statsd)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def self.record_state_transitioned(envelope, statsd:)
|
|
74
|
+
payload = envelope.payload
|
|
75
|
+
event_name = state_transitioned_event_name(payload)
|
|
76
|
+
tags = state_transitioned_tags(envelope, payload, event_name)
|
|
77
|
+
|
|
78
|
+
statsd.increment("stoplight.state.transitioned", tags: tags, sample_rate: 1.0)
|
|
79
|
+
statsd.event("#{envelope.system_name}/#{envelope.light_name}: #{event_name}",
|
|
80
|
+
"#{payload.from_color} -> #{payload.to_color}", alert_type: state_transitioned_alert_type(payload),
|
|
81
|
+
tags: tags, truncate_if_too_long: true)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def self.state_transitioned_tags(envelope, payload, event_name)
|
|
85
|
+
[
|
|
86
|
+
*envelope_tags(envelope),
|
|
87
|
+
"event:#{event_name}",
|
|
88
|
+
"from_color:#{payload.from_color}",
|
|
89
|
+
"to_color:#{payload.to_color}"
|
|
90
|
+
] + state_transitioned_variant_tags(payload)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def self.state_transitioned_event_name(payload)
|
|
94
|
+
case payload
|
|
95
|
+
when Stoplight::Telemetry::TrafficBreached then "traffic_breached"
|
|
96
|
+
when Stoplight::Telemetry::RecoveryStarted then "recovery_started"
|
|
97
|
+
when Stoplight::Telemetry::RecoverySucceeded then "recovery_succeeded"
|
|
98
|
+
when Stoplight::Telemetry::RecoveryFailed then "recovery_failed"
|
|
99
|
+
when Stoplight::Telemetry::LockChanged then "lock_changed"
|
|
100
|
+
else raise Error, "unhandled state_transitioned payload: #{payload.class}"
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def self.state_transitioned_alert_type(payload)
|
|
105
|
+
case payload
|
|
106
|
+
when Stoplight::Telemetry::TrafficBreached, Stoplight::Telemetry::RecoveryFailed then "error"
|
|
107
|
+
when Stoplight::Telemetry::RecoverySucceeded then "success"
|
|
108
|
+
when Stoplight::Telemetry::RecoveryStarted, Stoplight::Telemetry::LockChanged then "info"
|
|
109
|
+
else raise Error, "unhandled state_transitioned payload: #{payload.class}"
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Tags beyond system_name/light_name/event/from_color/to_color, which every variant carries.
|
|
114
|
+
def self.state_transitioned_variant_tags(payload)
|
|
115
|
+
case payload
|
|
116
|
+
when Stoplight::Telemetry::TrafficBreached, Stoplight::Telemetry::RecoveryFailed
|
|
117
|
+
["policy:#{payload.policy}"] + state_transitioned_failure_tags(payload.failure)
|
|
118
|
+
when Stoplight::Telemetry::RecoverySucceeded then ["policy:#{payload.policy}"]
|
|
119
|
+
when Stoplight::Telemetry::LockChanged then ["from_state:#{payload.from_state}", "to_state:#{payload.to_state}"]
|
|
120
|
+
when Stoplight::Telemetry::RecoveryStarted then []
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def self.state_transitioned_failure_tags(failure)
|
|
125
|
+
failure ? ["tracked:#{failure.tracked}", "exception_class:#{failure.exception.class}"] : []
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def self.subscribe_light_registered(telemetry, statsd:)
|
|
129
|
+
telemetry.subscribe(Stoplight::Telemetry::LightRegistered) do |envelope|
|
|
130
|
+
statsd.increment("stoplight.light.registered", tags: envelope_tags(envelope), sample_rate: 1.0)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
private_class_method :subscribe_run_completed, :record_run_completed, :subscribe_recovery_probe_completed,
|
|
135
|
+
:subscribe_state_transitioned, :record_state_transitioned, :state_transitioned_tags,
|
|
136
|
+
:state_transitioned_event_name, :state_transitioned_alert_type, :state_transitioned_variant_tags,
|
|
137
|
+
:state_transitioned_failure_tags, :subscribe_light_registered
|
|
138
|
+
end
|
|
139
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Stoplight
|
|
2
|
+
module Statsd
|
|
3
|
+
VERSION: String
|
|
4
|
+
|
|
5
|
+
class Error < StandardError
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class SubscriptionGroup
|
|
9
|
+
@telemetry: Stoplight::Domain::_Telemetry
|
|
10
|
+
@subscriptions: Array[Stoplight::Domain::Telemetry::Subscription]
|
|
11
|
+
|
|
12
|
+
def initialize: (telemetry: Stoplight::Domain::_Telemetry, subscriptions: Array[Stoplight::Domain::Telemetry::Subscription]) -> void
|
|
13
|
+
def unsubscribe: () -> void
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.subscribe: (Stoplight::Domain::_Telemetry, statsd: Datadog::Statsd, ?sample_rate: Float) -> SubscriptionGroup
|
|
17
|
+
|
|
18
|
+
private def self.envelope_tags: [P < Stoplight::Domain::Telemetry::event] (Stoplight::Domain::Telemetry::Envelope[P]) -> Array[String]
|
|
19
|
+
private def self.subscribe_run_completed: (Stoplight::Domain::_Telemetry, statsd: Datadog::Statsd, sample_rate: Float) -> Stoplight::Domain::Telemetry::Subscription
|
|
20
|
+
private def self.record_run_completed: (Stoplight::Domain::Telemetry::Envelope[Stoplight::Domain::Telemetry::RunCompleted], statsd: Datadog::Statsd, sample_rate: Float) -> void
|
|
21
|
+
private def self.subscribe_recovery_probe_completed: (Stoplight::Domain::_Telemetry, statsd: Datadog::Statsd) -> Stoplight::Domain::Telemetry::Subscription
|
|
22
|
+
private def self.subscribe_state_transitioned: (Stoplight::Domain::_Telemetry, statsd: Datadog::Statsd) -> Stoplight::Domain::Telemetry::Subscription
|
|
23
|
+
private def self.record_state_transitioned: (Stoplight::Domain::Telemetry::Envelope[Stoplight::Domain::Telemetry::state_transitioned], statsd: Datadog::Statsd) -> void
|
|
24
|
+
private def self.state_transitioned_tags: (Stoplight::Domain::Telemetry::Envelope[Stoplight::Domain::Telemetry::state_transitioned], Stoplight::Domain::Telemetry::state_transitioned, String) -> Array[String]
|
|
25
|
+
private def self.state_transitioned_event_name: (Stoplight::Domain::Telemetry::state_transitioned) -> String
|
|
26
|
+
private def self.state_transitioned_alert_type: (Stoplight::Domain::Telemetry::state_transitioned) -> String
|
|
27
|
+
private def self.state_transitioned_variant_tags: (Stoplight::Domain::Telemetry::state_transitioned) -> Array[String]
|
|
28
|
+
private def self.state_transitioned_failure_tags: (Stoplight::Domain::Telemetry::Failure?) -> Array[String]
|
|
29
|
+
private def self.subscribe_light_registered: (Stoplight::Domain::_Telemetry, statsd: Datadog::Statsd) -> Stoplight::Domain::Telemetry::Subscription
|
|
30
|
+
end
|
|
31
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: stoplight-statsd
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Tëma Bolshakov
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: dogstatsd-ruby
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '5.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '5.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: stoplight
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: zeitwerk
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
description: Subscribes to Stoplight's telemetry bus and forwards circuit breaker
|
|
55
|
+
events as DogStatsD metrics to whatever StatsD/Datadog-compatible receiver you already
|
|
56
|
+
run.
|
|
57
|
+
email:
|
|
58
|
+
- tema@bolshakov.dev
|
|
59
|
+
executables: []
|
|
60
|
+
extensions: []
|
|
61
|
+
extra_rdoc_files: []
|
|
62
|
+
files:
|
|
63
|
+
- README.md
|
|
64
|
+
- lib/stoplight/statsd.rb
|
|
65
|
+
- lib/stoplight/statsd/subscription_group.rb
|
|
66
|
+
- lib/stoplight/statsd/version.rb
|
|
67
|
+
- sig/stoplight/statsd.rbs
|
|
68
|
+
homepage: https://github.com/bolshakov/stoplight-statsd
|
|
69
|
+
licenses:
|
|
70
|
+
- MIT
|
|
71
|
+
metadata:
|
|
72
|
+
homepage_uri: https://github.com/bolshakov/stoplight-statsd
|
|
73
|
+
source_code_uri: https://github.com/bolshakov/stoplight-statsd
|
|
74
|
+
rdoc_options: []
|
|
75
|
+
require_paths:
|
|
76
|
+
- lib
|
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '3.2'
|
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
|
+
requirements:
|
|
84
|
+
- - ">="
|
|
85
|
+
- !ruby/object:Gem::Version
|
|
86
|
+
version: '0'
|
|
87
|
+
requirements: []
|
|
88
|
+
rubygems_version: 4.0.16
|
|
89
|
+
specification_version: 4
|
|
90
|
+
summary: DogStatsD exporter for Stoplight's telemetry bus
|
|
91
|
+
test_files: []
|