Skip to content

Commit 69a1cc6

Browse files
committed
huge improvements to the way logs are typed. event-based log types instead of source-based for much finer control
1 parent cb57a34 commit 69a1cc6

154 files changed

Lines changed: 5325 additions & 1692 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.cspell/project-words.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ binstubs
88
Bugsnag
99
bytesize
1010
carrierwave
11+
codegen
1112
creds
1213
dalli
14+
defn
1315
docspring
1416
dotenv
1517
Dotenv
@@ -22,16 +24,19 @@ Honeybadger
2224
hotwire
2325
hrefs
2426
instrumenter
27+
Itest
2528
kamal
2629
klass
2730
kwargs
2831
lightningcss
2932
lockfiles
3033
logdev
34+
logfield
3135
Logstop
3236
LogStruct
3337
metaprogramming
3438
mswin
39+
nilability
3540
nilable
3641
optparse
3742
parseable

.prettierignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ site/.next
66
site/out
77

88
site/lib/log-generation/sample-data.ts
9-
site/lib/log-generation/log-keys.json
9+
site/lib/log-generation/log-fields.json
1010
site/lib/log-generation/log-types.ts
1111
site/lib/log-generation/sorbet-*.json
1212
site/public/coverage

.rubocop.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ AllCops:
1717
- public/**/*
1818
- vendor/**/*
1919
- tmp/**/*
20+
- docspring/**/*
2021
- sorbet/rbi/dsl/**/*
2122
- sorbet/rbi/gems/**/*
2223
- sorbet/rbi/annotations/**/*
@@ -86,6 +87,14 @@ Sorbet/StrictSigil:
8687
- 'scripts/**/*.rb'
8788
SuggestedStrictness: strict
8889

90+
Sorbet/ForbidUntypedStructProps:
91+
Exclude:
92+
- 'lib/log_struct/log/plain.rb'
93+
94+
Sorbet/ConstantsFromStrings:
95+
Exclude:
96+
- 'scripts/generate_log_fields_json.rb'
97+
8998
# Require typed: true for test files
9099
Sorbet/TrueSigil:
91100
Enabled: true

.vscode/settings.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
{
22
"rubyLsp.formatter": "rubocop",
33
"rubocop.safeAutocorrect": false,
4-
"editor.formatOnSave": true
4+
"editor.formatOnSave": true,
5+
"yaml.schemas": {
6+
"./schemas/meta/log-source-schema.json": ["schemas/log_sources/*.yml"]
7+
}
58
}

Gemfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ group :test do
3333
gem "simplecov-json", "~> 0.2", require: false
3434
gem "climate_control", "~> 1.2"
3535
gem "thor"
36+
gem "json_schemer"
3637
end
3738

3839
# Development and linting tools that may have higher Ruby version requirements
@@ -50,6 +51,7 @@ group :development do
5051
# gem "rubocop-rails", require: false
5152
gem "rubocop-minitest", require: false
5253
gem "rubocop-sorbet", require: false
54+
gem "rubocop-inflector", require: false
5355
gem "rubocop", require: false
5456
gem "solargraph", require: false
5557
gem "standard", ">= 1.35.1", require: false

Gemfile.lock

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ GEM
136136
ffi (1.17.1-x86_64-linux-musl)
137137
globalid (1.2.1)
138138
activesupport (>= 6.1)
139+
hana (1.3.7)
139140
honeybadger (5.26.4)
140141
logger
141142
ostruct
@@ -151,6 +152,11 @@ GEM
151152
reline (>= 0.4.2)
152153
jaro_winkler (1.6.0)
153154
json (2.10.1)
155+
json_schemer (2.4.0)
156+
bigdecimal
157+
hana (~> 1.3)
158+
regexp_parser (~> 2.0)
159+
simpleidn (~> 0.2)
154160
jsonapi-renderer (0.2.2)
155161
kramdown (2.5.1)
156162
rexml (>= 3.3.9)
@@ -298,13 +304,19 @@ GEM
298304
unicode-display_width (>= 2.4.0, < 4.0)
299305
rubocop-ast (1.38.1)
300306
parser (>= 3.3.1.0)
307+
rubocop-inflector (1.0.0)
308+
activesupport
309+
rubocop
310+
rubocop-rspec
301311
rubocop-minitest (0.37.0)
302312
lint_roller (~> 1.1)
303313
rubocop (>= 1.61, < 2.0)
304314
rubocop-ast (>= 1.38.0, < 2.0)
305315
rubocop-performance (1.23.1)
306316
rubocop (>= 1.48.1, < 2.0)
307317
rubocop-ast (>= 1.31.1, < 2.0)
318+
rubocop-rspec (3.4.0)
319+
rubocop (~> 1.61)
308320
rubocop-sorbet (0.8.9)
309321
rubocop (>= 1)
310322
ruby-progressbar (1.13.0)
@@ -336,6 +348,7 @@ GEM
336348
json
337349
simplecov
338350
simplecov_json_formatter (0.1.4)
351+
simpleidn (0.2.3)
339352
solargraph (0.52.0)
340353
backport (~> 1.2)
341354
benchmark
@@ -440,6 +453,7 @@ DEPENDENCIES
440453
debug
441454
drb
442455
honeybadger (~> 5.4)
456+
json_schemer
443457
listen
444458
logstruct!
445459
minitest (~> 5.20)
@@ -450,6 +464,7 @@ DEPENDENCIES
450464
redcarpet
451465
rollbar (~> 3.4)
452466
rubocop
467+
rubocop-inflector
453468
rubocop-minitest
454469
rubocop-performance
455470
rubocop-sorbet

