From 547fa953f1f88c912df8d46691275f398aee0318 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Cabrero <56631428+carlosfernandezcabrero@users.noreply.github.com> Date: Wed, 15 Jan 2025 09:12:50 +0100 Subject: [PATCH 1/3] feat: add pushApiPath option for Loki Transport configuration --- README.md | 5 +++++ src/cli.ts | 2 ++ src/index.ts | 1 + src/log_pusher.ts | 33 ++++++++++++++++++--------------- src/types.ts | 7 +++++++ 5 files changed, 33 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index c5b4a9e..43c9f42 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,10 @@ A map of pino log levels to Loki log levels. This can be used to map pino log le The URL for Loki. This is required. +#### `pushApiPath` + +The path to the Loki push API. Defaults to `/loki/api/v1/push`. + #### `basicAuth` Basic auth credentials for Loki. An object with the following shape: @@ -133,6 +137,7 @@ Options: -u, --user Loki username -p, --password Loki password --hostname URL for Loki + --pushApiPath Path to the Loki push API -b, --batch Should logs be sent in batch mode -i, --interval The interval at which batched logs are sent in seconds -t, --timeout Timeout for request to Loki diff --git a/src/cli.ts b/src/cli.ts index 441d02e..e0e5a61 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -10,6 +10,7 @@ program .option('-u, --user ', 'Loki username') .option('-p, --password ', 'Loki password') .option('--hostname ', 'URL for Loki') + .option('--pushApiPath ', 'Path to the Loki push API') .option('-b, --batch', 'Should logs be sent in batch mode') .option('-i, --interval ', 'The interval at which batched logs are sent in seconds') .option('-t, --timeout ', 'Timeout for request to Loki') @@ -32,6 +33,7 @@ export const createPinoLokiConfigFromArgs = () => { const config: LokiOptions = { host: opts.hostname, + pushApiPath: opts.pushApiPath, timeout: opts.timeout, silenceErrors: opts.silenceErrors, batching: opts.batch, diff --git a/src/index.ts b/src/index.ts index 616221e..fae3225 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,6 +11,7 @@ import type { PinoLog, LokiOptions } from './types' function resolveOptions(options: LokiOptions) { return { ...options, + pushApiPath: options.pushApiPath ?? 'loki/api/v1/push', timeout: options.timeout ?? 30_000, silenceErrors: options.silenceErrors ?? false, batching: options.batching ?? true, diff --git a/src/log_pusher.ts b/src/log_pusher.ts index bb8161c..b10b0f5 100644 --- a/src/log_pusher.ts +++ b/src/log_pusher.ts @@ -65,22 +65,25 @@ export class LogPusher { debug(`[LogPusher] pushing ${lokiLogs.length} logs to Loki`) try { - const response = await fetch(new URL('loki/api/v1/push', this.#options.host), { - method: 'POST', - signal: AbortSignal.timeout(this.#options.timeout ?? 30_000), - headers: { - ...this.#options.headers, - ...(this.#options.basicAuth && { - Authorization: - 'Basic ' + - Buffer.from( - `${this.#options.basicAuth.username}:${this.#options.basicAuth.password}`, - ).toString('base64'), - }), - 'Content-Type': 'application/json', + const response = await fetch( + new URL(this.#options.pushApiPath ?? 'loki/api/v1/push', this.#options.host), + { + method: 'POST', + signal: AbortSignal.timeout(this.#options.timeout ?? 30_000), + headers: { + ...this.#options.headers, + ...(this.#options.basicAuth && { + Authorization: + 'Basic ' + + Buffer.from( + `${this.#options.basicAuth.username}:${this.#options.basicAuth.password}`, + ).toString('base64'), + }), + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ streams: lokiLogs }), }, - body: JSON.stringify({ streams: lokiLogs }), - }) + ) if (!response.ok) { throw new RequestError('Got error when trying to send log to loki', await response.text()) diff --git a/src/types.ts b/src/types.ts index c27341f..d15633d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -44,6 +44,13 @@ export interface LokiOptions { */ host: string + /** + * Url for Loki push API + * + * @default loki/api/v1/push + */ + pushApiPath?: string + /** * Timeout for request to Loki * From 6f1fe7b5eb9fb956200fd49a9ebd58bb0469ab19 Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Cabrero <56631428+carlosfernandezcabrero@users.noreply.github.com> Date: Wed, 15 Jan 2025 09:13:39 +0100 Subject: [PATCH 2/3] test: add unit test for LogPusher with custom pushApiPath --- tests/unit/log_pusher.spec.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/unit/log_pusher.spec.ts b/tests/unit/log_pusher.spec.ts index d0314b8..d1aef0b 100644 --- a/tests/unit/log_pusher.spec.ts +++ b/tests/unit/log_pusher.spec.ts @@ -9,6 +9,9 @@ test.group('LogPusher', (group) => { http.post('http://localhost:3100/loki/api/v1/push', () => { return new Response(null, { status: 204 }) }), + http.post('http://localhost:3100/loki/api/v1/push/test', () => { + return new Response(null, { status: 204 }) + }), ) group.setup(() => { @@ -87,4 +90,20 @@ test.group('LogPusher', (group) => { console.error = consoleError }) + + test("should be send logs to Loki's push API if specified", async ({ assert }) => { + const pusher = new LogPusher({ + host: 'http://localhost:3100', + pushApiPath: 'loki/api/v1/push/test', + }) + + let url = '' + server.events.on('request:start', ({ request }) => { + url = request.url + }) + + pusher.push({ level: 30 }) + + assert.equal(url, 'http://localhost:3100/loki/api/v1/push/test') + }) }) From bb508d25ba01860b4bad9bfb8af9bbcd3b8d40a1 Mon Sep 17 00:00:00 2001 From: Julien Date: Wed, 15 Jan 2025 13:37:33 +0100 Subject: [PATCH 3/3] refactor: rename pushApiPath to endpoint --- README.md | 4 ++-- src/cli.ts | 4 ++-- src/index.ts | 2 +- src/log_pusher.ts | 2 +- src/types.ts | 2 +- tests/unit/log_pusher.spec.ts | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 43c9f42..cf9bac3 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ A map of pino log levels to Loki log levels. This can be used to map pino log le The URL for Loki. This is required. -#### `pushApiPath` +#### `endpoint` The path to the Loki push API. Defaults to `/loki/api/v1/push`. @@ -137,7 +137,7 @@ Options: -u, --user Loki username -p, --password Loki password --hostname URL for Loki - --pushApiPath Path to the Loki push API + --endpoint Path to the Loki push API -b, --batch Should logs be sent in batch mode -i, --interval The interval at which batched logs are sent in seconds -t, --timeout Timeout for request to Loki diff --git a/src/cli.ts b/src/cli.ts index e0e5a61..3e2a39a 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -10,7 +10,7 @@ program .option('-u, --user ', 'Loki username') .option('-p, --password ', 'Loki password') .option('--hostname ', 'URL for Loki') - .option('--pushApiPath ', 'Path to the Loki push API') + .option('--endpoint ', 'Path to the Loki push API') .option('-b, --batch', 'Should logs be sent in batch mode') .option('-i, --interval ', 'The interval at which batched logs are sent in seconds') .option('-t, --timeout ', 'Timeout for request to Loki') @@ -33,7 +33,7 @@ export const createPinoLokiConfigFromArgs = () => { const config: LokiOptions = { host: opts.hostname, - pushApiPath: opts.pushApiPath, + endpoint: opts.endpoint, timeout: opts.timeout, silenceErrors: opts.silenceErrors, batching: opts.batch, diff --git a/src/index.ts b/src/index.ts index fae3225..4af219c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,7 +11,7 @@ import type { PinoLog, LokiOptions } from './types' function resolveOptions(options: LokiOptions) { return { ...options, - pushApiPath: options.pushApiPath ?? 'loki/api/v1/push', + endpoint: options.endpoint ?? 'loki/api/v1/push', timeout: options.timeout ?? 30_000, silenceErrors: options.silenceErrors ?? false, batching: options.batching ?? true, diff --git a/src/log_pusher.ts b/src/log_pusher.ts index b10b0f5..9a2370a 100644 --- a/src/log_pusher.ts +++ b/src/log_pusher.ts @@ -66,7 +66,7 @@ export class LogPusher { try { const response = await fetch( - new URL(this.#options.pushApiPath ?? 'loki/api/v1/push', this.#options.host), + new URL(this.#options.endpoint ?? 'loki/api/v1/push', this.#options.host), { method: 'POST', signal: AbortSignal.timeout(this.#options.timeout ?? 30_000), diff --git a/src/types.ts b/src/types.ts index d15633d..b0a1437 100644 --- a/src/types.ts +++ b/src/types.ts @@ -49,7 +49,7 @@ export interface LokiOptions { * * @default loki/api/v1/push */ - pushApiPath?: string + endpoint?: string /** * Timeout for request to Loki diff --git a/tests/unit/log_pusher.spec.ts b/tests/unit/log_pusher.spec.ts index d1aef0b..8f03dac 100644 --- a/tests/unit/log_pusher.spec.ts +++ b/tests/unit/log_pusher.spec.ts @@ -94,7 +94,7 @@ test.group('LogPusher', (group) => { test("should be send logs to Loki's push API if specified", async ({ assert }) => { const pusher = new LogPusher({ host: 'http://localhost:3100', - pushApiPath: 'loki/api/v1/push/test', + endpoint: 'loki/api/v1/push/test', }) let url = ''