recheck 0.4.0 → 0.5.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 +4 -4
- data/lib/recheck/commands.rb +4 -3
- data/lib/recheck/reporters.rb +15 -9
- data/lib/recheck/results.rb +1 -1
- data/lib/recheck/runner.rb +32 -27
- data/lib/recheck/version.rb +1 -1
- data/template/regression_checker_sample.rb +206 -0
- data/template/reporter_sample.rb +178 -0
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 229b7b48547c7da457bff99e2d10cef1d46a915ad4f3699dd0ae3ad29b7075af
|
4
|
+
data.tar.gz: 55d665725da5fe601a0c86ba9c4f62943702b56c7ae239aa3c8c1fe31e01b94c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b2b403ea3658c20f66b825f1198c3c6ea341161b84face61a83529c284135f230b069bd4db13f2550dde0e7965944ac36d3de56b3ec0cb4b579a99796e16dc5a
|
7
|
+
data.tar.gz: 1dbfd3a4dd3252b9e8603a9b9bbb28fb35255acdb4d068dfe74d55fde7e0683b53ff66b59c89eae29848070193a0ea48c8da51a78195e88ede9e3f8c35b6039a
|
data/lib/recheck/commands.rb
CHANGED
@@ -136,7 +136,7 @@ module Recheck
|
|
136
136
|
|
137
137
|
def run
|
138
138
|
create_helper
|
139
|
-
|
139
|
+
create_samples
|
140
140
|
create_site_checks
|
141
141
|
setup_model_checks
|
142
142
|
run_linter
|
@@ -168,8 +168,9 @@ module Recheck
|
|
168
168
|
copy_template("#{template_dir}/recheck_helper.rb", "recheck/recheck_helper.rb")
|
169
169
|
end
|
170
170
|
|
171
|
-
def
|
172
|
-
|
171
|
+
def create_samples
|
172
|
+
copy_template("#{template_dir}/reporter_sample.rb", "recheck/reporter/reporter.rb.sample")
|
173
|
+
copy_template("#{template_dir}/regression_checker_sample.rb", "recheck/regression/regression_checker.rb.sample")
|
173
174
|
end
|
174
175
|
|
175
176
|
def create_site_checks
|
data/lib/recheck/reporters.rb
CHANGED
@@ -35,10 +35,12 @@ module Recheck
|
|
35
35
|
#
|
36
36
|
# around_run -> for each Checker class:
|
37
37
|
# around_checker ->
|
38
|
-
#
|
39
|
-
#
|
40
|
-
# for each
|
41
|
-
#
|
38
|
+
# around_query ->
|
39
|
+
# run each query() method
|
40
|
+
# for each 'check_' method on the checker:
|
41
|
+
# for each record queried:
|
42
|
+
# around_check ->
|
43
|
+
# check(record)
|
42
44
|
|
43
45
|
def around_run(checkers: [])
|
44
46
|
total_count = yield
|
@@ -48,6 +50,10 @@ module Recheck
|
|
48
50
|
counts = yield
|
49
51
|
end
|
50
52
|
|
53
|
+
def around_query(checker:, query:, checks: [])
|
54
|
+
yield
|
55
|
+
end
|
56
|
+
|
51
57
|
def around_check(checker:, query:, check:, record:)
|
52
58
|
result = yield
|
53
59
|
end
|
@@ -97,20 +103,20 @@ module Recheck
|
|
97
103
|
|
98
104
|
def print_errors
|
99
105
|
failure_details = []
|
100
|
-
grouped_errors = @errors.group_by { |e| [e.
|
106
|
+
grouped_errors = @errors.group_by { |e| [e.checker, e.query, e.check, e.type] }
|
101
107
|
|
102
|
-
grouped_errors.each do |(
|
108
|
+
grouped_errors.each do |(checker, query, check), group_errors|
|
103
109
|
case group_errors.first.type
|
104
110
|
when :fail
|
105
111
|
ids = group_errors.map { |e| fetch_record_id(e.record) }.join(", ")
|
106
|
-
failure_details << " #{
|
112
|
+
failure_details << " #{checker}##{query} -> #{check} failed for records: #{ids}"
|
107
113
|
when :exception
|
108
114
|
error = group_errors.first
|
109
|
-
error_message = " #{
|
115
|
+
error_message = " #{checker}##{query} -> #{check} exception #{error.exception.message} for #{group_errors.size} records"
|
110
116
|
failure_details << error_message
|
111
117
|
failure_details << error.record.full_message(highlight: false, order: :top) if error.record.respond_to?(:full_message)
|
112
118
|
when :blanket
|
113
|
-
failure_details << " #{
|
119
|
+
failure_details << " #{checker}: Skipping because the first 20 checks all failed. Either there's a lot of bad data or there's something wrong with the checks."
|
114
120
|
end
|
115
121
|
end
|
116
122
|
puts failure_details
|
data/lib/recheck/results.rb
CHANGED
@@ -12,7 +12,7 @@ module Recheck
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
Error = Data.define(:checker, :query, :check, :record, :
|
15
|
+
Error = Data.define(:type, :checker, :query, :check, :record, :exception) do
|
16
16
|
def initialize(*args)
|
17
17
|
super
|
18
18
|
raise ArgumentError unless ERROR_TYPES.include? type
|
data/lib/recheck/runner.rb
CHANGED
@@ -110,39 +110,43 @@ module Recheck
|
|
110
110
|
reduce(reporters: @reporters, hook: :around_checker, kwargs: {checker:, queries:, checks:}) do
|
111
111
|
# for each query_...
|
112
112
|
queries.each do |query|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
113
|
+
reduce(reporters: @reporters, hook: :around_query, kwargs: {checker:, query:, checks:}) do
|
114
|
+
checker_counts.increment :queries
|
115
|
+
# for each record...
|
116
|
+
# TODO: must handle if the query method yields (find_each) OR returns (current)
|
117
|
+
(checker.public_send(query) || []).each do |record|
|
118
|
+
# for each check_method...
|
119
|
+
checks.each do |check|
|
120
|
+
raw_result = nil
|
121
|
+
reduce(reporters: @reporters, hook: :around_check, kwargs: {checker:, query:, check:, record:}) do
|
122
|
+
raw_result = checker.public_send(check, record)
|
123
|
+
result = raw_result ? pass : Error.new(checker:, query:, check:, record:, type: :fail, exception: nil)
|
124
|
+
|
125
|
+
checker_counts.increment(result.type)
|
126
|
+
break if checker_counts.reached_blanket_failure?
|
127
|
+
|
128
|
+
result
|
129
|
+
rescue *PASSTHROUGH_EXCEPTIONS
|
130
|
+
raise
|
131
|
+
rescue => e
|
132
|
+
Error.new(checker:, query:, check:, record:, type: :exception, exception: e)
|
133
|
+
end
|
132
134
|
end
|
133
|
-
|
134
|
-
@yields.raise_unless_all_reporters_yielded(hook: :around_check)
|
135
|
+
@yields.raise_unless_all_reporters_yielded(hook: :around_check)
|
135
136
|
|
136
|
-
|
137
|
-
|
138
|
-
|
137
|
+
# if the first 20 error out, halt the check method, it's probably buggy
|
138
|
+
if checker_counts.reached_blanket_failure?
|
139
|
+
checker_counts.increment :blanket
|
139
140
|
|
140
|
-
|
141
|
-
|
141
|
+
error = Error.new(checker:, query:, check: nil, record: nil, type: :blanket, exception: nil)
|
142
|
+
@reporters.each { it.halt(checker:, query:, check: nil, error:) }
|
142
143
|
|
143
|
-
|
144
|
+
break
|
145
|
+
end
|
144
146
|
end
|
147
|
+
nil # yield nothing around_query
|
145
148
|
end
|
149
|
+
@yields.raise_unless_all_reporters_yielded(hook: :around_query)
|
146
150
|
rescue *PASSTHROUGH_EXCEPTIONS
|
147
151
|
raise
|
148
152
|
rescue => e
|
@@ -160,6 +164,7 @@ module Recheck
|
|
160
164
|
@total_counts
|
161
165
|
end
|
162
166
|
@yields.raise_unless_all_reporters_yielded(hook: :around_run)
|
167
|
+
@total_counts
|
163
168
|
end
|
164
169
|
end
|
165
170
|
end
|
data/lib/recheck/version.rb
CHANGED
@@ -0,0 +1,206 @@
|
|
1
|
+
# Recheck Checker API Documentation
|
2
|
+
#
|
3
|
+
# This file documents the complete Checker API for Recheck.
|
4
|
+
# Use this as a reference when creating your own checkers.
|
5
|
+
|
6
|
+
# All checkers must inherit from Recheck::Checker::Base to be registered
|
7
|
+
class SampleChecker < Recheck::Checker::Base
|
8
|
+
#
|
9
|
+
# CHECKER LIFECYCLE AND HOOKS
|
10
|
+
# ==========================
|
11
|
+
#
|
12
|
+
# Checkers have a simple lifecycle with four hooks:
|
13
|
+
#
|
14
|
+
# 1. initialize - Optional setup
|
15
|
+
# 2. query_* methods - Required to fetch records to check
|
16
|
+
# 3. check_* methods - Required to validate each record
|
17
|
+
# 4. Metadata methods - Optional for routing and prioritization
|
18
|
+
#
|
19
|
+
|
20
|
+
# Hook 1: initialize (optional)
|
21
|
+
# ----------------------------
|
22
|
+
# Use initialize to set up any resources needed by your checks.
|
23
|
+
# This runs once when the checker is instantiated.
|
24
|
+
def initialize
|
25
|
+
# You can:
|
26
|
+
# - Connect to external services
|
27
|
+
# - Load reference data
|
28
|
+
# - Set up caches or other shared resources
|
29
|
+
# - Configure the checker based on environment
|
30
|
+
|
31
|
+
@external_service = ExternalService.new(api_key: ENV["API_KEY"])
|
32
|
+
@reference_data = load_reference_data
|
33
|
+
@cache = {}
|
34
|
+
end
|
35
|
+
|
36
|
+
# You can use helper methods to organize your code
|
37
|
+
def load_reference_data
|
38
|
+
# Load data from a file, database, or API
|
39
|
+
# This is just a helper method, not part of the Checker API
|
40
|
+
{}
|
41
|
+
end
|
42
|
+
|
43
|
+
# Hook 2: query_* methods (one required)
|
44
|
+
# ---------------------------------
|
45
|
+
# At least one query method is required. Query methods must:
|
46
|
+
# - Start with "query" (or they won't be detected)
|
47
|
+
# - Return an Enumerable of records to check
|
48
|
+
# - Be efficient (they often run against production databases)
|
49
|
+
|
50
|
+
# Basic query method - returns all records of a type
|
51
|
+
def query
|
52
|
+
# The simplest query just returns all records
|
53
|
+
# Use find_each with ActiveRecord for batching
|
54
|
+
Model.find_each
|
55
|
+
end
|
56
|
+
|
57
|
+
# You can have multiple query methods to:
|
58
|
+
# - Check different record types
|
59
|
+
# - Optimize performance with targeted queries
|
60
|
+
# - Focus on specific subsets of data
|
61
|
+
def query_recent
|
62
|
+
# Focus on recently created/updated records
|
63
|
+
Model.where("updated_at > ?", 1.day.ago).find_each
|
64
|
+
end
|
65
|
+
|
66
|
+
def query_problematic
|
67
|
+
# Target records that might have issues
|
68
|
+
Model.where(status: "error")
|
69
|
+
.or(Model.where(processed_at: nil))
|
70
|
+
.includes(:related_records) # Eager load associations
|
71
|
+
.find_each
|
72
|
+
end
|
73
|
+
|
74
|
+
# Query methods can return any Enumerable, not just ActiveRecord
|
75
|
+
def query_external_data
|
76
|
+
# You can check data from external sources
|
77
|
+
@external_service.fetch_records.map do |record|
|
78
|
+
# Transform external data if needed
|
79
|
+
{id: record["id"], data: record["payload"]}
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Query methods can return arrays, hashes, or custom objects
|
84
|
+
def query_composite
|
85
|
+
# You can join data from multiple sources
|
86
|
+
[
|
87
|
+
{type: "config", value: AppConfig.settings},
|
88
|
+
{type: "status", value: SystemStatus.current}
|
89
|
+
]
|
90
|
+
end
|
91
|
+
|
92
|
+
# Hook 3: check_* methods (one required)
|
93
|
+
# ---------------------------------
|
94
|
+
# Check methods must:
|
95
|
+
# - Start with "check_" (or they won't be detected)
|
96
|
+
# - Take a single record parameter
|
97
|
+
# - Return false/nil for failing records, anything else for passing
|
98
|
+
|
99
|
+
# Basic check - validates a single aspect of a record
|
100
|
+
def check_record_is_valid(record)
|
101
|
+
# The simplest check just calls ActiveRecord validations
|
102
|
+
# Returns false if invalid, true if valid
|
103
|
+
record.valid?
|
104
|
+
end
|
105
|
+
|
106
|
+
# Checks can implement complex business rules
|
107
|
+
def check_business_rule(record)
|
108
|
+
# Implement any business logic
|
109
|
+
# Return false/nil for failing records
|
110
|
+
if record.status == "completed" && record.completed_at.nil?
|
111
|
+
# This is a failing condition
|
112
|
+
return false
|
113
|
+
end
|
114
|
+
|
115
|
+
# Any non-false/nil return is considered passing
|
116
|
+
true
|
117
|
+
end
|
118
|
+
|
119
|
+
# Checks can integrate with external systems
|
120
|
+
def check_external_consistency(record)
|
121
|
+
# Check that record matches external system
|
122
|
+
external_data = @external_service.find(record.external_id)
|
123
|
+
|
124
|
+
# Return false if inconsistent
|
125
|
+
return false if external_data.nil?
|
126
|
+
return false if external_data["status"] != record.status
|
127
|
+
|
128
|
+
# Return true if consistent
|
129
|
+
true
|
130
|
+
end
|
131
|
+
|
132
|
+
# Checks can automatically fix issues (use carefully!)
|
133
|
+
def check_and_fix(record)
|
134
|
+
# Check if there's an issue
|
135
|
+
if record.calculated_total != record.stored_total
|
136
|
+
# Fix the issue
|
137
|
+
record.stored_total = record.calculated_total
|
138
|
+
record.save!
|
139
|
+
|
140
|
+
# Log the fix
|
141
|
+
LoggingService.info("Fixed total for record #{record.id}")
|
142
|
+
end
|
143
|
+
|
144
|
+
# Return true since we've fixed the issue
|
145
|
+
true
|
146
|
+
end
|
147
|
+
|
148
|
+
# Checks can handle different record types from different queries
|
149
|
+
def check_config_is_valid(record)
|
150
|
+
# Handle records from query_composite
|
151
|
+
if record[:type] == "config"
|
152
|
+
# Check config settings
|
153
|
+
return record[:value].valid?
|
154
|
+
elsif record[:type] == "status"
|
155
|
+
# Check system status
|
156
|
+
return record[:value].ok?
|
157
|
+
end
|
158
|
+
|
159
|
+
# Skip records this check doesn't understand
|
160
|
+
true
|
161
|
+
end
|
162
|
+
|
163
|
+
#
|
164
|
+
# METADATA METHODS
|
165
|
+
# ===============
|
166
|
+
#
|
167
|
+
# These optional methods provide metadata about your checker
|
168
|
+
# for use by reporters and the Recheck runner.
|
169
|
+
#
|
170
|
+
|
171
|
+
# Team responsible for this checker
|
172
|
+
# Used by reporters to route notifications
|
173
|
+
def team
|
174
|
+
:data_integrity
|
175
|
+
end
|
176
|
+
|
177
|
+
# Priority of this checker
|
178
|
+
# Used by reporters to prioritize notifications
|
179
|
+
def priority
|
180
|
+
:high # :high, :medium, :low
|
181
|
+
end
|
182
|
+
|
183
|
+
# Tags for this checker
|
184
|
+
# Used for filtering and categorization
|
185
|
+
def tags
|
186
|
+
[:critical, :customer_facing]
|
187
|
+
end
|
188
|
+
|
189
|
+
# Documentation URL
|
190
|
+
# Link to runbook or documentation
|
191
|
+
def documentation_url
|
192
|
+
"https://internal-docs.example.com/data-integrity/sample-checker"
|
193
|
+
end
|
194
|
+
|
195
|
+
# Slack channel for notifications
|
196
|
+
# Used by SlackReporter
|
197
|
+
def slack_channel
|
198
|
+
"#data-alerts"
|
199
|
+
end
|
200
|
+
|
201
|
+
# Email recipients for notifications
|
202
|
+
# Perhaps used by EmailReporter
|
203
|
+
def email_recipients
|
204
|
+
["data-team@example.com", "oncall@example.com"]
|
205
|
+
end
|
206
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Reporters are how you turn failing checks into emails, bug tracker tickets,
|
4
|
+
# or any other useful notification or report. You can notify different teams
|
5
|
+
# however they most "enjoy" hearing about bad data.
|
6
|
+
|
7
|
+
class SampleReporter < Recheck::Reporter::Base
|
8
|
+
# Optional but strongly recommended: Provide help text that appears when running `recheck
|
9
|
+
# reporters`. This should briefly explain what your reporter does and any argument it takes.
|
10
|
+
def self.help
|
11
|
+
"A template reporter showing how to implement your own custom reporter. Takes an optional argument."
|
12
|
+
end
|
13
|
+
|
14
|
+
# Optional: Initialize with the argument string from the command line.
|
15
|
+
# The arg is passed as a single string, or nil if no arg is provided
|
16
|
+
# Arguments:
|
17
|
+
# * arg: The string argument passed after the colon in the reporter specification
|
18
|
+
# For example: `--reporter SampleReporter:api_key_123` -> `api_key_123`
|
19
|
+
def initialize(arg:)
|
20
|
+
# Process your argument here if needed
|
21
|
+
@config = arg || "default_config"
|
22
|
+
end
|
23
|
+
|
24
|
+
# Important: If you define an around_ hook, it must 'yield' to run the next step.
|
25
|
+
# A hook method's return value is not used.
|
26
|
+
|
27
|
+
# around_run: Fires around the entire run.
|
28
|
+
# This is a good place to set up resources, send summary emails, etc.
|
29
|
+
# Arguments:
|
30
|
+
# * checkers: Array of checker instances that will be run
|
31
|
+
def around_run(checkers: [])
|
32
|
+
# Setup before the run
|
33
|
+
start_time = Time.now
|
34
|
+
|
35
|
+
# yield returns: a CountStats about the entire run
|
36
|
+
# CountStats tracks counts of passes, failures, and other result types
|
37
|
+
# It provides methods like #all_pass?, #any_errors?, #summary, etc.
|
38
|
+
total_counts = yield
|
39
|
+
|
40
|
+
# Teardown/reporting after the run
|
41
|
+
duration = Time.now - start_time
|
42
|
+
|
43
|
+
# Example of how you might report results
|
44
|
+
if total_counts.any_errors?
|
45
|
+
puts "SampleReporter: Found errors in #{duration.round(2)}s: #{total_counts.summary}"
|
46
|
+
# In a real reporter, you might:
|
47
|
+
# - Send an email
|
48
|
+
# - Post to Slack
|
49
|
+
# - Create a ticket in your issue tracker
|
50
|
+
# - Log to a monitoring service
|
51
|
+
end
|
52
|
+
|
53
|
+
# Return the counts (optional)
|
54
|
+
total_counts
|
55
|
+
end
|
56
|
+
|
57
|
+
# around_checker: Fires around each checker.
|
58
|
+
# Arguments:
|
59
|
+
# * checker: The checker instance being run
|
60
|
+
# * queries: Array of query method names defined on the checker
|
61
|
+
# * checks: Array of check method names defined on the checker
|
62
|
+
def around_checker(checker:, queries: [], checks: [])
|
63
|
+
# Before running this checker
|
64
|
+
checker_name = checker.class.name
|
65
|
+
|
66
|
+
# yields returns a CountStats for the checker
|
67
|
+
counts = yield
|
68
|
+
|
69
|
+
# After running this checker
|
70
|
+
if counts.any_errors?
|
71
|
+
puts "SampleReporter: Checker #{checker_name} had issues: #{counts.summary}"
|
72
|
+
# In a real reporter, you might group errors by checker
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# around_query: Fires around each query
|
77
|
+
# This is useful for tracking which queries are slow or problematic
|
78
|
+
# Arguments:
|
79
|
+
# * checker: The checker instance being run
|
80
|
+
# * query: The name of the query method being executed
|
81
|
+
# * checks: Array of check method names that will be run against query results
|
82
|
+
def around_query(checker:, query:, checks: [])
|
83
|
+
# Before running this query
|
84
|
+
query_start = Time.now
|
85
|
+
|
86
|
+
# yield does not return anything for this hook
|
87
|
+
yield
|
88
|
+
|
89
|
+
# After running this query
|
90
|
+
query_duration = Time.now - query_start
|
91
|
+
if query_duration > 5 # seconds
|
92
|
+
puts "SampleReporter: Slow query #{checker.class.name}##{query} took #{query_duration.round(2)}s"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# The around_check and halt hooks both receive one of two result objects.
|
97
|
+
#
|
98
|
+
# Recheck::Pass: A successful check.
|
99
|
+
# Attributes:
|
100
|
+
# #type: always :pass
|
101
|
+
#
|
102
|
+
# Recheck::Error: A failed check.
|
103
|
+
# Attributes:
|
104
|
+
# #type: One of the following symbols
|
105
|
+
# fail: The check returned a falsey value
|
106
|
+
# exception: The check raised an exception
|
107
|
+
# blanket: The first 20 checks all failed or raised; the runner skips
|
108
|
+
# no_query_methods: The checker does not define a query_methods
|
109
|
+
# no_queries: The checker defines query_methods, but did not return any
|
110
|
+
# no_check_methods: The checker does not define a check_methods
|
111
|
+
# no_checks: The checker defines check_methods, but did not return any
|
112
|
+
# #checker: Checker instance
|
113
|
+
# #query: Query method name
|
114
|
+
# #check: Check method name
|
115
|
+
# #record: The record being checked
|
116
|
+
# #exception: rescued Exception
|
117
|
+
#
|
118
|
+
|
119
|
+
# around_check: Fires for each call to a check_ method on each record
|
120
|
+
# This is where you can collect detailed information about failures.
|
121
|
+
# Arguments:
|
122
|
+
# * checker: The checker instance being run
|
123
|
+
# * query: The name of the query method that produced this record
|
124
|
+
# * check: The name of the check method being executed
|
125
|
+
# * record: The individual record being checked
|
126
|
+
def around_check(checker:, query:, check:, record:)
|
127
|
+
# Returns a result object, see comment above
|
128
|
+
result = yield
|
129
|
+
|
130
|
+
# Process the result
|
131
|
+
if result.is_a?(Recheck::Error)
|
132
|
+
case result.type
|
133
|
+
when :fail
|
134
|
+
record_id = fetch_record_id(result.record)
|
135
|
+
puts "SampleReporter: #{checker.class.name}##{check} failed for record: #{record_id}"
|
136
|
+
when :exception
|
137
|
+
puts "SampleReporter: #{checker.class.name}##{check} raised exception: #{result.exception.message}"
|
138
|
+
end
|
139
|
+
|
140
|
+
# In a real reporter, you might:
|
141
|
+
# - Collect failures to report in a batch
|
142
|
+
# - Send immediate alerts for critical failures
|
143
|
+
# - Log to a monitoring system
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# halt: Called when a checker is halted due to an error.
|
148
|
+
# This is useful for reporting fatal errors that prevent checks from running
|
149
|
+
# Arguments:
|
150
|
+
# * checker: The checker instance that was halted
|
151
|
+
# * query: The name of the query method that was running (if any)
|
152
|
+
# * check: The name of the check method that was running (if any)
|
153
|
+
# * error: The error result, see comment above around_check
|
154
|
+
def halt(checker:, query:, error:, check: nil)
|
155
|
+
puts "SampleReporter: Halted #{checker.class.name}##{query} due to #{error.type}"
|
156
|
+
|
157
|
+
# In a real reporter, you might:
|
158
|
+
# - Send an urgent alert
|
159
|
+
# - Create a high-priority ticket
|
160
|
+
# - Log a critical error
|
161
|
+
end
|
162
|
+
|
163
|
+
# You can add any helper methods, include modules, etc.
|
164
|
+
|
165
|
+
# Example of a helper method to format data for reporting
|
166
|
+
def format_error_message(error)
|
167
|
+
case error.type
|
168
|
+
when :fail
|
169
|
+
"Record is invalid"
|
170
|
+
when :exception
|
171
|
+
"Exception occurred: #{error.exception.message}"
|
172
|
+
when :blanket
|
173
|
+
"Blanket failure - first 20 checks all failed"
|
174
|
+
else
|
175
|
+
"Other error: #{error.type}"
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: recheck
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Bhat Harkins
|
@@ -71,6 +71,8 @@ files:
|
|
71
71
|
- lib/recheck/runner.rb
|
72
72
|
- lib/recheck/version.rb
|
73
73
|
- template/recheck_helper.rb
|
74
|
+
- template/regression_checker_sample.rb
|
75
|
+
- template/reporter_sample.rb
|
74
76
|
- template/site/dns_checker.rb
|
75
77
|
- template/site/tls_checker.rb
|
76
78
|
- template/site/whois_checker.rb
|