INTEGRATIONS.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@
6868
2. Register the log type
6969
- In `lib/log_struct/log.rb`:
7070
- `require_relative "log/<name>"`
71-
- Add `T.class_of(LogStruct::Log::<Name>)` to `LogClassType`.
7271

7372
3. Add a config toggle
7473
- In `lib/log_struct/config_struct/integrations.rb`:
@@ -134,7 +133,6 @@
134133
- Don’t emit generic/plain logs for integrations that deserve a first‑class type.
135134
- Keep message names short and stable; avoid dumping raw payloads into `msg`.
136135
- Don’t raise in integration hooks; always call `handle_exception` with the correct `Source`.
137-
- Docs auto‑generation depends on the log type being included in `LogClassType` and the TypeScript export.
138136

139137
**One‑Time Commands (after adding or changing log types)**
140138

lefthook.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ pre-commit:
2020
glob: 'lib/**/*.rb'
2121
run: scripts/export_typescript_types.rb
2222

23+
- name: codegen-sync
24+
glob: '{schemas/log_sources/**/*,scripts/templates/generate_log_structs/**/*,scripts/generate_log_structs.rb}'
25+
run: scripts/check_generated.sh
26+
2327
- name: cspell
2428
glob: '*.{rb,md,yml,yaml,txt,ts,tsx,js,jsx}'
2529
run: scripts/spellcheck.sh
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# typed: strict
2+
# frozen_string_literal: true
3+
4+
require_relative "../log/active_job/enqueue"
5+
require_relative "../log/active_job/schedule"
6+
require_relative "../log/active_job/start"
7+
require_relative "../log/active_job/finish"
8+
9+
module LogStruct
10+
module Builders
11+
module ActiveJob
12+
extend T::Sig
13+
14+
sig { params(job: T.untyped).returns(T.nilable(String)) }
15+
def self.safe_provider_job_id(job)
16+
job.respond_to?(:provider_job_id) ? job.provider_job_id : nil
17+
end
18+
19+
sig { params(job: T.untyped).returns(T.nilable(Integer)) }
20+
def self.safe_executions(job)
21+
job.respond_to?(:executions) ? job.executions : nil
22+
end
23+
24+
sig { params(job: T.untyped).returns(T.nilable(T::Array[T.untyped])) }
25+
def self.safe_arguments(job)
26+
return nil unless job.class.respond_to?(:log_arguments?)
27+
job.class.log_arguments? ? job.arguments : nil
28+
end
29+
30+
sig { params(job: T.untyped).returns(Log::ActiveJob::Enqueue) }
31+
def self.enqueue(job)
32+
Log::ActiveJob::Enqueue.new(
33+
job_id: job.job_id,
34+
job_class: job.class.to_s,
35+
queue_name: job.queue_name,
36+
arguments: safe_arguments(job),
37+
executions: safe_executions(job),
38+
provider_job_id: safe_provider_job_id(job)
39+
)
40+
end
41+
42+
sig { params(job: T.untyped, scheduled_at: Time).returns(Log::ActiveJob::Schedule) }
43+
def self.schedule(job, scheduled_at:)
44+
Log::ActiveJob::Schedule.new(
45+
job_id: job.job_id,
46+
job_class: job.class.to_s,
47+
queue_name: job.queue_name,
48+
arguments: safe_arguments(job),
49+
executions: safe_executions(job),
50+
provider_job_id: safe_provider_job_id(job),
51+
scheduled_at: scheduled_at
52+
)
53+
end
54+
55+
sig { params(job: T.untyped, started_at: Time, attempt: T.nilable(Integer)).returns(Log::ActiveJob::Start) }
56+
def self.start(job, started_at:, attempt:)
57+
Log::ActiveJob::Start.new(
58+
job_id: job.job_id,
59+
job_class: job.class.to_s,
60+
queue_name: job.queue_name,
61+
arguments: safe_arguments(job),
62+
executions: safe_executions(job),
63+
provider_job_id: safe_provider_job_id(job),
64+
started_at: started_at,
65+
attempt: attempt
66+
)
67+
end
68+
69+
sig { params(job: T.untyped, duration_ms: Float, finished_at: Time).returns(Log::ActiveJob::Finish) }
70+
def self.finish(job, duration_ms:, finished_at:)
71+
Log::ActiveJob::Finish.new(
72+
job_id: job.job_id,
73+
job_class: job.class.to_s,
74+
queue_name: job.queue_name,
75+
arguments: safe_arguments(job),
76+
executions: safe_executions(job),
77+
provider_job_id: safe_provider_job_id(job),
78+
duration_ms: duration_ms,
79+
finished_at: finished_at
80+
)
81+
end
82+
end
83+
end
84+
end

lib/log_struct/concerns/error_handling.rb

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,7 @@ def error_handling_mode_for(source)
3838
sig { params(error: StandardError, source: Source, context: T.nilable(T::Hash[Symbol, T.untyped])).void }
3939
def log_error(error, source:, context: nil)
4040
# Create structured log entry
41-
error_log = Log::Error.from_exception(
42-
source,
43-
error,
44-
context || {}
45-
)
41+
error_log = Log.from_exception(source, error, context || {})
4642
LogStruct.error(error_log)
4743
end
4844

0 commit comments

Comments
 (0)