slimy 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: eaf9b13b8237cd4762f4c47604094655839f8a3038325e82f09c7f80332e8323
4
+ data.tar.gz: 1b0265a125ed7d39f19b82950a0e2b0ce26a42f6eed340125069366321fcf0f7
5
+ SHA512:
6
+ metadata.gz: 7bb3891e0c988132baa3a795cef5405e9e458f1d2d423948d01a9aa6f199caa0f12a9470a09f4764eb8144d44e61c87f8185e88939ce5efe94c6ec81924fccfb
7
+ data.tar.gz: e305fa2a3d37ae07567e34aad79c40a606c507006d018a7a0179acc27b40842541b2e5c9dbc7e12fa31c0b34b6ba987a69d844f5f60038e50ca7d9b379b7b4a8
@@ -0,0 +1,56 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ # Ignore Byebug command history file.
17
+ .byebug_history
18
+
19
+ ## Specific to RubyMotion:
20
+ .dat*
21
+ .repl_history
22
+ build/
23
+ *.bridgesupport
24
+ build-iPhoneOS/
25
+ build-iPhoneSimulator/
26
+
27
+ ## Specific to RubyMotion (use of CocoaPods):
28
+ #
29
+ # We recommend against adding the Pods directory to your .gitignore. However
30
+ # you should judge for yourself, the pros and cons are mentioned at:
31
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
32
+ #
33
+ # vendor/Pods/
34
+
35
+ ## Documentation cache and generated files:
36
+ /.yardoc/
37
+ /_yardoc/
38
+ /doc/
39
+ /rdoc/
40
+
41
+ ## Environment normalization:
42
+ /.bundle/
43
+ /vendor/bundle
44
+ /lib/bundler/man/
45
+
46
+ # for a library or gem, you might want to ignore these files since the code is
47
+ # intended to run in multiple environments; otherwise, check them in:
48
+ # Gemfile.lock
49
+ # .ruby-version
50
+ # .ruby-gemset
51
+
52
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
53
+ .rvmrc
54
+
55
+ # Used by RuboCop. Remote config files pulled in from inherit_from directive.
56
+ # .rubocop-https?--*
@@ -0,0 +1,8 @@
1
+
2
+ AllCops:
3
+ TargetRubyVersion: 2.6
4
+ TargetRailsVersion: 6.0
5
+
6
+ Style/StringLiterals:
7
+ Enabled: true
8
+ EnforcedStyle: double_quotes
@@ -0,0 +1,3 @@
1
+ ruby 2.6.5
2
+ nodejs 10.23.0
3
+ yarn 1.19.1
@@ -0,0 +1,4 @@
1
+ ### v0.0.3 - 2020-12-04
2
+ - Tested changelog
3
+ ### v0.0.2 - 2020-12-04
4
+ - Added changelog
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gemspec
6
+
@@ -0,0 +1,52 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ slimy (0.0.3)
5
+ rack (~> 2.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ ansi (1.5.0)
11
+ ast (2.4.1)
12
+ builder (3.2.4)
13
+ bump (0.10.0)
14
+ jaro_winkler (1.5.3)
15
+ minitest (5.14.2)
16
+ minitest-reporters (1.4.2)
17
+ ansi
18
+ builder
19
+ minitest (>= 5.0)
20
+ ruby-progressbar
21
+ parallel (1.18.0)
22
+ parser (2.6.5.0)
23
+ ast (~> 2.4.0)
24
+ rack (2.2.3)
25
+ rainbow (3.0.0)
26
+ rake (10.5.0)
27
+ rubocop (0.75.1)
28
+ jaro_winkler (~> 1.5.1)
29
+ parallel (~> 1.10)
30
+ parser (>= 2.6)
31
+ rainbow (>= 2.2.2, < 4.0)
32
+ ruby-progressbar (~> 1.7)
33
+ unicode-display_width (>= 1.4.0, < 1.7)
34
+ ruby-progressbar (1.10.1)
35
+ timecop (0.9.2)
36
+ unicode-display_width (1.6.0)
37
+
38
+ PLATFORMS
39
+ ruby
40
+
41
+ DEPENDENCIES
42
+ bump
43
+ bundler (>= 1.0, < 3)
44
+ minitest (~> 5.14)
45
+ minitest-reporters (~> 1.4)
46
+ rake (~> 10.4, >= 10.4.2)
47
+ rubocop
48
+ slimy!
49
+ timecop (~> 0.9)
50
+
51
+ BUNDLED WITH
52
+ 2.0.2
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Lessonly
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,39 @@
1
+ # slimy
2
+
3
+ SLI middleware for rack. Most monitoring instrumentation is organized around Golden Signals, USE, RED, etc. The goal of this library is to provide direct measurement useful for determining SLIs, SLOs and error budgets.
4
+ ## What is a Service Level Indicator (SLI)?
5
+
6
+ This is a concept we learned from the [Google SRE BOOK (free)](https://sre.google/sre-book/service-level-objectives/). Simply put this is a measure of (good event) / (total events). Ideally this should measure of how the system is meeting user expectations.
7
+
8
+ ### Example
9
+
10
+ Maybe your target for your homepage is to respond to requests within 50 milliseconds.
11
+
12
+
13
+ * If you get 100 requests and all responses are then your SLI value is 100/100 (100%)
14
+ * If you get 100 requests and 5 of the responses are errors and 5 of them take 100ms then your SLI value is 90/100 (90%)
15
+
16
+ ## What is a Service Level Objective (SLO)?
17
+
18
+ An SLO is an SLI with some threshold you're trying to meet.
19
+
20
+ In the homepage example above, that would be a high visiblity, high importance page so maybe you want 99.95% of requests to meet your success criteria.
21
+
22
+ Maybe you have report that is fast for some customers, and slow for others. The slow customers don't need the data urgently and everybody is happy so you might be happy with 90% of reports being generated in 120 seconds.
23
+
24
+ This allows us to define error budgets and gives us a firm framework for prioritizing feature work vs performance issues that can often be seen as a "Nice to have" until it becomes an "Ooops this is functionally not working."
25
+
26
+
27
+
28
+ [Error Budgets](https://sre.google/sre-book/embracing-risk/#xref_risk-management_unreliability-budgets)
29
+
30
+
31
+ ## SLAs?
32
+
33
+ Service Level Agreements are contracts with external teams. They're not unrelated but a bit beyond the scope of the goal here.
34
+
35
+ ## SLIs and other types of Monitoring
36
+
37
+ There are many ways to monitoring running systems. Golden Signals, RED, USE, are all important frameworks for monitoring and analyzing the health of a running system. SLOs are
38
+
39
+
@@ -0,0 +1,17 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+ require 'rake/testtask'
4
+ require 'bump/tasks'
5
+ require 'rubocop/rake_task'
6
+
7
+
8
+ RuboCop::RakeTask.new
9
+
10
+ Rake::TestTask.new do |t|
11
+ t.libs << "test"
12
+ t.libs << "lib"
13
+ t.test_files = FileList['test/**/*_test.rb']
14
+ end
15
+ desc "Run tests"
16
+
17
+ task default: [:test, :rubocop]
@@ -0,0 +1,19 @@
1
+ require "slimy/version"
2
+ require "slimy/context"
3
+ require "slimy/config"
4
+ require "slimy/rack"
5
+ require "slimy/rails"
6
+ require "slimy/reporters"
7
+
8
+
9
+ module Slimy
10
+ class << self
11
+ def configure
12
+ if block_given?
13
+ yield(Configuration.default)
14
+ else
15
+ Configuration.default
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module Slimy
2
+ class Configuration
3
+
4
+ def initialize
5
+ @reporter = nil
6
+ end
7
+
8
+ attr_accessor :reporter
9
+
10
+
11
+ def self.default
12
+ @@default ||= Configuration.new
13
+ end
14
+
15
+ def configure
16
+ yield(self) if block_given?
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,104 @@
1
+ module Slimy
2
+
3
+ # Slimy::Context
4
+ #
5
+ # This is a group of metadata that exists for the duration of some request to be measured
6
+ # as part of an SLI.
7
+ #
8
+ class Context
9
+
10
+ # Create a new context sets the `start_time` to now
11
+ #
12
+ # == Parameters
13
+ # start_time::
14
+ # An overriden Time at which the event started. Defaults to now.
15
+ #
16
+ # deadline::
17
+ # ms that this context should be finished in to be considered acceptable
18
+ #
19
+ def initialize(start_time: nil, type: "request", deadline: nil)
20
+ @start_time = start_time || Time.now
21
+ @deadline = deadline
22
+ @result_status = :success
23
+ @end_time = nil
24
+ @tags = {}
25
+ @reportable = true
26
+ @type = type
27
+ end
28
+
29
+ attr_reader :start_time, :end_time, :type
30
+
31
+
32
+ attr_accessor :tags, :deadline
33
+
34
+ # Set the end_time value for the context if not already set
35
+ #
36
+ # == Parameters
37
+ # end_time::
38
+ # An overriden Time at which the event ended. Defaults to now.
39
+ #
40
+ def finish(end_time: nil)
41
+ @end_time = end_time || Time.now unless finished?
42
+ end
43
+
44
+ # Whether or not an end time has been set
45
+ def finished?
46
+ !@end_time.nil?
47
+ end
48
+
49
+ # mark request as having an error, or otherwise unacceptable for users
50
+ def result_error!
51
+ @result_status = :error
52
+ end
53
+
54
+ # was the result of the request an error?
55
+ def result_error?
56
+ @result_status == :error
57
+ end
58
+
59
+ # mark the result as being successful.
60
+ # This will not override deadline failure
61
+ def result_success!
62
+ @result_status = :success
63
+ end
64
+
65
+ # Was the execution path of this request normal (not an error)?
66
+ # This does not include deadline failures
67
+ def result_success?
68
+ @result_status == :success
69
+ end
70
+
71
+ # Returns true if there was no error and if the deadline was not reached.
72
+ def success?
73
+ result_success? && deadline_success?
74
+ end
75
+
76
+ # duration in ms of the event
77
+ def duration
78
+ return -1 unless finished?
79
+ [@end_time - @start_time,0].max * 1000.0
80
+ end
81
+
82
+ # Did the request finish before the deadline (or was there no deadline)
83
+ def deadline_success?
84
+ return true if @deadline.nil? || ! finished?
85
+ duration < @deadline
86
+ end
87
+
88
+ # Whether or not this context should be reported
89
+ def reportable?
90
+ @reportable
91
+ end
92
+
93
+ def don_not_report!
94
+ @reportable = false
95
+ end
96
+
97
+ # tool for debugging
98
+ def debug_format
99
+ "slimy_ctx:\n\tfinished: #{finished?}\n\tduration: #{duration}\n\tresult_success: #{result_success?}\n\tduration_success: #{deadline_success?}\n\tsuccess: #{success?}\n\tdeadline: #{deadline}\n\ttags: #{tags.inspect}"
100
+ end
101
+
102
+ end
103
+
104
+ end
@@ -0,0 +1,3 @@
1
+ module Slimy::Rack
2
+ autoload :SLIMiddleware, "slimy/rack/middleware"
3
+ end
@@ -0,0 +1,31 @@
1
+ module Slimy::Rack
2
+ class SLIMiddleware
3
+
4
+ MIDDLEWARE_CONTEXT_KEY="slimy.milddeware.context"
5
+
6
+ def initialize(app)
7
+ @app = app
8
+ @reporter = Slimy::Configuration.default.reporter
9
+ end
10
+
11
+ def call(env)
12
+ context = Slimy::Context.new(deadline: 200, type: 'rack')
13
+ env[MIDDLEWARE_CONTEXT_KEY] = context
14
+ begin
15
+ response = @app.call(env)
16
+ context.result_error! if response[0] >= 500
17
+ rescue Exception => error
18
+ context.result_error!
19
+ raise error
20
+ ensure
21
+ context.finish
22
+ report(context)
23
+ return response
24
+ end
25
+ end
26
+
27
+ def report(context)
28
+ @reporter.report(context) unless @reporter.nil?
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module Slimy::Rails
2
+ autoload :SLITools, "slimy/rails/sli_concern"
3
+ end
@@ -0,0 +1,52 @@
1
+ module Slimy::Rails
2
+
3
+ module SLITools extend ActiveSupport::Concern
4
+
5
+ included do
6
+
7
+ # class-level meta commands
8
+ def self.sli_tag(tag, value, except: nil, only: nil)
9
+ self.before_action only: only, except: except do
10
+ add_sli_tag(tag,value)
11
+ end
12
+ end
13
+
14
+ def self.sli_ignore(except: nil, only: nil)
15
+ self.before_action only: only, except: except do
16
+ add_sli_ignore
17
+ end
18
+ end
19
+
20
+ def self.sli_deadline(deadline, except: nil, only: nil)
21
+ self.before_action only: only, except: except do
22
+ add_sli_deadline(deadline)
23
+ end
24
+ end
25
+
26
+ before_action do
27
+ add_sli_tag("controller", controller_name)
28
+ add_sli_tag("action", action_name)
29
+ end
30
+
31
+ # helpers
32
+ def slimy_context
33
+ request.env[Slimy::Rack::SLIMiddleware::MIDDLEWARE_CONTEXT_KEY]
34
+ end
35
+
36
+ def add_sli_tag(tag,value)
37
+ ctx = slimy_context
38
+ ctx.tags[tag] = value unless ctx.nil?
39
+ end
40
+
41
+ def add_sli_ignore
42
+ ctx = slimy_context
43
+ ctx.do_not_report! unless ctx.nil?
44
+ end
45
+
46
+ def add_sli_deadline(deadline)
47
+ ctx = slimy_context
48
+ ctx.deadline = deadline unless ctx.nil?
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,6 @@
1
+ require "slimy/reporters/reporter"
2
+
3
+ module Slimy::Reporters
4
+ autoload :RailsLogReporter, "slimy/reporters/rails_log_reporter"
5
+ autoload :DatadogReporter, "slimy/reporters/datadog"
6
+ end
@@ -0,0 +1,25 @@
1
+ module Slimy::Reporters
2
+ class DatadogReporter < BaseReporter
3
+
4
+ def initialize(dogstatsd)
5
+ @dogstatsd = dogstatsd
6
+ end
7
+
8
+ def report(context)
9
+ return unless context.reportable?
10
+
11
+ current_span = Datadog.tracer.active_span
12
+ unless current_span.nil?
13
+ sli_status =(context.success? ? "success" : "failure")
14
+ current_span.set_tag('sli_status', sli_status)
15
+ current_span.set_tag('sli_deadline', context.deadline)
16
+ context.tags.each_pair do |key, value|
17
+ current_span.set_tag(key,value)
18
+ end
19
+ @dogstatsd.increment("sli.#{context.type}.#{sli_status}", tags: context.tags)
20
+ else
21
+ Rails.logger.debug("COULD NOT FIND SPAN")
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,16 @@
1
+ module Slimy::Reporters
2
+
3
+ class RailsLogReporter
4
+ def initialize(level: :debug)
5
+ @level = level
6
+ end
7
+
8
+ def report(context)
9
+ log(context.debug_format)
10
+ end
11
+
12
+ def log(msg)
13
+ Rails.logger.send(@level, msg)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,9 @@
1
+ module Slimy::Reporters
2
+
3
+ class BaseReporter
4
+
5
+ def report(context)
6
+ raise NotImplementedError
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module Slimy
2
+ VERSION = "0.0.3"
3
+ end
@@ -0,0 +1,28 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require "slimy/version"
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "slimy"
6
+ s.version = Slimy::VERSION
7
+ s.date = "2020-12-01"
8
+ s.summary = "SLI metrics middleware"
9
+ s.description = "Provide a simple and consistent library for recording SLI" \
10
+ + "type metrics for Rack, Sidekiq, and maybe more."
11
+ s.authors = ["Tyler Henrichs", "Stephen Gregory"]
12
+ s.email = "devops+slimy@lessonly.com"
13
+ s.homepage = "https://rubygems.org/gems/slimy"
14
+ s.license = "MIT"
15
+ s.files = `git ls-files`.split("\n")
16
+
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_runtime_dependency "rack", "~> 2.0"
20
+
21
+ s.add_development_dependency "bump"
22
+ s.add_development_dependency "bundler", ">= 1.0", "< 3"
23
+ s.add_development_dependency "minitest", "~> 5.14"
24
+ s.add_development_dependency "minitest-reporters", "~> 1.4"
25
+ s.add_development_dependency "rake", "~> 10.4", ">= 10.4.2"
26
+ s.add_development_dependency "rubocop"
27
+ s.add_development_dependency "timecop", "~> 0.9"
28
+ end
@@ -0,0 +1,48 @@
1
+ require "test_helper"
2
+
3
+ class ContextTest < Minitest::Test
4
+
5
+ def test_that_context_new_works
6
+ context = Slimy::Context.new
7
+ refute_nil context
8
+ refute context.finished?
9
+ end
10
+
11
+ def test_finish_exceeds_deadline
12
+ context = Slimy::Context.new(deadline: 20)
13
+
14
+ freeze_ms(30) do
15
+ context.finish
16
+ assert context.finished?
17
+ refute context.deadline_success?, "duration: #{context.duration} should be less than 20"
18
+ assert context.result_success?
19
+ refute context.success?
20
+ end
21
+ end
22
+
23
+ def test_finish_within_deadline
24
+ context = Slimy::Context.new(deadline: 200)
25
+
26
+ freeze_ms(100) do
27
+ context.finish
28
+ assert context.finished?
29
+ assert context.deadline_success?
30
+ assert context.result_success?
31
+ assert context.success?
32
+ end
33
+ end
34
+
35
+ def test_error_finish_within_deadline
36
+ context = Slimy::Context.new(deadline: 200)
37
+
38
+ freeze_ms(100) do
39
+ context.result_error!
40
+ context.finish
41
+ assert context.finished?
42
+ assert context.deadline_success?
43
+ refute context.result_success?
44
+ refute context.success?
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,10 @@
1
+ require 'minitest/autorun'
2
+ require 'slimy'
3
+ require 'timecop'
4
+
5
+
6
+ def freeze_ms(duration_ms)
7
+ Timecop.freeze(Time.now+(duration_ms/1000.0)) do
8
+ yield
9
+ end
10
+ end
metadata ADDED
@@ -0,0 +1,192 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: slimy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Tyler Henrichs
8
+ - Stephen Gregory
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2020-12-01 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rack
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '2.0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '2.0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: bump
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: bundler
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '1.0'
49
+ - - "<"
50
+ - !ruby/object:Gem::Version
51
+ version: '3'
52
+ type: :development
53
+ prerelease: false
54
+ version_requirements: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: '1.0'
59
+ - - "<"
60
+ - !ruby/object:Gem::Version
61
+ version: '3'
62
+ - !ruby/object:Gem::Dependency
63
+ name: minitest
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '5.14'
69
+ type: :development
70
+ prerelease: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '5.14'
76
+ - !ruby/object:Gem::Dependency
77
+ name: minitest-reporters
78
+ requirement: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.4'
83
+ type: :development
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.4'
90
+ - !ruby/object:Gem::Dependency
91
+ name: rake
92
+ requirement: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '10.4'
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: 10.4.2
100
+ type: :development
101
+ prerelease: false
102
+ version_requirements: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - "~>"
105
+ - !ruby/object:Gem::Version
106
+ version: '10.4'
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: 10.4.2
110
+ - !ruby/object:Gem::Dependency
111
+ name: rubocop
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ type: :development
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ - !ruby/object:Gem::Dependency
125
+ name: timecop
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '0.9'
131
+ type: :development
132
+ prerelease: false
133
+ version_requirements: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: '0.9'
138
+ description: Provide a simple and consistent library for recording SLItype metrics
139
+ for Rack, Sidekiq, and maybe more.
140
+ email: devops+slimy@lessonly.com
141
+ executables: []
142
+ extensions: []
143
+ extra_rdoc_files: []
144
+ files:
145
+ - ".gitignore"
146
+ - ".rubocop.yml"
147
+ - ".tool-versions"
148
+ - CHANGELOG.md
149
+ - Gemfile
150
+ - Gemfile.lock
151
+ - LICENSE
152
+ - README.md
153
+ - Rakefile
154
+ - lib/slimy.rb
155
+ - lib/slimy/config.rb
156
+ - lib/slimy/context.rb
157
+ - lib/slimy/rack.rb
158
+ - lib/slimy/rack/middleware.rb
159
+ - lib/slimy/rails.rb
160
+ - lib/slimy/rails/sli_concern.rb
161
+ - lib/slimy/reporters.rb
162
+ - lib/slimy/reporters/datadog.rb
163
+ - lib/slimy/reporters/rails_log_reporter.rb
164
+ - lib/slimy/reporters/reporter.rb
165
+ - lib/slimy/version.rb
166
+ - slimy.gemspec
167
+ - test/slimy/context_test.rb
168
+ - test/test_helper.rb
169
+ homepage: https://rubygems.org/gems/slimy
170
+ licenses:
171
+ - MIT
172
+ metadata: {}
173
+ post_install_message:
174
+ rdoc_options: []
175
+ require_paths:
176
+ - lib
177
+ required_ruby_version: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ required_rubygems_version: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - ">="
185
+ - !ruby/object:Gem::Version
186
+ version: '0'
187
+ requirements: []
188
+ rubygems_version: 3.1.2
189
+ signing_key:
190
+ specification_version: 4
191
+ summary: SLI metrics middleware
192
+ test_files: []