Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support for mix&match pipelines #1954

Merged
merged 20 commits into from
May 13, 2024

Conversation

dbacarel
Copy link
Contributor

@dbacarel dbacarel commented Apr 27, 2024

This PR wants to address the use-case of mix matching pipelines and targets, see discussion #1302.
Currently only pipeline or targets can be defined.

As a stretch, the current prototype proposes to introduce support for named pipelines that can be referred within the definition of a target.

  const transport = pino.transport({
    targets: [
      {
        target: join(__dirname, '..', 'fixtures', 'to-file-transport.js'),
        options: { destination: '/path/to/A'},
        pipeline: 'pipelineA'
      },
      {
        target: join(__dirname, '..', 'fixtures', 'to-file-transport.js'),
        options: { destination: '/path/to/B' }
      },
      {
        target: join(__dirname, '..', 'fixtures', 'to-file-transport.js'),
        options: { destination: '/path/to/C'},
        pipeline: 'pipelineB'
      }
    ],
    pipelines: {
      pipelineA: [
        {
          target: join(__dirname, '..', 'fixtures', 'transform-1.js')
        },
        {
          target: join(__dirname, '..', 'fixtures', 'transform-2.js')
        }
      ],
      pipelineB: [
        {
          target: join(__dirname, '..', 'fixtures', 'transform-3.js')
        },
        {
          target: join(__dirname, '..', 'fixtures', 'transform-4.js')
        }
      ]
    }
  })

More details will follow

Update

The idea of named pipelines was abandoned.
This PR extends targets to support mixing in pipeline definitions within the array of transport configurations

Example:

const pino = require('pino')
const transport = pino.transport({
  targets: [{
    level: 'info',
    target: 'pino-pretty' // must be installed separately
  }, {
    level: 'trace',
    target: 'pino/file',
    options: { destination: '/path/to/store/logs' }
  }, {
    pipeline: [{
      target: 'pino-syslog' // must be installed separately
    }, {
      target: 'pino-socket' // must be installed separately
    }]
  }
  ]
})
pino(transport)

@mcollina
Copy link
Member

I think this is too complex, would avoid the "naming" altogether.

@dbacarel
Copy link
Contributor Author

dbacarel commented May 1, 2024

One of the advantages that I saw in adopting named pipeline would have been enabling the implementation of one input, multiple outputs, similarly to tee. Potentially, the transformation for an input would have been produced only once (for a given pipeline) and only then passed through to the destination target(s).

On the user side, this simplifies the configuration since the pipeline requires to be defined only once.
On the implementation side, it would have been easier to identify identical pipes, if the optimization mentioned above were to be implemented.

Besides the technical aspects, I also understand that it also comes down to how common such use case is so, I don't feel like pushing this idea too much.

@mcollina
Copy link
Member

mcollina commented May 1, 2024

I feel most devs won't understand that.

@dbacarel dbacarel changed the title Adding support for named, mix&match pipelines Adding support for mix&match pipelines May 4, 2024
@dbacarel
Copy link
Contributor Author

dbacarel commented May 4, 2024

Pity but fair enough.

I'll revert the changes related to the named pipelines in favor to a configuration like the following one, looks intuitive enough to me.

const pino = require('pino')
const transport = pino.transport({
  targets: [{
    level: 'info',
    target: 'pino-pretty' // must be installed separately
  }, {
    level: 'trace',
    target: 'pino/file',
    options: { destination: '/path/to/store/logs' }
  }, {
    pipeline: [{
      target: 'pino-syslog' // must be installed separately
    }, {
      target: 'pino-socket' // must be installed separately
    }]
  }
  ]
})
pino(transport)

dbacarel and others added 5 commits May 5, 2024 11:52
- Implemented support for mixed target&pipeline definitions  within `targets` in `transport.js`
- Merged logic from both `worker.js` and `worker-pipeline.js` into `worker.js`
- Fixed `pipeline.test.js`
- Fixed docs to reflect changes above

TODO:
 - Remove `worker-pipeline.js`
 - Fix `transport.js` to use only `worker.js`
 - Fix related docs
 - Fix UTs
- Updated docs to remove mentions of `worker-pipeline.js`
- Fixed failing UTs
- Fixed `transport.js` to use only `worker.js` also when `pipeline` is defined
- Fixed `worker.js` to work properly when only `pipeline` is defined
@dbacarel dbacarel marked this pull request as ready for review May 5, 2024 11:46
@dbacarel
Copy link
Contributor Author

dbacarel commented May 5, 2024

Removing the Draft mark as the code is now in a more decent shape for some feedback.

Besides the implementation of the support for pipelines illustrated above, I also thought to get rid of worker-pipeline and unify the logic into one worker only, worker.js.

The following schema illustrates how the streams in targets with pipelines and pipeline are handled in the new worker

