react-native-nitro-logger 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/NitroLogger.podspec +29 -0
- package/README.md +214 -0
- package/android/CMakeLists.txt +24 -0
- package/android/build.gradle +124 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/cpp/cpp-adapter.cpp +11 -0
- package/android/src/main/java/com/margelo/nitro/nitrologger/AndroidPlatformIo.kt +100 -0
- package/android/src/main/java/com/margelo/nitro/nitrologger/HybridFileSink.kt +292 -0
- package/android/src/main/java/com/margelo/nitro/nitrologger/HybridNativeConsoleSink.kt +23 -0
- package/android/src/main/java/com/margelo/nitro/nitrologger/LogFileWriter.kt +1328 -0
- package/android/src/main/java/com/margelo/nitro/nitrologger/LogRotationPolicy.kt +186 -0
- package/android/src/main/java/com/margelo/nitro/nitrologger/LogSecureFile.kt +80 -0
- package/android/src/main/java/com/margelo/nitro/nitrologger/LogWriterRegistry.kt +420 -0
- package/android/src/main/java/com/margelo/nitro/nitrologger/NativeConsoleWriter.kt +237 -0
- package/android/src/main/java/com/margelo/nitro/nitrologger/NitroLoggerPackage.kt +22 -0
- package/android/src/main/java/com/margelo/nitro/nitrologger/PlatformIo.kt +165 -0
- package/docs/PARITY.md +330 -0
- package/docs/PRIVACY.md +341 -0
- package/eslint-plugin/README.md +238 -0
- package/eslint-plugin/index.js +62 -0
- package/eslint-plugin/rules/literal-subsystem.js +102 -0
- package/eslint-plugin/rules/no-computed-metadata-key.js +174 -0
- package/eslint-plugin/rules/no-derived-correlation.js +171 -0
- package/eslint-plugin/rules/no-dynamic-message.js +60 -0
- package/eslint-plugin/shared.js +1948 -0
- package/ios/Gzip.swift +203 -0
- package/ios/HybridFileSink.swift +291 -0
- package/ios/HybridNativeConsoleSink.swift +20 -0
- package/ios/LogFileWriter.swift +1280 -0
- package/ios/LogSecureFile.swift +296 -0
- package/ios/LogWriterRegistry.swift +444 -0
- package/ios/NativeConsoleWriter.swift +180 -0
- package/lib/module/Logger.js +381 -0
- package/lib/module/Logger.js.map +1 -0
- package/lib/module/ScopedLogger.js +70 -0
- package/lib/module/ScopedLogger.js.map +1 -0
- package/lib/module/config.js +23 -0
- package/lib/module/config.js.map +1 -0
- package/lib/module/destinations/Batcher.js +647 -0
- package/lib/module/destinations/Batcher.js.map +1 -0
- package/lib/module/destinations/ConsoleDestination.js +51 -0
- package/lib/module/destinations/ConsoleDestination.js.map +1 -0
- package/lib/module/destinations/FileDestination.js +360 -0
- package/lib/module/destinations/FileDestination.js.map +1 -0
- package/lib/module/destinations/NativeConsoleDestination.js +170 -0
- package/lib/module/destinations/NativeConsoleDestination.js.map +1 -0
- package/lib/module/destinations/types.js +4 -0
- package/lib/module/destinations/types.js.map +1 -0
- package/lib/module/formatters/DefaultFormatter.js +136 -0
- package/lib/module/formatters/DefaultFormatter.js.map +1 -0
- package/lib/module/formatters/JsonLinesFormatter.js +162 -0
- package/lib/module/formatters/JsonLinesFormatter.js.map +1 -0
- package/lib/module/formatters/timestamp.js +15 -0
- package/lib/module/formatters/timestamp.js.map +1 -0
- package/lib/module/formatters/types.js +4 -0
- package/lib/module/formatters/types.js.map +1 -0
- package/lib/module/index.js +31 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/integrations/appState.js +81 -0
- package/lib/module/integrations/appState.js.map +1 -0
- package/lib/module/integrations/errorHandler.js +166 -0
- package/lib/module/integrations/errorHandler.js.map +1 -0
- package/lib/module/integrations/sanitizeError.js +238 -0
- package/lib/module/integrations/sanitizeError.js.map +1 -0
- package/lib/module/levels.js +35 -0
- package/lib/module/levels.js.map +1 -0
- package/lib/module/metadata.js +52 -0
- package/lib/module/metadata.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/privacy.js +349 -0
- package/lib/module/privacy.js.map +1 -0
- package/lib/module/specs/FileSink.nitro.js +4 -0
- package/lib/module/specs/FileSink.nitro.js.map +1 -0
- package/lib/module/specs/NativeConsoleSink.nitro.js +4 -0
- package/lib/module/specs/NativeConsoleSink.nitro.js.map +1 -0
- package/lib/module/types.js +4 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/utf8.js +42 -0
- package/lib/module/utf8.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/Logger.d.ts +122 -0
- package/lib/typescript/src/Logger.d.ts.map +1 -0
- package/lib/typescript/src/ScopedLogger.d.ts +36 -0
- package/lib/typescript/src/ScopedLogger.d.ts.map +1 -0
- package/lib/typescript/src/config.d.ts +12 -0
- package/lib/typescript/src/config.d.ts.map +1 -0
- package/lib/typescript/src/destinations/Batcher.d.ts +244 -0
- package/lib/typescript/src/destinations/Batcher.d.ts.map +1 -0
- package/lib/typescript/src/destinations/ConsoleDestination.d.ts +27 -0
- package/lib/typescript/src/destinations/ConsoleDestination.d.ts.map +1 -0
- package/lib/typescript/src/destinations/FileDestination.d.ts +200 -0
- package/lib/typescript/src/destinations/FileDestination.d.ts.map +1 -0
- package/lib/typescript/src/destinations/NativeConsoleDestination.d.ts +86 -0
- package/lib/typescript/src/destinations/NativeConsoleDestination.d.ts.map +1 -0
- package/lib/typescript/src/destinations/types.d.ts +19 -0
- package/lib/typescript/src/destinations/types.d.ts.map +1 -0
- package/lib/typescript/src/formatters/DefaultFormatter.d.ts +22 -0
- package/lib/typescript/src/formatters/DefaultFormatter.d.ts.map +1 -0
- package/lib/typescript/src/formatters/JsonLinesFormatter.d.ts +73 -0
- package/lib/typescript/src/formatters/JsonLinesFormatter.d.ts.map +1 -0
- package/lib/typescript/src/formatters/timestamp.d.ts +6 -0
- package/lib/typescript/src/formatters/timestamp.d.ts.map +1 -0
- package/lib/typescript/src/formatters/types.d.ts +27 -0
- package/lib/typescript/src/formatters/types.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +34 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/integrations/appState.d.ts +33 -0
- package/lib/typescript/src/integrations/appState.d.ts.map +1 -0
- package/lib/typescript/src/integrations/errorHandler.d.ts +55 -0
- package/lib/typescript/src/integrations/errorHandler.d.ts.map +1 -0
- package/lib/typescript/src/integrations/sanitizeError.d.ts +89 -0
- package/lib/typescript/src/integrations/sanitizeError.d.ts.map +1 -0
- package/lib/typescript/src/levels.d.ts +9 -0
- package/lib/typescript/src/levels.d.ts.map +1 -0
- package/lib/typescript/src/metadata.d.ts +23 -0
- package/lib/typescript/src/metadata.d.ts.map +1 -0
- package/lib/typescript/src/privacy.d.ts +103 -0
- package/lib/typescript/src/privacy.d.ts.map +1 -0
- package/lib/typescript/src/specs/FileSink.nitro.d.ts +131 -0
- package/lib/typescript/src/specs/FileSink.nitro.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeConsoleSink.nitro.d.ts +21 -0
- package/lib/typescript/src/specs/NativeConsoleSink.nitro.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +37 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/lib/typescript/src/utf8.d.ts +15 -0
- package/lib/typescript/src/utf8.d.ts.map +1 -0
- package/nitro.json +33 -0
- package/nitrogen/generated/android/c++/JAppendResult.hpp +79 -0
- package/nitrogen/generated/android/c++/JClearOutcome.hpp +88 -0
- package/nitrogen/generated/android/c++/JFlushOutcome.hpp +81 -0
- package/nitrogen/generated/android/c++/JHybridFileSinkSpec.cpp +120 -0
- package/nitrogen/generated/android/c++/JHybridFileSinkSpec.hpp +69 -0
- package/nitrogen/generated/android/c++/JHybridNativeConsoleSinkSpec.cpp +71 -0
- package/nitrogen/generated/android/c++/JHybridNativeConsoleSinkSpec.hpp +64 -0
- package/nitrogen/generated/android/c++/JRejectReason.hpp +64 -0
- package/nitrogen/generated/android/c++/JRotationConfig.hpp +77 -0
- package/nitrogen/generated/android/c++/JSinkStatus.hpp +69 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/AppendResult.kt +76 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/ClearOutcome.kt +66 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/FlushOutcome.kt +81 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/HybridFileSinkSpec.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/HybridNativeConsoleSinkSpec.kt +58 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/RejectReason.kt +25 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/RotationConfig.kt +76 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/SinkStatus.kt +66 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/nitrologgerOnLoad.kt +35 -0
- package/nitrogen/generated/android/nitrologger+autolinking.cmake +83 -0
- package/nitrogen/generated/android/nitrologger+autolinking.gradle +27 -0
- package/nitrogen/generated/android/nitrologgerOnLoad.cpp +70 -0
- package/nitrogen/generated/android/nitrologgerOnLoad.hpp +34 -0
- package/nitrogen/generated/ios/NitroLogger+autolinking.rb +62 -0
- package/nitrogen/generated/ios/NitroLogger-Swift-Cxx-Bridge.cpp +50 -0
- package/nitrogen/generated/ios/NitroLogger-Swift-Cxx-Bridge.hpp +216 -0
- package/nitrogen/generated/ios/NitroLogger-Swift-Cxx-Umbrella.hpp +69 -0
- package/nitrogen/generated/ios/NitroLoggerAutolinking.mm +41 -0
- package/nitrogen/generated/ios/NitroLoggerAutolinking.swift +38 -0
- package/nitrogen/generated/ios/c++/HybridFileSinkSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridFileSinkSpecSwift.hpp +150 -0
- package/nitrogen/generated/ios/c++/HybridNativeConsoleSinkSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridNativeConsoleSinkSpecSwift.hpp +87 -0
- package/nitrogen/generated/ios/swift/AppendResult.swift +60 -0
- package/nitrogen/generated/ios/swift/ClearOutcome.swift +50 -0
- package/nitrogen/generated/ios/swift/FlushOutcome.swift +59 -0
- package/nitrogen/generated/ios/swift/HybridFileSinkSpec.swift +61 -0
- package/nitrogen/generated/ios/swift/HybridFileSinkSpec_cxx.swift +227 -0
- package/nitrogen/generated/ios/swift/HybridNativeConsoleSinkSpec.swift +56 -0
- package/nitrogen/generated/ios/swift/HybridNativeConsoleSinkSpec_cxx.swift +148 -0
- package/nitrogen/generated/ios/swift/RejectReason.swift +48 -0
- package/nitrogen/generated/ios/swift/RotationConfig.swift +93 -0
- package/nitrogen/generated/ios/swift/SinkStatus.swift +44 -0
- package/nitrogen/generated/shared/c++/AppendResult.hpp +105 -0
- package/nitrogen/generated/shared/c++/ClearOutcome.hpp +96 -0
- package/nitrogen/generated/shared/c++/FlushOutcome.hpp +107 -0
- package/nitrogen/generated/shared/c++/HybridFileSinkSpec.cpp +28 -0
- package/nitrogen/generated/shared/c++/HybridFileSinkSpec.hpp +84 -0
- package/nitrogen/generated/shared/c++/HybridNativeConsoleSinkSpec.cpp +22 -0
- package/nitrogen/generated/shared/c++/HybridNativeConsoleSinkSpec.hpp +64 -0
- package/nitrogen/generated/shared/c++/RejectReason.hpp +84 -0
- package/nitrogen/generated/shared/c++/RotationConfig.hpp +103 -0
- package/nitrogen/generated/shared/c++/SinkStatus.hpp +95 -0
- package/package.json +151 -0
- package/src/Logger.ts +417 -0
- package/src/ScopedLogger.ts +94 -0
- package/src/config.ts +25 -0
- package/src/destinations/Batcher.ts +805 -0
- package/src/destinations/ConsoleDestination.ts +60 -0
- package/src/destinations/FileDestination.ts +473 -0
- package/src/destinations/NativeConsoleDestination.ts +220 -0
- package/src/destinations/types.ts +19 -0
- package/src/formatters/DefaultFormatter.ts +150 -0
- package/src/formatters/JsonLinesFormatter.ts +195 -0
- package/src/formatters/timestamp.ts +12 -0
- package/src/formatters/types.ts +29 -0
- package/src/index.tsx +106 -0
- package/src/integrations/appState.ts +111 -0
- package/src/integrations/errorHandler.ts +223 -0
- package/src/integrations/sanitizeError.ts +287 -0
- package/src/levels.ts +35 -0
- package/src/metadata.ts +52 -0
- package/src/privacy.ts +389 -0
- package/src/specs/FileSink.nitro.ts +144 -0
- package/src/specs/NativeConsoleSink.nitro.ts +21 -0
- package/src/types.ts +45 -0
- package/src/utf8.ts +39 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { DefaultFormatter } from "../formatters/DefaultFormatter.js";
|
|
4
|
+
import { LEVEL_ORDER } from "../levels.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Renders to the JS console (Metro in dev). warning → console.warn and
|
|
8
|
+
* error/todo → console.error deliberately: LogBox surfacing errors in dev is
|
|
9
|
+
* a feature, not noise.
|
|
10
|
+
*
|
|
11
|
+
* `outputSink` mirrors SwiftLogger's test hook: when set, lines are also
|
|
12
|
+
* handed to the sink, and `isEnabled` stays true even with printing off.
|
|
13
|
+
*/
|
|
14
|
+
export class ConsoleDestination {
|
|
15
|
+
label = 'console';
|
|
16
|
+
printEnabled = true;
|
|
17
|
+
constructor(options) {
|
|
18
|
+
this.minimumLevel = options?.minimumLevel;
|
|
19
|
+
this.formatter = options?.formatter ?? new DefaultFormatter();
|
|
20
|
+
}
|
|
21
|
+
get isEnabled() {
|
|
22
|
+
return this.printEnabled || this.outputSink !== undefined;
|
|
23
|
+
}
|
|
24
|
+
write(entry) {
|
|
25
|
+
const line = this.formatter.format(entry);
|
|
26
|
+
if (this.outputSink) {
|
|
27
|
+
// Guarded: a faulty observer must not suppress console output or get
|
|
28
|
+
// the whole destination disabled as repeatedly failing.
|
|
29
|
+
try {
|
|
30
|
+
this.outputSink(line);
|
|
31
|
+
} catch {
|
|
32
|
+
// observer-only failure; console printing below still runs
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (!this.printEnabled) return;
|
|
36
|
+
if (LEVEL_ORDER[entry.level] >= LEVEL_ORDER.error) {
|
|
37
|
+
console.error(line);
|
|
38
|
+
} else if (entry.level === 'warning') {
|
|
39
|
+
console.warn(line);
|
|
40
|
+
} else {
|
|
41
|
+
console.log(line);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
flush() {
|
|
45
|
+
// console writes are synchronous; nothing buffers here
|
|
46
|
+
}
|
|
47
|
+
dispose() {
|
|
48
|
+
this.outputSink = undefined;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=ConsoleDestination.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["DefaultFormatter","LEVEL_ORDER","ConsoleDestination","label","printEnabled","constructor","options","minimumLevel","formatter","isEnabled","outputSink","undefined","write","entry","line","format","level","error","console","warn","log","flush","dispose"],"sourceRoot":"../../../src","sources":["destinations/ConsoleDestination.ts"],"mappings":";;AAGA,SAASA,gBAAgB,QAAQ,mCAAgC;AACjE,SAASC,WAAW,QAAQ,cAAW;;AAEvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,kBAAkB,CAA2B;EAC/CC,KAAK,GAAG,SAAS;EAE1BC,YAAY,GAAG,IAAI;EAKnBC,WAAWA,CAACC,OAA+D,EAAE;IAC3E,IAAI,CAACC,YAAY,GAAGD,OAAO,EAAEC,YAAY;IACzC,IAAI,CAACC,SAAS,GAAGF,OAAO,EAAEE,SAAS,IAAI,IAAIR,gBAAgB,CAAC,CAAC;EAC/D;EAEA,IAAIS,SAASA,CAAA,EAAY;IACvB,OAAO,IAAI,CAACL,YAAY,IAAI,IAAI,CAACM,UAAU,KAAKC,SAAS;EAC3D;EAEAC,KAAKA,CAACC,KAAe,EAAQ;IAC3B,MAAMC,IAAI,GAAG,IAAI,CAACN,SAAS,CAACO,MAAM,CAACF,KAAK,CAAC;IACzC,IAAI,IAAI,CAACH,UAAU,EAAE;MACnB;MACA;MACA,IAAI;QACF,IAAI,CAACA,UAAU,CAACI,IAAI,CAAC;MACvB,CAAC,CAAC,MAAM;QACN;MAAA;IAEJ;IACA,IAAI,CAAC,IAAI,CAACV,YAAY,EAAE;IACxB,IAAIH,WAAW,CAACY,KAAK,CAACG,KAAK,CAAC,IAAIf,WAAW,CAACgB,KAAK,EAAE;MACjDC,OAAO,CAACD,KAAK,CAACH,IAAI,CAAC;IACrB,CAAC,MAAM,IAAID,KAAK,CAACG,KAAK,KAAK,SAAS,EAAE;MACpCE,OAAO,CAACC,IAAI,CAACL,IAAI,CAAC;IACpB,CAAC,MAAM;MACLI,OAAO,CAACE,GAAG,CAACN,IAAI,CAAC;IACnB;EACF;EAEAO,KAAKA,CAAA,EAAS;IACZ;EAAA;EAGFC,OAAOA,CAAA,EAAS;IACd,IAAI,CAACZ,UAAU,GAAGC,SAAS;EAC7B;AACF","ignoreList":[]}
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { Batcher } from "./Batcher.js";
|
|
4
|
+
import { JsonLinesFormatter } from "../formatters/JsonLinesFormatter.js";
|
|
5
|
+
import { utf8Length } from "../utf8.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The part of `FileSink` a `FileDestination` uses.
|
|
9
|
+
*
|
|
10
|
+
* Structural rather than the Nitro interface itself, so the destination can
|
|
11
|
+
* be driven by a scripted double in tests. The real `FileSink` satisfies it.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const DEFAULT_LABEL = 'file';
|
|
15
|
+
const DEFAULT_FILENAME = 'app.log';
|
|
16
|
+
const DEFAULT_MAX_ENTRY_BYTES = 64 * 1024;
|
|
17
|
+
const DEFAULT_DEADLINE_MS = 2000;
|
|
18
|
+
|
|
19
|
+
/** Fixed text: a diagnostic that interpolates caller data is a log-injection
|
|
20
|
+
* hole and a privacy hole at once. Only counts travel with it. */
|
|
21
|
+
const LOSS_MESSAGE = 'log entries were dropped';
|
|
22
|
+
const OVERSIZE_MESSAGE = 'a log entry was too large to record';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Writes formatted records to a native file sink, batched and backpressured.
|
|
26
|
+
*
|
|
27
|
+
* The division of labour is the whole design: this side decides what to write
|
|
28
|
+
* and what to give up on, the sink only appends text and reports counters.
|
|
29
|
+
* Everything interesting — batching, drop policy, loss notices, the purge
|
|
30
|
+
* handshake — is therefore testable without a device.
|
|
31
|
+
*
|
|
32
|
+
* Three behaviours are worth knowing about before using it.
|
|
33
|
+
*
|
|
34
|
+
* **Oversized entries are never sliced.** A formatter that can shed structure
|
|
35
|
+
* is asked to re-render within the limit; one that cannot has its output
|
|
36
|
+
* replaced whole by a fixed notice. Cutting a rendered record to length is
|
|
37
|
+
* how a log file stops being parseable, and an unparseable file is worth less
|
|
38
|
+
* than an honestly incomplete one.
|
|
39
|
+
*
|
|
40
|
+
* **Framing is declared, not assumed.** A formatter guaranteeing one record
|
|
41
|
+
* per line lets the native side trim a torn trailing record after a crash.
|
|
42
|
+
* Without that guarantee the file is left as the crash left it, because a
|
|
43
|
+
* writer cannot tell a torn record from an intentional newline.
|
|
44
|
+
*
|
|
45
|
+
* **A fenced handle stays fenced.** When the sink reports that this handle's
|
|
46
|
+
* generation is stale — someone purged the file underneath it — the buffer is
|
|
47
|
+
* discarded rather than replayed into the new file, and the destination
|
|
48
|
+
* disables itself. Pre-purge records must not reappear after a compliance
|
|
49
|
+
* deletion. The handle that invoked the purge rebinds; any other one does
|
|
50
|
+
* not, and reacquisition is the native registry's job.
|
|
51
|
+
*/
|
|
52
|
+
export class FileDestination {
|
|
53
|
+
/** Held for the M5 registry's reacquisition path, which needs the same
|
|
54
|
+
* config the handle was opened with. */
|
|
55
|
+
|
|
56
|
+
fenced = false;
|
|
57
|
+
disposed = false;
|
|
58
|
+
constructor(sink, options = {}) {
|
|
59
|
+
this.sink = sink;
|
|
60
|
+
this.label = options.label ?? DEFAULT_LABEL;
|
|
61
|
+
this.minimumLevel = options.minimumLevel;
|
|
62
|
+
this.formatter = options.formatter ?? new JsonLinesFormatter();
|
|
63
|
+
this.maxEntryBytes = positive(options.maxEntryBytes, DEFAULT_MAX_ENTRY_BYTES);
|
|
64
|
+
this.path = options.path ?? `${sink.defaultLogDirectory}/${DEFAULT_FILENAME}`;
|
|
65
|
+
this.rotation = options.rotation;
|
|
66
|
+
this.batcher = new Batcher(sink, {
|
|
67
|
+
renderNotice: lost => this.renderLossNotice(lost),
|
|
68
|
+
onFenced: reason => this.onFenced(reason),
|
|
69
|
+
batchBytes: options.batchBytes,
|
|
70
|
+
flushIntervalMs: options.flushIntervalMs,
|
|
71
|
+
maxPendingEntries: options.maxPendingEntries,
|
|
72
|
+
maxPendingBytes: options.maxPendingBytes,
|
|
73
|
+
watermarkBytes: options.watermarkBytes
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Throws on open failure or on a config conflict with an existing writer,
|
|
77
|
+
// and deliberately so: a file destination that silently writes nowhere is
|
|
78
|
+
// worse than one that refuses to be constructed.
|
|
79
|
+
sink.open(this.path, this.rotation, this.lineFramed);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** True only while this handle may write. */
|
|
83
|
+
get isEnabled() {
|
|
84
|
+
return !this.fenced && !this.disposed;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Where records are going. */
|
|
88
|
+
get filePath() {
|
|
89
|
+
return this.path;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Whether the native side may trim a torn trailing record after a crash.
|
|
94
|
+
* Follows the formatter's declaration; nothing infers it.
|
|
95
|
+
*/
|
|
96
|
+
get lineFramed() {
|
|
97
|
+
return this.formatter.framing === 'line';
|
|
98
|
+
}
|
|
99
|
+
write(entry) {
|
|
100
|
+
if (!this.isEnabled) return;
|
|
101
|
+
const record = this.renderRecord(entry);
|
|
102
|
+
if (record === undefined) return;
|
|
103
|
+
this.batcher.add(record);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Drain to disk and fsync, bounded by a wall-clock deadline.
|
|
108
|
+
*
|
|
109
|
+
* Returns the outcome even though `LogDestination` asks only for `void`: a
|
|
110
|
+
* caller flushing before backgrounding or on a crash path needs to know
|
|
111
|
+
* whether it worked, and `durable: false` is the answer that matters.
|
|
112
|
+
*/
|
|
113
|
+
flush(deadlineMs = DEFAULT_DEADLINE_MS) {
|
|
114
|
+
return this.batcher.flush(deadlineMs);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Current file and archives, newest first; empty if the sink refuses. */
|
|
118
|
+
getLogFilePaths() {
|
|
119
|
+
try {
|
|
120
|
+
return this.sink.getLogFilePaths();
|
|
121
|
+
} catch {
|
|
122
|
+
return [];
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Losses with no notice in the file yet. */
|
|
127
|
+
unreportedLoss() {
|
|
128
|
+
return this.batcher.unreported();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* What has stopped working underneath, as a payload-free bitmask —
|
|
133
|
+
* rotation, gzip, prune, sidecar, protection.
|
|
134
|
+
*
|
|
135
|
+
* The mask exists because the alternative is a message, and a message built
|
|
136
|
+
* from an `errno` string or a path is exactly the kind of thing that carries
|
|
137
|
+
* a username into a log file. Bits carry no payload, so an app can surface
|
|
138
|
+
* "log rotation is failing" to support without surfacing anything else.
|
|
139
|
+
*
|
|
140
|
+
* Non-zero does not mean records are being lost — a failed compression or a
|
|
141
|
+
* failed prune costs disk, not data. Check {@link unreportedLoss} for that.
|
|
142
|
+
*/
|
|
143
|
+
degradation() {
|
|
144
|
+
return this.batcher.degradation();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Delete every log artifact, then rebind.
|
|
149
|
+
*
|
|
150
|
+
* The ordering is the point. This handle is fenced first, so nothing can be
|
|
151
|
+
* written into the window where deletion is in flight; the JS buffer is
|
|
152
|
+
* discarded rather than flushed, because flushing it would write pre-purge
|
|
153
|
+
* records into the file a moment before deleting it — or worse, a moment
|
|
154
|
+
* after. Only a durable deletion lifts the fence. A partial or timed-out
|
|
155
|
+
* one leaves this handle disabled until an explicit retry, so a late
|
|
156
|
+
* deletion can never race a fresh write.
|
|
157
|
+
*
|
|
158
|
+
* Discarded counts come back here rather than going into a loss notice: a
|
|
159
|
+
* "4,182 entries dropped" line at the top of a file that was just cleared
|
|
160
|
+
* for compliance describes the clearing, which the caller already knows
|
|
161
|
+
* about.
|
|
162
|
+
*/
|
|
163
|
+
purge(deadlineMs = DEFAULT_DEADLINE_MS) {
|
|
164
|
+
// A disposed destination has closed its sink, and a closed sink has no
|
|
165
|
+
// handle left to delete through — so this call cannot do the one thing it
|
|
166
|
+
// exists to do. Saying so is the entire point: the alternative is a
|
|
167
|
+
// `durable: true` over files that are still on disk, told to the one caller
|
|
168
|
+
// who asked because they are legally obliged to know. `removeDestination()`
|
|
169
|
+
// then a compliance purge is an ordinary sequence, not a contrived one.
|
|
170
|
+
if (this.disposed) {
|
|
171
|
+
return {
|
|
172
|
+
durable: false,
|
|
173
|
+
rebound: false,
|
|
174
|
+
deletedCount: 0,
|
|
175
|
+
failedPaths: [],
|
|
176
|
+
discardedEntries: 0,
|
|
177
|
+
discardedBytes: 0
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
this.fenced = true;
|
|
181
|
+
const discarded = this.batcher.discard();
|
|
182
|
+
let outcome;
|
|
183
|
+
try {
|
|
184
|
+
outcome = this.sink.clearLogs(deadlineMs);
|
|
185
|
+
} catch {
|
|
186
|
+
return {
|
|
187
|
+
durable: false,
|
|
188
|
+
// The call threw, so nothing is known about the sink's state and the
|
|
189
|
+
// fence set above stays up. Reporting a rebind here would lift it.
|
|
190
|
+
rebound: false,
|
|
191
|
+
deletedCount: 0,
|
|
192
|
+
failedPaths: [],
|
|
193
|
+
discardedEntries: discarded.entries,
|
|
194
|
+
discardedBytes: discarded.bytes
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Both facts, not just the first. `durable` says the artifacts are gone;
|
|
199
|
+
// `rebound` says the sink has a usable file again. Lifting the fence on
|
|
200
|
+
// `durable` alone resumes writing into a handle the sink never rebound —
|
|
201
|
+
// every record accepted, rejected as `staleGeneration`, and dropped. The
|
|
202
|
+
// deletion is still complete and still reported as such; the destination
|
|
203
|
+
// just stays disabled until an explicit retry gets a live file back.
|
|
204
|
+
//
|
|
205
|
+
// `=== true`, not `!== false`. An absent field is not a promise, and the
|
|
206
|
+
// sink most likely to omit it is one that predates it — including a native
|
|
207
|
+
// build that deletes by closing and never reopens at all. A JS bundle can
|
|
208
|
+
// be updated over the air without the binary underneath it changing, so
|
|
209
|
+
// "old native, new JS" is a real pairing, and reading silence as success
|
|
210
|
+
// there rebuilds exactly the silent post-purge loss this flag exists to
|
|
211
|
+
// stop. Staying fenced until a retry is the failure that announces itself.
|
|
212
|
+
const resumed = outcome.durable && outcome.rebound === true;
|
|
213
|
+
if (resumed) {
|
|
214
|
+
this.fenced = this.disposed;
|
|
215
|
+
this.batcher.rebind();
|
|
216
|
+
}
|
|
217
|
+
return {
|
|
218
|
+
durable: outcome.durable,
|
|
219
|
+
rebound: resumed,
|
|
220
|
+
deletedCount: count(outcome.deletedCount),
|
|
221
|
+
failedPaths: Array.isArray(outcome.failedPaths) ? outcome.failedPaths : [],
|
|
222
|
+
discardedEntries: discarded.entries,
|
|
223
|
+
discardedBytes: discarded.bytes
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** Idempotent: flush what is buffered, release the timer, close the sink. */
|
|
228
|
+
dispose() {
|
|
229
|
+
if (this.disposed) return;
|
|
230
|
+
try {
|
|
231
|
+
this.batcher.flush(DEFAULT_DEADLINE_MS);
|
|
232
|
+
} catch {
|
|
233
|
+
// a failing drain must not leak the handle below
|
|
234
|
+
}
|
|
235
|
+
this.disposed = true;
|
|
236
|
+
this.batcher.dispose();
|
|
237
|
+
try {
|
|
238
|
+
this.sink.close(DEFAULT_DEADLINE_MS);
|
|
239
|
+
} catch {
|
|
240
|
+
// nothing left to salvage
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// ── Internals ───────────────────────────────────────────────────────────
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Render one entry, or account for why it could not be rendered.
|
|
248
|
+
*
|
|
249
|
+
* Returns undefined when nothing writable came out; the loss is recorded
|
|
250
|
+
* before returning, so an entry is either in the file or in the counters
|
|
251
|
+
* and never in neither.
|
|
252
|
+
*/
|
|
253
|
+
renderRecord(entry) {
|
|
254
|
+
const record = this.formatOrUndefined(entry);
|
|
255
|
+
if (record === undefined) {
|
|
256
|
+
this.batcher.noteLoss(1, 0);
|
|
257
|
+
return undefined;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// The ORIGINAL size, held onto for the rest of this method. What gets
|
|
261
|
+
// discarded is the entry the caller wrote, so that is the number the
|
|
262
|
+
// counters and the notice have to carry — not the size of whatever
|
|
263
|
+
// undersized floor the formatter came back with instead.
|
|
264
|
+
const bytes = utf8Length(record);
|
|
265
|
+
if (bytes <= this.maxEntryBytes) return record;
|
|
266
|
+
|
|
267
|
+
// Structural shedding first: a formatter that knows its own shape can
|
|
268
|
+
// drop whole fields and truncate one at code-point boundaries, and what
|
|
269
|
+
// comes back is still valid in that format.
|
|
270
|
+
if (this.formatter.formatWithin) {
|
|
271
|
+
const shorter = this.formatWithinOrUndefined(entry);
|
|
272
|
+
if (shorter !== undefined && utf8Length(shorter) <= this.maxEntryBytes) {
|
|
273
|
+
return shorter;
|
|
274
|
+
}
|
|
275
|
+
// Still over: a record has a floor below which it identifies nothing.
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Nothing renderable fits, so the entry is replaced whole by a notice in
|
|
279
|
+
// the same format. Never sliced: a fragment of a record is not a record.
|
|
280
|
+
this.batcher.noteLoss(1, bytes);
|
|
281
|
+
return this.boundedNotice(noticeEntry(entry.timestamp, OVERSIZE_MESSAGE, {
|
|
282
|
+
droppedBytes: bytes
|
|
283
|
+
}));
|
|
284
|
+
}
|
|
285
|
+
renderLossNotice(lost) {
|
|
286
|
+
return this.boundedNotice(noticeEntry(Date.now(), LOSS_MESSAGE, {
|
|
287
|
+
droppedEntries: lost.entries,
|
|
288
|
+
droppedBytes: lost.bytes
|
|
289
|
+
}));
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Render one of the pipeline's own notices under the same per-entry limit
|
|
294
|
+
* as everything else.
|
|
295
|
+
*
|
|
296
|
+
* The limit exists so a batch always fits the sink. A notice exempt from it
|
|
297
|
+
* could be refused forever by a sink that will never take it, and the loss
|
|
298
|
+
* it describes would sit undelivered behind it — the pipeline's own
|
|
299
|
+
* diagnostics jamming the pipeline. Returning undefined when nothing fits
|
|
300
|
+
* leaves the loss counted and owed, which is the honest outcome.
|
|
301
|
+
*/
|
|
302
|
+
boundedNotice(entry) {
|
|
303
|
+
const text = this.formatOrUndefined(entry);
|
|
304
|
+
if (text === undefined) return undefined;
|
|
305
|
+
if (utf8Length(text) <= this.maxEntryBytes) return text;
|
|
306
|
+
if (this.formatter.formatWithin) {
|
|
307
|
+
const shorter = this.formatWithinOrUndefined(entry);
|
|
308
|
+
if (shorter !== undefined && utf8Length(shorter) <= this.maxEntryBytes) {
|
|
309
|
+
return shorter;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return undefined;
|
|
313
|
+
}
|
|
314
|
+
formatOrUndefined(entry) {
|
|
315
|
+
try {
|
|
316
|
+
const text = this.formatter.format(entry);
|
|
317
|
+
return typeof text === 'string' ? text : undefined;
|
|
318
|
+
} catch {
|
|
319
|
+
return undefined;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
formatWithinOrUndefined(entry) {
|
|
323
|
+
try {
|
|
324
|
+
const text = this.formatter.formatWithin(entry, this.maxEntryBytes);
|
|
325
|
+
return typeof text === 'string' ? text : undefined;
|
|
326
|
+
} catch {
|
|
327
|
+
return undefined;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
onFenced(_reason) {
|
|
331
|
+
this.fenced = true;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* A synthetic entry describing the pipeline's own state.
|
|
337
|
+
*
|
|
338
|
+
* Built directly rather than routed through the logger: it carries only
|
|
339
|
+
* counts, so there is nothing for redaction to protect, and going through the
|
|
340
|
+
* logger would put it behind the very destination that is trying to report a
|
|
341
|
+
* problem.
|
|
342
|
+
*/
|
|
343
|
+
function noticeEntry(timestamp, message, metadata) {
|
|
344
|
+
return Object.freeze({
|
|
345
|
+
timestamp,
|
|
346
|
+
level: 'warning',
|
|
347
|
+
message,
|
|
348
|
+
metadata: Object.freeze({
|
|
349
|
+
...metadata
|
|
350
|
+
}),
|
|
351
|
+
subsystem: 'logger'
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
function positive(value, fallback) {
|
|
355
|
+
return typeof value === 'number' && Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
|
|
356
|
+
}
|
|
357
|
+
function count(value) {
|
|
358
|
+
return typeof value === 'number' && Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
|
|
359
|
+
}
|
|
360
|
+
//# sourceMappingURL=FileDestination.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["Batcher","JsonLinesFormatter","utf8Length","DEFAULT_LABEL","DEFAULT_FILENAME","DEFAULT_MAX_ENTRY_BYTES","DEFAULT_DEADLINE_MS","LOSS_MESSAGE","OVERSIZE_MESSAGE","FileDestination","fenced","disposed","constructor","sink","options","label","minimumLevel","formatter","maxEntryBytes","positive","path","defaultLogDirectory","rotation","batcher","renderNotice","lost","renderLossNotice","onFenced","reason","batchBytes","flushIntervalMs","maxPendingEntries","maxPendingBytes","watermarkBytes","open","lineFramed","isEnabled","filePath","framing","write","entry","record","renderRecord","undefined","add","flush","deadlineMs","getLogFilePaths","unreportedLoss","unreported","degradation","purge","durable","rebound","deletedCount","failedPaths","discardedEntries","discardedBytes","discarded","discard","outcome","clearLogs","entries","bytes","resumed","rebind","count","Array","isArray","dispose","close","formatOrUndefined","noteLoss","formatWithin","shorter","formatWithinOrUndefined","boundedNotice","noticeEntry","timestamp","droppedBytes","Date","now","droppedEntries","text","format","_reason","message","metadata","Object","freeze","level","subsystem","value","fallback","Number","isFinite","Math","floor"],"sourceRoot":"../../../src","sources":["destinations/FileDestination.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { DefaultFormatter } from "../formatters/DefaultFormatter.js";
|
|
4
|
+
import { LEVEL_ORDER } from "../levels.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The part of `NativeConsoleSink` this destination uses.
|
|
8
|
+
*
|
|
9
|
+
* Structural rather than the Nitro interface itself, so tests can drive it
|
|
10
|
+
* with a double. The real `NativeConsoleSink` satisfies it.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const DEFAULT_BATCH_SIZE = 64;
|
|
14
|
+
const DEFAULT_FLUSH_INTERVAL_MS = 100;
|
|
15
|
+
const DEFAULT_MAX_PENDING = 1000;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Number of consecutive failed `logBatch` calls before the destination stops
|
|
19
|
+
* trying. A native sink that is throwing every time will not start working
|
|
20
|
+
* because we asked once more, and a try/catch per drain forever is a cost the
|
|
21
|
+
* app pays for nothing.
|
|
22
|
+
*/
|
|
23
|
+
const FAILURE_LIMIT = 3;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Renders entries into the platform log stream — os_log on iOS, logcat on
|
|
27
|
+
* Android — so JS logs interleave with native ones in Console.app and Xcode.
|
|
28
|
+
*
|
|
29
|
+
* Batched, unlike {@link ConsoleDestination}: one bridge crossing per drain
|
|
30
|
+
* with two parallel primitive arrays, rather than a crossing per entry.
|
|
31
|
+
*
|
|
32
|
+
* Deliberately simpler than {@link FileDestination}. There is no backpressure
|
|
33
|
+
* and no loss accounting because there is nothing to push back on: os_log
|
|
34
|
+
* accepts what it is given and never blocks on a disk. What this destination
|
|
35
|
+
* does account for is its own buffer — entries dropped at the ceiling, and
|
|
36
|
+
* entries lost to a throwing sink — through {@link dropped}, because a
|
|
37
|
+
* diagnostic channel that quietly loses records is worse than one that says
|
|
38
|
+
* it did.
|
|
39
|
+
*
|
|
40
|
+
* The durable copy is the file destination's. Nothing here is a system of
|
|
41
|
+
* record, which is what makes best-effort the right posture.
|
|
42
|
+
*/
|
|
43
|
+
export class NativeConsoleDestination {
|
|
44
|
+
levels = [];
|
|
45
|
+
messages = [];
|
|
46
|
+
disposed = false;
|
|
47
|
+
failures = 0;
|
|
48
|
+
droppedEntries = 0;
|
|
49
|
+
constructor(sink, options) {
|
|
50
|
+
this.sink = sink;
|
|
51
|
+
this.label = options?.label ?? 'native-console';
|
|
52
|
+
this.minimumLevel = options?.minimumLevel;
|
|
53
|
+
this.formatter = options?.formatter ?? new DefaultFormatter();
|
|
54
|
+
this.batchSize = positive(options?.batchSize, DEFAULT_BATCH_SIZE);
|
|
55
|
+
this.flushIntervalMs = positive(options?.flushIntervalMs, DEFAULT_FLUSH_INTERVAL_MS);
|
|
56
|
+
this.maxPending = positive(options?.maxPendingEntries, DEFAULT_MAX_PENDING);
|
|
57
|
+
|
|
58
|
+
// An empty subsystem is legal and produces a logger nobody can find in
|
|
59
|
+
// Console; the native side substitutes the bundle identifier for it.
|
|
60
|
+
this.sink.install(options?.subsystem ?? '', options?.category ?? 'log');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* False once disposed, or once the native sink has failed enough times in a
|
|
65
|
+
* row to be considered gone. The Logger checks this before formatting, so a
|
|
66
|
+
* dead sink stops costing render work as well as bridge calls.
|
|
67
|
+
*/
|
|
68
|
+
get isEnabled() {
|
|
69
|
+
return !this.disposed && this.failures < FAILURE_LIMIT;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Entries this destination never handed to the platform log. */
|
|
73
|
+
dropped() {
|
|
74
|
+
return this.droppedEntries;
|
|
75
|
+
}
|
|
76
|
+
write(entry) {
|
|
77
|
+
if (!this.isEnabled) return;
|
|
78
|
+
if (this.messages.length >= this.maxPending) {
|
|
79
|
+
// Drop-newest, matching the Batcher. Under a burst the oldest entries
|
|
80
|
+
// are the ones that explain how it started, which is what a reader is
|
|
81
|
+
// looking for; keeping the newest would leave only the aftermath.
|
|
82
|
+
this.droppedEntries += 1;
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Render first, then append both halves together. The two arrays are
|
|
87
|
+
// parallel and are read by index natively, so pushing the level before the
|
|
88
|
+
// message that might not arrive leaves them one apart — and from that point
|
|
89
|
+
// on every entry in the batch is logged at its predecessor's severity. The
|
|
90
|
+
// Logger catches a throwing destination and carries on, which is exactly
|
|
91
|
+
// what would let the misalignment survive unnoticed.
|
|
92
|
+
let rendered;
|
|
93
|
+
try {
|
|
94
|
+
rendered = this.formatter.format(entry);
|
|
95
|
+
} catch {
|
|
96
|
+
// Not counted against the sink's failure run: the sink is fine, the
|
|
97
|
+
// formatter is not, and disabling the channel over someone else's bug
|
|
98
|
+
// would take the console down for every entry a working formatter could
|
|
99
|
+
// still have rendered.
|
|
100
|
+
this.droppedEntries += 1;
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
this.levels.push(LEVEL_ORDER[entry.level]);
|
|
104
|
+
this.messages.push(rendered);
|
|
105
|
+
if (this.messages.length >= this.batchSize) {
|
|
106
|
+
this.drain();
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
this.arm();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Hands everything buffered to the platform log.
|
|
114
|
+
*
|
|
115
|
+
* The deadline is accepted and ignored, deliberately: `logBatch` does not
|
|
116
|
+
* wait on anything, so there is no wait to bound. Taking the parameter keeps
|
|
117
|
+
* the destination interchangeable with the ones that do need it.
|
|
118
|
+
*/
|
|
119
|
+
flush(_deadlineMs) {
|
|
120
|
+
this.drain();
|
|
121
|
+
}
|
|
122
|
+
dispose() {
|
|
123
|
+
if (this.disposed) return;
|
|
124
|
+
// Flush before the flag, not after: entries buffered up to this moment
|
|
125
|
+
// were accepted, and disposing is not a reason to drop them.
|
|
126
|
+
this.drain();
|
|
127
|
+
this.disposed = true;
|
|
128
|
+
this.cancel();
|
|
129
|
+
}
|
|
130
|
+
drain() {
|
|
131
|
+
this.cancel();
|
|
132
|
+
if (this.messages.length === 0) return;
|
|
133
|
+
const levels = this.levels;
|
|
134
|
+
const messages = this.messages;
|
|
135
|
+
this.levels = [];
|
|
136
|
+
this.messages = [];
|
|
137
|
+
if (this.disposed) return;
|
|
138
|
+
try {
|
|
139
|
+
this.sink.logBatch(levels, messages);
|
|
140
|
+
this.failures = 0;
|
|
141
|
+
} catch {
|
|
142
|
+
// Payload-free: whatever the native side threw is not worth risking on
|
|
143
|
+
// the way back through a logger. The batch is gone either way, so it is
|
|
144
|
+
// counted rather than retried — replaying it against a sink that just
|
|
145
|
+
// rejected it only doubles the chance of the same failure.
|
|
146
|
+
this.failures += 1;
|
|
147
|
+
this.droppedEntries += messages.length;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
arm() {
|
|
151
|
+
if (this.timer !== undefined) return;
|
|
152
|
+
this.timer = setTimeout(() => {
|
|
153
|
+
this.timer = undefined;
|
|
154
|
+
this.drain();
|
|
155
|
+
}, this.flushIntervalMs);
|
|
156
|
+
}
|
|
157
|
+
cancel() {
|
|
158
|
+
if (this.timer === undefined) return;
|
|
159
|
+
clearTimeout(this.timer);
|
|
160
|
+
this.timer = undefined;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** Finite positive integers only; anything else falls back. */
|
|
165
|
+
function positive(value, fallback) {
|
|
166
|
+
if (value === undefined) return fallback;
|
|
167
|
+
if (!Number.isSafeInteger(value) || value < 1) return fallback;
|
|
168
|
+
return value;
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=NativeConsoleDestination.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["DefaultFormatter","LEVEL_ORDER","DEFAULT_BATCH_SIZE","DEFAULT_FLUSH_INTERVAL_MS","DEFAULT_MAX_PENDING","FAILURE_LIMIT","NativeConsoleDestination","levels","messages","disposed","failures","droppedEntries","constructor","sink","options","label","minimumLevel","formatter","batchSize","positive","flushIntervalMs","maxPending","maxPendingEntries","install","subsystem","category","isEnabled","dropped","write","entry","length","rendered","format","push","level","drain","arm","flush","_deadlineMs","dispose","cancel","logBatch","timer","undefined","setTimeout","clearTimeout","value","fallback","Number","isSafeInteger"],"sourceRoot":"../../../src","sources":["destinations/NativeConsoleDestination.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["destinations/types.ts"],"mappings":"","ignoreList":[]}
|