Repository: pinojs/pino
Pull request #2052 (2024-09-29 21:37:25)

fix: Ensure silent log level is respected with browser.transmit option
The silent log level currently does not work in the browser when the `browser.transmit` option is used.

- When `options.level` is set to `"silent"` and `options.browser.transmit` is used, everything gets logged as if `options.level` was the most verbose.
- When `options.level` is non-silent (e.g. `"info"`) and `options.browser.transmit.level` is `"silent"`, the `options.browser.transmit.send` method is called for every log event above `options.level`, which should not occur.

This PR uses the `levelToValue` method which correctly handles the silent level to determine the `transmitValue` and `methodValue`, so the silent level works even when `options.browser.transmit` is used. 


Patch:
diff --git a/browser.js b/browser.js
index 522de1a..7d0aa2b 100644
--- a/browser.js
+++ b/browser.js
@@ -280,8 +280,8 @@ function set (self, opts, rootLogger, level) {
     if (!opts.transmit) return
 
     const transmitLevel = opts.transmit.level || self.level
-    const transmitValue = rootLogger.levels.values[transmitLevel]
-    const methodValue = rootLogger.levels.values[level]
+    const transmitValue = levelToValue(transmitLevel, rootLogger)
+    const methodValue = levelToValue(level, rootLogger)
     if (methodValue < transmitValue) return
   }
 
