diff --git a/README.md b/README.md index 4a4c593..304ba01 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,22 @@ import { LokiReporter } from "consola-loki"; const { LokiReporter } = require("consola-loki"); ``` +Example: +```ts +const consola = createConsola({ + reporters: [ + new LokiReporter({ + baseUrl: "your base url here", + user: "123456", + token: "glc_......", + labels: { // custom global labels + hostname: hostname(), // example + }, + }), + ], +}); +``` + ## Development - Clone this repository diff --git a/package.json b/package.json index 752229d..19f0411 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "consola-loki", - "version": "0.0.0", + "version": "0.0.1", "description": "", - "repository": "unjs/consola-loki", + "repository": "niki2k1/consola-loki", "license": "MIT", "sideEffects": false, "type": "module", diff --git a/src/reporters/loki.ts b/src/reporters/loki.ts index aea5f2c..ce6e66d 100644 --- a/src/reporters/loki.ts +++ b/src/reporters/loki.ts @@ -31,17 +31,21 @@ export class LokiReporter implements ConsolaReporter { public async flush() { try { + const headers: HeadersInit = {}; + + if (this.options.user && this.options.token) { + headers.Authorization = `Basic ${Buffer.from(`${this.options.user}:${this.options.token}`).toString("base64")}`; + } + await $fetch("/loki/api/v1/push", { - baseURL: this.options.baseUrl, + baseURL: this.options.baseURL, method: "POST", - headers: { - Authorization: `Basic ${Buffer.from(`${this.options.user}:${this.options.token}`).toString("base64")}`, - }, + headers, body: { streams: this.buffer.map((logStream) => ({ stream: logStream.labels, values: logStream.entries.map((entry) => [ - JSON.stringify(entry.timestamp.getTime() * 1000 * 1000), + JSON.stringify(entry.timestamp.getTime() * 1000 * 1000), // Loki expects nanoseconds entry.message, ]), })), @@ -62,7 +66,7 @@ export class LokiReporter implements ConsolaReporter { if (this.buffer.length > 0) { this.flush(); } - }, 1000); + }, 5000); } const defaultLabels = { diff --git a/src/types.ts b/src/types.ts index 1da368e..c2e6500 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,6 +1,6 @@ export interface LokiOptions { - baseUrl: string; - user: string; - token: string; - labels: Record; + baseURL: string; + user?: string; + token?: string; + labels?: Record; } diff --git a/test/index.test.ts b/test/index.test.ts index 89d75f4..aac3661 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -1,8 +1,78 @@ -import { expect, it, describe } from "vitest"; -import {} from "../src"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { createConsola } from "consola"; +import { $fetch } from "ofetch"; +import { LokiReporter } from "../src"; -describe("packageName", () => { - it.todo("pass", () => { - expect(true).toBe(true); +const mocks = vi.hoisted(() => { + return { + $fetch: vi.fn(), + }; +}); + +vi.mock("ofetch", () => { + return { + $fetch: mocks.$fetch, + }; +}); + +describe("consola-loki", () => { + beforeEach(() => { + vi.clearAllMocks(); + vi.useFakeTimers(); + }); + + afterEach(() => { + vi.useRealTimers(); + }); + + it("should log to loki", async () => { + const date = new Date(2024, 3, 8, 14, 38); + vi.setSystemTime(date); + + vi.mocked($fetch).mockResolvedValue(() => {}); + + const baseURL = "https://loki-endpoint.example"; + + const lokiReporter = new LokiReporter({ + baseURL, + user: "123456", + token: "glc_", + }); + + const consola = createConsola({ + reporters: [lokiReporter], + }); + + consola.warn("Test Warn"); + consola.error("Test Error"); + + // flush manually + await lokiReporter.flush(); + + const timestmap = (date.getTime() * 1000 * 1000).toString(); + + expect($fetch).toHaveBeenCalledWith("/loki/api/v1/push", { + baseURL, + body: { + streams: [ + { + stream: { + level: "warn", + }, + values: [[timestmap, "Test Warn"]], + }, + { + stream: { + level: "error", + }, + values: [[timestmap, "Test Error"]], + }, + ], + }, + headers: { + Authorization: "Basic MTIzNDU2OmdsY18=", + }, + method: "POST", + }); }); });