errbit-ruby 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: bf16e360e4211384b9c7064f3981b586810521f44102067186e63b7cba2522ba
4
+ data.tar.gz: 31ffc9af3350871133ee0e6c92684736b3e56b76021e5d083246de24fd2314e9
5
+ SHA512:
6
+ metadata.gz: 656b9b99cb0a66d575ebe7825ee5e8d0c995707aebba25dc6ca69c603149be50235d530aea9a4c23ca98f3554717be99ba6aa7d3fb1f4d064abf774e7dd243f6
7
+ data.tar.gz: 291339ec37a09eb42bf877a50bbede6f3aeaff8bf8621658a3c254c93f9e020d4a4c00f65f85604dd771381d75c88836e08dd1a9991d9e527ce83925c501bb60
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --require spec_helper
2
+ --format documentation
3
+ -Ilib
4
+ -Ispec
data/.rubocop.yml ADDED
@@ -0,0 +1,20 @@
1
+ AllCops:
2
+ NewCops: enable
3
+ TargetRubyVersion: 4.0
4
+ SuggestExtensions: false
5
+ Exclude:
6
+ - "bin/*"
7
+
8
+ Style/StringLiterals:
9
+ EnforcedStyle: double_quotes
10
+
11
+ Style/Documentation:
12
+ Enabled: false
13
+
14
+ Metrics/MethodLength:
15
+ Max: 20
16
+
17
+ Metrics/BlockLength:
18
+ Exclude:
19
+ - "spec/**/*"
20
+ - "errbit-ruby.gemspec"
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 4.0.7
data/AGENTS.md ADDED
@@ -0,0 +1 @@
1
+ See [CLAUDE.md](./CLAUDE.md) for agent instructions for this project.
data/CLAUDE.md ADDED
@@ -0,0 +1,79 @@
1
+ # errbit-ruby
2
+
3
+ A dependency-free Ruby client for reporting exceptions to an Errbit server.
4
+ Plain Ruby — no Rails, no Rack. Targets Ruby >= 4.0.
5
+
6
+ ## Design constraints (do not violate without asking)
7
+
8
+ - **Zero runtime dependencies.** The gem may only use Ruby's standard
9
+ library (`net/http`, `json`, `uri`, ...) at runtime. `rspec`, `webmock`,
10
+ `rubocop`, `rake`, `irb` are development-only (`add_development_dependency`
11
+ in `errbit-ruby.gemspec`, or plain `gem` lines in the `Gemfile`).
12
+ - **No Rails, no Rack.** Nothing in `lib/` may assume either is loaded.
13
+ - **This is a new, custom API** — not Airbrake- or Sentry-compatible. The
14
+ wire format is defined in `openapi/errbit-api.yaml` and that file is the
15
+ source of truth for the request/response shape the client builds and
16
+ parses. If you change the payload shape in `lib/errbit/error_report.rb`
17
+ or `lib/errbit/client.rb`, update the OpenAPI spec to match (and vice
18
+ versa).
19
+ - **Synchronous delivery only.** `Errbit::Client#notify` makes a blocking
20
+ `Net::HTTP` call on the caller's thread. No background thread/queue.
21
+ - Target Ruby version is 4.0 (`.ruby-version` pins the local dev version to
22
+ 4.0.7 via rbenv; `required_ruby_version` in the gemspec is `>= 4.0`).
23
+
24
+ ## Project layout
25
+
26
+ - `lib/errbit.rb` — public entry point: `Errbit.configure`, `Errbit.notify`.
27
+ - `lib/errbit/configuration.rb` — `host`, `project_id`, `api_key`, `ignore`
28
+ list, timeouts.
29
+ - `lib/errbit/backtrace.rb` — parses `exception.backtrace` lines into
30
+ `{file:, line:, method:}` hashes. Handles both the pre-3.4 backtick/quote
31
+ format and the 3.4+ single-quote format.
32
+ - `lib/errbit/error_report.rb` — builds the JSON payload from an
33
+ `Exception`, matching the `ErrorReport` schema in the OpenAPI spec.
34
+ - `lib/errbit/client.rb` — POSTs to
35
+ `{host}/api/v1/projects/{project_id}/errors/{api_key}` via `Net::HTTP`,
36
+ returns an `Errbit::Result`.
37
+ - `lib/errbit/result.rb` — outcome object: `success?` / `ignored?` /
38
+ `failure?`.
39
+ - `lib/errbit/errors.rb` — `Errbit::Error`, `ConfigurationError`,
40
+ `DeliveryError` (raised only on network failure, never on a well-formed
41
+ 4xx/5xx from the server — those come back as a failed `Result`).
42
+ - `openapi/errbit-api.yaml` — OpenAPI 3.1 spec for the single ingestion
43
+ endpoint this gem calls. Update alongside any payload/response change.
44
+
45
+ ## Commands
46
+
47
+ ```sh
48
+ bundle install
49
+ bundle exec rspec # run the test suite (spec/)
50
+ bundle exec rubocop # lint
51
+ bundle exec rake # defaults to spec
52
+ bin/console # IRB session with Errbit pre-configured
53
+ ```
54
+
55
+ Note: a `rubocop --server` daemon can get stuck/orphaned on this machine
56
+ and hang `bundle exec rubocop`. If it hangs, check `ps aux | grep rubocop`
57
+ and confirm with the user before killing anything; `--no-server` may not
58
+ help if the daemon itself is wedged.
59
+
60
+ ## Testing conventions
61
+
62
+ - RSpec, with WebMock stubbing all HTTP (`WebMock.disable_net_connect!` in
63
+ `spec/spec_helper.rb` — real network calls in specs are a bug, not a
64
+ feature).
65
+ - WebMock's `hash_including` body matchers compare against the
66
+ **JSON-decoded body with string keys**, not symbols — write
67
+ `hash_including("error" => hash_including("class" => ...))`, not
68
+ `hash_including(error: hash_including(class: ...))`. Getting this wrong
69
+ is a common mistake here and fails silently-looking WebMock diffs.
70
+ - Every spec file lives under `spec/`, mirroring `lib/errbit/*` files
71
+ 1:1 (`lib/errbit/client.rb` <-> `spec/errbit/client_spec.rb`).
72
+
73
+ ## Style
74
+
75
+ - `# frozen_string_literal: true` at the top of every Ruby file.
76
+ - Double-quoted string literals (enforced by `.rubocop.yml`).
77
+ - No comments explaining *what* code does; only *why*, when non-obvious
78
+ (see the `DeliveryError` note above for an example of the kind of thing
79
+ worth a comment).
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Igor Zubkov
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.
data/README.md ADDED
@@ -0,0 +1,92 @@
1
+ # errbit-ruby
2
+
3
+ A dependency-free Ruby client for reporting exceptions to an Errbit server.
4
+ Plain Ruby only — no Rails, no Rack required. Targets Ruby >= 4.0 and has
5
+ **zero runtime dependencies** (uses only `net/http`, `json`, and `uri` from
6
+ the standard library).
7
+
8
+ This gem talks to a new, purpose-built error-ingestion API — it is **not**
9
+ compatible with the Airbrake or Sentry APIs. The API is specified in
10
+ [`openapi/errbit-api.yaml`](openapi/errbit-api.yaml).
11
+
12
+ ## Installation
13
+
14
+ Add to your Gemfile:
15
+
16
+ ```ruby
17
+ gem "errbit-ruby", require: "errbit"
18
+ ```
19
+
20
+ or install directly:
21
+
22
+ ```sh
23
+ gem install errbit-ruby
24
+ ```
25
+
26
+ ## Usage
27
+
28
+ Configure once, near your application's boot:
29
+
30
+ ```ruby
31
+ require "errbit"
32
+
33
+ Errbit.configure do |config|
34
+ config.host = "https://errbit.example.com"
35
+ config.project_id = ENV.fetch("ERRBIT_PROJECT_ID")
36
+ config.api_key = ENV.fetch("ERRBIT_API_KEY")
37
+
38
+ # Optional: exception classes, class-name strings, or regexps to skip.
39
+ config.ignore = [ArgumentError, /expected, harmless/i]
40
+ end
41
+ ```
42
+
43
+ Then report exceptions where you rescue them:
44
+
45
+ ```ruby
46
+ begin
47
+ risky_operation
48
+ rescue => e
49
+ Errbit.notify(e)
50
+ raise
51
+ end
52
+ ```
53
+
54
+ `Errbit.notify` returns an `Errbit::Result`:
55
+
56
+ ```ruby
57
+ result = Errbit.notify(e)
58
+
59
+ result.success? # => true/false
60
+ result.ignored? # => true if the exception matched config.ignore
61
+ result.failure? # => true on a 4xx/5xx response from the server
62
+ result.id # => server-assigned id, on success
63
+ result.error # => server error message, on failure
64
+ ```
65
+
66
+ A report is delivered synchronously over HTTP(S) on the calling thread. A
67
+ network failure (timeout, connection refused, etc.) raises
68
+ `Errbit::DeliveryError`; a well-formed error response from the server
69
+ (400/401/404) does not raise — check `result.failure?` instead.
70
+
71
+ ## Development
72
+
73
+ ```sh
74
+ bundle install
75
+ bundle exec rspec
76
+ ```
77
+
78
+ `bin/console` starts an IRB session with the gem pre-configured against a
79
+ placeholder host for manual experimentation.
80
+
81
+ ## API
82
+
83
+ See [`openapi/errbit-api.yaml`](openapi/errbit-api.yaml) for the full
84
+ OpenAPI 3.1 definition of the single endpoint this gem calls:
85
+
86
+ ```
87
+ POST /api/v1/projects/{project_id}/errors/{api_key}
88
+ ```
89
+
90
+ ## License
91
+
92
+ MIT
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Errbit
4
+ module Backtrace
5
+ # Matches both backtrace line formats Ruby has used:
6
+ # "file.rb:12:in `method'" (Ruby <= 3.3)
7
+ # "file.rb:12:in 'method'" (Ruby >= 3.4)
8
+ # and lines with no method info at all: "file.rb:12"
9
+ LINE_PATTERN = /\A(?<file>.+):(?<line>\d+)(?::in\s+[`'](?<method>.+)')?\z/.freeze
10
+
11
+ module_function
12
+
13
+ def parse(exception)
14
+ Array(exception&.backtrace).map { |line| parse_line(line) }
15
+ end
16
+
17
+ def parse_line(line)
18
+ match = LINE_PATTERN.match(line.to_s)
19
+ return { file: line.to_s, line: nil, method: nil } unless match
20
+
21
+ {
22
+ file: match[:file],
23
+ line: match[:line].to_i,
24
+ method: match[:method]
25
+ }
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "net/http"
4
+ require "json"
5
+ require "uri"
6
+
7
+ module Errbit
8
+ class Client
9
+ NETWORK_ERRORS = [
10
+ Errno::ECONNREFUSED,
11
+ Errno::ECONNRESET,
12
+ Errno::EHOSTUNREACH,
13
+ SocketError,
14
+ Timeout::Error,
15
+ Net::OpenTimeout,
16
+ Net::ReadTimeout,
17
+ OpenSSL::SSL::SSLError
18
+ ].freeze
19
+
20
+ def initialize(configuration)
21
+ @configuration = configuration
22
+ end
23
+
24
+ def notify(exception)
25
+ return Result.ignored if configuration.ignored?(exception)
26
+
27
+ configuration.validate!
28
+ deliver(ErrorReport.build(exception))
29
+ end
30
+
31
+ private
32
+
33
+ attr_reader :configuration
34
+
35
+ def deliver(payload)
36
+ uri = endpoint_uri
37
+ request = Net::HTTP::Post.new(uri)
38
+ request["Content-Type"] = "application/json"
39
+ request["Accept"] = "application/json"
40
+ request.body = JSON.generate(payload)
41
+
42
+ response = http_client(uri).request(request)
43
+ build_result(response)
44
+ rescue *NETWORK_ERRORS => e
45
+ raise DeliveryError, e
46
+ end
47
+
48
+ def http_client(uri)
49
+ http = Net::HTTP.new(uri.host, uri.port)
50
+ http.use_ssl = uri.scheme == "https"
51
+ http.open_timeout = configuration.open_timeout
52
+ http.read_timeout = configuration.read_timeout
53
+ http
54
+ end
55
+
56
+ def endpoint_uri
57
+ base = configuration.host.to_s.chomp("/")
58
+ URI.parse(
59
+ "#{base}/api/v1/projects/#{escape(configuration.project_id)}/errors/#{escape(configuration.api_key)}"
60
+ )
61
+ end
62
+
63
+ def escape(value)
64
+ URI.encode_www_form_component(value.to_s)
65
+ end
66
+
67
+ def build_result(response)
68
+ body = parse_json(response.body)
69
+
70
+ case response
71
+ when Net::HTTPAccepted
72
+ Result.success(status_code: response.code.to_i, id: body["id"], created_at: body["created_at"])
73
+ else
74
+ Result.failure(status_code: response.code.to_i, error: body["error"] || response.message)
75
+ end
76
+ end
77
+
78
+ def parse_json(raw)
79
+ return {} if raw.nil? || raw.empty?
80
+
81
+ JSON.parse(raw)
82
+ rescue JSON::ParserError
83
+ {}
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Errbit
4
+ class Configuration
5
+ attr_accessor :host, :project_id, :api_key, :ignore, :open_timeout, :read_timeout
6
+
7
+ def initialize
8
+ @host = nil
9
+ @project_id = nil
10
+ @api_key = nil
11
+ @ignore = []
12
+ @open_timeout = 2
13
+ @read_timeout = 2
14
+ end
15
+
16
+ def ignored?(exception)
17
+ ignore.any? do |pattern|
18
+ case pattern
19
+ when Module
20
+ exception.is_a?(pattern)
21
+ when Regexp
22
+ pattern.match?(exception.message.to_s) || pattern.match?(exception.class.name.to_s)
23
+ else
24
+ pattern.to_s == exception.class.name
25
+ end
26
+ end
27
+ end
28
+
29
+ def validate!
30
+ missing = %i[host project_id api_key].select { |attr| public_send(attr).nil? || public_send(attr).to_s.empty? }
31
+ return if missing.empty?
32
+
33
+ raise ConfigurationError, "Errbit is missing required configuration: #{missing.join(', ')}"
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Errbit
4
+ module ErrorReport
5
+ module_function
6
+
7
+ # Builds a payload matching the ErrorReport schema in
8
+ # openapi/errbit-api.yaml.
9
+ def build(exception)
10
+ {
11
+ error: {
12
+ class: exception.class.name,
13
+ message: exception.message.to_s,
14
+ backtrace: Backtrace.parse(exception)
15
+ }
16
+ }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Errbit
4
+ Error = Class.new(StandardError)
5
+ ConfigurationError = Class.new(Error)
6
+
7
+ # Raised when the exception could not be delivered at all (network
8
+ # failure, timeout, connection refused, ...). A well-formed HTTP error
9
+ # response from the server (4xx/5xx) is *not* raised as this error; it is
10
+ # surfaced via a failed Result instead.
11
+ class DeliveryError < Error
12
+ attr_reader :cause_error
13
+
14
+ def initialize(cause_error)
15
+ @cause_error = cause_error
16
+ super("Failed to deliver error report: #{cause_error.class}: #{cause_error.message}")
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Errbit
4
+ # Outcome of a Client#notify call.
5
+ class Result
6
+ attr_reader :status, :status_code, :id, :created_at, :error
7
+
8
+ def self.ignored
9
+ new(status: :ignored)
10
+ end
11
+
12
+ def self.success(status_code:, id:, created_at:)
13
+ new(status: :success, status_code: status_code, id: id, created_at: created_at)
14
+ end
15
+
16
+ def self.failure(status_code:, error:)
17
+ new(status: :failure, status_code: status_code, error: error)
18
+ end
19
+
20
+ def initialize(status:, status_code: nil, id: nil, created_at: nil, error: nil)
21
+ @status = status
22
+ @status_code = status_code
23
+ @id = id
24
+ @created_at = created_at
25
+ @error = error
26
+ end
27
+
28
+ def success?
29
+ status == :success
30
+ end
31
+
32
+ def ignored?
33
+ status == :ignored
34
+ end
35
+
36
+ def failure?
37
+ status == :failure
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Errbit
4
+ VERSION = "0.1.0"
5
+ end
data/lib/errbit.rb ADDED
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "errbit/version"
4
+ require_relative "errbit/errors"
5
+ require_relative "errbit/result"
6
+ require_relative "errbit/backtrace"
7
+ require_relative "errbit/error_report"
8
+ require_relative "errbit/configuration"
9
+ require_relative "errbit/client"
10
+
11
+ module Errbit
12
+ class << self
13
+ def configuration
14
+ @configuration ||= Configuration.new
15
+ end
16
+
17
+ def configure
18
+ yield configuration
19
+ @client = nil
20
+ configuration
21
+ end
22
+
23
+ def notify(exception)
24
+ client.notify(exception)
25
+ end
26
+
27
+ # Resets configuration and memoized client. Primarily useful in tests.
28
+ def reset!
29
+ @configuration = nil
30
+ @client = nil
31
+ end
32
+
33
+ private
34
+
35
+ def client
36
+ @client ||= Client.new(configuration)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,139 @@
1
+ openapi: 3.1.0
2
+ info:
3
+ title: Errbit Error Ingestion API
4
+ description: >
5
+ A minimal API for reporting application exceptions to an Errbit server.
6
+ This is a new API design, not compatible with the Airbrake or Sentry
7
+ APIs. v1 covers error ingestion only.
8
+ version: "1.0.0"
9
+
10
+ servers:
11
+ - url: https://errbit.example.com
12
+ description: Example Errbit server
13
+
14
+ paths:
15
+ /api/v1/projects/{project_id}/errors/{api_key}:
16
+ post:
17
+ operationId: createError
18
+ summary: Report an exception
19
+ description: >
20
+ Submits a single exception occurrence for a project. Authenticates
21
+ the request via the project's API key embedded in the URL path.
22
+ parameters:
23
+ - $ref: '#/components/parameters/ProjectId'
24
+ - $ref: '#/components/parameters/ApiKey'
25
+ requestBody:
26
+ required: true
27
+ content:
28
+ application/json:
29
+ schema:
30
+ $ref: '#/components/schemas/ErrorReport'
31
+ responses:
32
+ '202':
33
+ description: Error report accepted.
34
+ content:
35
+ application/json:
36
+ schema:
37
+ $ref: '#/components/schemas/ErrorAck'
38
+ '400':
39
+ description: Malformed request body.
40
+ content:
41
+ application/json:
42
+ schema:
43
+ $ref: '#/components/schemas/ErrorResponse'
44
+ '401':
45
+ description: Invalid project_id/api_key combination.
46
+ content:
47
+ application/json:
48
+ schema:
49
+ $ref: '#/components/schemas/ErrorResponse'
50
+ '404':
51
+ description: Unknown project_id.
52
+ content:
53
+ application/json:
54
+ schema:
55
+ $ref: '#/components/schemas/ErrorResponse'
56
+
57
+ components:
58
+ parameters:
59
+ ProjectId:
60
+ name: project_id
61
+ in: path
62
+ required: true
63
+ description: Identifier of the project the error belongs to.
64
+ schema:
65
+ type: string
66
+ ApiKey:
67
+ name: api_key
68
+ in: path
69
+ required: true
70
+ description: Secret API key authorizing writes to this project.
71
+ schema:
72
+ type: string
73
+
74
+ schemas:
75
+ BacktraceFrame:
76
+ type: object
77
+ properties:
78
+ file:
79
+ type: string
80
+ description: Source file path for this stack frame.
81
+ line:
82
+ type: integer
83
+ description: Line number within the file, if known.
84
+ method:
85
+ type: string
86
+ description: Method or block name the frame was executing in.
87
+ additionalProperties: false
88
+
89
+ ErrorReport:
90
+ type: object
91
+ required:
92
+ - error
93
+ properties:
94
+ error:
95
+ type: object
96
+ required:
97
+ - class
98
+ - message
99
+ properties:
100
+ class:
101
+ type: string
102
+ description: Fully qualified exception class name.
103
+ examples:
104
+ - RuntimeError
105
+ - "Net::OpenTimeout"
106
+ message:
107
+ type: string
108
+ description: Exception message.
109
+ backtrace:
110
+ type: array
111
+ description: Ordered stack frames, innermost first.
112
+ items:
113
+ $ref: '#/components/schemas/BacktraceFrame'
114
+ additionalProperties: false
115
+ additionalProperties: false
116
+
117
+ ErrorAck:
118
+ type: object
119
+ required:
120
+ - id
121
+ - created_at
122
+ properties:
123
+ id:
124
+ type: string
125
+ description: Server-assigned identifier for the stored error occurrence.
126
+ created_at:
127
+ type: string
128
+ format: date-time
129
+ additionalProperties: false
130
+
131
+ ErrorResponse:
132
+ type: object
133
+ required:
134
+ - error
135
+ properties:
136
+ error:
137
+ type: string
138
+ description: Human-readable error message.
139
+ additionalProperties: false
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: errbit-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Igor Zubkov
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: rspec
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '3.13'
19
+ type: :development
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '3.13'
26
+ - !ruby/object:Gem::Dependency
27
+ name: webmock
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '3.23'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '3.23'
40
+ - !ruby/object:Gem::Dependency
41
+ name: rubocop
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.65'
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.65'
54
+ description: |
55
+ A dependency-free Ruby gem that catches and reports exceptions to an
56
+ Errbit server over its error-ingestion API. No Rails, no Rack required.
57
+ email:
58
+ - igor.zubkov@gmail.com
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".rspec"
64
+ - ".rubocop.yml"
65
+ - ".ruby-version"
66
+ - AGENTS.md
67
+ - CLAUDE.md
68
+ - LICENSE.txt
69
+ - README.md
70
+ - Rakefile
71
+ - lib/errbit.rb
72
+ - lib/errbit/backtrace.rb
73
+ - lib/errbit/client.rb
74
+ - lib/errbit/configuration.rb
75
+ - lib/errbit/error_report.rb
76
+ - lib/errbit/errors.rb
77
+ - lib/errbit/result.rb
78
+ - lib/errbit/version.rb
79
+ - openapi/errbit-api.yaml
80
+ homepage: https://github.com/errbit/errbit-ruby
81
+ licenses:
82
+ - MIT
83
+ metadata:
84
+ homepage_uri: https://github.com/errbit/errbit-ruby
85
+ source_code_uri: https://github.com/errbit/errbit-ruby
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '4.0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubygems_version: 4.0.21
101
+ specification_version: 4
102
+ summary: Plain-Ruby client for reporting exceptions to an Errbit server.
103
+ test_files: []