Skip to content

Commit

Permalink
Merge pull request #1151 from appsignal/pino-transport-as-transport
Browse files Browse the repository at this point in the history
Allow Pino transport to be used as transport
  • Loading branch information
unflxw authored Nov 22, 2024
2 parents edadd7c + 11b789d commit 6df38ca
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 26 deletions.
50 changes: 50 additions & 0 deletions .changesets/allow-pino-transport-to-be-used-as-a-transport.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
bump: patch
type: fix
---

Allow Pino transport to be used as a transport. Before, our Pino transport could only be used as a destination:

```js
import pino from "pino";
import { Appsignal, AppsignalPinoTransport } from "@appsignal/nodejs";

pino(AppsignalPinoTransport({
client: Appsignal.client,
group: "pino"
}));
```

This meant it was not possible to log both to our transport and to another destination.

Now, it is also possible to use it as a Pino transport, with the `transport` Pino config option or the `pino.transport()` function:

```js
import pino from "pino";

pino({
transport: {
target: "@appsignal/nodejs/pino",
options: {
group: "pino"
}
}
});
```

It is no longer necessary to pass the AppSignal client to the Pino transport. AppSignal must be active for the Pino transport to work.

By enabling its use as a transport, it is now possible to use it alongside other transports:

```js
pino({
transport: {
targets: [
// Send logs to AppSignal...
{ target: "@appsignal/nodejs/pino" },
// ... and to standard output!
{ target: "pino/file" }
]
}
});
```
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
*
!/dist/**/*
!/pino/**/*
!/scripts/**/*
scripts/**/*.test.js
!/ext/appsignal_extension.cpp
Expand Down
2 changes: 2 additions & 0 deletions pino/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
"use strict"
module.exports = require("../dist/pino_transport")
55 changes: 29 additions & 26 deletions src/pino_transport.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,47 @@
import { LOGGER_LEVEL_SEVERITY } from "./logger"
import { LOGGER_LEVEL_SEVERITY, LOGGER_FORMAT } from "./logger"
import build from "pino-abstract-transport"
import { Client } from "./client"
import { Extension } from "./extension"

type PinoTransportOptions = {
client: Client
group: string
group?: string
}

const appsignalPinoTransport = ({
client,
group = "app"
}: PinoTransportOptions) => {
type LogData = {
severity: number
message: string
attributes: Record<string, any>
}

const appsignalPinoTransport = ({ group = "app" }: PinoTransportOptions) => {
return build(async (source: any) => {
// We expect this code to be running in a worker thread and for the
// extension to have already been loaded and started on the main thread.
// Since we expect the extension to already have been initialised, we
// pass `{ active: false }` to avoid initialising it again.
const extension = new Extension({ active: false })

for await (const obj of source) {
sendLogs(parseInfo(obj, group), client)
sendLogs(extension, group, parseInfo(obj))
}
})
}

async function sendLogs(data: Record<string, any>, client: Client) {
client.extension.log(
data.group || "app",
data.severity,
0,
data.msg,
data.attributes
)
}
async function sendLogs(extension: Extension, group: string, data: LogData) {
extension.log(
group,
data.severity,
LOGGER_FORMAT.plaintext,
data.message,
data.attributes
)
}

function parseInfo(
obj: Record<string, any>,
group: string
): Record<string, any> {
const { hostname, level, msg, ...attributes } = obj
function parseInfo(obj: Record<string, any>): LogData {
const { level, msg, ...attributes } = obj

return {
severity: getSeverity(level),
hostname,
group,
msg,
message: msg,
attributes: flattenAttributes(attributes)
}
}
Expand Down

0 comments on commit 6df38ca

Please sign in to comment.