┌──────────────────────────────────────────────────┐   ┌─────┐                
│                                                  │   │     │                
│                                                  │   │  p  │                
│                   target    ┌───────────────┐    │   │  i  │                
│                 ──────────► │               │    │   │  n  │                
│   targets         target    │  pino.        │    │   │  o  │                
│ ────────────►   ──────────► │  multistream  ├────┼──►│  .  │       source   
│                   target    │               │    │   │  m  │         │      
│                 ──────────► └───────────────┘    │   │  u  │         │write 
│                                                  │   │  l  │         ▼      
│                  pipeline   ┌───────────────┐    │   │  t  │      ┌────────┐
│                 ──────────► │ PassThrough   ├────┼──►│  i  ├──────┤        │
│                             └───────────────┘    │   │  s  │ write│ Thread │
│                                                  │   │  t  │◄─────┤ Stream │
│                  pipeline   ┌───────────────┐    │   │  r  │      │        │
│                 ──────────► │ PassThrough   ├────┼──►│  e  │      └────────┘
│                             └───────────────┘    │   │  a  │                
│                                                  │   │  m  │                
│                                                  │   │     │                
│                        OR                        │   │     │                
│                                                  │   │     │                
│  pipeline     ┌──────────────┐                   │   │     │                
│ ────────────► │ PassThrough  ├───────────────────┼──►│     │                
│               └──────────────┘                   │   │     │                
│                                                  │   │     │                
└──────────────────────────────────────────────────┘   └─────┘                

There're probably some naïve decisions here with impacts I don't see, for example pipelines defined via pipeline property now need to go through an additional stream layer represented by pino.multistream.

@mcollina
Copy link
Member

mcollina commented May 7, 2024

pino.multistream() has a few additional consideration (such as the minimum level), that makes this architecture a bit more fragile.

I would recommend:

  • moreving the 2nd multistream for all targets, just reusing the top one.
  • add a special cases for 1 target or 1 pipeline that bypass all the heavy machinery, essentially being used by ThreadStream directly (same as it is right now).

@dbacarel
Copy link
Contributor Author

dbacarel commented May 9, 2024

pino.multistream() has a few additional consideration (such as the minimum level), that makes this architecture a bit more fragile.

Yes, that's something I wanted follow up a bit as I wasn't sure about the implications of logging level vs pipelines in this context. I'll read more about this. Thanks for the heads up.

About the recommended changes:

moreving the 2nd multistream for all targets, just reusing the top one.

There is actually one layer of pino.multistream, the current state looks in fact like this

┌────────────────────────────────────────────────┐     ┌─────┐                
│                                                │     │     │                
│                                                │     │     │                
│                   target                       │     │     │                
│               │ ───────────────────────────────┼────►│     │                
│   targets     │   target                       │     │  p  │                
│ ────────────► │ ───────────────────────────────┼────►│  i  │       source   
│               │   target                       │     │  n  │         │      
│               │ ───────────────────────────────┼────►│  o  │         │write 
│               │                                │     │  .  │         ▼      
│               │  pipeline   ┌───────────────┐  │     │  m  │      ┌────────┐
│               │ ──────────► │ PassThrough   ├──┼────►│  u  ├──────┤        │
│               │             └───────────────┘  │     │  l  │ write│ Thread │
│               │                                │     │  t  │◄─────┤ Stream │
│               │  pipeline   ┌───────────────┐  │     │  i  │      │        │
│               │ ──────────► │ PassThrough   ├──┼────►│  s  │      └────────┘
│                             └───────────────┘  │     │  t  │                
│                                                │     │  r  │                
│                                                │     │  e  │                
│                        OR                      │     │  a  │                
│                                                │     │  m  │                
│  pipeline                   ┌───────────────┐  │     │     │                
│ ───────────────────────────►│ PassThrough   ├──┼────►│     │                
│                             └───────────────┘  │     │     │                
│                                                │     │     │                
└────────────────────────────────────────────────┘     └─────┘                

I drew the wrong schema, my bad.

add a special cases for 1 target or 1 pipeline that bypass all the heavy machinery, essentially being used by ThreadStream directly (same as it is right now).

Makes sense, will do.

- A level can now be defined for pipelines defined inside 'targets'
- Added UT in 'pipeline.test.js' to check expected behaviour with 'dedupe'
@dbacarel
Copy link
Contributor Author

dbacarel commented May 11, 2024

So

  • moreving the 2nd multistream for all targets, just reusing the top one.
    No actions here, there was already one single layer of multistream involved. My drawing was wrong.

  • add a special cases for 1 target or 1 pipeline that bypass all the heavy machinery, essentially being used by ThreadStream directly (same as it is right now).
    I added a check here to skip it in cases either one target or one pipeline only is defined in targets.

