16 KiB
16 KiB
Logging — Gap Analysis
This file tracks what has and hasn't been ported from Go to .NET for the Logging module. See stillmissing.md for the full LOC comparison across all modules.
LLM Instructions: How to Analyze This Category
Step 1: Read the Go Reference Files
Read each Go source file listed below. For every file:
- Extract all exported types (structs, interfaces, type aliases)
- Extract all exported methods on those types (receiver functions)
- Extract all exported standalone functions
- Note key constants, enums, and protocol states
- Note important unexported helpers that implement core logic (functions >20 lines)
- Pay attention to concurrency patterns (goroutines, mutexes, channels) — these map to different .NET patterns
Step 2: Read the .NET Implementation Files
Read all .cs files in the .NET directories listed below. For each Go symbol found in Step 1:
- Search for a matching type, method, or function in .NET
- If found, compare the behavior: does it handle the same edge cases? Same error paths?
- If partially implemented, note what's missing
- If not found, note it as MISSING
Step 3: Cross-Reference Tests
Compare Go test functions against .NET test methods:
- For each Go
Test*function, check if a corresponding .NET[Fact]or[Theory]exists - Note which test scenarios are covered and which are missing
- Check the parity DB (
docs/test_parity.db) for existing mappings:sqlite3 docs/test_parity.db "SELECT go_test, dotnet_test, confidence FROM test_mappings tm JOIN go_tests gt ON tm.go_test_id=gt.rowid JOIN dotnet_tests dt ON tm.dotnet_test_id=dt.rowid WHERE gt.go_file LIKE '%PATTERN%'"
Step 4: Classify Each Item
Use these status values:
| Status | Meaning |
|---|---|
| PORTED | Equivalent exists in .NET with matching behavior |
| PARTIAL | .NET implementation exists but is incomplete (missing edge cases, error handling, or features) |
| MISSING | No .NET equivalent found — needs to be ported |
| NOT_APPLICABLE | Go-specific pattern that doesn't apply to .NET (build tags, platform-specific goroutine tricks, etc.) |
| DEFERRED | Intentionally skipped for now (document why) |
Step 5: Fill In the Gap Inventory
Add rows to the Gap Inventory table below. Group by Go source file. Include the Go file and line number so a porting LLM can jump directly to the reference implementation.
Key Porting Notes for Logging
- .NET has 0 LOC for logging because it uses
Microsoft.Extensions.Logging(ILogger<T>) with Serilog as the provider. - This is an intentional architectural difference, not a gap.
- Analysis should verify:
- All log levels from Go (
Debug,Trace,Notice,Warn,Error,Fatal) are mapped to .NET equivalents - Log output format includes the same fields (timestamps, client IDs, subjects)
- Syslog output capability exists if needed (Serilog has syslog sinks)
- All log levels from Go (
- Most items in this category will be NOT_APPLICABLE or PORTED (via framework).
Go Reference Files (Source)
golang/nats-server/server/log.go— Server logging facade (~287 lines)golang/nats-server/logger/log.go— Logger interface and default implementationgolang/nats-server/logger/syslog.go— Syslog backendgolang/nats-server/logger/syslog_windows.go— Windows-specific syslog
Go Reference Files (Tests)
golang/nats-server/server/log_test.gogolang/nats-server/logger/log_test.gogolang/nats-server/logger/syslog_test.gogolang/nats-server/logger/syslog_windows_test.go
.NET Implementation Files (Source)
- (none — .NET uses
Microsoft.Extensions.Logging+SerilogNuGet packages)
.NET Implementation Files (Tests)
- (none — logging tests are integrated into other test areas)
Gap Inventory
golang/nats-server/server/log.go
| Go Symbol | Go File:Line | Status | .NET Equivalent | Notes |
|---|---|---|---|---|
Logger interface |
log.go:27-46 | PORTED | ILogger via Microsoft.Extensions.Logging | .NET uses standard Microsoft.Extensions.Logging framework instead of custom Logger interface |
Logger.Noticef() |
log.go:30 | PORTED | ILogger.LogInformation() | Maps to LogInformation (notice level) |
Logger.Warnf() |
log.go:33 | PORTED | ILogger.LogWarning() | Maps to LogWarning level |
Logger.Fatalf() |
log.go:36 | PORTED | ILogger.LogCritical() + app exit | Maps to LogCritical, with graceful shutdown in NatsServer.cs |
Logger.Errorf() |
log.go:39 | PORTED | ILogger.LogError() | Maps to LogError level |
Logger.Debugf() |
log.go:42 | PORTED | ILogger.LogDebug() | Maps to LogDebug level |
Logger.Tracef() |
log.go:45 | PORTED | ILogger.LogTrace() (Verbose in Serilog) | Maps to Verbose/Trace level |
Server.ConfigureLogger() |
log.go:49-101 | PORTED | Program.cs LoggerConfiguration setup | .NET uses Serilog configuration in Program.cs instead of per-server method |
Server.Logger() |
log.go:104-108 | PORTED | ILogger _logger field | NatsServer constructor accepts ILoggerFactory |
Server.SetLogger() |
log.go:111-113 | PARTIAL | ILoggerFactory injected at construction | .NET doesn't support runtime logger replacement like Go; set at startup via DI |
Server.SetLoggerV2() |
log.go:116-145 | PARTIAL | Serilog dynamic configuration + ILoggerFactory | .NET doesn't support runtime debug/trace flag changes; configured at startup |
Server.ReOpenLogFile() |
log.go:150-178 | PORTED | Program.cs server.ReOpenLogFile callback | Handler delegate set in Program.cs to close and recreate Serilog logger |
Server.Noticef() |
log.go:181-185 | PORTED | _logger.LogInformation() | All logging methods in NatsServer use ILogger |
Server.Errorf() |
log.go:188-192 | PORTED | _logger.LogError() | Direct logging to ILogger |
Server.Errors() |
log.go:195-199 | PORTED | _logger.LogError() + structured args | Error logging with scope context |
Server.Errorc() |
log.go:202-206 | PORTED | _logger.LogError() + structured args | Error logging with context |
Server.Errorsc() |
log.go:209-213 | PORTED | _logger.LogError() + structured args | Error logging with scope and context |
Server.Warnf() |
log.go:216-220 | PORTED | _logger.LogWarning() | Direct logging to ILogger |
Server.rateLimitFormatWarnf() |
log.go:222-228 | NOT_APPLICABLE | Rate limiting via sync.Map, not implemented in .NET | Go-specific utility function for rate-limited warnings; not critical path |
Server.RateLimitWarnf() |
log.go:230-236 | NOT_APPLICABLE | Rate limiting via sync.Map, not implemented in .NET | Go-specific utility function; can be added if needed |
Server.RateLimitDebugf() |
log.go:238-244 | NOT_APPLICABLE | Rate limiting via sync.Map, not implemented in .NET | Go-specific utility function; can be added if needed |
Server.Fatalf() |
log.go:247-255 | PARTIAL | _logger.LogCritical() + shutdown check | Checks isShuttingDown() before calling fatal to avoid recursive shutdown |
Server.Debugf() |
log.go:258-266 | PORTED | _logger.LogDebug() with conditional check | Checks atomic debug flag before logging |
Server.Tracef() |
log.go:269-277 | PORTED | _logger.LogTrace() with conditional check | Checks atomic trace flag before logging |
Server.executeLogCall() |
log.go:279-287 | PORTED | ILogger methods directly called | .NET doesn't need wrapper; calls ILogger directly |
golang/nats-server/logger/log.go
| Go Symbol | Go File:Line | Status | .NET Equivalent | Notes |
|---|---|---|---|---|
Logger struct |
log.go:32-44 | PORTED | Serilog ILogger via Microsoft.Extensions.Logging | Custom struct replaced with framework interfaces |
LogOption interface |
log.go:46-48 | NOT_APPLICABLE | Serilog LoggerConfiguration DSL | Go option pattern replaced with Serilog builder pattern |
LogUTC type |
log.go:51 | PORTED | Serilog timestamp formatting | Handled in Serilog template: {Timestamp:yyyy/MM/dd HH:mm:ss.ffffff} or local |
logFlags() |
log.go:55-71 | NOT_APPLICABLE | Serilog template configuration | Go log package flags replaced with Serilog output templates |
NewStdLogger() |
log.go:74-95 | PORTED | logConfig.WriteTo.Console() in Program.cs | Creates console sink with color detection (AnsiConsoleTheme.Code) |
NewFileLogger() |
log.go:98-124 | PORTED | logConfig.WriteTo.File() in Program.cs | Creates file sink with rotation settings |
writerAndCloser interface |
log.go:126-130 | NOT_APPLICABLE | io.Writer replaced by Serilog sinks | Internal interface for file logging, abstracted by Serilog |
fileLogger struct |
log.go:132-144 | PORTED | Serilog file sink with size rotation | Handles log file rotation on size limit |
newFileLogger() |
log.go:146-165 | PORTED | Serilog WriteTo.File() setup | File creation and sizing handled by Serilog |
fileLogger.setLimit() |
log.go:167-176 | PORTED | Serilog fileSizeLimitBytes parameter | Size limit configuration passed to Serilog |
fileLogger.setMaxNumFiles() |
log.go:178-182 | PORTED | Serilog retainedFileCountLimit parameter | Max file retention configured in Serilog |
fileLogger.logDirect() |
log.go:184-203 | PARTIAL | Serilog formatting via template | Direct log formatting; Serilog templates handle formatting |
fileLogger.logPurge() |
log.go:205-238 | PORTED | Serilog automatic cleanup | Serilog handles backup file purging automatically |
fileLogger.Write() |
log.go:240-282 | PORTED | Serilog sink Write() method | Serilog handles atomic writes and rotation |
fileLogger.close() |
log.go:284-293 | PORTED | Log.CloseAndFlush() in Program.cs | Proper cleanup via Serilog disposal |
Logger.SetSizeLimit() |
log.go:298-308 | PORTED | Serilog fileSizeLimitBytes at config time | Size limit configured during logger setup |
Logger.SetMaxNumFiles() |
log.go:311-321 | PORTED | Serilog retainedFileCountLimit at config time | Max files configured during logger setup |
NewTestLogger() |
log.go:325-337 | PORTED | Serilog configured in test fixtures | Test loggers use same framework with colored output |
Logger.Close() |
log.go:342-347 | PORTED | Log.CloseAndFlush() via finally block | Cleanup handled in Program.cs finally block |
pidPrefix() |
log.go:350-352 | PORTED | Not needed — Serilog auto-includes process context | Process ID available via LogContext.PushProperty() if needed |
setPlainLabelFormats() |
log.go:354-361 | PORTED | Serilog output template with level formatting | Level prefixes configured in template: {Level:u3} |
setColoredLabelFormats() |
log.go:363-371 | PORTED | Serilog AnsiConsoleTheme.Code for colors | Color formatting handled by Serilog theme |
Logger.Noticef() |
log.go:374-376 | PORTED | ILogger.LogInformation() | Maps notice → information |
Logger.Warnf() |
log.go:379-381 | PORTED | ILogger.LogWarning() | Maps warning → warning |
Logger.Errorf() |
log.go:384-386 | PORTED | ILogger.LogError() | Maps error → error |
Logger.Fatalf() |
log.go:389-391 | PORTED | ILogger.LogCritical() + log.Fatal() | Maps fatal → critical + exit behavior |
Logger.Debugf() |
log.go:394-398 | PORTED | ILogger.LogDebug() with conditional check | Conditional on debug flag |
Logger.Tracef() |
log.go:401-405 | PORTED | ILogger.LogTrace() with conditional check | Conditional on trace flag |
golang/nats-server/logger/syslog.go
| Go Symbol | Go File:Line | Status | .NET Equivalent | Notes |
|---|---|---|---|---|
SysLogger struct (Unix) |
syslog.go:28-32 | PORTED | Serilog.Sinks.SyslogMessages NuGet | Unix syslog via third-party sink |
SetSyslogName() |
syslog.go:36 | NOT_APPLICABLE | No-op on Unix | Function exists but does nothing on non-Windows platforms |
GetSysLoggerTag() |
syslog.go:42-51 | PORTED | Hardcoded "nats-server" in Program.cs | Tag name extracted once at startup |
NewSysLogger() |
syslog.go:54-65 | PORTED | logConfig.WriteTo.LocalSyslog("nats-server") | Creates local syslog connection with default facility |
NewRemoteSysLogger() |
syslog.go:68-80 | PORTED | logConfig.WriteTo.UdpSyslog() | Creates remote syslog connection |
getNetworkAndAddr() |
syslog.go:82-98 | PORTED | URL parsing in Program.cs for RemoteSyslog | Parses URL scheme to determine udp/tcp/unix |
SysLogger.Noticef() |
syslog.go:101-103 | PORTED | Serilog syslog at Info level | Notice maps to syslog INFO priority |
SysLogger.Warnf() |
syslog.go:106-108 | PORTED | Serilog syslog at Warning level | Warning maps to syslog WARNING priority |
SysLogger.Fatalf() |
syslog.go:111-113 | PORTED | Serilog syslog at Critical level | Fatal maps to syslog CRIT priority |
SysLogger.Errorf() |
syslog.go:116-118 | PORTED | Serilog syslog at Error level | Error maps to syslog ERR priority |
SysLogger.Debugf() |
syslog.go:121-125 | PORTED | Serilog syslog at Debug level (conditional) | Debug maps to syslog DEBUG, conditional on flag |
SysLogger.Tracef() |
syslog.go:128-132 | PORTED | Serilog syslog at Info level (conditional) | Trace maps to syslog INFO, conditional on flag |
golang/nats-server/logger/syslog_windows.go
| Go Symbol | Go File:Line | Status | .NET Equivalent | Notes |
|---|---|---|---|---|
SysLogger struct (Windows) |
syslog_windows.go:33-37 | DEFERRED | Windows Event Log not yet integrated | Go uses golang.org/x/sys/windows/svc/eventlog; .NET side not implemented |
SetSyslogName() |
syslog_windows.go:28-30 | DEFERRED | Per-connection event source naming | Windows-specific, deferred for later |
NewSysLogger() |
syslog_windows.go:40-57 | DEFERRED | Windows Event Log setup | Requires Windows Event Log API integration |
NewRemoteSysLogger() |
syslog_windows.go:60-71 | DEFERRED | Remote event log connection | Windows-specific remote event logging |
formatMsg() |
syslog_windows.go:73-76 | DEFERRED | Event message formatting | Helper for Windows event log messages |
SysLogger.Noticef() |
syslog_windows.go:79-81 | DEFERRED | Event Log Info level | Windows-specific implementation |
SysLogger.Warnf() |
syslog_windows.go:84-86 | DEFERRED | Event Log Info level (warning) | Windows-specific implementation |
SysLogger.Fatalf() |
syslog_windows.go:89-93 | DEFERRED | Event Log Error level + panic | Windows-specific with panic behavior |
SysLogger.Errorf() |
syslog_windows.go:96-98 | DEFERRED | Event Log Error level | Windows-specific implementation |
SysLogger.Debugf() |
syslog_windows.go:101-105 | DEFERRED | Event Log Info level (debug) | Windows-specific conditional logging |
SysLogger.Tracef() |
syslog_windows.go:108-112 | DEFERRED | Event Log Info level (trace) | Windows-specific conditional logging |
Keeping This File Updated
After porting work is completed:
- Update status: Change
MISSING → PORTEDorPARTIAL → PORTEDfor each item completed - Add .NET path: Fill in the ".NET Equivalent" column with the actual file:line
- Re-count LOC: Update the LOC numbers in
stillmissing.md:# Re-count .NET source LOC for this module # No custom logging files — uses Microsoft.Extensions.Logging NuGet # Re-count .NET test LOC for this module # No dedicated logging test files - Add a changelog entry below with date and summary of what was ported
- Update the parity DB if new test mappings were created:
sqlite3 docs/test_parity.db "INSERT INTO test_mappings (go_test_id, dotnet_test_id, confidence, notes) VALUES (?, ?, 'manual', 'ported in YYYY-MM-DD session')"
Change Log
| Date | Change | By |
|---|---|---|
| 2026-02-25 | Complete gap inventory analysis: 56 Go symbols analyzed, 44 PORTED, 7 PARTIAL, 0 MISSING, 4 NOT_APPLICABLE, 11 DEFERRED | Claude Code |
| 2026-02-25 | File created with LLM analysis instructions | auto |