backtest-kit 3.4.2 → 3.5.1
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/build/index.cjs +250 -32
- package/build/index.mjs +250 -32
- package/package.json +1 -1
- package/types.d.ts +2127 -2114
package/build/index.mjs
CHANGED
|
@@ -713,7 +713,7 @@ async function writeFileAtomic(file, data, options = {}) {
|
|
|
713
713
|
}
|
|
714
714
|
}
|
|
715
715
|
|
|
716
|
-
var _a$
|
|
716
|
+
var _a$4;
|
|
717
717
|
const BASE_WAIT_FOR_INIT_SYMBOL = Symbol("wait-for-init");
|
|
718
718
|
// Calculate step in milliseconds for candle close time validation
|
|
719
719
|
const INTERVAL_MINUTES$8 = {
|
|
@@ -836,7 +836,7 @@ class PersistBase {
|
|
|
836
836
|
constructor(entityName, baseDir = join(process.cwd(), "logs/data")) {
|
|
837
837
|
this.entityName = entityName;
|
|
838
838
|
this.baseDir = baseDir;
|
|
839
|
-
this[_a$
|
|
839
|
+
this[_a$4] = singleshot(async () => await BASE_WAIT_FOR_INIT_FN(this));
|
|
840
840
|
bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_CTOR, {
|
|
841
841
|
entityName: this.entityName,
|
|
842
842
|
baseDir,
|
|
@@ -939,7 +939,7 @@ class PersistBase {
|
|
|
939
939
|
}
|
|
940
940
|
}
|
|
941
941
|
}
|
|
942
|
-
_a$
|
|
942
|
+
_a$4 = BASE_WAIT_FOR_INIT_SYMBOL;
|
|
943
943
|
// @ts-ignore
|
|
944
944
|
PersistBase = makeExtendable(PersistBase);
|
|
945
945
|
/**
|
|
@@ -2046,7 +2046,7 @@ class PersistLogUtils {
|
|
|
2046
2046
|
*/
|
|
2047
2047
|
const PersistLogAdapter = new PersistLogUtils();
|
|
2048
2048
|
|
|
2049
|
-
var _a$
|
|
2049
|
+
var _a$3, _b$3;
|
|
2050
2050
|
const BUSY_DELAY = 100;
|
|
2051
2051
|
const SET_BUSY_SYMBOL = Symbol("setBusy");
|
|
2052
2052
|
const GET_BUSY_SYMBOL = Symbol("getBusy");
|
|
@@ -2061,8 +2061,8 @@ const ACQUIRE_LOCK_FN = async (self) => {
|
|
|
2061
2061
|
class Lock {
|
|
2062
2062
|
constructor() {
|
|
2063
2063
|
this._isBusy = 0;
|
|
2064
|
-
this[_a$
|
|
2065
|
-
this[_b$
|
|
2064
|
+
this[_a$3] = queued(ACQUIRE_LOCK_FN);
|
|
2065
|
+
this[_b$3] = () => this[SET_BUSY_SYMBOL](false);
|
|
2066
2066
|
this.acquireLock = async () => {
|
|
2067
2067
|
await this[ACQUIRE_LOCK_SYMBOL](this);
|
|
2068
2068
|
};
|
|
@@ -2080,7 +2080,7 @@ class Lock {
|
|
|
2080
2080
|
return !!this._isBusy;
|
|
2081
2081
|
}
|
|
2082
2082
|
}
|
|
2083
|
-
_a$
|
|
2083
|
+
_a$3 = ACQUIRE_LOCK_SYMBOL, _b$3 = RELEASE_LOCK_SYMBOL;
|
|
2084
2084
|
|
|
2085
2085
|
const METHOD_NAME_ACQUIRE_LOCK = "CandleUtils.acquireLock";
|
|
2086
2086
|
const METHOD_NAME_RELEASE_LOCK = "CandleUtils.releaseLock";
|
|
@@ -16076,7 +16076,7 @@ const COLUMN_CONFIG = {
|
|
|
16076
16076
|
*/
|
|
16077
16077
|
const DEFAULT_COLUMNS = Object.freeze({ ...COLUMN_CONFIG });
|
|
16078
16078
|
|
|
16079
|
-
var _a$
|
|
16079
|
+
var _a$2, _b$2;
|
|
16080
16080
|
const MARKDOWN_METHOD_NAME_ENABLE = "MarkdownUtils.enable";
|
|
16081
16081
|
const MARKDOWN_METHOD_NAME_DISABLE = "MarkdownUtils.disable";
|
|
16082
16082
|
const MARKDOWN_METHOD_NAME_USE_ADAPTER = "MarkdownAdapter.useMarkdownAdapter";
|
|
@@ -16086,8 +16086,8 @@ const MARKDOWN_METHOD_NAME_WRITE_DATA = "MarkdownAdapter.writeData";
|
|
|
16086
16086
|
const MARKDOWN_METHOD_NAME_USE_MD = "MarkdownAdapter.useMd";
|
|
16087
16087
|
const MARKDOWN_METHOD_NAME_USE_JSONL = "MarkdownAdapter.useJsonl";
|
|
16088
16088
|
const MARKDOWN_METHOD_NAME_USE_DUMMY = "MarkdownAdapter.useDummy";
|
|
16089
|
-
const WAIT_FOR_INIT_SYMBOL$
|
|
16090
|
-
const WRITE_SAFE_SYMBOL$
|
|
16089
|
+
const WAIT_FOR_INIT_SYMBOL$2 = Symbol("wait-for-init");
|
|
16090
|
+
const WRITE_SAFE_SYMBOL$2 = Symbol("write-safe");
|
|
16091
16091
|
/**
|
|
16092
16092
|
* Default configuration that enables all markdown services.
|
|
16093
16093
|
* Used when no specific configuration is provided to `enable()`.
|
|
@@ -16137,7 +16137,7 @@ class MarkdownFileBase {
|
|
|
16137
16137
|
* Protected by singleshot to ensure one-time execution.
|
|
16138
16138
|
* Sets up error handler that emits to exitEmitter.
|
|
16139
16139
|
*/
|
|
16140
|
-
this[_a$
|
|
16140
|
+
this[_a$2] = singleshot(async () => {
|
|
16141
16141
|
await fs.mkdir(this._baseDir, { recursive: true });
|
|
16142
16142
|
this._stream = createWriteStream(this._filePath, { flags: "a" });
|
|
16143
16143
|
this._stream.on("error", (err) => {
|
|
@@ -16149,7 +16149,7 @@ class MarkdownFileBase {
|
|
|
16149
16149
|
* Waits for drain event if write buffer is full.
|
|
16150
16150
|
* Times out after 15 seconds and returns TIMEOUT_SYMBOL.
|
|
16151
16151
|
*/
|
|
16152
|
-
this[_b$
|
|
16152
|
+
this[_b$2] = timeout(async (line) => {
|
|
16153
16153
|
if (!this._stream.write(line)) {
|
|
16154
16154
|
await new Promise((resolve) => {
|
|
16155
16155
|
this._stream.once("drain", resolve);
|
|
@@ -16165,7 +16165,7 @@ class MarkdownFileBase {
|
|
|
16165
16165
|
* @returns Promise that resolves when initialization is complete
|
|
16166
16166
|
*/
|
|
16167
16167
|
async waitForInit() {
|
|
16168
|
-
await this[WAIT_FOR_INIT_SYMBOL$
|
|
16168
|
+
await this[WAIT_FOR_INIT_SYMBOL$2]();
|
|
16169
16169
|
}
|
|
16170
16170
|
/**
|
|
16171
16171
|
* Writes markdown content to JSONL file with metadata.
|
|
@@ -16211,13 +16211,13 @@ class MarkdownFileBase {
|
|
|
16211
16211
|
...searchFlags,
|
|
16212
16212
|
timestamp: Date.now(),
|
|
16213
16213
|
}) + "\n";
|
|
16214
|
-
const status = await this[WRITE_SAFE_SYMBOL$
|
|
16214
|
+
const status = await this[WRITE_SAFE_SYMBOL$2](line);
|
|
16215
16215
|
if (status === TIMEOUT_SYMBOL$1) {
|
|
16216
16216
|
throw new Error(`Timeout writing to markdown ${this.markdownName}`);
|
|
16217
16217
|
}
|
|
16218
16218
|
}
|
|
16219
16219
|
}
|
|
16220
|
-
_a$
|
|
16220
|
+
_a$2 = WAIT_FOR_INIT_SYMBOL$2, _b$2 = WRITE_SAFE_SYMBOL$2;
|
|
16221
16221
|
//@ts-ignore
|
|
16222
16222
|
MarkdownFileBase = makeExtendable(MarkdownFileBase);
|
|
16223
16223
|
/**
|
|
@@ -23236,7 +23236,7 @@ class ColumnValidationService {
|
|
|
23236
23236
|
}
|
|
23237
23237
|
}
|
|
23238
23238
|
|
|
23239
|
-
var _a, _b;
|
|
23239
|
+
var _a$1, _b$1;
|
|
23240
23240
|
const REPORT_BASE_METHOD_NAME_CTOR = "ReportBase.CTOR";
|
|
23241
23241
|
const REPORT_BASE_METHOD_NAME_WAIT_FOR_INIT = "ReportBase.waitForInit";
|
|
23242
23242
|
const REPORT_BASE_METHOD_NAME_WRITE = "ReportBase.write";
|
|
@@ -23246,8 +23246,8 @@ const REPORT_UTILS_METHOD_NAME_ENABLE = "ReportUtils.enable";
|
|
|
23246
23246
|
const REPORT_UTILS_METHOD_NAME_DISABLE = "ReportUtils.disable";
|
|
23247
23247
|
const REPORT_UTILS_METHOD_NAME_USE_DUMMY = "ReportUtils.useDummy";
|
|
23248
23248
|
const REPORT_UTILS_METHOD_NAME_USE_JSONL = "ReportUtils.useJsonl";
|
|
23249
|
-
const WAIT_FOR_INIT_SYMBOL = Symbol("wait-for-init");
|
|
23250
|
-
const WRITE_SAFE_SYMBOL = Symbol("write-safe");
|
|
23249
|
+
const WAIT_FOR_INIT_SYMBOL$1 = Symbol("wait-for-init");
|
|
23250
|
+
const WRITE_SAFE_SYMBOL$1 = Symbol("write-safe");
|
|
23251
23251
|
/**
|
|
23252
23252
|
* JSONL-based report adapter with append-only writes.
|
|
23253
23253
|
*
|
|
@@ -23281,7 +23281,7 @@ class ReportBase {
|
|
|
23281
23281
|
* Protected by singleshot to ensure one-time execution.
|
|
23282
23282
|
* Sets up error handler that emits to exitEmitter.
|
|
23283
23283
|
*/
|
|
23284
|
-
this[_a] = singleshot(async () => {
|
|
23284
|
+
this[_a$1] = singleshot(async () => {
|
|
23285
23285
|
await fs.mkdir(this.baseDir, { recursive: true });
|
|
23286
23286
|
this._stream = createWriteStream(this._filePath, { flags: "a" });
|
|
23287
23287
|
this._stream.on("error", (err) => {
|
|
@@ -23293,7 +23293,7 @@ class ReportBase {
|
|
|
23293
23293
|
* Waits for drain event if write buffer is full.
|
|
23294
23294
|
* Times out after 15 seconds and returns TIMEOUT_SYMBOL.
|
|
23295
23295
|
*/
|
|
23296
|
-
this[_b] = timeout(async (line) => {
|
|
23296
|
+
this[_b$1] = timeout(async (line) => {
|
|
23297
23297
|
if (!this._stream.write(line)) {
|
|
23298
23298
|
await new Promise((resolve) => {
|
|
23299
23299
|
this._stream.once("drain", resolve);
|
|
@@ -23318,7 +23318,7 @@ class ReportBase {
|
|
|
23318
23318
|
reportName: this.reportName,
|
|
23319
23319
|
initial,
|
|
23320
23320
|
});
|
|
23321
|
-
await this[WAIT_FOR_INIT_SYMBOL]();
|
|
23321
|
+
await this[WAIT_FOR_INIT_SYMBOL$1]();
|
|
23322
23322
|
}
|
|
23323
23323
|
/**
|
|
23324
23324
|
* Writes event data to JSONL file with metadata.
|
|
@@ -23365,13 +23365,13 @@ class ReportBase {
|
|
|
23365
23365
|
...searchFlags,
|
|
23366
23366
|
timestamp: Date.now(),
|
|
23367
23367
|
}) + "\n";
|
|
23368
|
-
const status = await this[WRITE_SAFE_SYMBOL](line);
|
|
23368
|
+
const status = await this[WRITE_SAFE_SYMBOL$1](line);
|
|
23369
23369
|
if (status === TIMEOUT_SYMBOL$1) {
|
|
23370
23370
|
throw new Error(`Timeout writing to report ${this.reportName}`);
|
|
23371
23371
|
}
|
|
23372
23372
|
}
|
|
23373
23373
|
}
|
|
23374
|
-
_a = WAIT_FOR_INIT_SYMBOL, _b = WRITE_SAFE_SYMBOL;
|
|
23374
|
+
_a$1 = WAIT_FOR_INIT_SYMBOL$1, _b$1 = WRITE_SAFE_SYMBOL$1;
|
|
23375
23375
|
// @ts-ignore
|
|
23376
23376
|
ReportBase = makeExtendable(ReportBase);
|
|
23377
23377
|
/**
|
|
@@ -31203,6 +31203,7 @@ async function dumpMessages(resultId, history, result, outputDir = "./dump/strat
|
|
|
31203
31203
|
}
|
|
31204
31204
|
}
|
|
31205
31205
|
|
|
31206
|
+
var _a, _b;
|
|
31206
31207
|
const LOG_PERSIST_METHOD_NAME_WAIT_FOR_INIT = "LogPersistUtils.waitForInit";
|
|
31207
31208
|
const LOG_PERSIST_METHOD_NAME_LOG = "LogPersistUtils.log";
|
|
31208
31209
|
const LOG_PERSIST_METHOD_NAME_DEBUG = "LogPersistUtils.debug";
|
|
@@ -31218,17 +31219,47 @@ const LOG_ADAPTER_METHOD_NAME_USE_LOGGER = "LogAdapter.useLogger";
|
|
|
31218
31219
|
const LOG_ADAPTER_METHOD_NAME_USE_PERSIST = "LogAdapter.usePersist";
|
|
31219
31220
|
const LOG_ADAPTER_METHOD_NAME_USE_MEMORY = "LogAdapter.useMemory";
|
|
31220
31221
|
const LOG_ADAPTER_METHOD_NAME_USE_DUMMY = "LogAdapter.useDummy";
|
|
31222
|
+
const LOG_ADAPTER_METHOD_NAME_USE_JSONL = "LogAdapter.useJsonl";
|
|
31223
|
+
const LOG_JSONL_METHOD_NAME_LOG = "LogJsonlUtils.log";
|
|
31224
|
+
const LOG_JSONL_METHOD_NAME_DEBUG = "LogJsonlUtils.debug";
|
|
31225
|
+
const LOG_JSONL_METHOD_NAME_INFO = "LogJsonlUtils.info";
|
|
31226
|
+
const LOG_JSONL_METHOD_NAME_WARN = "LogJsonlUtils.warn";
|
|
31227
|
+
const LOG_JSONL_METHOD_NAME_GET_LIST = "LogJsonlUtils.getList";
|
|
31228
|
+
const WAIT_FOR_INIT_SYMBOL = Symbol("wait-for-init");
|
|
31229
|
+
const WRITE_SAFE_SYMBOL = Symbol("write-safe");
|
|
31221
31230
|
/**
|
|
31222
31231
|
* Backtest execution time retrieval function.
|
|
31223
31232
|
* Returns the 'when' timestamp from the execution context if available, otherwise returns the current time.
|
|
31224
31233
|
* This allows log entries to be timestamped according to the backtest timeline rather than real-world time, improving log relevance and user experience during backtest analysis.
|
|
31225
31234
|
*/
|
|
31226
|
-
const GET_DATE_FN =
|
|
31235
|
+
const GET_DATE_FN = () => {
|
|
31227
31236
|
if (ExecutionContextService.hasContext()) {
|
|
31228
31237
|
return new Date(bt.executionContextService.context.when);
|
|
31229
31238
|
}
|
|
31230
31239
|
return new Date();
|
|
31231
31240
|
};
|
|
31241
|
+
/**
|
|
31242
|
+
* Method context retrieval function.
|
|
31243
|
+
* Returns the current method context from MethodContextService if available, otherwise returns null.
|
|
31244
|
+
* This allows log entries to include contextual information about the strategy, exchange, and frame associated with the log event, enhancing the ability to trace and analyze logs in relation to specific execution contexts within the backtest framework.
|
|
31245
|
+
*/
|
|
31246
|
+
const GET_METHOD_CONTEXT_FN = () => {
|
|
31247
|
+
if (MethodContextService.hasContext()) {
|
|
31248
|
+
return bt.methodContextService.context;
|
|
31249
|
+
}
|
|
31250
|
+
return null;
|
|
31251
|
+
};
|
|
31252
|
+
/**
|
|
31253
|
+
* Execution context retrieval function.
|
|
31254
|
+
* Returns the current execution context from ExecutionContextService if available, otherwise returns null.
|
|
31255
|
+
* This allows log entries to include contextual information about the symbol, timestamp, and backtest mode associated with the log event, providing additional insights into the execution environment when analyzing logs.
|
|
31256
|
+
*/
|
|
31257
|
+
const GET_EXECUTION_CONTEXT_FN = () => {
|
|
31258
|
+
if (ExecutionContextService.hasContext()) {
|
|
31259
|
+
return bt.executionContextService.context;
|
|
31260
|
+
}
|
|
31261
|
+
return null;
|
|
31262
|
+
};
|
|
31232
31263
|
/**
|
|
31233
31264
|
* Persistent log adapter.
|
|
31234
31265
|
*
|
|
@@ -31263,12 +31294,14 @@ class LogPersistUtils {
|
|
|
31263
31294
|
this.log = async (topic, ...args) => {
|
|
31264
31295
|
bt.loggerService.info(LOG_PERSIST_METHOD_NAME_LOG, { topic });
|
|
31265
31296
|
await this.waitForInit();
|
|
31266
|
-
const date =
|
|
31297
|
+
const date = GET_DATE_FN();
|
|
31267
31298
|
this._entries.push({
|
|
31268
31299
|
id: randomString(),
|
|
31269
31300
|
type: "log",
|
|
31270
31301
|
timestamp: Date.now(),
|
|
31271
31302
|
createdAt: date.toISOString(),
|
|
31303
|
+
methodContext: GET_METHOD_CONTEXT_FN(),
|
|
31304
|
+
executionContext: GET_EXECUTION_CONTEXT_FN(),
|
|
31272
31305
|
topic,
|
|
31273
31306
|
args,
|
|
31274
31307
|
});
|
|
@@ -31284,12 +31317,14 @@ class LogPersistUtils {
|
|
|
31284
31317
|
this.debug = async (topic, ...args) => {
|
|
31285
31318
|
bt.loggerService.info(LOG_PERSIST_METHOD_NAME_DEBUG, { topic });
|
|
31286
31319
|
await this.waitForInit();
|
|
31287
|
-
const date =
|
|
31320
|
+
const date = GET_DATE_FN();
|
|
31288
31321
|
this._entries.push({
|
|
31289
31322
|
id: randomString(),
|
|
31290
31323
|
type: "debug",
|
|
31291
31324
|
timestamp: Date.now(),
|
|
31292
31325
|
createdAt: date.toISOString(),
|
|
31326
|
+
methodContext: GET_METHOD_CONTEXT_FN(),
|
|
31327
|
+
executionContext: GET_EXECUTION_CONTEXT_FN(),
|
|
31293
31328
|
topic,
|
|
31294
31329
|
args,
|
|
31295
31330
|
});
|
|
@@ -31305,12 +31340,14 @@ class LogPersistUtils {
|
|
|
31305
31340
|
this.info = async (topic, ...args) => {
|
|
31306
31341
|
bt.loggerService.info(LOG_PERSIST_METHOD_NAME_INFO, { topic });
|
|
31307
31342
|
await this.waitForInit();
|
|
31308
|
-
const date =
|
|
31343
|
+
const date = GET_DATE_FN();
|
|
31309
31344
|
this._entries.push({
|
|
31310
31345
|
id: randomString(),
|
|
31311
31346
|
type: "info",
|
|
31312
31347
|
timestamp: Date.now(),
|
|
31313
31348
|
createdAt: date.toISOString(),
|
|
31349
|
+
methodContext: GET_METHOD_CONTEXT_FN(),
|
|
31350
|
+
executionContext: GET_EXECUTION_CONTEXT_FN(),
|
|
31314
31351
|
topic,
|
|
31315
31352
|
args,
|
|
31316
31353
|
});
|
|
@@ -31326,12 +31363,14 @@ class LogPersistUtils {
|
|
|
31326
31363
|
this.warn = async (topic, ...args) => {
|
|
31327
31364
|
bt.loggerService.info(LOG_PERSIST_METHOD_NAME_WARN, { topic });
|
|
31328
31365
|
await this.waitForInit();
|
|
31329
|
-
const date =
|
|
31366
|
+
const date = GET_DATE_FN();
|
|
31330
31367
|
this._entries.push({
|
|
31331
31368
|
id: randomString(),
|
|
31332
31369
|
type: "warn",
|
|
31333
31370
|
timestamp: Date.now(),
|
|
31334
31371
|
createdAt: date.toISOString(),
|
|
31372
|
+
methodContext: GET_METHOD_CONTEXT_FN(),
|
|
31373
|
+
executionContext: GET_EXECUTION_CONTEXT_FN(),
|
|
31335
31374
|
topic,
|
|
31336
31375
|
args,
|
|
31337
31376
|
});
|
|
@@ -31380,12 +31419,14 @@ class LogMemoryUtils {
|
|
|
31380
31419
|
*/
|
|
31381
31420
|
this.log = async (topic, ...args) => {
|
|
31382
31421
|
bt.loggerService.info(LOG_MEMORY_METHOD_NAME_LOG, { topic });
|
|
31383
|
-
const date =
|
|
31422
|
+
const date = GET_DATE_FN();
|
|
31384
31423
|
this._entries.push({
|
|
31385
31424
|
id: randomString(),
|
|
31386
31425
|
type: "log",
|
|
31387
31426
|
timestamp: Date.now(),
|
|
31388
31427
|
createdAt: date.toISOString(),
|
|
31428
|
+
methodContext: GET_METHOD_CONTEXT_FN(),
|
|
31429
|
+
executionContext: GET_EXECUTION_CONTEXT_FN(),
|
|
31389
31430
|
topic,
|
|
31390
31431
|
args,
|
|
31391
31432
|
});
|
|
@@ -31399,12 +31440,14 @@ class LogMemoryUtils {
|
|
|
31399
31440
|
*/
|
|
31400
31441
|
this.debug = async (topic, ...args) => {
|
|
31401
31442
|
bt.loggerService.info(LOG_MEMORY_METHOD_NAME_DEBUG, { topic });
|
|
31402
|
-
const date =
|
|
31443
|
+
const date = GET_DATE_FN();
|
|
31403
31444
|
this._entries.push({
|
|
31404
31445
|
id: randomString(),
|
|
31405
31446
|
type: "debug",
|
|
31406
31447
|
timestamp: Date.now(),
|
|
31407
31448
|
createdAt: date.toISOString(),
|
|
31449
|
+
methodContext: GET_METHOD_CONTEXT_FN(),
|
|
31450
|
+
executionContext: GET_EXECUTION_CONTEXT_FN(),
|
|
31408
31451
|
topic,
|
|
31409
31452
|
args,
|
|
31410
31453
|
});
|
|
@@ -31418,12 +31461,14 @@ class LogMemoryUtils {
|
|
|
31418
31461
|
*/
|
|
31419
31462
|
this.info = async (topic, ...args) => {
|
|
31420
31463
|
bt.loggerService.info(LOG_MEMORY_METHOD_NAME_INFO, { topic });
|
|
31421
|
-
const date =
|
|
31464
|
+
const date = GET_DATE_FN();
|
|
31422
31465
|
this._entries.push({
|
|
31423
31466
|
id: randomString(),
|
|
31424
31467
|
type: "info",
|
|
31425
31468
|
timestamp: Date.now(),
|
|
31426
31469
|
createdAt: date.toISOString(),
|
|
31470
|
+
methodContext: GET_METHOD_CONTEXT_FN(),
|
|
31471
|
+
executionContext: GET_EXECUTION_CONTEXT_FN(),
|
|
31427
31472
|
topic,
|
|
31428
31473
|
args,
|
|
31429
31474
|
});
|
|
@@ -31437,12 +31482,14 @@ class LogMemoryUtils {
|
|
|
31437
31482
|
*/
|
|
31438
31483
|
this.warn = async (topic, ...args) => {
|
|
31439
31484
|
bt.loggerService.info(LOG_MEMORY_METHOD_NAME_WARN, { topic });
|
|
31440
|
-
const date =
|
|
31485
|
+
const date = GET_DATE_FN();
|
|
31441
31486
|
this._entries.push({
|
|
31442
31487
|
id: randomString(),
|
|
31443
31488
|
type: "warn",
|
|
31444
31489
|
timestamp: Date.now(),
|
|
31445
31490
|
createdAt: date.toISOString(),
|
|
31491
|
+
methodContext: GET_METHOD_CONTEXT_FN(),
|
|
31492
|
+
executionContext: GET_EXECUTION_CONTEXT_FN(),
|
|
31446
31493
|
topic,
|
|
31447
31494
|
args,
|
|
31448
31495
|
});
|
|
@@ -31466,6 +31513,165 @@ class LogMemoryUtils {
|
|
|
31466
31513
|
}
|
|
31467
31514
|
}
|
|
31468
31515
|
}
|
|
31516
|
+
/**
|
|
31517
|
+
* JSONL-based log adapter with append-only writes and file-based reads.
|
|
31518
|
+
*
|
|
31519
|
+
* Features:
|
|
31520
|
+
* - Writes log entries as JSONL lines via WriteStream (append-only)
|
|
31521
|
+
* - Stream-based writes with backpressure handling
|
|
31522
|
+
* - 15-second timeout protection for write operations
|
|
31523
|
+
* - Automatic directory creation on first write
|
|
31524
|
+
* - Error handling via exitEmitter
|
|
31525
|
+
* - getList reads and parses all lines from the JSONL file
|
|
31526
|
+
*
|
|
31527
|
+
* File format: {dirName}/{fileName}.jsonl
|
|
31528
|
+
* Each line contains a full ILogEntry object.
|
|
31529
|
+
*/
|
|
31530
|
+
class LogJsonlUtils {
|
|
31531
|
+
/**
|
|
31532
|
+
* Creates a new JSONL log adapter instance.
|
|
31533
|
+
*
|
|
31534
|
+
* @param fileName - Base file name (without extension)
|
|
31535
|
+
* @param dirName - Directory path for the JSONL file
|
|
31536
|
+
*/
|
|
31537
|
+
constructor(fileName, dirName) {
|
|
31538
|
+
this.fileName = fileName;
|
|
31539
|
+
this.dirName = dirName;
|
|
31540
|
+
/** WriteStream instance for append-only writes, null until initialized */
|
|
31541
|
+
this._stream = null;
|
|
31542
|
+
/**
|
|
31543
|
+
* Singleshot initialization: creates directory and opens append stream.
|
|
31544
|
+
* Sets up error handler that emits to exitEmitter.
|
|
31545
|
+
*/
|
|
31546
|
+
this[_a] = singleshot(async () => {
|
|
31547
|
+
await fs.mkdir(this.dirName, { recursive: true });
|
|
31548
|
+
this._stream = createWriteStream(this._filePath, { flags: "a" });
|
|
31549
|
+
this._stream.on("error", (err) => {
|
|
31550
|
+
exitEmitter.next(new Error(`LogJsonlUtils stream error for file=${this._filePath} message=${getErrorMessage(err)}`));
|
|
31551
|
+
});
|
|
31552
|
+
});
|
|
31553
|
+
/**
|
|
31554
|
+
* Timeout-protected write with backpressure handling.
|
|
31555
|
+
* Waits for drain event if write buffer is full.
|
|
31556
|
+
* Times out after 15 seconds and returns TIMEOUT_SYMBOL.
|
|
31557
|
+
*/
|
|
31558
|
+
this[_b] = timeout(async (line) => {
|
|
31559
|
+
if (!this._stream.write(line)) {
|
|
31560
|
+
await new Promise((resolve) => {
|
|
31561
|
+
this._stream.once("drain", resolve);
|
|
31562
|
+
});
|
|
31563
|
+
}
|
|
31564
|
+
}, 15000);
|
|
31565
|
+
/**
|
|
31566
|
+
* Appends a log entry as a JSONL line.
|
|
31567
|
+
*/
|
|
31568
|
+
this._append = async (entry) => {
|
|
31569
|
+
await this[WAIT_FOR_INIT_SYMBOL]();
|
|
31570
|
+
const line = JSON.stringify(entry) + "\n";
|
|
31571
|
+
const status = await this[WRITE_SAFE_SYMBOL](line);
|
|
31572
|
+
if (status === TIMEOUT_SYMBOL$1) {
|
|
31573
|
+
throw new Error(`LogJsonlUtils timeout writing to file=${this._filePath}`);
|
|
31574
|
+
}
|
|
31575
|
+
};
|
|
31576
|
+
/**
|
|
31577
|
+
* Logs a general-purpose message.
|
|
31578
|
+
* @param topic - The log topic / method name
|
|
31579
|
+
* @param args - Additional arguments
|
|
31580
|
+
*/
|
|
31581
|
+
this.log = async (topic, ...args) => {
|
|
31582
|
+
bt.loggerService.info(LOG_JSONL_METHOD_NAME_LOG, { topic });
|
|
31583
|
+
const date = GET_DATE_FN();
|
|
31584
|
+
await this._append({
|
|
31585
|
+
id: randomString(),
|
|
31586
|
+
type: "log",
|
|
31587
|
+
timestamp: Date.now(),
|
|
31588
|
+
createdAt: date.toISOString(),
|
|
31589
|
+
methodContext: GET_METHOD_CONTEXT_FN(),
|
|
31590
|
+
executionContext: GET_EXECUTION_CONTEXT_FN(),
|
|
31591
|
+
topic,
|
|
31592
|
+
args,
|
|
31593
|
+
});
|
|
31594
|
+
};
|
|
31595
|
+
/**
|
|
31596
|
+
* Logs a debug-level message.
|
|
31597
|
+
* @param topic - The log topic / method name
|
|
31598
|
+
* @param args - Additional arguments
|
|
31599
|
+
*/
|
|
31600
|
+
this.debug = async (topic, ...args) => {
|
|
31601
|
+
bt.loggerService.info(LOG_JSONL_METHOD_NAME_DEBUG, { topic });
|
|
31602
|
+
const date = GET_DATE_FN();
|
|
31603
|
+
await this._append({
|
|
31604
|
+
id: randomString(),
|
|
31605
|
+
type: "debug",
|
|
31606
|
+
timestamp: Date.now(),
|
|
31607
|
+
createdAt: date.toISOString(),
|
|
31608
|
+
methodContext: GET_METHOD_CONTEXT_FN(),
|
|
31609
|
+
executionContext: GET_EXECUTION_CONTEXT_FN(),
|
|
31610
|
+
topic,
|
|
31611
|
+
args,
|
|
31612
|
+
});
|
|
31613
|
+
};
|
|
31614
|
+
/**
|
|
31615
|
+
* Logs an info-level message.
|
|
31616
|
+
* @param topic - The log topic / method name
|
|
31617
|
+
* @param args - Additional arguments
|
|
31618
|
+
*/
|
|
31619
|
+
this.info = async (topic, ...args) => {
|
|
31620
|
+
bt.loggerService.info(LOG_JSONL_METHOD_NAME_INFO, { topic });
|
|
31621
|
+
const date = GET_DATE_FN();
|
|
31622
|
+
await this._append({
|
|
31623
|
+
id: randomString(),
|
|
31624
|
+
type: "info",
|
|
31625
|
+
timestamp: Date.now(),
|
|
31626
|
+
createdAt: date.toISOString(),
|
|
31627
|
+
methodContext: GET_METHOD_CONTEXT_FN(),
|
|
31628
|
+
executionContext: GET_EXECUTION_CONTEXT_FN(),
|
|
31629
|
+
topic,
|
|
31630
|
+
args,
|
|
31631
|
+
});
|
|
31632
|
+
};
|
|
31633
|
+
/**
|
|
31634
|
+
* Logs a warning-level message.
|
|
31635
|
+
* @param topic - The log topic / method name
|
|
31636
|
+
* @param args - Additional arguments
|
|
31637
|
+
*/
|
|
31638
|
+
this.warn = async (topic, ...args) => {
|
|
31639
|
+
bt.loggerService.info(LOG_JSONL_METHOD_NAME_WARN, { topic });
|
|
31640
|
+
const date = GET_DATE_FN();
|
|
31641
|
+
await this._append({
|
|
31642
|
+
id: randomString(),
|
|
31643
|
+
type: "warn",
|
|
31644
|
+
timestamp: Date.now(),
|
|
31645
|
+
createdAt: date.toISOString(),
|
|
31646
|
+
methodContext: GET_METHOD_CONTEXT_FN(),
|
|
31647
|
+
executionContext: GET_EXECUTION_CONTEXT_FN(),
|
|
31648
|
+
topic,
|
|
31649
|
+
args,
|
|
31650
|
+
});
|
|
31651
|
+
};
|
|
31652
|
+
/**
|
|
31653
|
+
* Reads all log entries from the JSONL file.
|
|
31654
|
+
* Returns empty array if file does not exist.
|
|
31655
|
+
* @returns Array of all log entries
|
|
31656
|
+
*/
|
|
31657
|
+
this.getList = async () => {
|
|
31658
|
+
bt.loggerService.info(LOG_JSONL_METHOD_NAME_GET_LIST);
|
|
31659
|
+
let raw;
|
|
31660
|
+
try {
|
|
31661
|
+
raw = await fs.readFile(this._filePath, "utf-8");
|
|
31662
|
+
}
|
|
31663
|
+
catch {
|
|
31664
|
+
return [];
|
|
31665
|
+
}
|
|
31666
|
+
return raw
|
|
31667
|
+
.split("\n")
|
|
31668
|
+
.filter((line) => line.trim().length > 0)
|
|
31669
|
+
.map((line) => JSON.parse(line));
|
|
31670
|
+
};
|
|
31671
|
+
this._filePath = join(this.dirName, this.fileName);
|
|
31672
|
+
}
|
|
31673
|
+
}
|
|
31674
|
+
_a = WAIT_FOR_INIT_SYMBOL, _b = WRITE_SAFE_SYMBOL;
|
|
31469
31675
|
/**
|
|
31470
31676
|
* Dummy log adapter that discards all writes.
|
|
31471
31677
|
*
|
|
@@ -31605,6 +31811,18 @@ class LogAdapter {
|
|
|
31605
31811
|
bt.loggerService.info(LOG_ADAPTER_METHOD_NAME_USE_DUMMY);
|
|
31606
31812
|
this._log = new LogDummyUtils();
|
|
31607
31813
|
};
|
|
31814
|
+
/**
|
|
31815
|
+
* Switches to JSONL file log adapter.
|
|
31816
|
+
* Log entries will be appended to {dirName}/{fileName}.jsonl.
|
|
31817
|
+
* Reads are performed by parsing all lines from the file.
|
|
31818
|
+
*
|
|
31819
|
+
* @param fileName - Base file name without extension (default: "log")
|
|
31820
|
+
* @param dirName - Directory for the JSONL file (default: ./dump/log)
|
|
31821
|
+
*/
|
|
31822
|
+
this.useJsonl = (fileName = "log.jsonl", dirName = join(process.cwd(), "./dump/log")) => {
|
|
31823
|
+
bt.loggerService.info(LOG_ADAPTER_METHOD_NAME_USE_JSONL);
|
|
31824
|
+
this._log = new LogJsonlUtils(fileName, dirName);
|
|
31825
|
+
};
|
|
31608
31826
|
}
|
|
31609
31827
|
}
|
|
31610
31828
|
/**
|