pino.multistream() has a few additional consideration (such as the minimum level), that makes this architecture a bit more fragile.

Now regarding this, I thought that we could introduce the optional level property to pipeline definitions as well, in this way multistream would know how to properly sort them, related #1832
I added this UT

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@mcollina mcollina requested a review from jsumners May 12, 2024 11:35
@mcollina mcollina merged commit 8a20d79 into pinojs:main May 13, 2024
2 checks passed
@jsumners
Copy link
Member

Sorry. I didn't have a chance over the weekend. I was going to try and review today.

@dbacarel
Copy link
Contributor Author

Thank you 🥳

drazisil added a commit to rustymotors/server that referenced this pull request Jun 3, 2024
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [pino](https://getpino.io)
([source](https://togithub.com/pinojs/pino)) | [`^8.18.0` ->
`^9.0.0`](https://renovatebot.com/diffs/npm/pino/8.21.0/9.1.0) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/pino/9.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/pino/9.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/pino/8.21.0/9.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/pino/8.21.0/9.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>pinojs/pino (pino)</summary>

### [`v9.1.0`](https://togithub.com/pinojs/pino/releases/tag/v9.1.0)

[Compare
Source](https://togithub.com/pinojs/pino/compare/v9.0.0...v9.1.0)

#### What's Changed

- fix(transport-stream): Fix import error when using pkg with node v20
by [@&#8203;nagyszabi](https://togithub.com/nagyszabi) in
[pinojs/pino#1949
- Update LTS doc by [@&#8203;jsumners](https://togithub.com/jsumners) in
[pinojs/pino#1955
- Update pino types for browser.formatters by
[@&#8203;KatelynKim](https://togithub.com/KatelynKim) in
[pinojs/pino#1946
- add node v22 to CI by
[@&#8203;mcollina](https://togithub.com/mcollina) in
[pinojs/pino#1953
- Add Platformatic to sponsors by
[@&#8203;mcollina](https://togithub.com/mcollina) in
[pinojs/pino#1956
- Update h3 example by [@&#8203;mcollina](https://togithub.com/mcollina)
in
[pinojs/pino#1968
- Support file URLs when configuring multiple transports by
[@&#8203;haines](https://togithub.com/haines) in
[pinojs/pino#1961
- Adding support for mix\&match pipelines by
[@&#8203;dbacarel](https://togithub.com/dbacarel) in
[pinojs/pino#1954
- apply serializers to args once before asObject or transmit by
[@&#8203;emmyakin](https://togithub.com/emmyakin) in
[pinojs/pino#1971
- build(deps-dev): bump pino-pretty from 10.3.1 to 11.0.0 by
[@&#8203;dependabot](https://togithub.com/dependabot) in
[pinojs/pino#1933
- build(deps): bump sonic-boom from 3.8.1 to 4.0.1 by
[@&#8203;dependabot](https://togithub.com/dependabot) in
[pinojs/pino#1960
- build(deps): bump pino-std-serializers from 6.2.2 to 7.0.0 by
[@&#8203;dependabot](https://togithub.com/dependabot) in
[pinojs/pino#1957
- build(deps-dev): bump tsd from 0.30.7 to 0.31.0 by
[@&#8203;dependabot](https://togithub.com/dependabot) in
[pinojs/pino#1937
- build(deps): bump actions/dependency-review-action from 3 to 4 by
[@&#8203;dependabot](https://togithub.com/dependabot) in
[pinojs/pino#1894
- build(deps): bump pnpm/action-setup from 2.4.0 to 3.0.0 by
[@&#8203;dependabot](https://togithub.com/dependabot) in
[pinojs/pino#1913
- Drop yarn support and update pnpm by
[@&#8203;mcollina](https://togithub.com/mcollina) in
[pinojs/pino#1972
- build(deps): bump thread-stream from 2.7.0 to 3.0.0 by
[@&#8203;dependabot](https://togithub.com/dependabot) in
[pinojs/pino#1959

#### New Contributors

- [@&#8203;nagyszabi](https://togithub.com/nagyszabi) made their first
contribution in
[pinojs/pino#1949
- [@&#8203;haines](https://togithub.com/haines) made their first
contribution in
[pinojs/pino#1961
- [@&#8203;emmyakin](https://togithub.com/emmyakin) made their first
contribution in
[pinojs/pino#1971

**Full Changelog**:
pinojs/pino@v9.0.0...v9.1.0

###
[`v9.0.0`](https://togithub.com/pinojs/pino/compare/v8.21.0...4f8ea32aa69ec94b2fb5561716a7701aec991ce7)

[Compare
Source](https://togithub.com/pinojs/pino/compare/v8.21.0...v9.0.0)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/rustymotors/server).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4zMTMuMSIsInVwZGF0ZWRJblZlciI6IjM3LjM1MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants