effect 3.5.0 → 3.5.2
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/dist/cjs/Effect.js +78 -15
- package/dist/cjs/Effect.js.map +1 -1
- package/dist/cjs/Logger.js +223 -12
- package/dist/cjs/Logger.js.map +1 -1
- package/dist/cjs/Random.js +15 -0
- package/dist/cjs/Random.js.map +1 -1
- package/dist/cjs/internal/cause.js +7 -3
- package/dist/cjs/internal/cause.js.map +1 -1
- package/dist/cjs/internal/core.js +5 -1
- package/dist/cjs/internal/core.js.map +1 -1
- package/dist/cjs/internal/effect/circular.js +1 -1
- package/dist/cjs/internal/effect/circular.js.map +1 -1
- package/dist/cjs/internal/logger.js +100 -22
- package/dist/cjs/internal/logger.js.map +1 -1
- package/dist/cjs/internal/version.js +1 -1
- package/dist/dts/Console.d.ts +2 -2
- package/dist/dts/Console.d.ts.map +1 -1
- package/dist/dts/Effect.d.ts +78 -15
- package/dist/dts/Effect.d.ts.map +1 -1
- package/dist/dts/Logger.d.ts +223 -12
- package/dist/dts/Logger.d.ts.map +1 -1
- package/dist/dts/Random.d.ts +15 -0
- package/dist/dts/Random.d.ts.map +1 -1
- package/dist/dts/internal/core.d.ts.map +1 -1
- package/dist/esm/Effect.js +78 -15
- package/dist/esm/Effect.js.map +1 -1
- package/dist/esm/Logger.js +223 -12
- package/dist/esm/Logger.js.map +1 -1
- package/dist/esm/Random.js +15 -0
- package/dist/esm/Random.js.map +1 -1
- package/dist/esm/internal/cause.js +7 -3
- package/dist/esm/internal/cause.js.map +1 -1
- package/dist/esm/internal/core.js +3 -0
- package/dist/esm/internal/core.js.map +1 -1
- package/dist/esm/internal/effect/circular.js +1 -1
- package/dist/esm/internal/effect/circular.js.map +1 -1
- package/dist/esm/internal/logger.js +99 -21
- package/dist/esm/internal/logger.js.map +1 -1
- package/dist/esm/internal/version.js +1 -1
- package/package.json +1 -1
- package/src/Console.ts +2 -2
- package/src/Effect.ts +78 -15
- package/src/Logger.ts +223 -12
- package/src/Random.ts +15 -0
- package/src/internal/cause.ts +7 -3
- package/src/internal/core.ts +4 -0
- package/src/internal/effect/circular.ts +1 -1
- package/src/internal/logger.ts +102 -18
- package/src/internal/version.ts +1 -1
package/src/Logger.ts
CHANGED
|
@@ -73,6 +73,35 @@ export declare namespace Logger {
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
/**
|
|
76
|
+
* Creates a custom logger that formats log messages according to the provided
|
|
77
|
+
* function.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* import { Effect, Logger, LogLevel } from "effect"
|
|
81
|
+
*
|
|
82
|
+
* const logger = Logger.make(({ logLevel, message }) => {
|
|
83
|
+
* globalThis.console.log(`[${logLevel.label}] ${message}`)
|
|
84
|
+
* })
|
|
85
|
+
*
|
|
86
|
+
* const task1 = Effect.logDebug("task1 done")
|
|
87
|
+
* const task2 = Effect.logDebug("task2 done")
|
|
88
|
+
*
|
|
89
|
+
* const program = Effect.gen(function*() {
|
|
90
|
+
* yield* Effect.log("start")
|
|
91
|
+
* yield* task1
|
|
92
|
+
* yield* task2
|
|
93
|
+
* yield* Effect.log("done")
|
|
94
|
+
* }).pipe(
|
|
95
|
+
* Logger.withMinimumLogLevel(LogLevel.Debug),
|
|
96
|
+
* Effect.provide(Logger.replace(Logger.defaultLogger, logger))
|
|
97
|
+
* )
|
|
98
|
+
*
|
|
99
|
+
* // Effect.runFork(program)
|
|
100
|
+
* // [INFO] start
|
|
101
|
+
* // [DEBUG] task1 done
|
|
102
|
+
* // [DEBUG] task2 done
|
|
103
|
+
* // [INFO] done
|
|
104
|
+
*
|
|
76
105
|
* @category constructors
|
|
77
106
|
* @since 2.0.0
|
|
78
107
|
*/
|
|
@@ -160,25 +189,36 @@ export const map: {
|
|
|
160
189
|
} = internal.map
|
|
161
190
|
|
|
162
191
|
/**
|
|
163
|
-
*
|
|
164
|
-
*
|
|
192
|
+
* Creates a batched logger that groups log messages together and processes them
|
|
193
|
+
* in intervals.
|
|
194
|
+
*
|
|
195
|
+
* @param window - The time window in which to batch log messages.
|
|
196
|
+
*
|
|
165
197
|
* @example
|
|
166
|
-
* import { Console, Effect, Logger } from "effect"
|
|
198
|
+
* import { Console, Effect, Logger } from "effect"
|
|
167
199
|
*
|
|
168
200
|
* const LoggerLive = Logger.replaceScoped(
|
|
169
201
|
* Logger.defaultLogger,
|
|
170
202
|
* Logger.logfmtLogger.pipe(
|
|
171
|
-
* Logger.batched("500 millis", (messages) =>
|
|
172
|
-
* Console.log("BATCH", messages.join("\n"))
|
|
173
|
-
* )
|
|
203
|
+
* Logger.batched("500 millis", (messages) => Console.log("BATCH", `[\n${messages.join("\n")}\n]`))
|
|
174
204
|
* )
|
|
175
|
-
* )
|
|
205
|
+
* )
|
|
206
|
+
*
|
|
207
|
+
* const program = Effect.gen(function*() {
|
|
208
|
+
* yield* Effect.log("one")
|
|
209
|
+
* yield* Effect.log("two")
|
|
210
|
+
* yield* Effect.log("three")
|
|
211
|
+
* }).pipe(Effect.provide(LoggerLive))
|
|
212
|
+
*
|
|
213
|
+
* // Effect.runFork(program)
|
|
214
|
+
* // BATCH [
|
|
215
|
+
* // timestamp=... level=INFO fiber=#0 message=one
|
|
216
|
+
* // timestamp=... level=INFO fiber=#0 message=two
|
|
217
|
+
* // timestamp=... level=INFO fiber=#0 message=three
|
|
218
|
+
* // ]
|
|
176
219
|
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
* yield* _(Effect.log("two"));
|
|
180
|
-
* yield* _(Effect.log("three"));
|
|
181
|
-
* }).pipe(Effect.provide(LoggerLive), Effect.runFork);
|
|
220
|
+
* @since 2.0.0
|
|
221
|
+
* @category mapping
|
|
182
222
|
*/
|
|
183
223
|
export const batched: {
|
|
184
224
|
<Output, R>(
|
|
@@ -278,6 +318,17 @@ export const test: {
|
|
|
278
318
|
} = internalCircular.test
|
|
279
319
|
|
|
280
320
|
/**
|
|
321
|
+
* Sets the minimum log level for subsequent logging operations, allowing
|
|
322
|
+
* control over which log messages are displayed based on their severity.
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* import { Effect, Logger, LogLevel } from "effect"
|
|
326
|
+
*
|
|
327
|
+
* const program = Effect.logDebug("message1").pipe(Logger.withMinimumLogLevel(LogLevel.Debug))
|
|
328
|
+
*
|
|
329
|
+
* // Effect.runFork(program)
|
|
330
|
+
* // timestamp=... level=DEBUG fiber=#0 message=message1
|
|
331
|
+
*
|
|
281
332
|
* @since 2.0.0
|
|
282
333
|
* @category context
|
|
283
334
|
*/
|
|
@@ -345,12 +396,40 @@ export const zipRight: {
|
|
|
345
396
|
export const defaultLogger: Logger<unknown, void> = fiberRuntime.defaultLogger
|
|
346
397
|
|
|
347
398
|
/**
|
|
399
|
+
* The `jsonLogger` logger formats log entries as JSON objects, making them easy to
|
|
400
|
+
* integrate with logging systems that consume JSON data.
|
|
401
|
+
*
|
|
402
|
+
* @example
|
|
403
|
+
* import { Effect, Logger } from "effect"
|
|
404
|
+
*
|
|
405
|
+
* const program = Effect.log("message1", "message2").pipe(
|
|
406
|
+
* Effect.annotateLogs({ key1: "value1", key2: "value2" }),
|
|
407
|
+
* Effect.withLogSpan("myspan")
|
|
408
|
+
* )
|
|
409
|
+
*
|
|
410
|
+
* // Effect.runFork(program.pipe(Effect.provide(Logger.json)))
|
|
411
|
+
* // {"message":["message1","message2"],"logLevel":"INFO","timestamp":"...","annotations":{"key2":"value2","key1":"value1"},"spans":{"myspan":0},"fiberId":"#0"}
|
|
412
|
+
*
|
|
348
413
|
* @since 2.0.0
|
|
349
414
|
* @category constructors
|
|
350
415
|
*/
|
|
351
416
|
export const jsonLogger: Logger<unknown, string> = internal.jsonLogger
|
|
352
417
|
|
|
353
418
|
/**
|
|
419
|
+
* This logger outputs logs in a human-readable format that is easy to read
|
|
420
|
+
* during development or in a production console.
|
|
421
|
+
*
|
|
422
|
+
* @example
|
|
423
|
+
* import { Effect, Logger } from "effect"
|
|
424
|
+
*
|
|
425
|
+
* const program = Effect.log("message1", "message2").pipe(
|
|
426
|
+
* Effect.annotateLogs({ key1: "value1", key2: "value2" }),
|
|
427
|
+
* Effect.withLogSpan("myspan")
|
|
428
|
+
* )
|
|
429
|
+
*
|
|
430
|
+
* // Effect.runFork(program.pipe(Effect.provide(Logger.logFmt)))
|
|
431
|
+
* // timestamp=... level=INFO fiber=#0 message=message1 message=message2 myspan=0ms key2=value2 key1=value1
|
|
432
|
+
*
|
|
354
433
|
* @since 2.0.0
|
|
355
434
|
* @category constructors
|
|
356
435
|
*/
|
|
@@ -363,6 +442,27 @@ export const logfmtLogger: Logger<unknown, string> = internal.logfmtLogger
|
|
|
363
442
|
export const stringLogger: Logger<unknown, string> = internal.stringLogger
|
|
364
443
|
|
|
365
444
|
/**
|
|
445
|
+
* The pretty logger utilizes the capabilities of the console API to generate
|
|
446
|
+
* visually engaging and color-enhanced log outputs. This feature is
|
|
447
|
+
* particularly useful for improving the readability of log messages during
|
|
448
|
+
* development and debugging processes.
|
|
449
|
+
*
|
|
450
|
+
* @example
|
|
451
|
+
* import { Effect, Logger } from "effect"
|
|
452
|
+
*
|
|
453
|
+
* const program = Effect.log("message1", "message2").pipe(
|
|
454
|
+
* Effect.annotateLogs({ key1: "value1", key2: "value2" }),
|
|
455
|
+
* Effect.withLogSpan("myspan")
|
|
456
|
+
* )
|
|
457
|
+
*
|
|
458
|
+
* // Effect.runFork(program.pipe(Effect.provide(Logger.pretty)))
|
|
459
|
+
* // green --v v-- bold and cyan
|
|
460
|
+
* // [07:51:54.434] INFO (#0) myspan=1ms: message1
|
|
461
|
+
* // message2
|
|
462
|
+
* // v-- bold
|
|
463
|
+
* // key2: value2
|
|
464
|
+
* // key1: value1
|
|
465
|
+
*
|
|
366
466
|
* @since 3.5.0
|
|
367
467
|
* @category constructors
|
|
368
468
|
*/
|
|
@@ -376,6 +476,29 @@ export const prettyLogger: (
|
|
|
376
476
|
) => Logger<unknown, void> = internal.prettyLogger
|
|
377
477
|
|
|
378
478
|
/**
|
|
479
|
+
* The structured logger provides detailed log outputs, structured in a way that
|
|
480
|
+
* retains comprehensive traceability of the events, suitable for deeper
|
|
481
|
+
* analysis and troubleshooting.
|
|
482
|
+
*
|
|
483
|
+
* @example
|
|
484
|
+
* import { Effect, Logger } from "effect"
|
|
485
|
+
*
|
|
486
|
+
* const program = Effect.log("message1", "message2").pipe(
|
|
487
|
+
* Effect.annotateLogs({ key1: "value1", key2: "value2" }),
|
|
488
|
+
* Effect.withLogSpan("myspan")
|
|
489
|
+
* )
|
|
490
|
+
*
|
|
491
|
+
* // Effect.runFork(program.pipe(Effect.provide(Logger.structured)))
|
|
492
|
+
* // {
|
|
493
|
+
* // message: [ 'message1', 'message2' ],
|
|
494
|
+
* // logLevel: 'INFO',
|
|
495
|
+
* // timestamp: '2024-07-09T14:05:41.623Z',
|
|
496
|
+
* // cause: undefined,
|
|
497
|
+
* // annotations: { key2: 'value2', key1: 'value1' },
|
|
498
|
+
* // spans: { myspan: 0 },
|
|
499
|
+
* // fiberId: '#0'
|
|
500
|
+
* // }
|
|
501
|
+
*
|
|
379
502
|
* @since 2.0.0
|
|
380
503
|
* @category constructors
|
|
381
504
|
*/
|
|
@@ -399,30 +522,118 @@ export const structuredLogger: Logger<
|
|
|
399
522
|
export const tracerLogger: Logger<unknown, void> = fiberRuntime.tracerLogger
|
|
400
523
|
|
|
401
524
|
/**
|
|
525
|
+
* The `json` logger formats log entries as JSON objects, making them easy to
|
|
526
|
+
* integrate with logging systems that consume JSON data.
|
|
527
|
+
*
|
|
528
|
+
* @example
|
|
529
|
+
* import { Effect, Logger } from "effect"
|
|
530
|
+
*
|
|
531
|
+
* const program = Effect.log("message1", "message2").pipe(
|
|
532
|
+
* Effect.annotateLogs({ key1: "value1", key2: "value2" }),
|
|
533
|
+
* Effect.withLogSpan("myspan")
|
|
534
|
+
* )
|
|
535
|
+
*
|
|
536
|
+
* // Effect.runFork(program.pipe(Effect.provide(Logger.json)))
|
|
537
|
+
* // {"message":["message1","message2"],"logLevel":"INFO","timestamp":"...","annotations":{"key2":"value2","key1":"value1"},"spans":{"myspan":0},"fiberId":"#0"}
|
|
538
|
+
*
|
|
402
539
|
* @since 2.0.0
|
|
403
540
|
* @category constructors
|
|
404
541
|
*/
|
|
405
542
|
export const json: Layer.Layer<never> = replace(fiberRuntime.defaultLogger, fiberRuntime.jsonLogger)
|
|
406
543
|
|
|
407
544
|
/**
|
|
545
|
+
* This logger outputs logs in a human-readable format that is easy to read
|
|
546
|
+
* during development or in a production console.
|
|
547
|
+
*
|
|
548
|
+
* @example
|
|
549
|
+
* import { Effect, Logger } from "effect"
|
|
550
|
+
*
|
|
551
|
+
* const program = Effect.log("message1", "message2").pipe(
|
|
552
|
+
* Effect.annotateLogs({ key1: "value1", key2: "value2" }),
|
|
553
|
+
* Effect.withLogSpan("myspan")
|
|
554
|
+
* )
|
|
555
|
+
*
|
|
556
|
+
* // Effect.runFork(program.pipe(Effect.provide(Logger.logFmt)))
|
|
557
|
+
* // timestamp=... level=INFO fiber=#0 message=message1 message=message2 myspan=0ms key2=value2 key1=value1
|
|
558
|
+
*
|
|
408
559
|
* @since 2.0.0
|
|
409
560
|
* @category constructors
|
|
410
561
|
*/
|
|
411
562
|
export const logFmt: Layer.Layer<never> = replace(fiberRuntime.defaultLogger, fiberRuntime.logFmtLogger)
|
|
412
563
|
|
|
413
564
|
/**
|
|
565
|
+
* The pretty logger utilizes the capabilities of the console API to generate
|
|
566
|
+
* visually engaging and color-enhanced log outputs. This feature is
|
|
567
|
+
* particularly useful for improving the readability of log messages during
|
|
568
|
+
* development and debugging processes.
|
|
569
|
+
*
|
|
570
|
+
* @example
|
|
571
|
+
* import { Effect, Logger } from "effect"
|
|
572
|
+
*
|
|
573
|
+
* const program = Effect.log("message1", "message2").pipe(
|
|
574
|
+
* Effect.annotateLogs({ key1: "value1", key2: "value2" }),
|
|
575
|
+
* Effect.withLogSpan("myspan")
|
|
576
|
+
* )
|
|
577
|
+
*
|
|
578
|
+
* // Effect.runFork(program.pipe(Effect.provide(Logger.pretty)))
|
|
579
|
+
* // green --v v-- bold and cyan
|
|
580
|
+
* // [07:51:54.434] INFO (#0) myspan=1ms: message1
|
|
581
|
+
* // message2
|
|
582
|
+
* // v-- bold
|
|
583
|
+
* // key2: value2
|
|
584
|
+
* // key1: value1
|
|
585
|
+
*
|
|
414
586
|
* @since 3.5.0
|
|
415
587
|
* @category constructors
|
|
416
588
|
*/
|
|
417
589
|
export const pretty: Layer.Layer<never> = replace(fiberRuntime.defaultLogger, fiberRuntime.prettyLogger)
|
|
418
590
|
|
|
419
591
|
/**
|
|
592
|
+
* The structured logger provides detailed log outputs, structured in a way that
|
|
593
|
+
* retains comprehensive traceability of the events, suitable for deeper
|
|
594
|
+
* analysis and troubleshooting.
|
|
595
|
+
*
|
|
596
|
+
* @example
|
|
597
|
+
* import { Effect, Logger } from "effect"
|
|
598
|
+
*
|
|
599
|
+
* const program = Effect.log("message1", "message2").pipe(
|
|
600
|
+
* Effect.annotateLogs({ key1: "value1", key2: "value2" }),
|
|
601
|
+
* Effect.withLogSpan("myspan")
|
|
602
|
+
* )
|
|
603
|
+
*
|
|
604
|
+
* // Effect.runFork(program.pipe(Effect.provide(Logger.structured)))
|
|
605
|
+
* // {
|
|
606
|
+
* // message: [ 'message1', 'message2' ],
|
|
607
|
+
* // logLevel: 'INFO',
|
|
608
|
+
* // timestamp: '2024-07-09T14:05:41.623Z',
|
|
609
|
+
* // cause: undefined,
|
|
610
|
+
* // annotations: { key2: 'value2', key1: 'value1' },
|
|
611
|
+
* // spans: { myspan: 0 },
|
|
612
|
+
* // fiberId: '#0'
|
|
613
|
+
* // }
|
|
614
|
+
*
|
|
420
615
|
* @since 2.0.0
|
|
421
616
|
* @category constructors
|
|
422
617
|
*/
|
|
423
618
|
export const structured: Layer.Layer<never> = replace(fiberRuntime.defaultLogger, fiberRuntime.structuredLogger)
|
|
424
619
|
|
|
425
620
|
/**
|
|
621
|
+
* Sets the minimum log level for logging operations, allowing control over
|
|
622
|
+
* which log messages are displayed based on their severity.
|
|
623
|
+
*
|
|
624
|
+
* @example
|
|
625
|
+
* import { Effect, Logger, LogLevel } from "effect"
|
|
626
|
+
*
|
|
627
|
+
* const program = Effect.gen(function*() {
|
|
628
|
+
* yield* Effect.log("Executing task...")
|
|
629
|
+
* yield* Effect.sleep("100 millis")
|
|
630
|
+
* console.log("task done")
|
|
631
|
+
* })
|
|
632
|
+
*
|
|
633
|
+
* // Logging disabled using a layer
|
|
634
|
+
* // Effect.runFork(program.pipe(Effect.provide(Logger.minimumLogLevel(LogLevel.None))))
|
|
635
|
+
* // task done
|
|
636
|
+
*
|
|
426
637
|
* @since 2.0.0
|
|
427
638
|
* @category context
|
|
428
639
|
*/
|
package/src/Random.ts
CHANGED
|
@@ -122,6 +122,21 @@ export const Random: Context.Tag<Random, Random> = internal.randomTag
|
|
|
122
122
|
/**
|
|
123
123
|
* Constructs the `Random` service, seeding the pseudo-random number generator
|
|
124
124
|
* with an hash of the specified seed.
|
|
125
|
+
* This constructor is useful for generating predictable sequences of random values for specific use cases.
|
|
126
|
+
*
|
|
127
|
+
* Example uses:
|
|
128
|
+
* - Generating random UI data for visual tests.
|
|
129
|
+
* - Creating data that needs to change daily but remain the same throughout a single day, such as using a date as the seed.
|
|
130
|
+
*
|
|
131
|
+
* @param seed - The seed value used to initialize the generator.
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* import { Effect, Random } from "effect"
|
|
135
|
+
*
|
|
136
|
+
* const random1 = Random.make("myseed")
|
|
137
|
+
* const random2 = Random.make("myseed")
|
|
138
|
+
*
|
|
139
|
+
* assert.equal(Effect.runSync(random1.next), Effect.runSync(random2.next))
|
|
125
140
|
*
|
|
126
141
|
* @since 3.5.0
|
|
127
142
|
* @category constructors
|
package/src/internal/cause.ts
CHANGED
|
@@ -1100,9 +1100,13 @@ const prettyErrorStack = (message: string, stack: string, span?: Span | undefine
|
|
|
1100
1100
|
const stackFn = spanToTrace.get(current)
|
|
1101
1101
|
if (typeof stackFn === "function") {
|
|
1102
1102
|
const stack = stackFn()
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1103
|
+
if (typeof stack === "string") {
|
|
1104
|
+
const locationMatch = stack.match(locationRegex)
|
|
1105
|
+
const location = locationMatch ? locationMatch[1] : stack.replace(/^at /, "")
|
|
1106
|
+
out.push(` at ${current.name} (${location})`)
|
|
1107
|
+
} else {
|
|
1108
|
+
out.push(` at ${current.name}`)
|
|
1109
|
+
}
|
|
1106
1110
|
} else {
|
|
1107
1111
|
out.push(` at ${current.name}`)
|
|
1108
1112
|
}
|
package/src/internal/core.ts
CHANGED
|
@@ -5,6 +5,7 @@ import * as Chunk from "../Chunk.js"
|
|
|
5
5
|
import * as Context from "../Context.js"
|
|
6
6
|
import type * as Deferred from "../Deferred.js"
|
|
7
7
|
import type * as Differ from "../Differ.js"
|
|
8
|
+
import * as Duration from "../Duration.js"
|
|
8
9
|
import type * as Effect from "../Effect.js"
|
|
9
10
|
import * as Either from "../Either.js"
|
|
10
11
|
import * as Equal from "../Equal.js"
|
|
@@ -2297,6 +2298,9 @@ export const TimeoutExceptionTypeId: Cause.TimeoutExceptionTypeId = Symbol.for(
|
|
|
2297
2298
|
export const TimeoutException = makeException<Cause.TimeoutException>({
|
|
2298
2299
|
[TimeoutExceptionTypeId]: TimeoutExceptionTypeId
|
|
2299
2300
|
}, "TimeoutException")
|
|
2301
|
+
/** @internal */
|
|
2302
|
+
export const timeoutExceptionFromDuration = (duration: Duration.DurationInput): Cause.TimeoutException =>
|
|
2303
|
+
new TimeoutException(`Operation timed out before the specified duration of '${Duration.format(duration)}' elapsed`)
|
|
2300
2304
|
|
|
2301
2305
|
/** @internal */
|
|
2302
2306
|
export const isTimeoutException = (u: unknown): u is Cause.TimeoutException => hasProperty(u, TimeoutExceptionTypeId)
|
|
@@ -419,7 +419,7 @@ export const timeout = dual<
|
|
|
419
419
|
) => Effect.Effect<A, E | Cause.TimeoutException, R>
|
|
420
420
|
>(2, (self, duration) =>
|
|
421
421
|
timeoutFail(self, {
|
|
422
|
-
onTimeout: () =>
|
|
422
|
+
onTimeout: () => core.timeoutExceptionFromDuration(duration),
|
|
423
423
|
duration
|
|
424
424
|
}))
|
|
425
425
|
|
package/src/internal/logger.ts
CHANGED
|
@@ -369,9 +369,6 @@ export const isLogger = (u: unknown): u is Logger.Logger<unknown, unknown> => {
|
|
|
369
369
|
return typeof u === "object" && u != null && LoggerTypeId in u
|
|
370
370
|
}
|
|
371
371
|
|
|
372
|
-
const processStdoutIsTTY = typeof process === "object" && "stdout" in process && process.stdout.isTTY === true
|
|
373
|
-
const hasWindow = typeof window === "object"
|
|
374
|
-
|
|
375
372
|
const withColor = (text: string, ...colors: ReadonlyArray<string>) => {
|
|
376
373
|
let out = ""
|
|
377
374
|
for (let i = 0; i < colors.length; i++) {
|
|
@@ -403,12 +400,26 @@ const logLevelColors: Record<LogLevel.LogLevel["_tag"], ReadonlyArray<string>> =
|
|
|
403
400
|
Error: [colors.red],
|
|
404
401
|
Fatal: [colors.bgBrightRed, colors.black]
|
|
405
402
|
}
|
|
403
|
+
const logLevelStyle: Record<LogLevel.LogLevel["_tag"], string> = {
|
|
404
|
+
None: "",
|
|
405
|
+
All: "",
|
|
406
|
+
Trace: "color:gray",
|
|
407
|
+
Debug: "color:blue",
|
|
408
|
+
Info: "color:green",
|
|
409
|
+
Warning: "color:orange",
|
|
410
|
+
Error: "color:red",
|
|
411
|
+
Fatal: "background-color:red;color:white"
|
|
412
|
+
}
|
|
406
413
|
|
|
407
414
|
const defaultDateFormat = (date: Date): string =>
|
|
408
415
|
`${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}:${
|
|
409
416
|
date.getSeconds().toString().padStart(2, "0")
|
|
410
417
|
}.${date.getMilliseconds().toString().padStart(3, "0")}`
|
|
411
418
|
|
|
419
|
+
const processStdoutIsTTY = typeof process === "object" && "stdout" in process && process.stdout.isTTY === true
|
|
420
|
+
const hasWindow = typeof window === "object"
|
|
421
|
+
const isWorker = typeof self === "object" && self.constructor && self.constructor.name.includes("Worker")
|
|
422
|
+
|
|
412
423
|
/** @internal */
|
|
413
424
|
export const prettyLogger = (options?: {
|
|
414
425
|
readonly colors?: "auto" | boolean | undefined
|
|
@@ -417,21 +428,31 @@ export const prettyLogger = (options?: {
|
|
|
417
428
|
readonly mode?: "browser" | "tty" | "auto" | undefined
|
|
418
429
|
}) => {
|
|
419
430
|
const mode_ = options?.mode ?? "auto"
|
|
420
|
-
const mode = mode_ === "auto" ? (hasWindow ? "browser" : "tty") : mode_
|
|
431
|
+
const mode = mode_ === "auto" ? (hasWindow || isWorker ? "browser" : "tty") : mode_
|
|
421
432
|
const isBrowser = mode === "browser"
|
|
422
433
|
const showColors = typeof options?.colors === "boolean" ? options.colors : processStdoutIsTTY || isBrowser
|
|
423
|
-
const color = showColors ? withColor : withColorNoop
|
|
424
434
|
const formatDate = options?.formatDate ?? defaultDateFormat
|
|
435
|
+
return isBrowser
|
|
436
|
+
? prettyLoggerBrowser({ colors: showColors, formatDate })
|
|
437
|
+
: prettyLoggerTty({ colors: showColors, formatDate, stderr: options?.stderr === true })
|
|
438
|
+
}
|
|
425
439
|
|
|
440
|
+
const prettyLoggerTty = (options: {
|
|
441
|
+
readonly colors: boolean
|
|
442
|
+
readonly stderr: boolean
|
|
443
|
+
readonly formatDate: (date: Date) => string
|
|
444
|
+
}) => {
|
|
445
|
+
const processIsBun = typeof process === "object" && "isBun" in process && process.isBun === true
|
|
446
|
+
const color = options.colors && processStdoutIsTTY ? withColor : withColorNoop
|
|
426
447
|
return makeLogger<unknown, void>(
|
|
427
448
|
({ annotations, cause, context, date, fiberId, logLevel, message: message_, spans }) => {
|
|
428
449
|
const services = FiberRefs.getOrDefault(context, defaultServices.currentServices)
|
|
429
450
|
const console = Context.get(services, consoleTag).unsafe
|
|
430
|
-
const log = options
|
|
451
|
+
const log = options.stderr === true ? console.error : console.log
|
|
431
452
|
|
|
432
453
|
const message = Arr.ensure(message_)
|
|
433
454
|
|
|
434
|
-
let firstLine = color(`[${formatDate(date)}]`, colors.white)
|
|
455
|
+
let firstLine = color(`[${options.formatDate(date)}]`, colors.white)
|
|
435
456
|
+ ` ${color(logLevel.label, ...logLevelColors[logLevel._tag])}`
|
|
436
457
|
+ ` (${_fiberId.threadName(fiberId)})`
|
|
437
458
|
|
|
@@ -453,18 +474,11 @@ export const prettyLogger = (options?: {
|
|
|
453
474
|
}
|
|
454
475
|
}
|
|
455
476
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
log(firstLine)
|
|
460
|
-
console.group()
|
|
461
|
-
}
|
|
477
|
+
log(firstLine)
|
|
478
|
+
if (!processIsBun) console.group()
|
|
479
|
+
|
|
462
480
|
if (!Cause.isEmpty(cause)) {
|
|
463
|
-
|
|
464
|
-
console.error(Cause.pretty(cause, { renderErrorCause: true }))
|
|
465
|
-
} else {
|
|
466
|
-
log(Cause.pretty(cause, { renderErrorCause: true }))
|
|
467
|
-
}
|
|
481
|
+
log(Cause.pretty(cause, { renderErrorCause: true }))
|
|
468
482
|
}
|
|
469
483
|
|
|
470
484
|
if (messageIndex < message.length) {
|
|
@@ -478,6 +492,76 @@ export const prettyLogger = (options?: {
|
|
|
478
492
|
log(color(`${key}:`, colors.bold, colors.white), value)
|
|
479
493
|
}
|
|
480
494
|
}
|
|
495
|
+
|
|
496
|
+
if (!processIsBun) console.groupEnd()
|
|
497
|
+
}
|
|
498
|
+
)
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
const prettyLoggerBrowser = (options: {
|
|
502
|
+
readonly colors: boolean
|
|
503
|
+
readonly formatDate: (date: Date) => string
|
|
504
|
+
}) => {
|
|
505
|
+
const color = options.colors ? "%c" : ""
|
|
506
|
+
return makeLogger<unknown, void>(
|
|
507
|
+
({ annotations, cause, context, date, fiberId, logLevel, message: message_, spans }) => {
|
|
508
|
+
const services = FiberRefs.getOrDefault(context, defaultServices.currentServices)
|
|
509
|
+
const console = Context.get(services, consoleTag).unsafe
|
|
510
|
+
const message = Arr.ensure(message_)
|
|
511
|
+
|
|
512
|
+
let firstLine = `${color}[${options.formatDate(date)}]`
|
|
513
|
+
const firstParams = []
|
|
514
|
+
if (options.colors) {
|
|
515
|
+
firstParams.push("color:gray")
|
|
516
|
+
}
|
|
517
|
+
firstLine += ` ${color}${logLevel.label}${color} (${_fiberId.threadName(fiberId)})`
|
|
518
|
+
if (options.colors) {
|
|
519
|
+
firstParams.push(logLevelStyle[logLevel._tag], "")
|
|
520
|
+
}
|
|
521
|
+
if (List.isCons(spans)) {
|
|
522
|
+
const now = date.getTime()
|
|
523
|
+
const render = renderLogSpanLogfmt(now)
|
|
524
|
+
for (const span of spans) {
|
|
525
|
+
firstLine += " " + render(span)
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
firstLine += ":"
|
|
530
|
+
|
|
531
|
+
let messageIndex = 0
|
|
532
|
+
if (message.length > 0) {
|
|
533
|
+
const firstMaybeString = structuredMessage(message[0])
|
|
534
|
+
if (typeof firstMaybeString === "string") {
|
|
535
|
+
firstLine += ` ${color}${firstMaybeString}`
|
|
536
|
+
if (options.colors) {
|
|
537
|
+
firstParams.push("color:blue")
|
|
538
|
+
}
|
|
539
|
+
messageIndex++
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
console.groupCollapsed(firstLine, ...firstParams)
|
|
544
|
+
|
|
545
|
+
if (!Cause.isEmpty(cause)) {
|
|
546
|
+
console.error(Cause.pretty(cause, { renderErrorCause: true }))
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
if (messageIndex < message.length) {
|
|
550
|
+
for (; messageIndex < message.length; messageIndex++) {
|
|
551
|
+
console.log(message[messageIndex])
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
if (HashMap.size(annotations) > 0) {
|
|
556
|
+
for (const [key, value] of annotations) {
|
|
557
|
+
if (options.colors) {
|
|
558
|
+
console.log(`%c${key}:`, "color:gray", value)
|
|
559
|
+
} else {
|
|
560
|
+
console.log(`${key}:`, value)
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
481
565
|
console.groupEnd()
|
|
482
566
|
}
|
|
483
567
|
)
|
package/src/internal/version.ts
CHANGED