Skip to content

Commit

Permalink
Add custom push Loki API path support (#39)
Browse files Browse the repository at this point in the history
* feat: add pushApiPath option for Loki Transport configuration

* test: add unit test for LogPusher with custom pushApiPath

* refactor: rename pushApiPath to endpoint

---------

Co-authored-by: Julien <julien@ripouteau.com>
  • Loading branch information
carlosfernandezcabrero and Julien-R44 authored Jan 15, 2025
1 parent a73b346 commit 5b06de2
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 15 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

#### `endpoint`

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:
Expand Down Expand Up @@ -133,6 +137,7 @@ Options:
-u, --user <user> Loki username
-p, --password <password> Loki password
--hostname <hostname> URL for Loki
--endpoint <endpoint> Path to the Loki push API
-b, --batch Should logs be sent in batch mode
-i, --interval <interval> The interval at which batched logs are sent in seconds
-t, --timeout <timeout> Timeout for request to Loki
Expand Down
2 changes: 2 additions & 0 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ program
.option('-u, --user <user>', 'Loki username')
.option('-p, --password <password>', 'Loki password')
.option('--hostname <hostname>', 'URL for Loki')
.option('--endpoint <endpoint>', 'Path to the Loki push API')
.option('-b, --batch', 'Should logs be sent in batch mode')
.option('-i, --interval <interval>', 'The interval at which batched logs are sent in seconds')
.option('-t, --timeout <timeout>', 'Timeout for request to Loki')
Expand All @@ -32,6 +33,7 @@ export const createPinoLokiConfigFromArgs = () => {

const config: LokiOptions = {
host: opts.hostname,
endpoint: opts.endpoint,
timeout: opts.timeout,
silenceErrors: opts.silenceErrors,
batching: opts.batch,
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type { PinoLog, LokiOptions } from './types'
function resolveOptions(options: LokiOptions) {
return {
...options,
endpoint: options.endpoint ?? 'loki/api/v1/push',
timeout: options.timeout ?? 30_000,
silenceErrors: options.silenceErrors ?? false,
batching: options.batching ?? true,
Expand Down
33 changes: 18 additions & 15 deletions src/log_pusher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.endpoint ?? '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())
Expand Down
7 changes: 7 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ export interface LokiOptions {
*/
host: string

/**
* Url for Loki push API
*
* @default loki/api/v1/push
*/
endpoint?: string

/**
* Timeout for request to Loki
*
Expand Down
19 changes: 19 additions & 0 deletions tests/unit/log_pusher.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(() => {
Expand Down Expand Up @@ -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',
endpoint: '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')
})
})

0 comments on commit 5b06de2

Please sign in to comment.