v3.1.0 — Custom time/thread display, multi-format output, Quote pipeline
Three new capabilities: customizable time/thread display, configurable output format (txt/log/json), and a dedicated Quote pipeline for high-frequency tick/quote data with Binance-aligned schema. All additions are backward compatible — defaults preserve v3.0 behavior.
Added
Customizable Time & Thread Display
LogOptions.TimeFormat(default"HH:mm:ss.fff") — free-form .NET DateTime format string for the message prefix. Falls back to default on parse failure.LogOptions.ShowThreadId(defaulttrue) andLogOptions.ShowThreadName(defaultfalse) — independently toggle thread ID / name in the prefix. WhenShowThreadName=truebut the calling thread has no name (Thread.Name == null), the entire thread segment is omitted.LogOptions.HighPrecisionTimestamp(defaultfalse) — opt-inStopwatch-hybrid mode that reconstructs µs-level precision from the 1ms cache; raises caller-side ticks read cost from ~5ns to ~30ns.
Multiple Output Formats
LogOptions.OutputFormat(defaultLogOutputFormat.Txt) — global format selector:Txt/Log(same content, different extension) /Json(NDJSON with fixed schema{ts, lv, nm, tid?, tn?, msg, data?}).- JSON timestamps emit as epoch_ms integers. Field names use short forms (
lv,nm,tid,tn) for compactness.
Quote (Tick/Ticker) Pipeline
LOG.Quote(...)andLOG.QuoteTicker(...)— public API for high-frequency quote/ticker data with field names aligned to Binance REST 24hr Ticker schema (Last,LastQty,Bid,BidQty,Ask,AskQty,Open,PrevClose,High,Low,Volume,QuoteVolume).QuoteRecord(publicreadonly struct) — A2 core API for zero-allocation enqueue. Convenience A1 overloads for the common cases (tick only / bid+ask / full ticker / ticker+extras).QuoteOptions(opt-in viaopt.ConfigureQuote(q => q.Enable = true), default off) — independent async pipeline with its own dispatcher, queue, andFileStreamPool. ConfigurableOutputFormat(Txt/Log/Json),MaxOpenStreams(default 500),MaxQueueSize(default 50000),MaxBatchSize,FlushIntervalMs,OnDropped(long)callback.QuoteRecord.Extras(IReadOnlyDictionary<string, object>) for flexible attributes andQuoteRecord.ExtrasJson(raw pre-serialized JSON string for the zero-overhead path) — mutually exclusive; setting both throwsArgumentExceptionat the call site.- File naming:
{baseDir}/{LogPath}/{yyyyMMdd}/{QuotePath}/{Bucket}_{Symbol}_Quote.{ext}— no nested subdirectories. - Symbol/bucket sanitization: file-system-invalid characters (
/ \ : * ? " < > |) are automatically replaced with-in filenames; the original symbol/bucket text is preserved in the file content.
Tests
- Four new xUnit test files covering custom time formats, NDJSON formatting, Quote schema/error scenarios, and filename sanitization (48 tests total, all passing).
OzaLog.Test/Program.csrewritten to a comprehensive v3.1 smoke-test covering every API surface and error path in a single linear run, with optional CLI args for format selection (txt/log/json).
Improved
LogItemcarriesThreadNameso the dispatcher thread can render the calling thread's name (previously unavailable post-enqueue).- All Quote API overloads funnel through
LOG.Quote(in QuoteRecord)for centralized validation. Errors (null/empty Symbol or Bucket,Extras/ExtrasJsonboth set,Extraskey colliding with a reserved field) throwArgumentExceptionsynchronously on the calling thread — not deferred to the dispatcher. LogFormatterretains a fast path for the defaultHH:mm:ss.fffformat (hand-written, zero-allocation); other formats route throughDateTime.ToStringwithFormatExceptionfallback to default.FileStreamPoolsupports per-output extension (.txt/.log/.json) with corresponding part-detection logic for size-based file splitting.
Technical
System.Text.Json: bumped from8.0.5→9.0.16fornetstandard2.0/netstandard2.1targets (net8.0/net9.0/net10.0still use the BCL built-in — zero NuGet dependencies).Microsoft.SourceLink.GitHub: bumped from8.0.0→10.0.300(build-only,PrivateAssets=all, no consumer impact).- New internal types:
JsonLogFormatter,QuoteFormatter,QuoteFileStreamPool,QuoteLogHandler. Quote pipeline runs entirely in parallel with the mainAsyncLogHandler— they share no locks or stream pools. - Build verified across all 5 TargetFrameworks (
netstandard2.0/netstandard2.1/net8.0/net9.0/net10.0) with 0 errors.
📦 NuGet: https://www.nuget.org/packages/OzaLog/3.1.0
📖 Full changelog: https://github.com/ozakboy/OzaLog/blob/main/docs/en/changelog.md
🌐 Website: https://ozakboy.github.io/OzaLog/