team_logger 0.7.0
team_logger: ^0.7.0 copied to clipboard
A logging library for big teams, big applications and huge logs.
0.7.0 #
-
[breaking changes] Three names leave the public API, found by the review held before the surface is frozen at 1.0.
GrowableConstraintsValueswas dead: nothing in the package, the tests, the example or the README ever named it.AnsiStringExtensionsandMeasuredLineExtensionswere the printer's own layout machinery —applyConstraintsandterminatedSlice, which take aLogand aLogTheme— and exporting them putapplyConstraintson every String in every program importing this package, where it met anyone else'sapplyConstraintsonStringas an ambiguous extension; the second extendsMeasuredLine, which was never exported, so it could not be used at all. All three still exist inside the package; they are simply no longer yours to call. -
LogThemeDatais documented, class and palette both. It is the largest type here — 173 members, 133 of them ready-made themes — and it carried no dartdoc at all. The dartdoc now also states the rule that decides which colours have a preset: a colour gets one only if it can be a base, with an emphasis above it and a still-visible dim below. That is why channel level 5 never bases a preset (nothing is brighter to emphasise with, though it serves as an emphasis), why the eight darkest cornersrgb000–rgb111do not, and why the greys stop atgray5andgray20. -
LogNoDataandLoggableNoVieware documented. Both are named only because they are the types ofLog.noDataandProp.noView, both mark a distinctionnullcannot make, and neither can be constructed. -
Requires
logger_builder^0.8.0, which removed the deprecatedHasFlushalias ahead of its own 1.0. Nothing here used it and it was not among the nine names re-exported, so no code changes with the bump. -
Every JSONL meta line carries
formatVersion, the version of the on-disk format, alongsidesessionIdandstarted. A session file outlives the run that wrote it — an archive exported for diagnostics may be opened much later, by a tool built against a different version of this package — and until now it said nothing about which shape it was. It is the one thing that cannot be added afterwards: a file already written will never carry it. Compare againstFileLogCodec.formatVersion; it appears on every chunk, so a chunk taken out of the middle of a session still identifies itself, and like the other two it cannot be overridden throughmeta. Adding a key does not bump it — a reader that ignores unknown keys is unaffected. -
[breaking changes] Only the part of
logger_builderateam_loggeruser has to name is re-exported:CustomLogPublisher,CustomLogFormatter,MultiPublisher,TransformPublisher,AsyncPublisher,AsyncPublisherWithBuffer,Flushable,ClosableandLogTransformer— nine names where the whole toolkit used to come through.team_loggeris a logger, not a kit for building one, and the rest was clutter in its API reference:Levels, a second vocabulary of level constants besideLogLevels, which is the one this package uses;CustomLogger,CustomLogandCustomLevelLogger, the supertypes of the finalLogger,LogandLevelLogger, which nothing can extend; theLazyfamily, which a caller never constructs — closures are what the lazy parameters take; the*Baseclasses, meant for subclassing this package does internally; and the*WithParamaxis, which this package does not use at all. Anyone assembling a logger of their own importspackage:logger_builder/logger_builder.dartdirectly, and nothing there has been lost. -
ConsoleLogPrinterno longer requiresrows.ConsoleLogPrinter()now builds a working printer:rowsdefaults toConsoleLogPrinter.defaultRows, one row 120 columns wide carrying the sequence number, the short level name, the time, the namespace path, the trace ids and the message, with the tags right-aligned in itstail— the layout the README's Quick Start builds by hand, so the two agree. It was the only required parameter left, whilethemehad defaulted toLogMainTheme.defaultActiveThemeall along; the asymmetry meant nothing could be printed before a layout had been written out. 120 is a choice rather than a measurement: this library carries nodart:ioand cannot see the terminal's real width. Existing code is unaffected — a required named parameter becoming optional breaks nothing. -
ConsoleLogPrinter.oneCallPerLogdelivers a whole log throughoutputin a single call instead of one call per rendered line. The printer is line-oriented by default — each line repeats the number, level and time so it can stand on its own in a console or an IDE filter — but a sink whose unit is an event, such asdart:developer'slog(), had to reassemble the log with no signal for where its lines ended. With the flag set, every line of every row, wrapped lines included, is joined with\nand sent once. The text is unchanged; only the number of calls is. A log that prints nothing makes no call. -
[breaking changes] A
MapobeyscollectionMaxCountandcollectionMaxStringLength, and reports its size like any other collection. It obeyed neither: a list of a thousand elements folded up while a map of a thousand keys went into the log whole, in the console and in the JSONL file alike, and nothing an application could set would stop it. Truncation keeps the first entries and the last one, as for a list. Every map now carries the count marker —{₌₅ a: 1, …, e: 5}— becausecollectionShowCountmeans one thing across collections;collectionShowCount: falsetakes it off.collectionShowIndexesdoes not apply: entries have keys. With a redaction rule installed, the limit counts the entries that survive it and the reported size stays the size of the map, which is the only trace a dropped entry leaves. In JSON the shape changes only when the map is truncated, the way a list already behaves:{":k": "map", ":l": 5, ":v": {…}}.Loggable.mapBuilder()is a structure of properties rather than a collection and is unaffected. -
LoggableConfig.iterableEfficientLengthopts a bareIterableinto the rendering aListgets: the element count and the last element, rather than the leading elements and an ellipsis. AnIterablethat is neither aListnor aSetis still read exactly once by default — it may be single-pass or expensive to walk twice, and the package cannot tell one from a generator — so the richer form is the caller's assertion to make.LoggableJsonConfigtakes the same flag, where it turns":trim": trueinto a real":l"length. -
[breaking changes] Control sequences in logged text are shown instead of being sent, and the safe mode is on by default (
LoggableConfig.escapeAnsiCodes). Untrusted text — an HTTP header, an exception message, a filename — used to carry its own ANSI straight to the terminal, where it could clear the screen, overwrite lines already printed or forge an OSC 8 hyperlink. Such a sequence now prints as its parts,[CSI 2 ED]forged, with no ESC left in the result: the message, the error text, string values, map keys, property names, enum names and the value handed to aLoggableView, in the console and inFileLogStoragealike. What a view renders is left alone — it is a rendering extension handed the theme, and its result carries the package's own styling. Ordinary text and the theme's own styling are untouched, and BBCode in a message still compiles. Logging text you styled yourself is an explicit opt-out —config: LoggableConfig(escapeAnsiCodes: false)— that aLoggable.forceConfigpolicy can refuse. Rendering a data-heavy log measured about 1.6% slower. -
[breaking changes] Formatting settings resolve through a chain of layers: the package default,
Loggable.defaultConfig, the call site and the containers on the way to the value, andLoggable.forceConfigon top. The new statics give an application one place to state a preference and one place to state a rule —forceConfigcannot be lifted by a call site or by a container config merged in halfway down the data, which is what makes it a policy rather than a suggestion. Both are per-isolate, likeLoggable.sanitizer, and both apply toobjectToString()andobjectToJson(), not only to the console printer. -
[breaking changes]
LogMainThemeno longer carriesenumDotShorthand,collectionShowCount,collectionShowIndexesandstringInQuotes. They were the theme's only say in what is printed rather than how it looks, and resolving them meantconfig.x ?? theme.xin five separate places. They live in the chain now: move a theme that set them toLoggable.defaultConfiginstead. Defaults are unchanged — all four are stilltrue, and output with empty layers is identical to the byte.LoggableConfig.toEffectiveConfig()lost its theme argument with them. -
[breaking changes] Console layout measures terminal columns instead of UTF-16 code units.
LogRow.maxLength, wrapping, truncation, padding and tail alignment used to count code units, so a row of CJK ran to about twice the declared width, a combining sequence was charged for two columns and drew one, and an emoji could be cut in half. Text is now walked in grapheme clusters and each cluster is charged what a terminal draws it as — two columns for East Asian Wide and Fullwidth, zero for a stray combining mark, one otherwise. Nothing is ever cut inside a cluster, so a row can come out one column short ofmaxLengthrather than splitting a glyph; ASCII output is unchanged to the byte. This addscharacters^1.3.0 as the first new runtime dependency since 0.6.0 — the constraint stays on 1.3.x because Flutter 3.27 pins that version. -
A root replacement from
Loggable.sanitizeris now rendered with the formatting config ofLoggable.builder()andLoggable.mapBuilder()too, not only ofLoggableMultiData. The README promised the container's formatting for a replacement; a builder's owncollectionMaxCount,stringInQuotesand number formats were being dropped on the redaction path, so a masked root could print longer than the container it replaced — in the string output and inobjectToJson()alike.unitsare still removed, as before. -
[breaking changes]
Logger.zonedTags()now returns an unmodifiable view of the zone's tags, the wayLogger.zonedTraceIds()already did. Adding to or removing from the returned set throwsUnsupportedErrorinstead of silently retagging every later log in the same async zone. Code that mutated the result has to pass the tags toLogger.trace()instead. -
[breaking changes] Public configuration preconditions for
LogStorage,FileLogStorage,ConsoleLogPrinter,LogMainTheme, and the two iterable string renderers now throwArgumentErrorin production instead of relying on disabled assertions or failing later. The checks run at construction or rendering entry and do not add work to log publication or file I/O paths. -
[breaking changes] Empty custom file-session ids are now rejected with
ArgumentErrorinstead of creating chunk files that session listing cannot discover. Chunk names whose numeric index does not fit in a Dartintare treated as foreign files instead of disabling listing or storage startup. -
[breaking changes]
Log.tagsandLog.traceIdsare now unmodifiable snapshots. Mutating collections passed to the public constructor or ascopyWith()replacements no longer changes an existing log, and attempts to mutate the exposed collections throwUnsupportedError. The normalLoggerpath transfers fresh collections without copying their elements;copyWith()reuses snapshots when those fields are omitted. -
[breaking changes]
Loggable.objectToJson()now throwsArgumentErrorwhen distinct emitted map keys have the same JSON representation, such as1and'1', instead of silently keeping the later value. AffectedFileLogStorageJSON records use the existingencodeErrorfallback and report the original error throughonErrorwithout losing batch neighbors. -
[breaking changes] Replace
FileLogSessions.archiveTo()with streaminggzipTo(). It writes the selected sessions, in order and with each session's metadata line, into one GZIP-compressed JSON Lines file instead of a ZIP containing one file per session. Memory use is now bounded by I/O and compression buffers rather than the complete source set plus the output archive. Targets that alias selected chunks are rejected before writing, and source read failures are not masked by output cleanup. Thearchivepackage is no longer a dependency. -
[breaking changes]
FileLogStorage.flush()andclose()no longer report success after an initialization or write failure made an accepted log unavailable. The affected logs go toonDropped; both lifecycle methods drain or close resources and then complete with the first durability error, which remains sticky for that storage instance.onErrorstill receives the original failure when it happens. -
FileLogStorage.minLevelis now applied before the bounded queue, so logs excluded from file output neither consume queue capacity nor displace an eligible log intoonDropped. -
Fixed best-effort handling of accidental or pre-existing chunk symlinks in an application-private, trusted log directory: they are ignored rather than making reading or appending leave it. This is not a sandbox against a concurrent hostile actor that can race filesystem operations.
-
Fixed immediate
close()so it waits for initialization and the active chunk handle to close.isClosednow flips synchronously, andflush()called after closing starts returns the exact same full-lifecycle Future. -
Documented and tested the supported current-session deletion sequence: deleting it while its
FileLogStorageis active is unsupported; awaitclose()first. -
Clarified the existing file-retention contract:
maxChunkSizeandmaxSessionSizeare rotation and retention targets, whilemaxTotalSizeis a startup retention budget. JSON Lines records stay whole and the newest chunk is always retained, so one oversized record can exceed all three settings; callers that need a hard disk ceiling must bound their inputs. -
BbCodeFormatterno longer uses a backtracking regular expression: a single left-to-right scan now keeps malformed input from blocking the isolate. Properly nested tags, including identical tags, are supported; mismatched closing tags stay literal instead of closing an earlier tag. -
[breaking changes] A root-position rule (
ctx.depth == 0) now also applies to a plaintoString():'$obj'andprint(obj)for a [Loggable] or [LoggableData] go through the sanitizer, where before only their properties did. Everything the library renders outside the sanitizer's documented scope — the message, the error, the stack trace, the tags and the namespace path — is explicitly kept out of it, so a rule can no longer erase an error or rewrite the cached [Log.tags] thatactiveTagsfilters on. -
[breaking changes] A replacement no longer inherits
unitsanywhere: units describe the original quantity and a mask is not it. Properties already behaved this way; the root now matches. The rest of a container's config (collectionMaxCountand friends) is still inherited, since that describes how to print rather than what the value is. -
Two leaks found by a two-reviewer cross-review of 0.6.0 are closed. The console printer and the public [LoggableMultiData.toString] rendered multi-data sections themselves and never offered the ROOT value, so a root-level rule was honoured in JSONL files and silently ignored on the console. And a
viewthat re-enters the walkers (a raw [Loggable]/[LoggableWrapper], or a [LoggableView] converter that renders) restarted at an empty path, so a path-based rule both missed it and could over-redact an unrelated top-level property of the same name. -
A [Map] key is now rendered once instead of twice. It used to be rendered a first time to derive
ctx.nameand a second time for the output, the two firing the rule at different paths — and the printed one was the unsanitized second. The derivation also ran with no sanitizer installed, doublingtoString()calls and breaking a key whosetoString()throws; that path is back to its 0.5.2 behaviour. -
A rule that throws no longer persists what it refused: [FileLogStorage] writes only the error TYPE into the fallback line (
ArgumentError.valueputs the offending value into the message, and the file is where it must not end up). The full error still reachesonError. -
collectionMaxCountno longer offers the element it then discards; [LoggableData.toJson] no longer allocates a sanitizer-only list when no rule is installed; the printer and the file codec decide on an exact dropped signal instead of inferring one from an empty rendering, so data that legitimately renders empty keeps its colon while a multi-data whose sections were all dropped prints no data block at all. -
Documented boundaries that 0.6.0 stated too broadly: a [Map] key is not offered to the rule (its contents are, but only where the key's rendering enters the walkers, and under the container's path); for a non-
Stringkeyctx.nameis the key as that particular output renders it, so such entries are redacted by value rather than by key text; a [Prop] rendered on its own prints'<dropped>', having no container to remove it from. -
[breaking changes] Require
ansi_escape_codes^4.0.1, up from ^3.1.2. Its 530 top-level style constants are gone: the table is one class now, so a theme written asansi.rgb030is writtenStyles.rgb030, andansi.boldisStyles.bold. The names this package hands on are otherwise unchanged, andStylesis re-exported beside [Style], [NoStyle], [Color16] and [Color256] — a theme needs no direct dependency on the package that defines them. Code that reaches intoansi_escape_codesdirectly for other reasons also loses theparsingentry point (style.dartcarries the same names), and findsMatchasPiece,LinkasOscLinkandrgb/grayasrgb256/gray256; see its own changelog for the rest. -
[breaking changes] Require
logger_builder^0.7.0, up from ^0.5.0 (the changes flow through the re-export). The one that changes behaviour of code written against this package is publisher inheritance:child[level].publisher = ...now pins that one level and leaves the others following the parent, where before the coarse linked flag cut the whole sublogger — and everything under it — off the parent for good. That was a documented limitation here; it is gone.publisherLinkedtherefore staystruein cases that used to clear it, a commonlogger.publisher = ...no longer overwrites a pinned level (so the order of the two assignments stopped mattering), a linked sublogger takes the parent's publisher for that level instead of flattening the parent's exceptions, andrelink()drops every pin rather than the logger's own links. There is no idiom left for detaching all levels without changing a value —child[level].publisher = child[level].publishernow pins the level instead — andhasPublishercan consequently go back tofalseon a level that once had a real publisher: read it as "publishes somewhere right now", which is what it says. -
[breaking changes] The queue behind [FileLogStorage] is bounded now, because the base class it is built on bounds every asynchronous queue:
maxQueueSizedefaults to 100 000 logs accepted and not yet written. At the limit it is the incoming log that is refused, so a disk that cannot keep up costs the newest logs rather than the process, and everything already accepted is still written —flush()andclose()promise what they promised before. Before this, an unwritable directory grew the queue until memory ran out. -
[FileLogStorage] takes
onDroppedandmaxQueueSizeand hands both to the base class. A refused log reachesonDroppedas a one-element batch — the callback takes a list, the same one a spent retry budget would hand it; with no handler set, the loss is announced on stdout rather than hidden — the first one at once and the rest as a count, at most once every five seconds — so passonDropped: (_) {}for a storage that must stay quiet. This is the only way a log is lost after being accepted: a failed write is reported toonErrorand never retried, so the retry budget of the base class (maxRetries,retryDelay) never comes into play here and neither knob is exposed. -
Also from that upgrade, from the 0.6.x part of it: a transformer that logs through its own logger is caught by a reentrancy guard — the nested log is dropped and a [StateError] is reported — where before the call recursed into a
StackOverflowError; the dartdoc on [Logger] said the old thing and now says this one. A level logger is rejected at a threshold (Levels.all/Levels.off), registering one level logger in two loggers throws,TransformPublisher.close()is terminal and idempotent, and a sublogger holds its parent strongly, so an intermediate logger nobody kept no longer stops passinglevel/publisherchanges down. -
New from that upgrade, without any work here:
CustomLogger.onError— one hook for a throwing transformer, a reentrancy violation and a throwing publisher, resolved through the parent chain — plusCustomLevelLogger.hasPublisher, its new companionhasOwnPublisher(a pinned level against one that takes its publisher from above) and a per-levelrelink()that drops the pin and takes from the chain again.LevelLoggerdeclares neither name, so nothing here silently overrides them. -
That upgrade also carries the fixes that matter most under this package:
flush()during aclose()returns the close instead of a false all-clear,close()no longer sleeps through a pending retry, a failing sink no longer starves the event loop, a buffered publisher reports handler errors into the zone that built it rather than whichever scope logged first, registering a sublogger from insideprocessLogno longer throws aConcurrentModificationError, aCustomLogger.onErrorhandler that logs no longer recurses until the stack is gone, andTypedLazymemoizes a throwingconvert— which is what [Logger] resolves a namespace path and a lazy message through. -
The package installs into a Flutter application again, from Flutter 3.27 — the line that carries Dart 3.6, the floor this package declares. It did not: Flutter pins several packages to an exact version out of its own SDK, so a floor above such a pin is a version-solving failure rather than a newer resolve.
clock,metaandstack_tracenow sit at the 3.27 pins (^1.1.1, ^1.15.0, ^1.12.0) instead of the 3.29 ones, and nothing here needs anything newer. -
What blocked the Flutter line one level down was
format^1.6.0, the 0.6.0 dependency: 1.6.0 wantedcharacters^1.4.0 where Flutter 3.27 pins 1.3.0, andintl^0.20.2 whereflutter_localizationspins 0.19.0 on both 3.27 and 3.29, so a localized application could not take this package at all on those lines.intlis gone from the graph of every application that takes this package — and so, as the next entry says, isformatitself. -
[breaking changes]
formatis no longer a dependency of this package at all, and number formatting is a theme's job.intFormatanddoubleFormatkeep their names and theirString?type, but the package no longer reads them: the string goes to [LogMainTheme.numberFormatter] together with the value, and what it means is that formatter's business. A theme without one prints the number as it is — no exception, and no pattern applied, where an invalid specifier used to throw from insideformatat the logging call site. Two changes to make on the way up: install the formatter —numberFormatter: (theme, value, pattern) => format(pattern, value), withformatin your own pubspec — and write the whole template where a bare specifier used to go,'{:,d}'for',d'and'{:.4f}'for'.4f'. Nothing else here tookformat, so it leaves the dependency graph of every application that takes this package; a formatter oversprintf('%d'in the config then), or one with nothing to do withformatat all, is now equally installable.format^4.1.0 stays as a dev dependency, becausetest/loggable/number_format_test.dartbuilds the recipe above and pins what it renders —intFormat/doubleFormatare covered for the first time. One rendering there differs from the 0.6.0 line: withformat4.xdoubleFormat: '{:g}'prints1234.5678for 1234.5678 where 1.x printed1234.57. Padding, grouping, radices, fixed and exponential forms and rounding are unchanged. -
[breaking changes] A locale-aware
intFormat/doubleFormatno longer works by settingIntl.defaultLocale, because the specifier is handed toformatandformatstopped reading an ambientintllocale when it dropped the dependency.intFormat: ',n'now throwsInvalidSpecifierExceptionoutright —ntakes no grouping option — and a barenfollows the C locale rather than the application's. The README taught the old form and no longer does: the example that printed 123 456 789 in Bengali digits prints it in hexadecimal instead (intFormat: '#x'), andintlleavesexample/with it. There is no replacement for the locale-aware form here:formatreads itsNumberLocalefrom aFormatinstance, and this package calls the top-levelformat(). -
The example package is one example again.
example/example.dartis a single request through the logger — a namespace sublogger with a tag, a trace id across an async flow, a request as headers and body, a response object that prints itself, a redacted header, a failure with its stack trace — and it is what pub.dev shows on the Example tab, where thedart createboilerplate used to be. The 288-line "print everything" program that lived there has moved totool/and is not published; the per-section code behind the README screenshots stays where it was. -
Documented the terminal-output trust boundary. The default theme passes the ESC character through so that BBCode tags and theme colors survive, which also lets untrusted text — an HTTP header, an exception message, a filename — carry its own control sequences to the terminal. README gains a section, and
ControlCodeFormatter,BbCodeFormatter,LogMainTheme.valueFormatterandLogMainTheme.messageFormattersay so in their dartdoc. Behavior is unchanged: escaping untrusted text remains the application's job, andControlCodeFormatter(excludeEscCode: false)covers the message and plain containers but notLoggableproperties.
0.6.0 #
- Per-value sanitization of logged data: assign [Loggable.sanitizer] to
process every value on its way to the output. The callback receives a
[SanitizeContext] (name, value, a lazily built path such as
user.card.number, depth) and returns the value unchanged, a replacement, or [Sanitize.drop] to remove the property/entry from the output entirely. The hook is global, so it cannot be forgotten on a publisher: it applies to the console printer, file storage, session export and any direct [Loggable.objectToString]/[objectToJson] call — including an in-app log viewer. - A replacement is rendered as a plain value: the original's children are
no longer offered to the rule, but the replacement's own children are,
normally — a rule whose replacement itself matches the same rule
recurses forever. A property's
viewis what the rule sees, not the text it renders (no [LoggableView] goes through the walkers), so such a property must be redacted byname/path, not by matching rendered content. In a collection-element position [Sanitize.drop] renders'<dropped>'rather than removing the element, so the printed collection length stays honest. - The rule must be free of side effects and must neither render nor log from inside itself — [Loggable.sanitizer] is a per-isolate static, so set it again in any isolate you spawn. Cycle protection, collection limits and lazy iterables are unaffected: sanitization happens while rendering, so filtered-out logs still cost nothing. The raw value still lives in [Log.data]; reach for [Logger.transformer] when a value must not exist in memory at all.
0.5.2 #
- Pre-publication log processing (primarily for security — masking
secrets/PII, dropping forbidden logs): require
logger_builder^0.5.0, whose new API flows through the re-export. Assign [Logger.transformer] (Log? Function(Log)) to process every log right before publishing — subloggers inherit it likelevel/publisher; returningnulldrops the log. Wrap a single publisher in [TransformPublisher] to transform for one destination only. Fail-closed: a throwing transformer drops the log and reports the error toonError/the current zone — the untransformed log is never published. - Add [Log.copyWith] — the building block for transformers: replaces
message/data/tags/error/stackTrace/path/traceIds while always preserving
the log's identity ([Log.num], [Log.time], the level and zone; no new
sequence number is consumed).
copyWith(error: null)clears the error,data: Log.noDataclears the data.
0.5.1 #
- Internal: [FileLogStorage] drops its pending-log counter and the
flush()fast path — workarounds for theflush()hang of logger_builder <= 0.3.2.flush()now awaits initialization and relies on the drain semantics of the base class; the guarantees are unchanged (initialization completed, everything published is on disk).
0.5.0 #
- [breaking changes] Require
logger_builder^0.4.0 (the changes flow through the re-export):HasFlushis renamed to [Flushable] (the old name remains as a deprecated alias), the new [Closable] interface exposesclose(), [MultiPublisher] gains a closed state and copies the publisher list at construction, [CustomLevelLogger] can no longer be implemented outside logger_builder, async publishers getonError,isClosedand non-hanging drain-semanticsflush(). See the logger_builder 0.3.3/0.4.0 changelog for the full list. - [FileLogStorage.onError] is now the inherited base-class callback: it additionally receives the write-pipeline errors of [AsyncPublisherWithBufferBase] (previously they were reported to the current zone).
0.4.2 #
- Require
logger_builder^0.3.2: an exception thrown by one publisher in [MultiPublisher] no longer interrupts publishing to the remaining publishers and no longer propagates to the logging call site. The new [MultiPublisher.onError] callback receives the failing publisher along with the error; without it, the error is reported to the current zone as an uncaught asynchronous error. [MultiPublisher.flush] now starts flushing all publishers even if one of them throws synchronously.
0.4.1 #
- [breaking changes] The
ansi_escape_codesre-export is narrowed toStyle,NoStyle,Color16,Color256: the full barrel leaked names clashing with Flutter (Color,Colors,Stack,State,Text). For the predefined style shortcuts (rgb431, ...) depend onansi_escape_codesdirectly (ideally with an import prefix).
0.4.0 #
- [breaking changes] Rename [Log.sequenceNum] to [Log.num] ([lastSequenceNum] to [lastNum]).
- [breaking changes] Rename [LogSequenceNum] to [LogNum].
- [breaking changes] Rename [LogThemeData.sequenceNumStyle] to [numStyle].
- [breaking changes] Rename [LogStorage.indexBySequenceNum] to [indexByNum].
- [breaking changes] Rename [collectionShowLength] to [collectionShowCount] (in [LoggableConfig] and [LogMainTheme]).
- [breaking changes] Rename [LoggableResolvedConfig] to [LoggableEffectiveConfig], [LoggableConfig.resolved] to [toEffectiveConfig].
- [breaking changes] The [TypeProp] constructor is now private.
- Export [LoggableJsonConfig]; add [Prop.toMapEntry] and [Prop.toJson].
- [breaking changes] [LoggableTypeConverter] is reduced to [convertToData]: the [toJson]/[toLogString] members were never called by the library.
- [LoggableMultiView.toJson] now returns a structured object
(
{":k": "multi-view", ":v": [...]}) instead of a joined string. - [breaking changes] Rename [Constraints] to [LogConstraints] (the old name clashed with the Flutter type).
- [breaking changes] [LogThemeData.copyWith] no longer accepts the phantom [colon]/[ellipsis]/[lineBreak]/[padding] parameters (they were silently ignored; the real fields live in [LogMainTheme]).
- [activeNamespaces] now matches child namespaces by prefix ('app' activates 'app/net' but not 'application'); [ConsoleLogPrinter.pathSeparator] is configurable.
- The printer's minLevel gate takes the minimum of the active and inactive themes, so active logs are never suppressed harder than background ones.
- Add [LogMainTheme.ansiCodesEnabled]; colorless theme copies no longer leak ANSI codes. Default themes no longer stamp a '#log' tag.
- Level [LogTheme]s are cached per [LogMainTheme] (BbCode regex is no longer recompiled for every message).
- Re-export the
ansi_escape_codesstyles, so themes can be configured without a direct dependency. - Fix a batch of review findings: cyclic structures no longer crash
formatting ([StackOverflowError]) — a cycle is rendered as
↺ₙ(N = levels up, configurable via [LogMainTheme.cycleFormatter]/[cycleStyle]) and as{":k": "cycle", ":up": N}in JSON; [BbCodeFormatter] no longer truncates messages; single-character messages are printed; a tail wider than [maxLength] no longer drops the log line; truncation/wrapping is surrogate-safe; fillers show no ellipsis; stack trace frames wrap instead of losing the file name; [LogStorage] edge cases (maxCount 0, publish after dispose, reversed.reversed, growable snapshot); tags accept any iterable; collection length budgets include the ellipsis; [ControlCodeFormatter] no longer leaks a bare ANSI reset; [LogTime] column width no longer jitters with microseconds; [LoggableView] (null) and duplicate props are consistent between string and JSON output; non-finite doubles (nan/inf) omit units in both outputs; user map keys starting with ':' are escaped; [LogTags] prints nothing when there are no tags. - [breaking changes] Rename [collectionMaxLength] to [collectionMaxCount].
- [Loggable.efficientLengthIterableToString] and [Loggable.iterableToString] now accept the parameter [collectionMaxCount] = 0.
- Add [Loggable.objectToJson].
- Add [LoggableData.round].
- Add file-based session log storage
(
package:team_logger/team_logger_io.dart): [FileLogStorage] writes logs to per-session JSON Lines files with chunk rotation ([maxSessionSize]/[maxChunkSize]), startup cleanup ([maxAge], [maxTotalSize]) and a metadata line; [FileLogSessions]/[FileLogSession] list, read, delete, export sessions and pack them into a single ZIP archive ([archiveTo]).
0.3.0 #
- Update README.
- [breaking changes] Rename [activeLoggers] to [activeNamespaces].
- [breaking changes] Rename [activeLevel] to [activeMinLevel].
- [breaking changes] Remove [AnsiPair].
- Add [activeLevels].
- Fix minor bugs.
0.2.0-0.2.2 #
- Publish.
0.1.0-0.1.70 #
- Initial version.
