Skip to content

Commit 3959206

Browse files
committed
chore: cleaning up codebase
1 parent e0dcec5 commit 3959206

15 files changed

+184
-75
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ This library provides a JavaScript/TypeScript logger inspired by Python's logger
44

55
* Simple logging with default handlers supporting `console.log`, `console.error`, and `process.stderr`.
66
* Fast, logging level checks or log filters are applied **before** log records are created
7-
* Complex log records properties ssupport lazy evaluation, so they evaluated only when they need to be rendered
7+
* Complex log records properties support lazy evaluation, so they evaluated only when they need to be rendered
88
* Flexible composition of loggers, handlers and formatters
99
* Custom formatting using template literals
1010
* Supports structured logging through a JSON formatter

span.jsonl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{"span":{"spanId":"span-1744864565062-s7b","name":"Parent-0","startTime":1744864565062,"isCompleted":false,"children":[]},"type":"start"}
2+
{"span":{"spanId":"span-1744864566561-sz0","name":"Async-Chain-0","startTime":1744864566561,"isCompleted":false,"children":[]},"type":"start"}
3+
{"span":{"spanId":"span-1744864566561-aic","name":"Async-Job-1","startTime":1744864566561,"parentSpanId":"span-1744864565062-s7b","isCompleted":false,"children":[]},"type":"start"}
4+
{"span":{"spanId":"span-1744864566561-qdt","name":"Async-Job-2","startTime":1744864566561,"parentSpanId":"span-1744864566561-aic","isCompleted":false,"children":[]},"type":"start"}
5+
{"span":{"spanId":"span-1744864566561-sz0","name":"Async-Chain-0","startTime":1744864566561,"endTime":1744864566561,"isCompleted":true,"children":[]},"type":"end"}

src/Logger.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type Handler from './Handler.js';
33
import { LogLevel } from './types.js';
44
import ConsoleErrHandler from './handlers/ConsoleErrHandler.js';
55
import * as utils from './utils.js';
6-
import { openSpan, closeSpan } from './lib/tracingManager.js';
6+
import { openSpan, closeSpan } from './lib/TracingManager.js';
77

88
class Logger {
99
public readonly key: string;

src/bin/SpanTree.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type { FC } from 'react';
2-
import React from 'react';
32
import { Box, Text } from 'ink';
43
import Span from '../lib/Span.js';
54

src/bin/TimeLineView.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type { FC } from 'react';
2-
import React from 'react';
32
import { Box, Text } from 'ink';
43

54
interface Span {

src/bin/cli.tsx

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type Span from '../lib/Span.js';
22
import fs from 'fs';
33
import { Command } from 'commander';
4-
import React, { useEffect, useState } from 'react';
4+
import { useEffect, useState } from 'react';
55
import { render, Box, Text } from 'ink';
66
import SpanTree from './SpanTree.js';
77

@@ -14,17 +14,24 @@ program
1414
const options = program.opts();
1515
const sampleMode = options.sample;
1616

17-
function loadSpans(): Span[] {
18-
if (!fs.existsSync('spans.json')) return [];
19-
return JSON.parse(fs.readFileSync('spans.json', 'utf8')) as Span[];
17+
async function loadSpans(): Promise<Array<Span>> {
18+
if (!fs.existsSync('spans.jsonl')) return [];
19+
const spans: Array<Span> = [];
20+
const file = await fs.promises.open('testSpans.jsonl', 'r');
21+
for await (const line of file.readLines()) {
22+
spans.push(JSON.parse(line));
23+
}
24+
await file.close();
25+
return spans;
26+
// return JSON.parse(fs.readFileSync('spans.json', 'utf8')) as Span[];
2027
}
2128

2229
const App = () => {
23-
const [spans, setSpans] = useState<Span[]>([]);
30+
const [spans, setSpans] = useState<Array<Span>>([]);
2431

2532
useEffect(() => {
2633
const id = setInterval(() => {
27-
setSpans(loadSpans());
34+
loadSpans().then(setSpans);
2835
}, 1000);
2936

3037
const handleExit = () => {

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export { default } from './Logger.js';
22
export { default as Handler } from './Handler.js';
3-
export { openSpan, closeSpan, getTraceJSON } from './lib/tracingManager.js';
3+
export { openSpan, closeSpan, getTraceJSON } from './lib/TracingManager.js';
44
export { default as Span } from './lib/Span.js';
55
export * as formatting from './formatting.js';
66
export * from './handlers/index.js';

src/lib/Span.ts

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,29 @@
1-
export interface SpanJSON {
2-
spanId: string;
3-
name: string;
4-
startTime: number;
5-
endTime: number | undefined;
6-
parentSpanId: string | undefined;
7-
isCompleted: boolean;
8-
children: SpanJSON[];
9-
}
1+
import type { SpanJSON } from './types.js';
102

113
class Span {
12-
public spanId: string;
4+
public spanId: string = `span-${Date.now()}-${Math.random()
5+
.toString(36)
6+
.substring(2, 5)}`;
137
public name: string;
14-
public startTime: number;
8+
public startTime: number = Date.now();
159
public endTime?: number;
1610
public parentSpanId?: string;
17-
public children: Array<Span>;
11+
public children: Array<Span> = [];
1812

19-
constructor(name: string, parentSpanId: string | undefined = undefined) {
20-
this.spanId = `span-${Date.now()}-${Math.random()
21-
.toString(36)
22-
.substr(2, 5)}`;
13+
constructor(name: string, parentSpanId?: string) {
2314
this.name = name;
24-
this.startTime = Date.now();
25-
this.endTime = undefined;
2615
this.parentSpanId = parentSpanId;
27-
this.children = [];
2816
}
2917

3018
public close(): void {
3119
this.endTime = Date.now();
3220
}
3321

3422
public isCompleted(): boolean {
35-
return this.endTime !== undefined;
23+
return this.endTime != null;
3624
}
3725

38-
toJSON(): SpanJSON {
26+
public toJSON(): SpanJSON {
3927
return {
4028
spanId: this.spanId,
4129
name: this.name,

src/lib/Tracer.ts

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
import fs from 'fs';
21
import Span from './Span.js';
32

4-
export default class Tracer {
5-
private activeSpans: Map<string, Span> = new Map();
6-
private spanFile = 'spans.json';
7-
private jsonlStream = fs.createWriteStream('spans.jsonl', { flags: 'a' });
3+
class Tracer {
4+
protected activeSpans: Map<string, Span> = new Map();
5+
protected queue: Array<Span> = [];
6+
protected resolveWaitChunksP: (() => void) | undefined;
7+
protected ended: boolean = false;
8+
9+
protected queueSpan(span: Span) {
10+
this.queue.push(span);
11+
if (this.resolveWaitChunksP != null) this.resolveWaitChunksP();
12+
}
813

914
public startSpan(name: string, parentSpanId?: string): string {
1015
const span = new Span(name, parentSpanId);
@@ -14,45 +19,31 @@ export default class Tracer {
1419
this.activeSpans.get(parentSpanId)!.children.push(span);
1520
}
1621

17-
this.saveSpansToFile();
1822
return span.spanId;
1923
}
2024

21-
public endSpan(spanId: string): Span | null {
25+
public endSpan(spanId: string): Span | undefined {
2226
const span = this.activeSpans.get(spanId);
23-
if (!span) return null;
27+
if (!span) return;
2428

2529
span.close();
26-
this.jsonlStream.write(JSON.stringify(span.toJSON()) + '\n');
27-
this.saveSpansToFile();
30+
this.queueSpan(span);
2831
return span;
2932
}
3033

31-
public traced<T>(
34+
public async traced<T>(
3235
name: string,
3336
fn: () => Promise<T>,
3437
parentSpanId?: string,
3538
): Promise<T> {
3639
const spanId = this.startSpan(name, parentSpanId);
37-
return fn()
38-
.then((result) => {
39-
this.endSpan(spanId);
40-
return result;
41-
})
42-
.catch((err) => {
43-
this.endSpan(spanId);
44-
throw err;
45-
});
40+
return await fn().finally(() => this.endSpan(spanId));
4641
}
4742

48-
public getActiveSpans(): Span[] {
43+
public getActiveSpans(): Array<Span> {
4944
return Array.from(this.activeSpans.values());
5045
}
5146

52-
public flush(): void {
53-
this.saveSpansToFile();
54-
}
55-
5647
public getTraceJSON(): string {
5748
return JSON.stringify(
5849
this.getActiveSpans().map((s) => s.toJSON()),
@@ -61,10 +52,23 @@ export default class Tracer {
6152
);
6253
}
6354

64-
private saveSpansToFile(): void {
65-
fs.writeFileSync(
66-
this.spanFile,
67-
JSON.stringify(this.getActiveSpans(), null, 2),
68-
);
55+
public endTracing(): void {
56+
this.ended = true;
57+
}
58+
59+
public async *streamEvents(): AsyncGenerator<Span, void, void> {
60+
while (true) {
61+
const value = this.queue.shift();
62+
if (value == null) {
63+
if (this.ended) break;
64+
await new Promise<void>((resolve) => {
65+
this.resolveWaitChunksP = resolve;
66+
});
67+
continue;
68+
}
69+
yield value;
70+
}
6971
}
7072
}
73+
74+
export default Tracer;

src/lib/TracingManager.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import Tracer from '#lib/Tracer.js';
2+
3+
const tracer = new Tracer();
4+
5+
const openSpan = (spanId: string, parentSpanId?: string) =>
6+
tracer.startSpan(spanId, parentSpanId);
7+
const closeSpan = (spanId: string) => tracer.endSpan(spanId);
8+
const traced = (
9+
name: string,
10+
fn: () => Promise<unknown>,
11+
parentSpanId?: string,
12+
) => tracer.traced(name, fn, parentSpanId);
13+
const getActiveSpans = () => tracer.getActiveSpans();
14+
const getTraceJSON = () => tracer.getTraceJSON();
15+
const streamEvents = () => tracer.streamEvents();
16+
const endTracing = () => tracer.endTracing();
17+
18+
export default tracer;
19+
export {
20+
openSpan,
21+
closeSpan,
22+
traced,
23+
getActiveSpans,
24+
getTraceJSON,
25+
streamEvents,
26+
endTracing,
27+
};

0 commit comments

Comments
 (0)