uncaught 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 +7 -0
- data/lib/uncaught/breadcrumbs.rb +94 -0
- data/lib/uncaught/client.rb +248 -0
- data/lib/uncaught/env_detector.rb +102 -0
- data/lib/uncaught/fingerprint.rb +144 -0
- data/lib/uncaught/integrations/rails.rb +54 -0
- data/lib/uncaught/integrations/sinatra.rb +57 -0
- data/lib/uncaught/prompt_builder.rb +174 -0
- data/lib/uncaught/rate_limiter.rb +65 -0
- data/lib/uncaught/sanitizer.rb +111 -0
- data/lib/uncaught/transport.rb +340 -0
- data/lib/uncaught/types.rb +84 -0
- data/lib/uncaught/version.rb +5 -0
- data/lib/uncaught.rb +122 -0
- metadata +55 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Uncaught
|
|
4
|
+
# Severity levels mirroring syslog.
|
|
5
|
+
SEVERITY_LEVELS = %w[fatal error warning info debug].freeze
|
|
6
|
+
|
|
7
|
+
# Breadcrumb categories.
|
|
8
|
+
BREADCRUMB_TYPES = %w[click navigation api_call db_query auth console web_vital custom].freeze
|
|
9
|
+
|
|
10
|
+
# Issue statuses.
|
|
11
|
+
ISSUE_STATUSES = %w[open resolved ignored].freeze
|
|
12
|
+
|
|
13
|
+
# Transport modes.
|
|
14
|
+
TRANSPORT_MODES = %w[local console].freeze
|
|
15
|
+
|
|
16
|
+
# ---------------------------------------------------------------------------
|
|
17
|
+
# Struct definitions
|
|
18
|
+
# ---------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
# SDK metadata shipped with every event.
|
|
21
|
+
SdkInfo = Struct.new(:name, :version, keyword_init: true)
|
|
22
|
+
|
|
23
|
+
# Contextual HTTP request information attached to an event.
|
|
24
|
+
RequestInfo = Struct.new(:method, :url, :headers, :body, :query, keyword_init: true)
|
|
25
|
+
|
|
26
|
+
# Information about a failed external operation (DB, auth, API, etc.).
|
|
27
|
+
OperationInfo = Struct.new(:provider, :type, :method, :params, :error_code, :error_details, keyword_init: true)
|
|
28
|
+
|
|
29
|
+
# User context attached to events.
|
|
30
|
+
UserInfo = Struct.new(:id, :email, :username, :session_id, keyword_init: true)
|
|
31
|
+
|
|
32
|
+
# Structured representation of a captured error.
|
|
33
|
+
ErrorInfo = Struct.new(:message, :type, :stack, :resolved_stack, :component_stack, keyword_init: true)
|
|
34
|
+
|
|
35
|
+
# A single breadcrumb entry.
|
|
36
|
+
Breadcrumb = Struct.new(:type, :category, :message, :timestamp, :data, :level, keyword_init: true)
|
|
37
|
+
|
|
38
|
+
# Detected runtime / platform information.
|
|
39
|
+
EnvironmentInfo = Struct.new(
|
|
40
|
+
:framework, :framework_version, :runtime, :runtime_version,
|
|
41
|
+
:platform, :os, :browser, :browser_version, :device_type,
|
|
42
|
+
:locale, :timezone, :url, :deploy,
|
|
43
|
+
keyword_init: true
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
# The canonical event payload sent to transports.
|
|
47
|
+
UncaughtEvent = Struct.new(
|
|
48
|
+
:event_id, :timestamp, :project_key, :level, :fingerprint,
|
|
49
|
+
:release, :error, :breadcrumbs, :request, :operation,
|
|
50
|
+
:environment, :user, :user_feedback, :fix_prompt, :sdk,
|
|
51
|
+
keyword_init: true
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# An entry in the issues.json index file.
|
|
55
|
+
IssueEntry = Struct.new(
|
|
56
|
+
:fingerprint, :title, :error_type, :count, :affected_users,
|
|
57
|
+
:first_seen, :last_seen, :status, :fix_prompt_file,
|
|
58
|
+
:latest_event_file, :release, :environment,
|
|
59
|
+
keyword_init: true
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# Configuration object.
|
|
63
|
+
Configuration = Struct.new(
|
|
64
|
+
:project_key, :endpoint, :environment, :release, :debug,
|
|
65
|
+
:enabled, :max_breadcrumbs, :max_events_per_minute,
|
|
66
|
+
:before_send, :sanitize_keys, :ignore_errors,
|
|
67
|
+
:transport, :local_output_dir, :webhook_url,
|
|
68
|
+
:framework, :framework_version,
|
|
69
|
+
keyword_init: true
|
|
70
|
+
) do
|
|
71
|
+
def initialize(**kwargs)
|
|
72
|
+
super(
|
|
73
|
+
enabled: true,
|
|
74
|
+
debug: false,
|
|
75
|
+
max_breadcrumbs: 20,
|
|
76
|
+
max_events_per_minute: 30,
|
|
77
|
+
transport: "local",
|
|
78
|
+
sanitize_keys: [],
|
|
79
|
+
ignore_errors: [],
|
|
80
|
+
**kwargs
|
|
81
|
+
)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
data/lib/uncaught.rb
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "set"
|
|
4
|
+
require "json"
|
|
5
|
+
require "time"
|
|
6
|
+
|
|
7
|
+
require_relative "uncaught/version"
|
|
8
|
+
require_relative "uncaught/types"
|
|
9
|
+
require_relative "uncaught/fingerprint"
|
|
10
|
+
require_relative "uncaught/breadcrumbs"
|
|
11
|
+
require_relative "uncaught/rate_limiter"
|
|
12
|
+
require_relative "uncaught/sanitizer"
|
|
13
|
+
require_relative "uncaught/env_detector"
|
|
14
|
+
require_relative "uncaught/prompt_builder"
|
|
15
|
+
require_relative "uncaught/transport"
|
|
16
|
+
require_relative "uncaught/client"
|
|
17
|
+
|
|
18
|
+
module Uncaught
|
|
19
|
+
class Error < StandardError; end
|
|
20
|
+
|
|
21
|
+
# Module-level singleton client.
|
|
22
|
+
@client = nil
|
|
23
|
+
@config = nil
|
|
24
|
+
@mutex = Mutex.new
|
|
25
|
+
|
|
26
|
+
class << self
|
|
27
|
+
# Configure the Uncaught SDK.
|
|
28
|
+
#
|
|
29
|
+
# @yield [Configuration] Yields the configuration object for modification.
|
|
30
|
+
# @return [Client] The configured client instance.
|
|
31
|
+
#
|
|
32
|
+
# @example
|
|
33
|
+
# Uncaught.configure do |config|
|
|
34
|
+
# config.project_key = "my-project"
|
|
35
|
+
# config.environment = "production"
|
|
36
|
+
# config.release = "1.0.0"
|
|
37
|
+
# end
|
|
38
|
+
def configure
|
|
39
|
+
@mutex.synchronize do
|
|
40
|
+
@config ||= Configuration.new
|
|
41
|
+
yield @config if block_given?
|
|
42
|
+
@client = Client.new(@config)
|
|
43
|
+
end
|
|
44
|
+
@client
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Return the current singleton client, or nil if not configured.
|
|
48
|
+
#
|
|
49
|
+
# @return [Client, nil]
|
|
50
|
+
def client
|
|
51
|
+
@client
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Return the current configuration, or nil if not configured.
|
|
55
|
+
#
|
|
56
|
+
# @return [Configuration, nil]
|
|
57
|
+
def configuration
|
|
58
|
+
@config
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Convenience: capture an error on the singleton client.
|
|
62
|
+
#
|
|
63
|
+
# @param error [Exception, String, Hash]
|
|
64
|
+
# @param kwargs [Hash] Additional context (request:, operation:, level:, etc.)
|
|
65
|
+
# @return [String, nil] The event ID.
|
|
66
|
+
def capture_error(error, **kwargs)
|
|
67
|
+
return nil unless @client
|
|
68
|
+
|
|
69
|
+
@client.capture_error(error, **kwargs)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Convenience: capture a message on the singleton client.
|
|
73
|
+
#
|
|
74
|
+
# @param message [String]
|
|
75
|
+
# @param level [String]
|
|
76
|
+
# @return [String, nil]
|
|
77
|
+
def capture_message(message, level: "info")
|
|
78
|
+
return nil unless @client
|
|
79
|
+
|
|
80
|
+
@client.capture_message(message, level: level)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Convenience: add a breadcrumb on the singleton client.
|
|
84
|
+
def add_breadcrumb(**kwargs)
|
|
85
|
+
return unless @client
|
|
86
|
+
|
|
87
|
+
@client.add_breadcrumb(**kwargs)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Convenience: set user on the singleton client.
|
|
91
|
+
def set_user(user)
|
|
92
|
+
return unless @client
|
|
93
|
+
|
|
94
|
+
@client.set_user(user)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Convenience: flush on the singleton client.
|
|
98
|
+
def flush
|
|
99
|
+
return unless @client
|
|
100
|
+
|
|
101
|
+
@client.flush
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Install global exception handler for at_exit.
|
|
105
|
+
#
|
|
106
|
+
# @example
|
|
107
|
+
# Uncaught.install_at_exit_handler!
|
|
108
|
+
def install_at_exit_handler!
|
|
109
|
+
at_exit do
|
|
110
|
+
if $! && !$!.is_a?(SystemExit)
|
|
111
|
+
Uncaught.capture_error($!)
|
|
112
|
+
Uncaught.flush
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Auto-load Rails integration if Rails is present.
|
|
120
|
+
if defined?(::Rails::Railtie)
|
|
121
|
+
require_relative "uncaught/integrations/rails"
|
|
122
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: uncaught
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Uncaught Dev
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-03-08 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: Catch bugs locally, get AI-powered fixes. Works with Rails and Sinatra.
|
|
14
|
+
email:
|
|
15
|
+
executables: []
|
|
16
|
+
extensions: []
|
|
17
|
+
extra_rdoc_files: []
|
|
18
|
+
files:
|
|
19
|
+
- lib/uncaught.rb
|
|
20
|
+
- lib/uncaught/breadcrumbs.rb
|
|
21
|
+
- lib/uncaught/client.rb
|
|
22
|
+
- lib/uncaught/env_detector.rb
|
|
23
|
+
- lib/uncaught/fingerprint.rb
|
|
24
|
+
- lib/uncaught/integrations/rails.rb
|
|
25
|
+
- lib/uncaught/integrations/sinatra.rb
|
|
26
|
+
- lib/uncaught/prompt_builder.rb
|
|
27
|
+
- lib/uncaught/rate_limiter.rb
|
|
28
|
+
- lib/uncaught/sanitizer.rb
|
|
29
|
+
- lib/uncaught/transport.rb
|
|
30
|
+
- lib/uncaught/types.rb
|
|
31
|
+
- lib/uncaught/version.rb
|
|
32
|
+
homepage: https://github.com/ajeeshworkspace/uncaught
|
|
33
|
+
licenses:
|
|
34
|
+
- MIT
|
|
35
|
+
metadata: {}
|
|
36
|
+
post_install_message:
|
|
37
|
+
rdoc_options: []
|
|
38
|
+
require_paths:
|
|
39
|
+
- lib
|
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
41
|
+
requirements:
|
|
42
|
+
- - ">="
|
|
43
|
+
- !ruby/object:Gem::Version
|
|
44
|
+
version: 2.7.0
|
|
45
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
46
|
+
requirements:
|
|
47
|
+
- - ">="
|
|
48
|
+
- !ruby/object:Gem::Version
|
|
49
|
+
version: '0'
|
|
50
|
+
requirements: []
|
|
51
|
+
rubygems_version: 3.0.3.1
|
|
52
|
+
signing_key:
|
|
53
|
+
specification_version: 4
|
|
54
|
+
summary: Local-first, AI-ready error monitoring for Ruby
|
|
55
|
+
test_files: []
|