mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 03:05:19 +00:00
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:
@@ -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")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user