Skip to content

Commit c34630a

Browse files
authored
Move StenoIO into Steno namespace as Steno::LoggerIO (#4905)
- Add Steno::LoggerIO: IO adapter wrapping Steno::Logger, forwarding write/puts to the logger at a configured log level - Add tests for Steno::LoggerIO - Remove StenoIO and its spec - Update Steno::Logger: broaden callstack filter from logger.rb only to all frames within lib/steno/, so records logged via Steno::LoggerIO are attributed to the correct caller - Update PumaRunner to use Steno::LoggerIO instead of StenoIO - Update lib/steno/README.md: document changes as modification #8
1 parent 3e8a46c commit c34630a

8 files changed

Lines changed: 70 additions & 51 deletions

File tree

lib/cloud_controller/runners/puma_runner.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
require 'puma'
22
require 'puma/configuration'
33
require 'puma/events'
4-
require 'cloud_controller/logs/steno_io'
4+
require 'steno/steno'
55
require 'cloud_controller/execution_context'
66

77
module VCAP::CloudController
@@ -51,7 +51,7 @@ def initialize(config, app, logger, periodic_updater, request_logs)
5151
conf.before_worker_shutdown { request_logs.log_incomplete_requests if request_logs }
5252
end
5353

54-
log_writer = Puma::LogWriter.new(StenoIO.new(logger, :info), StenoIO.new(logger, :error))
54+
log_writer = Puma::LogWriter.new(Steno::LoggerIO.new(logger, :info), Steno::LoggerIO.new(logger, :error))
5555

5656
events = Puma::Events.new
5757
events.after_booted { @periodic_updater.setup_updates }

lib/steno/README.md

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ This is a **modified version** of the original Steno library, adapted for CCNG's
2323
- Custom RFC3339 codec (previously in `lib/steno_custom_codec_temp/`)
2424
- LICENSE file (Apache 2.0 - for attribution)
2525
- NOTICE file (Apache 2.0 copyright notices)
26-
- Test suite (in `spec/unit/lib/steno/`)
26+
- Test suite (in `spec/isolated_specs/steno/`)
2727

2828
## What Was Excluded
2929

@@ -66,7 +66,7 @@ Syslog.close if Syslog.opened?
6666
- Required adding `require 'active_support/core_ext/module/delegation'`
6767

6868
### 4. Test Structure Updates
69-
- Moved tests from `lib/steno/spec/` to `spec/unit/lib/steno/` (CCNG convention)
69+
- Moved tests from `lib/steno/spec/` to `spec/isolated_specs/steno/` (CCNG convention)
7070
- Removed global spec_helper requires, added explicit requires per test
7171
- Wrapped test describes in parent `RSpec.describe` blocks
7272

@@ -75,7 +75,7 @@ Syslog.close if Syslog.opened?
7575

7676
**Removed**:
7777
- `lib/steno/sink/eventlog.rb` (Windows Event Log sink)
78-
- `spec/unit/lib/steno/unit/sink/eventlog_spec.rb`
78+
- `spec/isolated_specs/steno/unit/sink/eventlog_spec.rb`
7979
- Windows conditionals from config.rb, syslog.rb, test files
8080
- `WINDOWS` constant from sink/base.rb
8181

@@ -86,8 +86,8 @@ Syslog.close if Syslog.opened?
8686
- `lib/steno/version.rb` - Version constant no longer needed (not a gem)
8787
- `lib/steno/json_prettifier.rb` - CLI tool for prettifying logs, unused (~110 lines)
8888
- `lib/steno/core_ext.rb` - Monkey patches for `.logger` on Module/Class/Object, CCNG uses `Steno.logger()` instead (~50 lines)
89-
- `spec/unit/lib/steno/unit/json_prettifier_spec.rb` - Tests for removed feature
90-
- `spec/unit/lib/steno/unit/core_ext_spec.rb` - Tests for removed feature
89+
- `spec/isolated_specs/steno/unit/json_prettifier_spec.rb` - Tests for removed feature
90+
- `spec/isolated_specs/steno/unit/core_ext_spec.rb` - Tests for removed feature
9191
- Removed `require 'steno/version'` from steno.rb
9292

9393
**What's kept** (even if unused):
@@ -120,6 +120,16 @@ Syslog.close if Syslog.opened?
120120
- `Steno::Context::Null` - Default fallback context
121121
- All log levels including debug1, debug2 - debug2 is actively used
122122

123+
### 8. LoggerIO Adapter for Puma Integration
124+
**Rationale**: `Puma::LogWriter` requires IO-compatible objects. Previously, a `StenoIO` class existed outside the Steno library to bridge this gap. Since Steno is now inlined, the adapter was moved into the Steno namespace for consistency.
125+
126+
**Added**:
127+
- `lib/steno/logger_io.rb`: `Steno::LoggerIO` - an IO adapter that wraps a `Steno::Logger` and forwards `write`/`puts` calls to it at a configured log level. Used by `PumaRunner` to pass Steno loggers as IO objects to `Puma::LogWriter`.
128+
- `spec/isolated_specs/steno/unit/logger_io_spec.rb`: Tests for `Steno::LoggerIO`.
129+
130+
**Modified**:
131+
- `lib/steno/logger.rb`: Broadened the callstack filter from removing only frames from `logger.rb` to removing all frames within `lib/steno/`. This ensures that log records originating via `Steno::LoggerIO` correctly attribute the source location to the caller rather than to the adapter itself.
132+
123133
---
124134

125135
## Making Future Modifications
@@ -129,7 +139,7 @@ If you modify this integrated steno library:
129139
1. **Document changes** in the "Modifications Made After Integration" section above
130140
2. **Include rationale** for why the change was made
131141
3. **List affected files** and what changed
132-
4. **Run tests** to ensure nothing breaks: `bundle exec rspec spec/unit/lib/steno/`
142+
4. **Run tests** to ensure nothing breaks: `bundle exec rspec spec/isolated_specs/steno/`
133143
5. **Update this README** in the same commit as your changes
134144

135145
## Original Steno Commit History (102 commits)

lib/steno/logger.rb

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -128,21 +128,11 @@ def log(level_name, message=nil, user_data=nil)
128128
private
129129

130130
def parse_record_loc(callstack)
131-
file = nil
132-
lineno = nil
133-
method = nil
131+
frame = callstack.find { |f| f !~ %r{/lib/steno/} } || callstack.last
134132

135-
callstack.each do |frame|
136-
next if frame =~ /logger\.rb/
137-
138-
file, lineno, method = frame.split(':')
139-
140-
lineno = lineno.to_i
141-
142-
method = ::Regexp.last_match(1) if method =~ /in `([^']+)/
143-
144-
break
145-
end
133+
file, lineno, method = frame.split(':')
134+
lineno = lineno.to_i
135+
method = ::Regexp.last_match(1) if method =~ /in `([^`']+)/
146136

147137
[file, lineno, method]
148138
end
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
class StenoIO
1+
module Steno
2+
end
3+
4+
class Steno::LoggerIO
25
def initialize(logger, level)
36
@logger = logger
47
@level = level

lib/steno/steno.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
require 'steno/context'
44
require 'steno/errors'
55
require 'steno/log_level'
6+
require 'steno/logger_io'
67
require 'steno/logger'
78
require 'steno/record'
89
require 'steno/sink'
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
require 'steno/steno'
2+
3+
RSpec.describe Steno::LoggerIO do
4+
let(:logger) { double(:logger) }
5+
let(:level) { :info }
6+
let(:logger_io) { described_class.new(logger, level) }
7+
8+
describe '#write' do
9+
it 'writes to the logger' do
10+
expect(logger).to receive(:log).with(level, 'message')
11+
12+
logger_io.write('message')
13+
end
14+
end
15+
16+
describe '#sync' do
17+
it 'returns true' do
18+
expect(logger_io.sync).to be(true)
19+
end
20+
end
21+
22+
context 'when writing a record' do
23+
let(:logger) { Steno::Logger.new('test', []) }
24+
25+
it 'removes logger_io.rb from the callstack' do
26+
expect(Steno::Record).to receive(:new).and_wrap_original do |original_method, source, log_level, message, loc, data|
27+
expect(loc[0]).not_to match(/logger_io\.rb/)
28+
original_method.call(source, log_level, message, loc, data)
29+
end
30+
31+
logger_io.write('message')
32+
end
33+
end
34+
end

spec/isolated_specs/steno/unit/logger_spec.rb

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,18 @@
7474
end
7575

7676
it 'creates a record with the proper level' do
77-
sink = double('sink')
7877
expect(Steno::Record).to receive(:new).with('test', :warn, 'message', anything, anything).and_call_original
79-
allow(sink).to receive(:add_record)
8078

81-
my_logger = described_class.new('test', [sink])
79+
logger.warn('message')
80+
end
81+
82+
it 'creates a record with logger.rb being removed from the callstack' do
83+
expect(Steno::Record).to receive(:new).and_wrap_original do |original_method, source, log_level, message, loc, data|
84+
expect(loc[0]).not_to match(/logger\.rb/)
85+
original_method.call(source, log_level, message, loc, data)
86+
end
8287

83-
my_logger.warn('message')
88+
logger.warn('message')
8489
end
8590
end
8691

spec/unit/lib/cloud_controller/logs/steno_io_spec.rb

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)