@@ -322,8 +322,8 @@ function createWrap (self, opts, rootLogger, level) {
 
       if (opts.transmit) {
         const transmitLevel = opts.transmit.level || self._level
-        const transmitValue = rootLogger.levels.values[transmitLevel]
-        const methodValue = rootLogger.levels.values[level]
+        const transmitValue = levelToValue(transmitLevel, rootLogger)
+        const methodValue = levelToValue(level, rootLogger)
         if (methodValue < transmitValue) return
         transmit(this, {
           ts,
diff --git a/docs/transports.md b/docs/transports.md
index 0e45730..9fd377a 100644
--- a/docs/transports.md
+++ b/docs/transports.md
@@ -15,7 +15,7 @@ now referred to as [Legacy Transports](#legacy-transports).
 
 From Pino v7 and upwards transports can also operate inside a [Worker Thread][worker-thread]
 and can be used or configured via the options object passed to `pino` on initialization.
-In this case the transports would always operate asynchronously, and logs would be
+In this case the transports would always operate asynchronously (unless `options.sync` is set to `true` in transport options), and logs would be
 flushed as quickly as possible (there is nothing to do).
 
 [worker-thread]: https://nodejs.org/dist/latest-v14.x/docs/api/worker_threads.html
@@ -124,6 +124,19 @@ const transport = pino.transport({
 pino(transport)
 ```
 
+To make pino log synchronously, pass `sync: true` to transport options.
+```js
+const pino = require('pino')
+const transport = pino.transport({
+  targets: [
+    { target: '/absolute/path/to/my-transport.mjs', level: 'error' },
+  ],
+  dedupe: true,
+  sync: true,
+});
+pino(transport);
+```
+
 For more details on `pino.transport` see the [API docs for `pino.transport`][pino-transport].
 
 [pino-transport]: /docs/api.md#pino-transport
@@ -410,23 +423,24 @@ PRs to this document are welcome for any new transports!
 
 ### Pino v7+ Compatible
 
++ [@axiomhq/pino](#@axiomhq/pino)
 + [@logtail/pino](#@logtail/pino)
-+ [pino-elasticsearch](#pino-elasticsearch)
-+ [pino-pretty](#pino-pretty)
-+ [pino-loki](#pino-loki)
-+ [pino-seq-transport](#pino-seq-transport)
-+ [pino-sentry-transport](#pino-sentry-transport)
++ [@macfja/pino-fingers-crossed](#macfja-pino-fingers-crossed)
 + [pino-airbrake-transport](#pino-airbrake-transport)
-+ [pino-datadog-transport](#pino-datadog-transport)
-+ [pino-slack-webhook](#pino-slack-webhook) 
 + [pino-axiom](#pino-axiom)
-+ [pino-opentelemetry-transport](#pino-opentelemetry-transport)
-+ [@axiomhq/pino](#@axiomhq/pino)
++ [pino-datadog-transport](#pino-datadog-transport)
 + [pino-discord-webhook](#pino-discord-webhook)
++ [pino-elasticsearch](#pino-elasticsearch)
++ [pino-hana](#pino-hana)
 + [pino-logfmt](#pino-logfmt)
++ [pino-loki](#pino-loki)
++ [pino-opentelemetry-transport](#pino-opentelemetry-transport)
++ [pino-pretty](#pino-pretty)
++ [pino-seq-transport](#pino-seq-transport)
++ [pino-sentry-transport](#pino-sentry-transport)
++ [pino-slack-webhook](#pino-slack-webhook)
 + [pino-telegram-webhook](#pino-telegram-webhook)
 + [pino-yc-transport](#pino-yc-transport)
-+ [@macfja/pino-fingers-crossed](#macfja-pino-fingers-crossed)
 
 ### Legacy
 
@@ -454,6 +468,34 @@ PRs to this document are welcome for any new transports!
 + [pino-websocket](#pino-websocket)
 
 
+<a id="@axiomhq/pino"></a>
+### @axiomhq/pino
+
+[@axiomhq/pino](https://www.npmjs.com/package/@axiomhq/pino) is the official [Axiom](https://axiom.co/) transport for Pino, using [axiom-js](https://github.com/axiomhq/axiom-js).
+
+```javascript
+import pino from 'pino';
+
+const logger = pino(
+  { level: 'info' },
+  pino.transport({
+    target: '@axiomhq/pino',
+    options: {
+      dataset: process.env.AXIOM_DATASET,
+      token: process.env.AXIOM_TOKEN,
+    },
+  }),
+);
+```
+
+then you can use the logger as usual:
+
+```js
+logger.info('Hello from pino!');
+```
+
+For further examples, head over to the [examples](https://github.com/axiomhq/axiom-js/tree/main/examples/pino) directory.
+
 <a id="@logtail/pino"></a>
 ### @logtail/pino
 
@@ -461,6 +503,56 @@ The [@logtail/pino](https://www.npmjs.com/package/@logtail/pino) NPM package is
 
 [Quick start guide ⇗](https://betterstack.com/docs/logs/javascript/pino)
 
+<a id="macfja-pino-fingers-crossed"></a>
+### @macfja/pino-fingers-crossed
+
+[@macfja/pino-fingers-crossed](https://github.com/MacFJA/js-pino-fingers-crossed) is a Pino v7+ transport that holds logs until a log level is reached, allowing to only have logs when it matters.
+
+```js
+const pino = require('pino');
+const { default: fingersCrossed, enable } = require('@macfja/pino-fingers-crossed')
+
+const logger = pino(fingersCrossed());
+
+logger.info('Will appear immedialty')
+logger.error('Will appear immedialty')
+
+logger.setBindings({ [enable]: 50 })
+logger.info('Will NOT appear immedialty')
+logger.info('Will NOT appear immedialty')
+logger.error('Will appear immedialty as well as the 2 previous messages') // error log are level 50
+logger.info('Will NOT appear')
+logger.info({ [enable]: false }, 'Will appear immedialty')
+logger.info('Will NOT appear')
+```
+
+<a id="pino-airbrake-transport"></a>
+### pino-airbrake-transport
+
+[pino-airbrake-transport][pino-airbrake-transport] is a Pino v7+ compatible transport to forward log events to [Airbrake][Airbrake]
+from a dedicated worker:
+
+```js
+const pino = require('pino')
+const transport = pino.transport({
+  target: 'pino-airbrake-transport',
+  options: {
+    airbrake: {
+      projectId: 1,
+      projectKey: "REPLACE_ME",
+      environment: "production",
+      // additional options for airbrake
+      performanceStats: false,
+    },
+  },
+  level: "error", // minimum log level that should be sent to airbrake
+})
+pino(transport)
+```
+
+[pino-airbrake-transport]: https://github.com/enricodeleo/pino-airbrake-transport
+[Airbrake]: https://airbrake.io/
+
 <a id="pino-applicationinsights"></a>
 ### pino-applicationinsights
 The [pino-applicationinsights](https://www.npmjs.com/package/pino-applicationinsights) module is a transport that will forward logs to [Azure Application Insights](https://docs.microsoft.com/en-us/azure/azure-monitor/app/app-insights-overview).
@@ -473,6 +565,24 @@ $ node foo | pino-applicationinsights --key blablabla
 
 For full documentation of command line switches read [README](https://github.com/ovhemert/pino-applicationinsights#readme)
 
+<a id="pino-axiom"></a>
+### pino-axiom
+
+[pino-axiom](https://www.npmjs.com/package/pino-axiom) is a transport that will forward logs to [Axiom](https://axiom.co).
+
+```javascript
+const pino = require('pino')
+const transport = pino.transport({
+  target: 'pino-axiom',
+  options: {
+    orgId: 'YOUR-ORG-ID', 
+    token: 'YOUR-TOKEN', 
+    dataset: 'YOUR-DATASET', 
+  },
+})
+pino(transport)
+```
+
 <a id="pino-azuretable"></a>
 ### pino-azuretable
 The [pino-azuretable](https://www.npmjs.com/package/pino-azuretable) module is a transport that will forward logs to the [Azure Table Storage](https://azure.microsoft.com/en-us/services/storage/tables/).
@@ -521,6 +631,87 @@ $ node foo | pino-datadog --key blablabla
 
 For full documentation of command line switches read [README](https://github.com/ovhemert/pino-datadog#readme)
 
+<a id="pino-datadog-transport"></a>
+### pino-datadog-transport
+
+[pino-datadog-transport][pino-datadog-transport] is a Pino v7+ compatible transport to forward log events to [Datadog][Datadog]
+from a dedicated worker:
+
+```js
+const pino = require('pino')
+const transport = pino.transport({
+  target: 'pino-datadog-transport',
+  options: {
+    ddClientConf: {
+      authMethods: {
+        apiKeyAuth: <your datadog API key>
+      }
+    },
+  },
+  level: "error", // minimum log level that should be sent to datadog
+})
+pino(transport)
+```
+
+[pino-datadog-transport]: https://github.com/theogravity/pino-datadog-transport
+[Datadog]: https://www.datadoghq.com/
+
+#### Logstash
+
+The [pino-socket][pino-socket] module can also be used to upload logs to
+[Logstash][logstash] via:
+
+```
+$ node app.js | pino-socket -a 127.0.0.1 -p 5000 -m tcp
+```
+
+Assuming logstash is running on the same host and configured as
+follows:
+
+```
+input {
+  tcp {
+    port => 5000
+  }
+}
+
+filter {
+  json {
+    source => "message"
+  }
+}
+
+output {
+  elasticsearch {
+    hosts => "127.0.0.1:9200"
+  }
+}
+```
+
+See <https://www.elastic.co/guide/en/kibana/current/setup.html> to learn
+how to setup [Kibana][kibana].
+
+For Docker users, see
+https://github.com/deviantony/docker-elk to setup an ELK stack.
+
+<a id="pino-discord-webhook"></a>
+### pino-discord-webhook
+
+[pino-discord-webhook](https://github.com/fabulousgk/pino-discord-webhook) is a  Pino v7+ compatible transport to forward log events to a [Discord](http://discord.com) webhook from a dedicated worker. 
+
+```js
+import pino from 'pino'
+
+const logger = pino({
+  transport: {
+    target: 'pino-discord-webhook',
+    options: {
+      webhookUrl: 'https://discord.com/api/webhooks/xxxx/xxxx',
+    }
+  }
+})
+```
+
 <a id="pino-elasticsearch"></a>
 ### pino-elasticsearch
 
@@ -571,6 +762,31 @@ $ node your-app.js | pino-gelf log
 [gelf]: https://docs.graylog.org/en/2.1/pages/gelf.html
 [graylog]: https://www.graylog.org/
 
+<a id="pino-hana"></a>
+### pino-hana
+[pino-hana](https://github.com/HiImGiovi/pino-hana) is a Pino v7+ transport that save pino logs to a SAP HANA database.
+```js
+const pino = require('pino')
+const logger = pino({
+  transport: {
+    target: 'pino-hana',
+    options: {
+      connectionOptions: {
+        host: <hana db host>,
+        port: <hana db port>,
+        user: <hana db user>,
+        password: <hana db password>,
+      },
+      schema: <schema of the table in which you want to save the logs>,
+      table: <table in which you want to save the logs>,
+    },
+  },
+})
+
+logger.info('hi') // this log will be saved into SAP HANA
+```
+For more detailed information about its usage please check the official [documentation](https://github.com/HiImGiovi/pino-hana#readme).
+
 <a id="pino-http-send"></a>
 ### pino-http-send
 
@@ -610,33 +826,20 @@ Tags and other metadata can be included using the available command line options
 $ node index.js | pino-logflare --key YOUR_KEY --source YOUR_SOURCE
 ```
 
-<a id="pino-mq"></a>
-### pino-mq
-
-The `pino-mq` transport will take all messages received on `process.stdin` and send them over a message bus using JSON serialization.
-
-This is useful for:
-
-* moving backpressure from application to broker
-* transforming messages pressure to another component
-
-```
-node app.js | pino-mq -u "amqp://guest:guest@localhost/" -q "pino-logs"
-```
-
-Alternatively, a configuration file can be used:
+<a id="pino-logfmt"></a>
+### pino-logfmt
 
-```
-node app.js | pino-mq -c pino-mq.json
-```
+[pino-logfmt](https://github.com/botflux/pino-logfmt) is a Pino v7+ transport that formats logs into [logfmt](https://brandur.org/logfmt). This transport can output the formatted logs to stdout or file.
 
-A base configuration file can be initialized with:
+```js
+import pino from 'pino'
 
+const logger = pino({
+  transport: {
+    target: 'pino-logfmt'
+  }
+})
 ```
-pino-mq -g
-```
-
-For full documentation of command line switches and configuration see [the `pino-mq` README](https://github.com/itavy/pino-mq#readme)
 
 <a id="pino-loki"></a>
 ### pino-loki
@@ -660,24 +863,33 @@ pino(transport)
 
 For full documentation and configuration, see the [README](https://github.com/Julien-R44/pino-loki).
 
-<a id="pino-papertrail"></a>
-### pino-papertrail
-pino-papertrail is a transport that will forward logs to the [papertrail](https://papertrailapp.com) log service through an UDPv4 socket.
+<a id="pino-mq"></a>
+### pino-mq
 
-Given an application `foo` that logs via pino, and a papertrail destination that collects logs on port UDP `12345` on address `bar.papertrailapp.com`, you would use `pino-papertrail`
-like so:
+The `pino-mq` transport will take all messages received on `process.stdin` and send them over a message bus using JSON serialization.
+
+This is useful for:
+
+* moving backpressure from application to broker
+* transforming messages pressure to another component
 
 ```
-node yourapp.js | pino-papertrail --host bar.papertrailapp.com --port 12345 --appname foo
+node app.js | pino-mq -u "amqp://guest:guest@localhost/" -q "pino-logs"
 ```
 
+Alternatively, a configuration file can be used:
 
-for full documentation of command line switches read [README](https://github.com/ovhemert/pino-papertrail#readme)
+```
+node app.js | pino-mq -c pino-mq.json
+```
 
-<a id="pino-pg"></a>
-### pino-pg
-[pino-pg](https://www.npmjs.com/package/pino-pg) stores logs into PostgreSQL.
-Full documentation in the [README](https://github.com/Xstoudi/pino-pg).
+A base configuration file can be initialized with:
+
+```
+pino-mq -g
+```
+
+For full documentation of command line switches and configuration see [the `pino-mq` README](https://github.com/itavy/pino-mq#readme)
 
 <a id="pino-mysql"></a>
 ### pino-mysql
@@ -698,6 +910,48 @@ For full documentation and command line switches read the [README][pino-mysql].
 [MariaDB]: https://mariadb.org/
 [JSONDT]: https://dev.mysql.com/doc/refman/8.0/en/json.html
 
+<a id="pino-opentelemetry-transport"></a>
+### pino-opentelemetry-transport
+
+[pino-opentelemetry-transport](https://www.npmjs.com/package/pino-opentelemetry-transport) is a transport that will forward logs to an [OpenTelemetry log collector](https://opentelemetry.io/docs/collector/) using [OpenTelemetry JS instrumentation](https://opentelemetry.io/docs/instrumentation/js/).
+
+```javascript
+const pino = require('pino')
+
+const transport = pino.transport({
+  target: 'pino-opentelemetry-transport',
+  options: {
+    resourceAttributes: {
+      'service.name': 'test-service',
+      'service.version': '1.0.0'
+    }
+  }
+})
+
+pino(transport)
+```
+
+Documentation on running a minimal example is available in the [README](https://github.com/Vunovati/pino-opentelemetry-transport#minimalistic-example).
+
+<a id="pino-papertrail"></a>
+### pino-papertrail
+pino-papertrail is a transport that will forward logs to the [papertrail](https://papertrailapp.com) log service through an UDPv4 socket.
+
+Given an application `foo` that logs via pino, and a papertrail destination that collects logs on port UDP `12345` on address `bar.papertrailapp.com`, you would use `pino-papertrail`
+like so:
+
+```
+node yourapp.js | pino-papertrail --host bar.papertrailapp.com --port 12345 --appname foo
+```
+
+
+for full documentation of command line switches read [README](https://github.com/ovhemert/pino-papertrail#readme)
+
+<a id="pino-pg"></a>
+### pino-pg
+[pino-pg](https://www.npmjs.com/package/pino-pg) stores logs into PostgreSQL.
+Full documentation in the [README](https://github.com/Xstoudi/pino-pg).
+
 <a id="pino-redis"></a>
 ### pino-redis
 
@@ -724,6 +978,27 @@ For full documentation of command line switches see the [pino-sentry README](htt
 [pino-sentry]: https://www.npmjs.com/package/pino-sentry
 [Sentry]: https://sentry.io/
 
+<a id="pino-sentry-transport"></a>
+### pino-sentry-transport
+
+[pino-sentry-transport][pino-sentry-transport] is a Pino v7+ compatible transport to forward log events to [Sentry][Sentry]
+from a dedicated worker:
+
+```js
+const pino = require('pino')
+const transport = pino.transport({
+  target: 'pino-sentry-transport',
+  options: {
+    sentry: {
+      dsn: 'https://******@sentry.io/12345',
+    }
+  }
+})
+pino(transport)
+```
+
+[pino-sentry-transport]: https://github.com/tomer-yechiel/pino-sentry-transport
+[Sentry]: https://sentry.io/
 
 <a id="pino-seq"></a>
 ### pino-seq
@@ -755,55 +1030,32 @@ pino(transport)
 [pino-seq-transport]: https://github.com/autotelic/pino-seq-transport
 [Seq]: https://datalust.co/seq
 
-<a id="pino-sentry-transport"></a>
-### pino-sentry-transport
+<a id="pino-slack-webhook"></a>
+### pino-slack-webhook
 
-[pino-sentry-transport][pino-sentry-transport] is a Pino v7+ compatible transport to forward log events to [Sentry][Sentry]
+[pino-slack-webhook][pino-slack-webhook] is a Pino v7+ compatible transport to forward log events to [Slack][Slack]
 from a dedicated worker:
 
 ```js
 const pino = require('pino')
 const transport = pino.transport({
-  target: 'pino-sentry-transport',
+  target: '@youngkiu/pino-slack-webhook',
   options: {
-    sentry: {
-      dsn: 'https://******@sentry.io/12345',
-    }
+    webhookUrl: 'https://hooks.slack.com/services/xxx/xxx/xxx',
+    channel: '#pino-log',
+    username: 'webhookbot',
+    icon_emoji: ':ghost:'
   }
 })
 pino(transport)
 ```
 
-[pino-sentry-transport]: https://github.com/tomer-yechiel/pino-sentry-transport
-[Sentry]: https://sentry.io/
-
-
-<a id="pino-airbrake-transport"></a>
-### pino-airbrake-transport
-
-[pino-airbrake-transport][pino-airbrake-transport] is a Pino v7+ compatible transport to forward log events to [Airbrake][Airbrake]
-from a dedicated worker:
+[pino-slack-webhook]: https://github.com/youngkiu/pino-slack-webhook
+[Slack]: https://slack.com/
 
-```js
-const pino = require('pino')
-const transport = pino.transport({
-  target: 'pino-airbrake-transport',
-  options: {
-    airbrake: {
-      projectId: 1,
-      projectKey: "REPLACE_ME",
-      environment: "production",
-      // additional options for airbrake
-      performanceStats: false,
-    },
-  },
-  level: "error", // minimum log level that should be sent to airbrake
-})
-pino(transport)
-```
+[pino-pretty]: https://github.com/pinojs/pino-pretty
 
-[pino-airbrake-transport]: https://github.com/enricodeleo/pino-airbrake-transport
-[Airbrake]: https://airbrake.io/
+For full documentation of command line switches read the [README](https://github.com/abeai/pino-websocket#readme).
 
 <a id="pino-socket"></a>
 ### pino-socket
@@ -827,69 +1079,6 @@ Logs from the application should be observed on both consoles.
 
 [pino-socket]: https://www.npmjs.com/package/pino-socket
 
-<a id="pino-datadog-transport"></a>
-### pino-datadog-transport
-
-[pino-datadog-transport][pino-datadog-transport] is a Pino v7+ compatible transport to forward log events to [Datadog][Datadog]
-from a dedicated worker:
-
-```js
-const pino = require('pino')
-const transport = pino.transport({
-  target: 'pino-datadog-transport',
-  options: {
-    ddClientConf: {
-      authMethods: {
-        apiKeyAuth: <your datadog API key>
-      }
-    },
-  },
-  level: "error", // minimum log level that should be sent to datadog
-})
-pino(transport)
-```
-
-[pino-datadog-transport]: https://github.com/theogravity/pino-datadog-transport
-[Datadog]: https://www.datadoghq.com/
-
-#### Logstash
-
-The [pino-socket][pino-socket] module can also be used to upload logs to
-[Logstash][logstash] via:
-
-```
-$ node app.js | pino-socket -a 127.0.0.1 -p 5000 -m tcp
-```
-
-Assuming logstash is running on the same host and configured as
-follows:
-
-```
-input {
-  tcp {
-    port => 5000
-  }
-}
-
-filter {
-  json {
-    source => "message"
-  }
-}
-
-output {
-  elasticsearch {
-    hosts => "127.0.0.1:9200"
-  }
-}
-```
-
-See <https://www.elastic.co/guide/en/kibana/current/setup.html> to learn
-how to setup [Kibana][kibana].
-
-For Docker users, see
-https://github.com/deviantony/docker-elk to setup an ELK stack.
-
 <a id="pino-stackdriver"></a>
 ### pino-stackdriver
 The [pino-stackdriver](https://www.npmjs.com/package/pino-stackdriver) module is a transport that will forward logs to the [Google Stackdriver](https://cloud.google.com/logging/) log service through its API.
@@ -925,147 +1114,6 @@ Example output for the "hello world" log:
 [rfc3164]: https://tools.ietf.org/html/rfc3164
 [logstash]: https://www.elastic.co/products/logstash
 
-
-<a id="pino-websocket"></a>
-### pino-websocket
-
-[pino-websocket](https://www.npmjs.com/package/@abeai/pino-websocket) is a transport that will forward each log line to a websocket server.
-
-```sh
-$ node app.js | pino-websocket -a my-websocket-server.example.com -p 3004
-```
-
-For full documentation of command line switches read the [README](https://github.com/abeai/pino-websocket#readme).
-
-<a id="pino-slack-webhook"></a>
-### pino-slack-webhook
-
-[pino-slack-webhook][pino-slack-webhook] is a Pino v7+ compatible transport to forward log events to [Slack][Slack]
-from a dedicated worker:
-
-```js
-const pino = require('pino')
-const transport = pino.transport({
-  target: '@youngkiu/pino-slack-webhook',
-  options: {
-    webhookUrl: 'https://hooks.slack.com/services/xxx/xxx/xxx',
-    channel: '#pino-log',
-    username: 'webhookbot',
-    icon_emoji: ':ghost:'
-  }
-})
-pino(transport)
-```
-
-[pino-slack-webhook]: https://github.com/youngkiu/pino-slack-webhook
-[Slack]: https://slack.com/
-
-[pino-pretty]: https://github.com/pinojs/pino-pretty
-
-For full documentation of command line switches read the [README](https://github.com/abeai/pino-websocket#readme).
-
-<a id="pino-axiom"></a>
-### pino-axiom
-
-[pino-axiom](https://www.npmjs.com/package/pino-axiom) is a transport that will forward logs to [Axiom](https://axiom.co).
-
-```javascript
-const pino = require('pino')
-const transport = pino.transport({
-  target: 'pino-axiom',
-  options: {
-    orgId: 'YOUR-ORG-ID', 
-    token: 'YOUR-TOKEN', 
-    dataset: 'YOUR-DATASET', 
-  },
-})
-pino(transport)
-```
-
-<a id="pino-opentelemetry-transport"></a>
-### pino-opentelemetry-transport
-
-[pino-opentelemetry-transport](https://www.npmjs.com/package/pino-opentelemetry-transport) is a transport that will forward logs to an [OpenTelemetry log collector](https://opentelemetry.io/docs/collector/) using [OpenTelemetry JS instrumentation](https://opentelemetry.io/docs/instrumentation/js/).
-
-```javascript
-const pino = require('pino')
-
-const transport = pino.transport({
-  target: 'pino-opentelemetry-transport',
-  options: {
-    resourceAttributes: {
-      'service.name': 'test-service',
-      'service.version': '1.0.0'
-    }
-  }
-})
-
-pino(transport)
-```
-
-Documentation on running a minimal example is available in the [README](https://github.com/Vunovati/pino-opentelemetry-transport#minimalistic-example).
-
-<a id="@axiomhq/pino"></a>
-### @axiomhq/pino
-
-[@axiomhq/pino](https://www.npmjs.com/package/@axiomhq/pino) is the official [Axiom](https://axiom.co/) transport for Pino, using [axiom-js](https://github.com/axiomhq/axiom-js).
-
-```javascript
-import pino from 'pino';
-
-const logger = pino(
-  { level: 'info' },
-  pino.transport({
-    target: '@axiomhq/pino',
-    options: {
-      dataset: process.env.AXIOM_DATASET,
-      token: process.env.AXIOM_TOKEN,
-    },
-  }),
-);
-```
-
-then you can use the logger as usual:
-
-```js
-logger.info('Hello from pino!');
-```
-
-For further examples, head over to the [examples](https://github.com/axiomhq/axiom-js/tree/main/examples/pino) directory.
-
-<a id="pino-discord-webhook"></a>
-### pino-discord-webhook
-
-[pino-discord-webhook](https://github.com/fabulousgk/pino-discord-webhook) is a  Pino v7+ compatible transport to forward log events to a [Discord](http://discord.com) webhook from a dedicated worker. 
-
-```js
-import pino from 'pino'
-
-const logger = pino({
-  transport: {
-    target: 'pino-discord-webhook',
-    options: {
-      webhookUrl: 'https://discord.com/api/webhooks/xxxx/xxxx',
-    }
-  }
-})
-```
-
-<a id="pino-logfmt"></a>
-### pino-logfmt
-
-[pino-logfmt](https://github.com/botflux/pino-logfmt) is a Pino v7+ transport that formats logs into [logfmt](https://brandur.org/logfmt). This transport can output the formatted logs to stdout or file.
-
-```js
-import pino from 'pino'
-
-const logger = pino({
-  transport: {
-    target: 'pino-logfmt'
-  }
-})
-```
-
 <a id="pino-telegram-webhook"></a>
 ### pino-telegram-webhook
 
@@ -1093,6 +1141,17 @@ logger.error('<b>test log!</b>');
 
 The `extra` parameter is optional. Parameters that the method [`sendMessage`](https://core.telegram.org/bots/api#sendmessage) supports can be passed to it.
 
+<a id="pino-websocket"></a>
+### pino-websocket
+
+[pino-websocket](https://www.npmjs.com/package/@abeai/pino-websocket) is a transport that will forward each log line to a websocket server.
+
+```sh
+$ node app.js | pino-websocket -a my-websocket-server.example.com -p 3004
+```
+
+For full documentation of command line switches read the [README](https://github.com/abeai/pino-websocket#readme).
+
 <a id="pino-yc-transport"></a>
 ### pino-yc-transport
 
@@ -1120,29 +1179,6 @@ logger.error(new Error("error"));
 logger.fatal("fatal");
 ```
 
-<a id="macfja-pino-fingers-crossed"></a>
-### @macfja/pino-fingers-crossed
-
-[@macfja/pino-fingers-crossed](https://github.com/MacFJA/js-pino-fingers-crossed) is a Pino v7+ transport that holds logs until a log level is reached, allowing to only have logs when it matters.
-
-```js
-const pino = require('pino');
-const { default: fingersCrossed, enable } = require('@macfja/pino-fingers-crossed')
-
-const logger = pino(fingersCrossed());
-
-logger.info('Will appear immedialty')
-logger.error('Will appear immedialty')
-
-logger.setBindings({ [enable]: 50 })
-logger.info('Will NOT appear immedialty')
-logger.info('Will NOT appear immedialty')
-logger.error('Will appear immedialty as well as the 2 previous messages') // error log are level 50
-logger.info('Will NOT appear')
-logger.info({ [enable]: false }, 'Will appear immedialty')
-logger.info('Will NOT appear')
-```
-
 <a id="communication-between-pino-and-transport"></a>
 ## Communication between Pino and Transports
 Here we discuss some technical details of how Pino communicates with its [worker threads](https://nodejs.org/api/worker_threads.html).
diff --git a/lib/transport.js b/lib/transport.js
index e768d35..8b5b48a 100644
--- a/lib/transport.js
+++ b/lib/transport.js
@@ -17,11 +17,12 @@ function setupOnExit (stream) {
   })
 }
 
-function buildStream (filename, workerData, workerOpts) {
+function buildStream (filename, workerData, workerOpts, sync) {
   const stream = new ThreadStream({
     filename,
     workerData,
-    workerOpts
+    workerOpts,
+    sync
   })
 
   stream.on('ready', onReady)
@@ -71,7 +72,7 @@ function flush (stream) {
 }
 
 function transport (fullOptions) {
-  const { pipeline, targets, levels, dedupe, worker = {}, caller = getCallers() } = fullOptions
+  const { pipeline, targets, levels, dedupe, worker = {}, caller = getCallers(), sync = false } = fullOptions
 
   const options = {
     ...fullOptions.options
@@ -126,7 +127,7 @@ function transport (fullOptions) {
 
   options.pinoWillSendConfig = true
 
-  return buildStream(fixTarget(target), options, worker)
+  return buildStream(fixTarget(target), options, worker, sync)
 
   function fixTarget (origin) {
     origin = bundlerOverrides[origin] || origin


Test patch:
diff --git a/test/browser-transmit.test.js b/test/browser-transmit.test.js
index 860524b..d5063ca 100644
--- a/test/browser-transmit.test.js
+++ b/test/browser-transmit.test.js
@@ -367,3 +367,51 @@ test('does not log below configured level', ({ end, is }) => {
 
   end()
 })
+
+test('silent level prevents logging even with transmit', ({ end, fail }) => {
+  const logger = pino({
+    level: 'silent',
+    browser: {
+      write () {
+        fail('no data should be logged by the write method')
+      },
+      transmit: {
+        send () {
+          fail('no data should be logged by the send method')
+        }
+      }
+    }
+  })
+
+  Object.keys(pino.levels.values).forEach((level) => {
+    logger[level]('ignored')
+  })
+
+  end()
+})
+
+test('does not call send when transmit.level is set to silent', ({ end, fail, is }) => {
+  let c = 0
+  const logger = pino({
+    level: 'trace',
+    browser: {
+      write () {
+        c++
+      },
+      transmit: {
+        level: 'silent',
+        send () {
+          fail('no data should be logged by the transmit method')
+        }
+      }
+    }
+  })
+
+  const levels = Object.keys(pino.levels.values)
+  levels.forEach((level) => {
+    logger[level]('message')
+  })
+
+  is(c, levels.length, 'write must be called exactly once per level')
+  end()
+})
diff --git a/test/transport/syncTrue.test.js b/test/transport/syncTrue.test.js
new file mode 100644
index 0000000..1d34ebc
--- /dev/null
+++ b/test/transport/syncTrue.test.js
@@ -0,0 +1,55 @@
+'use strict'
+
+const pino = require('../..')
+const { join } = require('node:path')
+const { readFileSync } = require('node:fs')
+const { test } = require('tap')
+const { file } = require('../helper')
+
+test('thread-stream sync true should log synchronously', async (t) => {
+  const outputPath = file()
+
+  function getOutputLogLines () {
+    return (readFileSync(outputPath)).toString().trim().split('\n').map(JSON.parse)
+  }
+
+  const transport = pino.transport({
+    target: join(__dirname, '..', 'fixtures', 'to-file-transport.js'),
+    options: { destination: outputPath, flush: true },
+    sync: true
+  })
+  const instance = pino(transport)
+
+  var value = { message: 'sync' }
+  instance.info(value)
+  instance.info(value)
+  instance.info(value)
+  instance.info(value)
+  instance.info(value)
+  instance.info(value)
+  let interrupt = false
+  let flushData
+  let loopCounter = 0
+
+  // Start a synchronous loop
+  while (!interrupt && loopCounter < (process.env.MAX_TEST_LOOP_ITERATION || 20000)) {
+    try {
+      loopCounter++
+      const data = getOutputLogLines()
+      flushData = data
+      if (data) {
+        interrupt = true
+        break
+      }
+    } catch (error) {
+      // File may not exist yet
+      // Wait till MAX_TEST_LOOP_ITERATION iterations
+    }
+  }
+
+  if (!interrupt) {
+    throw new Error('Sync loop did not get interrupt')
+  }
+
+  t.equal(flushData.length, 6)
+})