Stop paying for filtered log messages; sample per-event hot-path logs

SecureLogger's public wrappers evaluated their message autoclosure before
the level check inside log(), so every filtered debug message across the
codebase still paid for string interpolation - hundreds of call sites on
the per-packet/per-event hot paths. The wrappers now guard the level
first, and debug() compiles out of release builds entirely. Regression
tests verify filtered messages are never constructed.

The two heaviest per-event debug logs (NostrRelayManager inbound events,
ChatNostrCoordinator geo events) are now sampled every 100th with a
running count, so debug-enabled dev builds stop emitting hundreds of
lines per minute in busy geohashes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
jack
2026-06-10 20:55:25 +02:00
co-authored by Claude Fable 5
parent 3caf2d7663
commit 4b287f7490
5 changed files with 83 additions and 7 deletions
@@ -0,0 +1,54 @@
import XCTest
@testable import BitLogger
/// The public logging wrappers must not evaluate their message autoclosure
/// when the level is filtered out hot paths log per packet/event, and
/// building a discarded interpolated string on each call is real overhead.
final class LogLevelFilteringTests: XCTestCase {
private final class EvaluationCounter {
var count = 0
func message() -> String {
count += 1
return "expensive interpolation"
}
}
private var originalLevel: SecureLogger.LogLevel!
override func setUp() {
super.setUp()
originalLevel = SecureLogger.minimumLevel
}
override func tearDown() {
SecureLogger.minimumLevel = originalLevel
super.tearDown()
}
func testFilteredDebugMessageIsNeverEvaluated() {
SecureLogger.minimumLevel = .info
let counter = EvaluationCounter()
SecureLogger.debug(counter.message())
XCTAssertEqual(counter.count, 0, "Filtered debug message should not be constructed")
}
func testFilteredInfoMessageIsNeverEvaluated() {
SecureLogger.minimumLevel = .error
let counter = EvaluationCounter()
SecureLogger.info(counter.message())
XCTAssertEqual(counter.count, 0, "Filtered info message should not be constructed")
}
func testEnabledLevelStillEvaluatesMessage() {
SecureLogger.minimumLevel = .debug
let counter = EvaluationCounter()
SecureLogger.warning(counter.message())
XCTAssertEqual(counter.count, 1, "Enabled levels must still log")
}
}