This commit is contained in:
Anton Nesterov 2024-07-08 17:59:39 +02:00
parent 9754ce9cf8
commit 109994db57
8 changed files with 132 additions and 3 deletions

2
.gitignore vendored
View file

@ -118,7 +118,7 @@ out
# Nuxt.js build / generate output
.nuxt
dist
#dist
# Gatsby files

21
dist/index.d.ts vendored Normal file
View file

@ -0,0 +1,21 @@
export type Event = Record<string, string | string[]>;
export interface IHTTPLogger {
log(event: string, ...tags: string[]): void;
}
export type HTTPLoggerOptions = {
url: string;
bufferSize?: number;
throttle?: number;
fetch?: typeof fetch;
getMetadata?: () => Event;
};
declare class HTTPLog implements IHTTPLogger {
#private;
constructor({ url, bufferSize, throttle, fetch, getMetadata, }: HTTPLoggerOptions);
log(event: string, ...tags: string[]): Promise<void>;
}
declare global {
var HTTPLogger: typeof HTTPLog;
}
export {};
//# sourceMappingURL=index.d.ts.map

1
dist/index.d.ts.map vendored Normal file
View file

@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;AAEtD,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;CAC7C;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,KAAK,CAAC;CAC7B,CAAC;AAEF,cAAM,OAAQ,YAAW,WAAW;;gBAatB,EACV,GAAQ,EACR,UAAc,EACd,QAAe,EACf,KAAwB,EACxB,WAGE,GACH,EAAE,iBAAiB;IAsDd,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE;CAgB3C;AAED,OAAO,CAAC,MAAM,CAAC;IACb,IAAI,UAAU,EAAE,OAAO,OAAO,CAAC;CAChC"}

79
dist/index.js vendored Normal file
View file

@ -0,0 +1,79 @@
class HTTPLog {
#url;
#buffer = [];
#bufferSize = 3;
#throttle;
#timeout = void 0;
#getMetadata;
#fetch;
constructor({ url = "", bufferSize = 3, throttle = 1000, fetch = globalThis.fetch, getMetadata = () => ({
title: globalThis.document?.title || "",
url: globalThis.location?.href || "",
}), }) {
if (url === "") {
throw new Error("URL is required");
}
this.#url = url;
this.#bufferSize = bufferSize;
this.#throttle = throttle;
this.#fetch = (...args) => fetch(...args);
this.#getMetadata = getMetadata;
if (typeof window === "undefined") {
return;
}
addEventListener("unload", () => {
globalThis?.navigator?.sendBeacon?.(this.#url, JSON.stringify(this.#buffer));
});
}
async #post() {
const data = this.#buffer.slice();
if (data.length === 0) {
return;
}
this.#buffer = [];
const body = JSON.stringify(data);
try {
const res = await this.#fetch(this.#url, {
method: "POST",
body: body,
headers: {
"Content-Type": "application/json",
},
keepalive: true,
credentials: "include",
});
if (res.status >= 400 && res.status !== 422) {
this.#buffer.push(...data);
}
return res;
}
catch (e) {
console.log("Error", e);
this.#buffer.push(...data);
}
}
async #timer() {
this.#timeout = setTimeout(() => {
this.#post();
this.#timer();
}, this.#throttle);
}
async log(event, ...tags) {
this.#buffer.push({
event,
tags,
...this.#getMetadata(),
});
if (this.#buffer.length >= this.#bufferSize) {
this.#post();
}
if (this.#timeout === void 0) {
this.#post();
this.#timer();
}
}
}
// @ts-ignore
globalThis.HTTPLogger = HTTPLog;
export {};
//# sourceMappingURL=index.js.map

1
dist/index.js.map vendored Normal file
View file

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}

View file

@ -108,7 +108,7 @@ class HTTPLog implements IHTTPLogger {
}
declare global {
var HTTPLogger: IHTTPLogger;
var HTTPLogger: typeof HTTPLog;
}
// @ts-ignore

26
logger.test.ts Normal file
View file

@ -0,0 +1,26 @@
import { expect, test, beforeAll, jest } from "bun:test";
import './index.ts';
beforeAll(() => {
// Bun: not yet implemented
// jest.useFakeTimers();
});
test("HTTPLogger", async () => {
let ping = 0;
let instance = new HTTPLogger({
url: "http://localhost:3000",
fetch: async (_, body) => {
ping++;
return new Response(null, {
status: 200,
});
},
});
instance.log("test");
expect(ping).toBe(1);
instance.log("test2");
expect(ping).toBe(1);
await new Promise((resolve) => setTimeout(resolve, 1100));
expect(ping).toBe(2);
});

View file

@ -28,5 +28,6 @@
"declaration": true,
"declarationMap": true,
},
"include": ["./*"]
"include": ["./*"],
"exclude": ["node_modules", "dist", "./*.test.ts", "./*.spec.ts"]
}