<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Benthos Blog</title>
        <link>https://www.benthos.dev/blog</link>
        <description>Benthos Blog</description>
        <lastBuildDate>Mon, 07 Nov 2022 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[What's Next for Benthos?]]></title>
            <link>https://www.benthos.dev/blog/2022/11/07/whats-next</link>
            <guid>https://www.benthos.dev/blog/2022/11/07/whats-next</guid>
            <pubDate>Mon, 07 Nov 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[A summary of what's going on and what's coming up]]></description>
            <content:encoded><![CDATA[<p>A few months ago it was announced that <a href="https://www.benthos.dev/blog/2022/03/03/v4-coming">v4 was coming</a>. Well, that happened... and also <a href="https://github.com/benthosdev/benthos/blob/main/CHANGELOG.md" target="_blank" rel="noopener noreferrer">a bunch more releases</a> since then. Now that the fundamentals have been tidied up considerably we're adding new features and they're coming in hot and heavy (and a bit sticky). Almost entirely parallel to this effort is the work on the new <a href="https://studio.benthos.dev/" target="_blank" rel="noopener noreferrer">Benthos Studio</a>, which is a visual application for creating, modifying and sharing Benthos (and Bloblang) configs.</p>
<p>Things are certainly moving fast. However, we've clearly been lacking in the blog department. To remedy this here's a summary of all the stuff we would have blogged about if we had more time and bother.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="community-growth">Community Growth<a href="https://www.benthos.dev/blog/2022/11/07/whats-next#community-growth" class="hash-link" aria-label="Direct link to Community Growth" title="Direct link to Community Growth">​</a></h2>
<p>Benthos has now surpassed <a href="https://github.com/benthosdev/benthos/graphs/contributors" target="_blank" rel="noopener noreferrer">150 contributors</a>, and between our <a href="https://www.benthos.dev/community">discord and slack communities</a> we're steadily approaching 1,000 gossips, at which point we'll be too mainstream to be considered cool and hip. This site has daily traffic in the thousands and Benthos itself is downloaded around 2,000 times per day. The <a href="https://www.youtube.com/c/Jeffail" target="_blank" rel="noopener noreferrer">Jeffail youtube channel</a>, which features all of our Benthos and stream processing related video content, is also growing steadily in both content and precious subscribers. I'd promise none of this traffic is bots but I actually don't know.</p>
<p>Another major milestone reached is that I watched witlessly as my wife gave birth to a human child, she's never done that before. In order to support the incoherent squawker (and our new child) I took a month away from the project. If you're a keen follower of the open source work going on in Benthos land then you'll be aware that it has historically been a mostly one-person show (me), but I'm thrilled (perhaps a bit sour) to report that during my absence the project carried on at pretty much the same intense pace.</p>
<p>These are all signs that our codebase, community support and developer ecosystems are becoming more decentralised. This trend in growth is entirely organic (besides a few stickers sent to conferences) and mostly based on the volunteer effort of professionals that use Benthos in their daily work. We're also blessed with a number of hobbyists getting involved just because they enjoy it, we've tried sapping the fun out of the project but they just won't go away. For now I'm still retaining absolute control over what gets merged but the bus factor is certainly becoming less significant.</p>
<p>The trends I'm outlining here should be soothing for Benthos fans, we're growing, we're managing the growth just fine, and you can safely bet on the project continuing on that path. Over the years some users (active or prospective) have expressed concern that Benthos does not have an organisation around it with a pot of money, their worry being the longevity of the project is at risk. I've obviously not agreed as I haven't yet sought after such a pot of money (more on that later in this post). Over time it has become easier to shrug those concerns off as we continue to move at a pace that'd easily beat the expectations of any funded operation.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="benthos-studio">Benthos Studio<a href="https://www.benthos.dev/blog/2022/11/07/whats-next#benthos-studio" class="hash-link" aria-label="Direct link to Benthos Studio" title="Direct link to Benthos Studio">​</a></h2>
<p>I've been quietly working on <a href="https://studio.benthos.dev/" target="_blank" rel="noopener noreferrer">Benthos Studio</a> pretty much since the early years of Benthos itself. The idea being a visual editing application to complement the development and running of Benthos configs. What I like about having this exist as an entirely separate application is that the main project is still incentivised to make configuration as easy and intuitive as possible, we can't just rely on visual tooling to plug gaps in ergonomics or observability. This allows Studio to focus on lifting that experience up a few notches as an optional extra.</p>
<p>If you aren't familiar with it then here's a quick video introduction:</p>
<!-- -->
<!-- -->
<div class="container margin-vert--lg"><div class="row row--no-gutters"><div style="width:640px;height:300px" class="col"></div></div></div>
<p>Studio is currently offered as an open beta with new stuff coming in constantly. The main directions we're heading in are:</p>
<ul>
<li>More storage flexibility, including allowing you to use Studio to view and configure streams running in your own local deployments</li>
<li>More execution visibility, better visuals and ability to dig into what's happening within a Benthos configuration</li>
<li>A smoother configuration experience for beginners, including wizards for building new stream pipelines</li>
</ul>
<p>You may also have noticed that Benthos Studio is not open source. This is because I believe Studio is a good bet at putting together a scalable monetisation strategy that complements the goals of the open source work rather than causing friction against it, a sort of golden path for building a business around an existing open source ecosystem. It will take a while to work out which features should be paid for, but there will always be a free tier that provides all the interesting bits.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="monetisation">Monetisation<a href="https://www.benthos.dev/blog/2022/11/07/whats-next#monetisation" class="hash-link" aria-label="Direct link to Monetisation" title="Direct link to Monetisation">​</a></h2>
<p>Uh oh! He said monetisation, bag him! Monetising an open source project is a hefty topic and gets lots of people mad and sweaty, one far end of the spectrum believing it's entirely counter to the open source movement, the other end refusing to take seriously any project that <em>isn't</em> monetised.</p>
<p>The reality is obviously that neither extreme holds merit. People need to eat and when projects reach a certain size the time required to maintain them goes well beyond the scope of a fun hobby, but conversely there's nothing preventing a non-funded project from outperforming a funded one even with enterpisey things like support and product stability. A common feedback we get is that our stability and support goes well beyond what people are used to even with paid products. So, given that and all the stuff I outlined at the beginning of this post, do we even need funding?</p>
<p>Well yes, we do. In fact, as the main driving force behind Benthos I've been funded since day one, just not directly. I get returns from my Benthos work in the form of job opportunities that feed back into the project, support contracts, issue bounties and sponsorships dotted throughout. This is a similar story for many open source maintainers, where if you keep yourself from burning out then a project can get very far indeed without needing to commit to a more scalable business model.</p>
<p>This set up has been working out just fine but it's far from ideal. I spend a lot of energy keeping these gigs going which could be much better spent growing a team around a paid product. This team would then steward and give back to the open source community and we would all win, the only losers being people that hate teams, products or the abstract concept of winning, or me as a person.</p>
<p>Many may have jumped straight into the deep end and asked for VC funding up front. If/when we choose to go down that route we're locked in for the whole ride, where in abstract terms if that aforementioned golden path of monetisation gives us problems then we're going to be pressured into following a new path that prioritises the venture and not the open source. Well, that's life, every decision has risks and in reality we'd still do well as a community in any outcome, but for now I've been exploring that golden path and seeing how far I can get on my own.</p>
<p>So that's how we got to here, we have a ship that seems pretty much sea worthy and without any obligations or milestones to deliver. Dare I remain bootstrapped? Perhaps I should join a fleet? Do we finally rocket boost these salty decks and aim for the stars? Is that a dumb metaphor? Well keep checking this blog to find out a few months after all the Discord and Slack users do.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="supporting-the-project">Supporting the Project<a href="https://www.benthos.dev/blog/2022/11/07/whats-next#supporting-the-project" class="hash-link" aria-label="Direct link to Supporting the Project" title="Direct link to Supporting the Project">​</a></h2>
<p>The longer this project remains sustainable without obligation the more we can experiment freely and independently. If you want to help stretch that progress further and maybe help keep us on the golden path then <a href="https://github.com/benthosdev/benthos" target="_blank" rel="noopener noreferrer">get involved in the project</a>, get your organisation to <a href="https://github.com/sponsors/Jeffail" target="_blank" rel="noopener noreferrer">sponsor my work</a>, or consider some of the <a href="https://www.benthos.dev/support#paid-services">paid support options</a> we're currently offering.</p>]]></content:encoded>
            <category>v4</category>
            <category>studio</category>
        </item>
        <item>
            <title><![CDATA[V4 Coming Up]]></title>
            <link>https://www.benthos.dev/blog/2022/03/03/v4-coming</link>
            <guid>https://www.benthos.dev/blog/2022/03/03/v4-coming</guid>
            <pubDate>Thu, 03 Mar 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[How to prepare]]></description>
            <content:encoded><![CDATA[<p>The <a href="https://www.benthos.dev/blog/2021/01/04/v4-roadmap">v4 roadmap</a> was outlined more than a year ago, in that time all the major features planned have been completed and released in backwards compatible ways into v3, leaving only the breaking changes left (the fun stuff).</p>
<p>We're now also at a point where the breaking changes that we want to include in v4 have been completed on a branch, and a migration guide is ready to use <a href="https://www.benthos.dev/docs/guides/migration/v4">which describes how to prepare for v4</a>. Therefore, it seems to me, that we're ready to actually prepare the release.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why">Why<a href="https://www.benthos.dev/blog/2022/03/03/v4-coming#why" class="hash-link" aria-label="Direct link to Why" title="Direct link to Why">​</a></h2>
<p>Benthos follows semantic versioning, which means a major version release is not necessarily an indication of significant improvements to the product, but an indication that things have changed and therefore upgrading should be done with care (and likely some effort). As such, all the major improvements that <em>could</em> have been part of this release (config templates, new plugin APIs, etc) are already part of version 3 and being actively used.</p>
<p>The vast majority of these improvements have been an evolution or consolidation of prior features, which have since become deprecated (and hidden from the documentation). Doing things this way has enabled you to slowly learn about and adopt the nice new goodies whilst also running the old stuff. However, the reality is that the old deprecated features are a maintenance burden. Not only do we need to ensure that a growing number of potentially unused features remain bug free, but these features often frustrate or entirely prevent us from making improvements elsewhere.</p>
<p>As such, after keeping v3 going for more than two years, it feels like it's about the right time for spring cleaning. The absolute top priority of this release is to remove deprecated components, which for people keeping up with the newest features would in theory mean no breaking changes at all. However, since major releases are a rare event (this could possibly be the last one) it also makes sense to use this as an opportunity to change things about Benthos that we feel aren't intuitive.</p>
<p>The biggest of these intentionally breaking changes is the way in which metrics work. Benthos exposes a huge amount of metrics but the names can often be confusing and difficult to understand, and some components expose inconsistent or undocumented metrics. For v4 they have been massively simplified and made consistent, leaning on labels/tags for presenting (optionally) granular series, and allowing full customisation for all metric destination types with a generic <code>mapping</code> field.</p>
<p>The full list of changes we've decided to add are outlined in the <a href="https://www.benthos.dev/docs/guides/migration/v4">the migration guide</a>, which is an attempt at finding a good balance between keeping to a minimal impact for the majority of users, and tackling the biggest culprits of confusion in Benthos land. It's extremely important to stress that at this stage nothing is absolute, we can pull these changes back if they seem to heavy, and likewise we can push further if there's hunger for more. Ultimately, we need feedback in the coming weeks in order to get this right.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="timescales">Timescales<a href="https://www.benthos.dev/blog/2022/03/03/v4-coming#timescales" class="hash-link" aria-label="Direct link to Timescales" title="Direct link to Timescales">​</a></h2>
<p>None of this is set in stone but it currently looks as though we will have a release candidate available for v4 in the coming weeks. You can expect <code>edge</code> tagged docker images to include v4 changes soon, followed by an image tagged <code>4.0.0-rc1</code> and so on, at the same time there will be artifacts you can obtain from the github releases page: <a href="https://github.com/Jeffail/benthos/releases" target="_blank" rel="noopener noreferrer">https://github.com/Jeffail/benthos/releases</a>.</p>
<p>At this stage we'll be looking for general testing as well as feedback on the migration process. If you find yourself in a situation where a feature you rely upon in v3 is gone and you can't find an alternative in v4 then we want to hear about it as soon as possible. There will be a temporary website up with v4 documentation but the URL will change each time the docs are updated, so we'll post them in several of the <a href="https://www.benthos.dev/community">community spaces</a>, make sure you're in one if you're interested in testing.</p>
<p>We'll likely be playing with release candidates for a few weeks, in which time any official releases we put out will be v3 patches for any bug fixes we've added in the meantime. Once we're happy with release candidates the official v4 tag will be pushed, built and the documentation site will be bumped to represent v4. When this happens the domain v3.benthos.dev will be set up to contain the v3 documentation.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="preparing">Preparing<a href="https://www.benthos.dev/blog/2022/03/03/v4-coming#preparing" class="hash-link" aria-label="Direct link to Preparing" title="Direct link to Preparing">​</a></h2>
<p>If you're interested in minimizing the effort to migrate to v4 right now then the first thing worth doing is moving away from any deprecated components in your v3 configs. You can detect them by pulling the latest version of v3 and running the linter with the <code>--deprecated</code> flag:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">benthos lint --deprecated ./configs/*.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This will report any deprecated components and fields that you still have in your configs.</p>
<p>Next, if you're using plugins or have a custom build of Benthos then you need to ensure you're no longer using any of the packages within <code>./lib</code>, all of those packages are being removed in v4 in favour of the new <code>./public</code> packages. The plugin APIs within <code>./lib</code> all have a newer (and better) alternative, but if you were using some of the misc packages as helper libraries then copy them from the v3 branch into your codebase.</p>
<p>The metrics changes are likely to affect almost every deployment, it is recommended that you make the best use of the new labels and rework your dashboards. However, if in your case the dashboards are difficult to change then it is likely easier to use a <code>mapping</code> in your new v4 config to reproduce the metrics series your dashboards currently rely upon. In order to prepare for this it's worth making an inventory of each series you use, the labels they have, and preparing the mapping you'll need. The documentation for the new metrics system can be found here: <a href="https://github.com/Jeffail/benthos/blob/main/website/docs/components/metrics/about.md" target="_blank" rel="noopener noreferrer">https://github.com/Jeffail/benthos/blob/main/website/docs/components/metrics/about.md</a></p>
<p>Finally, it's worth getting familiar with the changes outlined in <a href="https://www.benthos.dev/docs/guides/migration/v4">the migration guide</a>. There are breaking changes in some components, mostly default values being changed in order to make them more intuitive, but they should all be understood before upgrading in order to avoid unintended consequences.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="please-help">Please Help<a href="https://www.benthos.dev/blog/2022/03/03/v4-coming#please-help" class="hash-link" aria-label="Direct link to Please Help" title="Direct link to Please Help">​</a></h2>
<p>If you're interested in helping out then we'd love to get you involved and the best way is to read the migration guide, try out the release candidates, and give us feedback in any of the <a href="https://www.benthos.dev/community">community spaces</a>.</p>
<p>The major concern that we're looking for feedback on is whether the breaking changes are manageable for you, if you have identified things that will significantly hinder your migration then it's important we hear about it as soon as possible. This allows us to triage whether it's worth building tooling to help with the transition, or to potentially roll-back those changes if necessary.</p>]]></content:encoded>
            <category>v4</category>
        </item>
        <item>
            <title><![CDATA[Go Plugins V2 are Ready]]></title>
            <link>https://www.benthos.dev/blog/2021/10/12/new-plugins-stable</link>
            <guid>https://www.benthos.dev/blog/2021/10/12/new-plugins-stable</guid>
            <pubDate>Tue, 12 Oct 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[In case you didn't see the Tweets, Discord posts and Github activity]]></description>
            <content:encoded><![CDATA[<p>The <a href="https://pkg.go.dev/github.com/Jeffail/benthos/v3/public/service" target="_blank" rel="noopener noreferrer">new plugin APIs</a> are ready to use, are being used, and <a href="https://youtu.be/uH6mKw-Ly0g" target="_blank" rel="noopener noreferrer">here's a video of them in action</a>.</p>
<!-- -->
<!-- -->
<div class="container margin-vert--lg"><div class="row row--no-gutters"><div style="width:640px;height:300px" class="col"></div></div></div>
<p>The full API docs can be found at <a href="https://pkg.go.dev/github.com/Jeffail/benthos/v3/public" target="_blank" rel="noopener noreferrer">pkg.go.dev/github.com/Jeffail/benthos/v3/public</a>, and there's an example repository demonstrating a few different component plugin types at <a href="https://github.com/benthosdev/benthos-plugin-example" target="_blank" rel="noopener noreferrer">github.com/benthosdev/benthos-plugin-example</a>.</p>]]></content:encoded>
            <category>v4</category>
            <category>plugins</category>
        </item>
        <item>
            <title><![CDATA[Preview: Go Plugins V2 and Config Templates]]></title>
            <link>https://www.benthos.dev/blog/2021/06/02/new-plugins-and-templates</link>
            <guid>https://www.benthos.dev/blog/2021/06/02/new-plugins-and-templates</guid>
            <pubDate>Wed, 02 Jun 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[It's ready, now we need test subjects]]></description>
            <content:encoded><![CDATA[<p>I need help, attention and affirmation, and therefore it's time for a development update. Around five months ago I posted a <a href="https://www.benthos.dev/blog/2021/01/04/v4-roadmap">roadmap for Benthos v4</a> that included some utterly unattainable goals that only a super human could achieve.</p>
<p>Now that most of those features are ready to test, namely a new plugins API and config templating, I'm looking for people to try them out and give feedback. Please read on if that sounds like fun to you, or also if it doesn't sound fun but you intend to do it anyway.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="config-templates">Config Templates<a href="https://www.benthos.dev/blog/2021/06/02/new-plugins-and-templates#config-templates" class="hash-link" aria-label="Direct link to Config Templates" title="Direct link to Config Templates">​</a></h2>
<p>The new config templates functionality allows you to define parameterised templates for Benthos configuration snippets. These templates can then be imported with a cli flag and used in Benthos configs like native Benthos components.</p>
<p>This is going to be super useful in situations where you have commonly used configuration patterns with small differences that prevent you from using resources.</p>
<p>The current state of templates is that they'll be included in the next release as an experimental feature, meaning any aspect of this functionality is subject to change outside of major version releases. This includes the config spec of templates, how they work, and so on.</p>
<p>Defining a template looks roughly like this:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> log_message</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> processor</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">summary</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Print a log line that shows the contents of a message.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">fields</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> level</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">description</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> The level to log at.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> string</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">default</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> INFO</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">mapping</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">  root.log.level = this.level</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">  root.log.message = "${! content() }"</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">  root.log.fields.metadata = "${! meta() }"</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">  root.log.fields.error = "${! error() }"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>And you're able to import templates with the <code>-t</code> flag:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">benthos -t ./templates/foo.yaml -c ./config.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>And using it in a config looks like any other component:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">pipeline</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">processors</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">log_message</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">level</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ERROR</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>To find out more about configuration templates, including how to try them out, check out <a href="https://www.benthos.dev/docs/configuration/templating">the new templates page</a>. More importantly, you can give feedback on them <a href="https://github.com/Jeffail/benthos/discussions/785" target="_blank" rel="noopener noreferrer">in this Github discussion</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-v2-go-plugins-api">The V2 Go Plugins API<a href="https://www.benthos.dev/blog/2021/06/02/new-plugins-and-templates#the-v2-go-plugins-api" class="hash-link" aria-label="Direct link to The V2 Go Plugins API" title="Direct link to The V2 Go Plugins API">​</a></h2>
<p>Benthos has had Go plugins for a while now and they're fairly well received. However, they can sometimes be confusing as they expose Benthos internals that aren't necessary to understand as plugin authors.</p>
<p>It was also an issue for me as a maintainer that the current plugin APIs hook directly into Benthos packages that have no business being public. This makes it extra difficult to improve the service without introducing breaking changes.</p>
<p>The new APIs are simpler, more powerful (in the ways that matter), add milk after the water, and most importantly are air-gapped from Benthos internals so that they can evolve independently. Here's a sneaky glance of what a processor plugin looks like:</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> ReverseProcessor </span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	logger </span><span class="token operator" style="color:#393A34">*</span><span class="token plain">service</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Logger</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">func</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">r </span><span class="token operator" style="color:#393A34">*</span><span class="token plain">ReverseProcessor</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">Process</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ctx context</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Context</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> m </span><span class="token operator" style="color:#393A34">*</span><span class="token plain">service</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Message</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token operator" style="color:#393A34">*</span><span class="token plain">service</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Message</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token builtin">error</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	bytesContent</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> err </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> m</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">AsBytes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> err </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> err</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	newBytes </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">make</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token builtin">byte</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">bytesContent</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> i</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> b </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">range</span><span class="token plain"> bytesContent </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		newBytes</span><span class="token punctuation" style="color:#393A34">[</span><span class="token function" style="color:#d73a49">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">newBytes</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">-</span><span class="token plain">i</span><span class="token operator" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> b</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> bytes</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Equal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">newBytes</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> bytesContent</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		r</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">logger</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Infof</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Woah! This is like totally a palindrome: %s"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> bytesContent</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	m</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">SetBytes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">newBytes</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token operator" style="color:#393A34">*</span><span class="token plain">service</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Message</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">m</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">func</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">r </span><span class="token operator" style="color:#393A34">*</span><span class="token plain">ReverseProcessor</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">Close</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ctx context</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Context</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token builtin">error</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">func</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	err </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> service</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">RegisterProcessor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token string" style="color:#e3116c">"reverse"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> service</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">NewConfigSpec</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">func</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">conf </span><span class="token operator" style="color:#393A34">*</span><span class="token plain">service</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">ParsedConfig</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> mgr </span><span class="token operator" style="color:#393A34">*</span><span class="token plain">service</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Resources</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">service</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Processor</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token builtin">error</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">ReverseProcessor</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">logger</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> mgr</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Logger</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> err </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token function" style="color:#d73a49">panic</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">err</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	service</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">RunCLI</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>You can play around with these APIs right now by pulling the latest commit with:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">go get -u github.com/Jeffail/benthos/v3@master</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>And you can find more examples along with the API docs at <a href="https://pkg.go.dev/github.com/Jeffail/benthos/v3/public/service" target="_blank" rel="noopener noreferrer">pkg.go.dev</a>.</p>
<p>The package will remain in an experimental state under <code>public/x/service</code> for a month or so, and once it's "ready" (I'm personally happy with it) then it'll be moved to <code>public/service</code> and will be considered stable.</p>
<p>The goal is to allow everyone to migrate to the new APIs whilst still supporting the old ones, and then when Benthos V4 is tagged the old ones will vanish and we're no longer blocked on them.</p>
<p>Similar to the templates there is <a href="https://github.com/Jeffail/benthos/discussions/754" target="_blank" rel="noopener noreferrer">a Github discussion open for feedback</a>. Be honest, be brutal.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="join-the-community">Join the Community<a href="https://www.benthos.dev/blog/2021/06/02/new-plugins-and-templates#join-the-community" class="hash-link" aria-label="Direct link to Join the Community" title="Direct link to Join the Community">​</a></h2>
<p>I've been babbling on for months so if this stuff is news to you then you're clearly out of the loop. Worry not, for you can remedy the situation by joining one or more of our <a href="https://www.benthos.dev/community">glorious community spaces</a>.</p>]]></content:encoded>
            <category>v4</category>
            <category>plugins</category>
            <category>templates</category>
            <category>roadmap</category>
        </item>
        <item>
            <title><![CDATA[Cross Post: We're Bringing Simple Back (to Streaming)]]></title>
            <link>https://www.benthos.dev/blog/2021/03/09/redpanda</link>
            <guid>https://www.benthos.dev/blog/2021/03/09/redpanda</guid>
            <pubDate>Tue, 09 Mar 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[(Cross-posted with https://vectorized.io/blog/benthos/)]]></description>
            <content:encoded><![CDATA[<p>(Cross-posted with <a href="https://vectorized.io/blog/benthos/" target="_blank" rel="noopener noreferrer">https://vectorized.io/blog/benthos/</a>)</p>
<p>Combining the power of Redpanda and Benthos for your streaming needs is so simple that this blog post is almost over already.</p>
<p><a href="https://www.benthos.dev/" target="_blank" rel="noopener noreferrer">Benthos</a> is an open source stream processor that provides data mapping, filtering, hydration and enrichment capabilities across a wide range of connectors. It is driven by a minimal, declarative configuration spec, and with a transaction based architecture it eliminates the development effort of building resilient stream processing pipelines.</p>
<p>Likewise, with its simplicity and high performance, Redpanda eliminates the operational effort of data persistence and availability by providing a Kafka-compatible streaming platform without the moving parts.</p>
<p>With so much taken care of you're well in for a boring, uneventful time when you combine the two. Make sure you've grabbed a copy of both services, full instructions can be found in the <a href="https://www.benthos.dev/docs/guides/getting_started" target="_blank" rel="noopener noreferrer">getting started guide for Benthos</a> and <a href="https://vectorized.io/docs" target="_blank" rel="noopener noreferrer">the Redpanda docs</a>. In this post we'll be running them with Docker so we'll start by pulling both images:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">docker pull vectorized/redpanda:latest</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">docker pull jeffail/benthos:latest</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>We can then create a new network for the services to connect with:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">docker network create -d bridge redpandanet</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Next, run Redpanda in the background, we'll go with a single node for now:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">docker run -d \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --network redpandanet \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name redpanda \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  -p 9092:9092 \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  vectorized/redpanda redpanda start \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --reserve-memory 0M \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --overprovisioned \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --smp 1 \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --memory 1G \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --advertise-kafka-addr redpanda:9092</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>In order to send data to Redpanda with Benthos we'll need to create a config, starting off with a simple Stdin to Kafka pipeline, copy the following config into a file <code>producer.yaml</code>:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">input</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">stdin</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">output</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">kafka</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">addresses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"> redpanda</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">9092</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">topic</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> topic_A</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Pro tip: You can also use Benthos itself to generate a config like this with <code>docker run --rm jeffail/benthos create stdin//kafka &gt; ./producer.yaml</code>.</p>
<p>And now run Benthos by adding the config as a Docker volume, along with a pseudo-TTY for writing our messages:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">docker run --rm -it \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --network redpandanet \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  -v $(pwd)/producer.yaml:/benthos.yaml \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  jeffail/benthos</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This will open an interactive shell where you can write in some data to send. Benthos will gobble up anything you throw at it, try mixing structured and unstructured messages, ending each message with a newline:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">{"id":"1","data":"a structured message"}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">but this here ain't structured at all!</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">[{"id":"2"},"also structured in a different (but totally valid) way"]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>When you're finished hit CTRL+C and it'll exit.</p>
<p>Next, let's try reading that data back out from Redpanda, this time let's also add a <a href="https://www.benthos.dev/docs/components/processors/about" target="_blank" rel="noopener noreferrer">processor</a> in order to mutate our data, copy the following into a file <code>consumer.yaml</code>:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">input</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">kafka</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">addresses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"> redpanda</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">9092</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">topics</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"> topic_A </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">consumer_group</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> example_group</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">pipeline</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">processors</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">bloblang</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">        root.doc = this | content().string()</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">        root.length = content().length()</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">        root.topic = meta("kafka_topic")</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">output</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">stdout</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>And run it with our new config, and without the pseudo-TTY this time:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">docker run --rm \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --network redpandanet \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  -v $(pwd)/consumer.yaml:/benthos.yaml \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  jeffail/benthos</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Now you should see it print mutated versions of the messages you sent to Stdout:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">{"doc":{"data":"a structured message","id":"1"},"length":40,"topic":"topic_A"}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">{"doc":"but this here ain't structured at all!","length":38,"topic":"topic_A"}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">{"doc":[{"id":"2"},"also structured in a different (but totally valid) way"],"length":69,"topic":"topic_A"}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <a href="https://www.benthos.dev/docs/components/processors/bloblang" target="_blank" rel="noopener noreferrer">Bloblang processor</a> in our consumer config has remapped the original message to a new field <code>doc</code>, first attempting to extract it as a structured document, but falling back to a stringified version of it when it's unstructured. We've also added a field <code>length</code> which contains the length of the original message, and <code>topic</code> which contains the Kafka topic the message was consumed from.</p>
<p>That's it for now, if you're still hungry for more then check out the Benthos website at <a href="https://www.benthos.dev/" target="_blank" rel="noopener noreferrer">https://www.benthos.dev</a>, and you can learn more about the Benthos mapping language Bloblang <a href="https://www.benthos.dev/docs/guides/bloblang/about" target="_blank" rel="noopener noreferrer">in this guide</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[First Look at the V4 Roadmap]]></title>
            <link>https://www.benthos.dev/blog/2021/01/04/v4-roadmap</link>
            <guid>https://www.benthos.dev/blog/2021/01/04/v4-roadmap</guid>
            <pubDate>Mon, 04 Jan 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[Well, it's roadmapish]]></description>
            <content:encoded><![CDATA[<p>Benthos has been at major version 3 for over a year now, and I consider it to be a pretty cool achievement that given <a href="https://github.com/Jeffail/benthos/blob/master/CHANGELOG.md" target="_blank" rel="noopener noreferrer">all the dope features added</a> we've managed to keep both the Benthos config spec and APIs fully backwards compatible.</p>
<p>However, eventually it would be nice to cut a new major release and prune all of the dead weight that has accumulated during this time. Since major version releases don't come often I wanted to be sure that we've considered and planned any other potential breaking changes that could be bundled along with it.</p>
<p>Up until now Benthos has never had a roadmap or really any plan beyond just building what we want to use or want to build, this is known in the industry as attention-span-driven development. Alas, if we're going to get mileage out of version 4 then <em>some</em> planning is necessary, and I figured we might as well put together our very first roadmap.</p>
<p>A few months ago I <a href="https://github.com/Jeffail/benthos/issues/503" target="_blank" rel="noopener noreferrer">asked for feedback</a>, I already had my own wish list of things to change in the next major release but I wanted to give you all an opportunity to factor in your own use cases. I've attempted to capture all of the feedback and create issues for the stuff that's achievable, then I marked the issues that require breaking changes and added them to my roadmap plans. I think it's currently in a state that works for me and is something deliverable, therefore I think it's now worth sharing and allowing you all to help shape it further.</p>
<p>Benthos is blessed with a decent and growing number of contributors. However, it's still clear that if I personally were to burn out then the project would pretty much grind to a temporary halt, and therefore my sanity is a higher priority than committing to a rigid plan. Here's a few things to clarify about this roadmap before you get too excited:</p>
<ol>
<li>This isn't final, it's going to mutate over time in order to flex around "everything else" going on.</li>
<li>This isn't everything. The only items included in this roadmap are items that I consider required to have ready for v4. Any features that can definitely be implemented without breaking changes are not included and can be worked on at any time, including right now.</li>
<li>There is no timeline or estimate for this work (by design). If you are blocked on any of the items on this roadmap and aren't able to contribute then please still make sure I'm aware and I'll factor that in, but do not expect promises or commitments (unless you're paying for them).</li>
</ol>
<p>With that made clear and everyone sufficiently bored let's get into the planned work <em>as it currently stands</em>. I've created an issue for every item here where you can read more details beyond my elevator pitch.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="improved-plugin-apis">Improved plugin APIs<a href="https://www.benthos.dev/blog/2021/01/04/v4-roadmap#improved-plugin-apis" class="hash-link" aria-label="Direct link to Improved plugin APIs" title="Direct link to Improved plugin APIs">​</a></h3>
<p><a href="https://github.com/Jeffail/benthos/issues/501" target="_blank" rel="noopener noreferrer">Click here to access the issue.</a></p>
<p>This is by far the biggest item of work I want to establish <em>before</em> v4. The plugin APIs are currently heavily tied into the same component interfaces that are used internally. This means that it's not possible for me to modify the signatures of internal components without breaking the plugin APIs. This has historically put us in awkward positions where in order to make a change that's backwards compatible with both our configuration spec and the plugin APIs we have to implement nasty tricks.</p>
<p>If we're instead able to isolate the plugin APIs with an air gap then it will allow us to iterate on the internal components without impacting the APIs used for plugins.</p>
<p>The plan is to fully implement an isolated (and nicer) plugin API, give everyone a lot of time to try it out, provide feedback, and migrate, all within good time <em>before</em> v4 so that I don't pull the rug out from under current plugin users.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="streams-mode-api-for-resources">Streams Mode API for Resources<a href="https://www.benthos.dev/blog/2021/01/04/v4-roadmap#streams-mode-api-for-resources" class="hash-link" aria-label="Direct link to Streams Mode API for Resources" title="Direct link to Streams Mode API for Resources">​</a></h3>
<p><a href="https://github.com/Jeffail/benthos/issues/566" target="_blank" rel="noopener noreferrer">Click here to access the issue.</a></p>
<p>This one's pretty simple, we want to expand the streams mode APIs to allow the mutation of resources. This is blocked behind a breaking change (to the plugin APIs) as it would require sweeping changes to how resources are accessed.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="input-scheduling-capabilities">Input Scheduling Capabilities<a href="https://www.benthos.dev/blog/2021/01/04/v4-roadmap#input-scheduling-capabilities" class="hash-link" aria-label="Direct link to Input Scheduling Capabilities" title="Direct link to Input Scheduling Capabilities">​</a></h3>
<p><a href="https://github.com/Jeffail/benthos/issues/580" target="_blank" rel="noopener noreferrer">Click here to access the issue.</a></p>
<p>Sometimes it's nice to slow things down, this issue would allow us to configure inputs that are triggered in scheduled bursts rather than realtime streams in order to have them behave similar to batch processors. Implementing this will require a minor review of the input initialization flow, which could potentially lead to breaking changes to the internal API.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="configuration-templating">Configuration Templating<a href="https://www.benthos.dev/blog/2021/01/04/v4-roadmap#configuration-templating" class="hash-link" aria-label="Direct link to Configuration Templating" title="Direct link to Configuration Templating">​</a></h3>
<p><a href="https://github.com/Jeffail/benthos/issues/590" target="_blank" rel="noopener noreferrer">Click here to access the issue.</a></p>
<p>This would allow you to create reusable, parameterized, configuration templates and have them natively supported within Benthos. This issue is pretty dope but also a significant amount of work, it could easily result in breaking changes being required and so I'd like to have this at least planned out and understood before v4.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="improved-logging">Improved Logging<a href="https://www.benthos.dev/blog/2021/01/04/v4-roadmap#improved-logging" class="hash-link" aria-label="Direct link to Improved Logging" title="Direct link to Improved Logging">​</a></h3>
<p><a href="https://github.com/Jeffail/benthos/issues/589" target="_blank" rel="noopener noreferrer">Click here to access the issue.</a></p>
<p>As Benthos has evolved it has gained a few oddities in how logging works. This issue adjusts logging to lean more into structured logging fields and update the configuration defaults to be more sensible. This will mostly impact internal components that create logs, and therefore depends on having the isolated plugin APIs.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="improved-metrics">Improved Metrics<a href="https://www.benthos.dev/blog/2021/01/04/v4-roadmap#improved-metrics" class="hash-link" aria-label="Direct link to Improved Metrics" title="Direct link to Improved Metrics">​</a></h3>
<p><a href="https://github.com/Jeffail/benthos/issues/510" target="_blank" rel="noopener noreferrer">Click here to access the issue.</a></p>
<p>Similar to the logging issue, metrics in Benthos are a bit wonky due to the collision between targets that do and don't support labels/tagging. Since Prometheus and other tag based metrics types seem to be winning out nowadays I think we can flip the defaults to favour tags over long metric names.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="configuration-file-reloading">Configuration File Reloading<a href="https://www.benthos.dev/blog/2021/01/04/v4-roadmap#configuration-file-reloading" class="hash-link" aria-label="Direct link to Configuration File Reloading" title="Direct link to Configuration File Reloading">​</a></h3>
<p><a href="https://github.com/Jeffail/benthos/issues/338" target="_blank" rel="noopener noreferrer">Click here to access the issue.</a></p>
<p>Pretty much self explanatory. I believe this can be implemented without any breaking changes, but it would be good to have it understood (or finished) before v4 just in case.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="tracking-these-features">Tracking these Features<a href="https://www.benthos.dev/blog/2021/01/04/v4-roadmap#tracking-these-features" class="hash-link" aria-label="Direct link to Tracking these Features" title="Direct link to Tracking these Features">​</a></h2>
<p>There's a <a href="https://github.com/Jeffail/benthos/projects/2" target="_blank" rel="noopener noreferrer">project on Github</a> containing all of these issues, but the way that I've configured it is unique as issues aren't necessarily tracked by their progress. Issues in the "Blocked" column are unable to progress without a breaking change and therefore are blocked on v4. Issues in the "Unblocked" column are features that can be worked on, and will either become done if they were able to be completed without breaking changes, or will be put back into "Blocked" once they reach a point where breaking changes are needed.</p>
<p>Once the "Unblocked" column has been emptied, and all of our v4 issues are either blocked or done, that will indicate that we are ready to commit to a new major version release, at which point a v4 branch will be created and that work can be started.</p>
<p>I'm hoping that this will make it easier for me to minimize disruption. Ideally, I want the process of implementing Benthos v4 to be a simple case of deleting old deprecated stuff, and then removing flags/feature toggles in order to make new breaking features the default, having already been implemented and tested. There should be no green field work as part of the new v4 branch.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="whats-next">What's Next<a href="https://www.benthos.dev/blog/2021/01/04/v4-roadmap#whats-next" class="hash-link" aria-label="Direct link to What's Next" title="Direct link to What's Next">​</a></h2>
<p>Make sure you get your thoughts and opinions added to the issues you're interested in. I'm also going to try and open up mini forums over <a href="https://www.benthos.dev/community">our Discord server</a> to get feedback on the plans. If any of these issues are something you'd personally like then please add a thumbs up emoji to it, as that helps me prioritize them.</p>
<p>If you're interested in getting involved then make sure you've joined one or more of our <a href="https://www.benthos.dev/community">glorious community spaces</a>.</p>]]></content:encoded>
            <category>v4</category>
        </item>
        <item>
            <title><![CDATA[Powered Up Workflows]]></title>
            <link>https://www.benthos.dev/blog/2020/08/30/improved-workflows</link>
            <guid>https://www.benthos.dev/blog/2020/08/30/improved-workflows</guid>
            <pubDate>Sun, 30 Aug 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Available in v3.26.0]]></description>
            <content:encoded><![CDATA[<p>For the last few weeks I've been working on improving the workflow story in Benthos. That means reducing the number of processors, simplifying them, and at the same time making them more powerful than before. The new functionality outlined here can be used in the latest release <a href="https://github.com/Jeffail/benthos/releases/tag/v3.26.0" target="_blank" rel="noopener noreferrer">v3.26.0</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-motivation">The Motivation<a href="https://www.benthos.dev/blog/2020/08/30/improved-workflows#the-motivation" class="hash-link" aria-label="Direct link to The Motivation" title="Direct link to The Motivation">​</a></h2>
<p>After similar efforts to <a href="https://www.benthos.dev/blog/2020/05/10/bloblang-beta/">improve the mapping story</a> in Benthos it seemed sensible to target workflows. Specifically, I've added a new <a href="https://www.benthos.dev/docs/components/processors/branch/"><code>branch</code> processor</a> for wrapping child processors in request/result maps, and have reworked the <a href="https://www.benthos.dev/docs/components/processors/workflow/"><code>workflow</code> processor</a> to use them.</p>
<p>If you haven't used workflows in Benthos then there's a section in the new <a href="https://www.benthos.dev/docs/components/processors/workflow/#why-use-a-workflow"><code>workflow</code> processor</a> page outlining why they're useful. In short, when performing multiple integrations within a pipeline such as hitting HTTP services, lambdas, caches, etc, it's best to perform them in parallel when possible in order to reduce the processing latency of messages, organizing these integrations into a topology with a workflow makes it easier to manage their interdependencies and ensure they're executed in the right order.</p>
<p>In the old world you could use the <code>process_dag</code> processor which has child <code>process_map</code> processors, where the mappings were a series of clunky to/from <a href="https://www.benthos.dev/docs/configuration/field_paths/">dot paths</a>, separated into optional and non-optional mappings. There was no way to manually specify the dependency tree, and conditional flows required a separate list of conditions which didn't factor into dependency resolution.</p>
<p>Having such complex and brittle mapping capabilities meant these processors were difficult to document and more so to understand and use.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="leaning-into-bloblang">Leaning into Bloblang<a href="https://www.benthos.dev/blog/2020/08/30/improved-workflows#leaning-into-bloblang" class="hash-link" aria-label="Direct link to Leaning into Bloblang" title="Direct link to Leaning into Bloblang">​</a></h2>
<p>Thankfully, with <a href="https://www.benthos.dev/docs/guides/bloblang/about/">Bloblang</a> now finished it was pretty easy to replace most of the complexity of the workflow mappings for the language itself.</p>
<p>For example, when mapping the request payload for an integration you can express a bunch of different patterns...</p>
<p>Empty request body:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">request_map</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> root = ""</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Sub-object (<code>foo</code>) as request body, if the sub-object doesn't exist (or is null) the integration is abandoned:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">request_map</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> root = this.foo.not_null()</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Sub-object as request body which can be obtained from one of a number of possible paths:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">request_map</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> root = this.(foo </span><span class="token punctuation" style="color:#393A34">|</span><span class="token plain"> bar </span><span class="token punctuation" style="color:#393A34">|</span><span class="token plain"> baz).doc.not_null()</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Conditional integration applies when the <code>type</code> is <code>foo</code>, with an unmodified message as request body:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">request_map</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">  root = if this.type != "foo" {</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">    deleted()</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">  }</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Conditional integration applies when the <code>type</code> is <code>foo</code>, with a sub-object as the request body:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">request_map</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">  root = if this.type == "foo" {</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">    this.foo.not_null()</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">  } else {</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">    deleted()</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">  }</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Similarly, it's possible to express a bunch of things in the result mapping...</p>
<p>Discard the result (the original message is unchanged):</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">result_map</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Place the entire result at a path:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">result_map</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> root.foo = this</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Place the result in a metadata field:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">result_map</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> meta foo = this</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>If you want to see what it looks like there is an <a href="https://www.benthos.dev/cookbooks/enrichments/">enrichment cookbook</a> that demonstrates workflows in action, but there are also smaller examples on the <a href="https://www.benthos.dev/docs/components/processors/workflow/#examples">workflow page</a> such as the following snippet:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">pipeline</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">processors</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">workflow</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">meta_path</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> meta.workflow</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">branches</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">foo</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">request_map</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'root = ""'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">processors</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                  </span><span class="token key atrule" style="color:#00a4db">url</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> TODO</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">result_map</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'root.foo = this'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">bar</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">request_map</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'root = this.body'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">processors</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">lambda</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                  </span><span class="token key atrule" style="color:#00a4db">function</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> TODO</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">result_map</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'root.bar = this'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">baz</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">request_map</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">              root.fooid = this.foo.id</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">              root.barstuff = this.bar.content</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">processors</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">cache</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                  </span><span class="token key atrule" style="color:#00a4db">resource</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> TODO</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                  </span><span class="token key atrule" style="color:#00a4db">operator</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> set</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                  </span><span class="token key atrule" style="color:#00a4db">key</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token tag" style="color:#00009f">!</span><span class="token plain"> json("fooid") </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                  </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token tag" style="color:#00009f">!</span><span class="token plain"> json("barstuff") </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://www.benthos.dev/blog/2020/08/30/improved-workflows#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h2>
<p>The docs have been updated to use these new goodies. Obviously the old processors are still being maintained but in a mostly dormant state. The workflow and branch processors are currently labelled as <code>beta</code>, but their general behavior is stable with the only exceptions being odd edge cases that might arise.</p>
<p>With the behavior of these processors being dramatically simplified I've also been able to simplify the documentation for them, which also means using more space on the page for example configs.</p>
<p>If you have feedback then <a href="https://www.benthos.dev/community/">get the absolute heck in the chat you utter recluse</a>.</p>]]></content:encoded>
            <category>Workflows</category>
        </item>
        <item>
            <title><![CDATA[Bloblang Beta]]></title>
            <link>https://www.benthos.dev/blog/2020/05/10/bloblang-beta</link>
            <guid>https://www.benthos.dev/blog/2020/05/10/bloblang-beta</guid>
            <pubDate>Sun, 10 May 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Available in v3.13]]></description>
            <content:encoded><![CDATA[<p>As of this weekend (and <a href="https://github.com/Jeffail/benthos/releases/tag/v3.13.0" target="_blank" rel="noopener noreferrer">Benthos v3.13</a>) you can now use a <a href="https://www.benthos.dev/docs/components/processors/bloblang"><code>bloblang</code> processor</a> and complementary condition. These components are in a beta phase, which means that based on feedback the mapping language might change in minor ways in upcoming minor releases.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-motivation">The Motivation<a href="https://www.benthos.dev/blog/2020/05/10/bloblang-beta#the-motivation" class="hash-link" aria-label="Direct link to The Motivation" title="Direct link to The Motivation">​</a></h2>
<p><a href="https://www.benthos.dev/blog/2020/04/18/sneak-peek-at-bloblang">In the last post</a> I outlined my motivations for experimenting with a mapping language. Words are stupid and boring and so to illustrate why a mapping language kicks ass here's a config example using the old processors compared to the new one. Keep in mind that the new version is simpler <em>and</em> performs better.</p>
<p>Using old processors:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">pipeline</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">processors</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">operator</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> set</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">key</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> bar</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token tag" style="color:#00009f">!json_field:foo.bar</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">json</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">operator</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> delete</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">path</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> foo.bar</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">json</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">operator</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> set</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">path</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> foo.topic</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token tag" style="color:#00009f">!metadata:topic</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">operator</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> delete</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">key</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> topic</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">conditional</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">condition</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">jmespath</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">query</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"foo.baz == 'thing'"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">processors</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">json</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">operator</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> set</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">path</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> foo.thing_id</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token tag" style="color:#00009f">!uuid_v4</span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Using Bloblang:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">pipeline</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">processors</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">bloblang</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">      root = this</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      foo.topic = meta("topic")</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      meta topic = deleted()</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      meta bar = foo.bar</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      foo.bar = deleted()</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      foo.thing_id = match </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        foo.baz == "thing" =</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"> uuid_v4()</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>My ultimate intention is to completely eradicate the need for a <code>json</code>, <code>metadata</code> and <code>text</code> processor, as well as a range of others. However, I'll need as much help as possible to get the language right, so please consider testing and feeding back on <a href="https://github.com/Jeffail/benthos/issues/439/" target="_blank" rel="noopener noreferrer">Github</a>, the <a href="https://gitter.im/jeffail-benthos/community" target="_blank" rel="noopener noreferrer">Gitter channel</a>, or event @ me <a href="https://twitter.com/Jeffail" target="_blank" rel="noopener noreferrer">on Twitter</a> for the good of blobkind.</p>]]></content:encoded>
            <category>Bloblang</category>
        </item>
        <item>
            <title><![CDATA[Sneak Peek at Bloblang]]></title>
            <link>https://www.benthos.dev/blog/2020/04/18/sneak-peek-at-bloblang</link>
            <guid>https://www.benthos.dev/blog/2020/04/18/sneak-peek-at-bloblang</guid>
            <pubDate>Sat, 18 Apr 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[An experiment in mapping languages]]></description>
            <content:encoded><![CDATA[<p>For the last few weekends I've been dipping my toes in a mapping language design that I'm calling Bloblang. Bloblang is specifically designed for data queries and (eventually) structural data mappings. In Benthos version 3.12, which I'm planning to release today, you can play around with a limited feature set of Bloblang by using it in <a href="https://www.benthos.dev/docs/configuration/interpolation">function interpolations</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why">Why<a href="https://www.benthos.dev/blog/2020/04/18/sneak-peek-at-bloblang#why" class="hash-link" aria-label="Direct link to Why" title="Direct link to Why">​</a></h2>
<p>My life has no meaning. Also, mapping is one of the most common boring tasks in stream and event processing. Given Benthos is meant to specialise in the boring and mundane it makes sense to treat mapping as a first class citizen.</p>
<p>Up until now the story for mapping documents in Benthos has been to use <a href="https://www.benthos.dev/docs/components/processors/jmespath">JMESPath</a>, <a href="https://www.benthos.dev/docs/components/processors/awk">AWK</a> or a string of the general purpose JSON processors. Time and time again it has been made apparent that it ain't good enough for many use cases.</p>
<p>I should mention at this point that there's also the option of <a href="https://idml.io/" target="_blank" rel="noopener noreferrer">IDML</a>, and although Benthos hasn't supported it internally there is a solution to <a href="https://www.benthos.dev/docs/components/processors/subprocess">running it in your pipeline</a>.</p>
<p>For the last few years I've been helping users adopt these options and each time they fall short I've taken note of where the gaps are. This is an important part of the "research" phase for a language, but I also don't want to dwell on it. Here's an insultingly terse summary of what we currently have within Benthos.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="jmespath">JMESPath<a href="https://www.benthos.dev/blog/2020/04/18/sneak-peek-at-bloblang#jmespath" class="hash-link" aria-label="Direct link to JMESPath" title="Direct link to JMESPath">​</a></h3>
<p>The spiritual cousin of <a href="https://stedolan.github.io/jq/" target="_blank" rel="noopener noreferrer">jq</a>, <a href="https://jmespath.org/" target="_blank" rel="noopener noreferrer">JMESPath</a> is a great spec for mapping JSON documents, especially so when your intention is to outright replace the original document.</p>
<p>However, when our goal is to preserve the majority of the existing document, and we only wish to express isolated mutations within the structure, it becomes ugly and risky. For example, changing just <code>foo.bar.baz</code> to <code>this value</code> looks like this:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">merge(@, {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "foo": merge(foo, {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	  "bar": merge(bar, {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	    "baz": "this value"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	  })</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  })</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">})</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Hopefully you don't add a typo there or miss on a <code>merge</code>, otherwise you're scrapping a large chunk of your original document!</p>
<p>Expressing your entire map in one single object also scales pretty poorly as the mapping grows in complexity.</p>
<p>A final and Benthos specific issue is that JMESPath only supports mapping the content of Benthos messages, without the ability to modify or reference the metadata of a message or other messages of a batch, which would be great for <a href="https://www.benthos.dev/docs/configuration/windowed_processing">windowed processing</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="awk">AWK<a href="https://www.benthos.dev/blog/2020/04/18/sneak-peek-at-bloblang#awk" class="hash-link" aria-label="Direct link to AWK" title="Direct link to AWK">​</a></h3>
<p>Benthos has an <a href="https://www.benthos.dev/docs/components/processors/awk">AWK processor</a>, and since this is a proper programming language it has uses far beyond mapping. However, this also makes it riskier to use for large and complex maps. More opportunities to write bugs, more opportunities to break your program, more opportunities to regress.</p>
<p>A simpler language specifically designed for mappings is a much more scalable solution as it reduces the opportunities for mistakes as both maps and teams grow. Although, risk aside, the major problem with using AWK within Benthos is the performance hit.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="json-processor">JSON Processor<a href="https://www.benthos.dev/blog/2020/04/18/sneak-peek-at-bloblang#json-processor" class="hash-link" aria-label="Direct link to JSON Processor" title="Direct link to JSON Processor">​</a></h3>
<p>The JSON processor is pretty flexible and would be the highest performer of all options here. However, beyond one or two mutations a mapping becomes an absolute mess of YAML, and if we need to add conditional maps into the mix it becomes much worse.</p>
<p>It has been clear to me for a while that this processor is so quickly and easily outgrown by a typical user config that it perhaps ought to be entirely replaced with a real mapping solution.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="idml">IDML<a href="https://www.benthos.dev/blog/2020/04/18/sneak-peek-at-bloblang#idml" class="hash-link" aria-label="Direct link to IDML" title="Direct link to IDML">​</a></h3>
<p>If I could run <a href="https://idml.io/" target="_blank" rel="noopener noreferrer">IDML</a> natively from Benthos then Bloblang wouldn't be happening. In my opinion <a href="https://idml.io/" target="_blank" rel="noopener noreferrer">IDML</a> is a criminally underused technology and absolutely nails the issue of mapping data at scale.</p>
<p>Similar to JMESPath the language itself doesn't have a concept of metadata, or querying across multiple documents (a batch). The issue I had here was that if I were going to go through the trouble of implementing IDML in Go I might as well add metadata and cross-batch querying, making it a different language anyway.</p>
<p>However, I'm definitely writing Bloblang with IDML in mind, and if I manage to reach feature parity with IDML then I intend to break it out into its own lib and offer it to the org, with my Bloblang extensions as Benthos specific plugins.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="features">Features<a href="https://www.benthos.dev/blog/2020/04/18/sneak-peek-at-bloblang#features" class="hash-link" aria-label="Direct link to Features" title="Direct link to Features">​</a></h2>
<p>So with that in mind what does Bloblang look like? Right now we only have queries, which is the "right hand side" of a mapping. These queries support literals:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">"string literal"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">true</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">93435.45</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>And arithmetic:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">50 + 34</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">("this" == "that") || ("that" == "that")</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>And functions:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">json("foo.bar.baz")</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">meta("kafka_key")</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">timestamp_unix()</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>And methods, which are attached to a function or value:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">json("foo.bar.baz").from_all().sum()</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>And path literals with coalescing:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">json().foo.(bar | something_else).baz</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="next-steps">Next Steps<a href="https://www.benthos.dev/blog/2020/04/18/sneak-peek-at-bloblang#next-steps" class="hash-link" aria-label="Direct link to Next Steps" title="Direct link to Next Steps">​</a></h2>
<p>In terms of core syntaxes Bloblang is basically complete. It's implemented using parser combinators, and is very easy for me to extend with new functions and methods. Soon I'll expand Bloblang to support left hand query targets, which is when it really becomes a mapping language. It'll look something like this:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">pipeline</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">processors</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">bloblang</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">mapping</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">        json.foo.bar = json().(something + another.thing)</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">        json.and_this = meta("kafka_key").base64()</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>And I'll also add a <code>condition</code> type for expressing logic as a Bloblang query:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">pipeline</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">processors</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">filter_parts</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">bloblang</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">query</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">          (meta("kafka_topic") == "junk") &amp;&amp;</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">            json().foo.(bar | baz.quz).id.contains("blah")</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Until I'm allowed to practice with my professional rock paper scissors team again I'm sure each weekend will deliver something new to the world of Bloblang.</p>]]></content:encoded>
            <category>Bloblang</category>
        </item>
        <item>
            <title><![CDATA[Write a Benthos Plugin]]></title>
            <link>https://www.benthos.dev/blog/2019/08/20/write-a-benthos-plugin</link>
            <guid>https://www.benthos.dev/blog/2019/08/20/write-a-benthos-plugin</guid>
            <pubDate>Tue, 20 Aug 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[I made it difficult for our job security]]></description>
            <content:encoded><![CDATA[<p>I'm going to walk you through writing a Benthos plugin from scratch in Go.</p>
<p>Too lazy to read? You can find a video equivalent of this post at: <a href="https://youtu.be/Ilah_Y0uMk4" target="_blank" rel="noopener noreferrer">https://youtu.be/Ilah_Y0uMk4</a>. If you prefer to dig straight into code then you should check out the <a href="https://github.com/benthosdev/benthos-plugin-example" target="_blank" rel="noopener noreferrer">benthos-plugin-example</a> repo.</p>
<p><img loading="lazy" alt="benthos-plugged" src="https://www.benthos.dev/assets/images/benthos-plugged-f4a43b8f3b7f1cf32d6cb58d90bd6fbe.png" width="1100" height="400" class="img_ev3q"></p>
<p>Plugins allow you to embed your code within Benthos as a component. <a href="https://benthos.dev/docs/components/processors/about" target="_blank" rel="noopener noreferrer">Processors</a> are the most common type of component to get plugged, which is what we're going to do in this post. If you want to run non-Go code from Benthos then you still have options, such as the <a href="https://benthos.dev/docs/components/processors/subprocess" target="_blank" rel="noopener noreferrer"><code>subprocess</code></a>, <a href="https://benthos.dev/docs/components/processors/http" target="_blank" rel="noopener noreferrer"><code>http</code></a> or <a href="https://benthos.dev/docs/components/processors/lambda" target="_blank" rel="noopener noreferrer"><code>lambda</code></a> processors.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="roleplay">Roleplay<a href="https://www.benthos.dev/blog/2019/08/20/write-a-benthos-plugin#roleplay" class="hash-link" aria-label="Direct link to Roleplay" title="Direct link to Roleplay">​</a></h2>
<p>Imagine you are a competent engineer. You wrote a function to detect sarcasm in internet posts on a linear scale of 0 to 100:</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// HowSarcastic TOTALLY detects sarcasm EVERY time.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">func</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">HowSarcastic</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">content </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token builtin">byte</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token builtin">float64</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> bytes</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Contains</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">content</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token function" style="color:#d73a49">byte</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/s"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">100</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>You are confident that <code>HowSarcastic</code> is 100% accurate and wish to apply it to a continuous stream of data by deploying it within a stream processing solution.</p>
<p>You want this service to be resilient with at-least-once delivery guarantees, scalable both horizontally and vertically, and able to expose various metrics about the health of the data stream.</p>
<p>You have decided to use Benthos for this service because you love the logo.</p>
<p><img loading="lazy" alt="charming-benthos-logo" src="https://www.benthos.dev/assets/images/blobfish-0c62c4bd0d596cd675b2fccbd9ae95db.jpg" width="1100" height="300" class="img_ev3q"></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="stuff-you-dont-need-to-care-about-yet">Stuff you don't need to care about yet<a href="https://www.benthos.dev/blog/2019/08/20/write-a-benthos-plugin#stuff-you-dont-need-to-care-about-yet" class="hash-link" aria-label="Direct link to Stuff you don't need to care about yet" title="Direct link to Stuff you don't need to care about yet">​</a></h3>
<p>Since you are using Benthos you don't need to choose a queue system, metrics aggregator or deployment platform yet, those items can be configured.</p>
<p>You don't even need to know what format the data comes in or how it needs to look when it leaves your service, as Benthos <a href="https://benthos.dev/docs/components/processors/about" target="_blank" rel="noopener noreferrer">has plenty of processors</a> for configuring that stuff on the fly.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="getting-started">Getting Started<a href="https://www.benthos.dev/blog/2019/08/20/write-a-benthos-plugin#getting-started" class="hash-link" aria-label="Direct link to Getting Started" title="Direct link to Getting Started">​</a></h2>
<p>You're going to use Go modules for this one, make a directory and create a <code>go.mod</code> file:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">mkdir foo &amp;&amp; cd foo</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">go mod init github.com/bar/foo</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Next, you need to pull in your only dependency, <a href="https://github.com/Jeffail/benthos" target="_blank" rel="noopener noreferrer">Benthos</a>:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">go get github.com/Jeffail/benthos/v3</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Look! Now you have more dependencies than friends!</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>That'll automatically add the dep to your <code>go.mod</code> file at the latest v3 tag. Next, you're going to write your stream processor service. Write this to the file <code>main.go</code>:</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">package</span><span class="token plain"> main</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"github.com/Jeffail/benthos/v3/lib/service"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">func</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    service</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>That's it, you've got a full Benthos. If you want to verify then you can run it:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">go run ./main.go --help</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="write-your-plugin">Write Your Plugin<a href="https://www.benthos.dev/blog/2019/08/20/write-a-benthos-plugin#write-your-plugin" class="hash-link" aria-label="Direct link to Write Your Plugin" title="Direct link to Write Your Plugin">​</a></h2>
<p>Now you will write the actual plugin that executes your function. Processor plugins implement <a href="https://godoc.org/github.com/Jeffail/benthos/lib/types#Processor" target="_blank" rel="noopener noreferrer"><code>types.Processor</code></a> and have the signature:</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">func</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">ProcessMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">msg types</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Message</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">types</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Message</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> types</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Response</span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>A message can have multiple parts (synonymous with a batch) and we are allowed to return either one or more messages or a response which is either an ack or noack.</p>
<p>A message part has both content and any number of metadata key/value pairs. It is therefore up to you as to whether you modify the contents of messages or whether the sarcasm level is added as metadata.</p>
<p>Thankfully you don't need to make that decision now. Instead, you're going to expose it as a config field and support both. The config field will be called <code>metadata_key</code>, and if left empty the contents of messages will be replaced entirely with the sarcasm level.</p>
<p>There won't be much code needed so for brevity you are going to write this straight into your <code>main.go</code> file:</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// SarcasmProc applies our sarcasm detector to messages.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> SarcasmProc </span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	MetadataKey </span><span class="token builtin">string</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">`json:"metadata_key" yaml:"metadata_key"`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// ProcessMessage returns messages mutated with their sarcasm level.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">func</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">s </span><span class="token operator" style="color:#393A34">*</span><span class="token plain">SarcasmProc</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">ProcessMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">msg types</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Message</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">types</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Message</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> types</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Response</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	newMsg </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> msg</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Copy</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	newMsg</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Iter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">func</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">i </span><span class="token builtin">int</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> p types</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Part</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token builtin">error</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		sarcasm </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">HowSarcastic</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">p</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		sarcasmStr </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> strconv</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">FormatFloat</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sarcasm</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token char">'f'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">64</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">s</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">MetadataKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			p</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Metadata</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Set</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">s</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">MetadataKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> sarcasmStr</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			p</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Set</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token function" style="color:#d73a49">byte</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sarcasmStr</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">types</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Message</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">newMsg</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// CloseAsync does nothing.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">func</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">s </span><span class="token operator" style="color:#393A34">*</span><span class="token plain">SarcasmProc</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">CloseAsync</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// WaitForClose does nothing.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">func</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">s </span><span class="token operator" style="color:#393A34">*</span><span class="token plain">SarcasmProc</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">WaitForClose</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">timeout time</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Duration</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token builtin">error</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Let's break this down. You have a struct called <code>SarcasmProc</code>, which contains a configuration field <code>MetadataKey</code>. The functions <code>CloseAsync</code> and <code>WaitForClose</code> can be ignored as your processor doesn't contain any state that requires termination.</p>
<p>Within your function <code>ProcessMessage</code> you iterate all the payloads within the message batch and calculate the sarcasm level with your function <code>HowSarcastic</code>. The result is converted into a string and, depending on whether a metadata key has been set, replaces the contents with the result or sets a new metadata value on the payload.</p>
<p>That's your processor completed. Now you need to register the plugin before calling <code>service.Run</code>. Since this is a processor plugin you're going to call <a href="https://godoc.org/github.com/Jeffail/benthos/lib/processor#RegisterPlugin" target="_blank" rel="noopener noreferrer"><code>processor.RegisterPlugin</code></a>:</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">func</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	processor</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">RegisterPlugin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token string" style="color:#e3116c">"how_sarcastic"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">func</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">interface</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			s </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> SarcasmProc</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">s</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">func</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			iconf </span><span class="token keyword" style="color:#00009f">interface</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			mgr types</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Manager</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			logger log</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Modular</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			stats metrics</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Type</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">types</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Processor</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token builtin">error</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> iconf</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">*</span><span class="token plain">SarcasmProc</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	service</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The first argument is a string that identifies the type of this plugin, that's the string used to specify it within a Benthos config file.</p>
<p>The second argument is a function that creates our config structure, this will be embedded within the Benthos config specification. In this case our processor implementation is the same type as the configuration struct, but you can separate them if you prefer.</p>
<p>The third argument is the generic function that constructs our processor. In this case we've already constructed it as our configuration type and so we can simply cast it and return it.</p>
<p>Now you're going to build your custom Benthos with:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">go build -o benthos</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="run-your-plugin">Run Your Plugin<a href="https://www.benthos.dev/blog/2019/08/20/write-a-benthos-plugin#run-your-plugin" class="hash-link" aria-label="Direct link to Run Your Plugin" title="Direct link to Run Your Plugin">​</a></h2>
<p>In order to execute your plugin with Benthos you need a config. Write the following to a file <code>config.yaml</code>:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">pipeline</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">processors</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> how_sarcastic</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>And run it:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">./benthos -c ./config.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Your config hasn't specified an input or output so they will default to <code>stdin</code> and <code>stdout</code>. Write the line <code>'this is not sarcastic'</code>, followed by the line <code>'this is sarcastic /s'</code>. Benthos should print <code>0</code> and <code>100</code> respectively.</p>
<p>Cool, but this config is pretty useless, good job idiot. Now you're going to fix your mistake. Let's imagine you are processing a stream of JSON documents of the form <code>{"id":"fooid","content":"this is the content"}</code> and you want to add a field <code>sarcasm</code> containing the sarcasm level of <code>content</code>. You can do that purely through config by using the <a href="https://benthos.dev/docs/components/processors/json" target="_blank" rel="noopener noreferrer"><code>json</code></a> and <a href="https://benthos.dev/docs/components/processors/process_field" target="_blank" rel="noopener noreferrer"><code>process_field</code></a> processors:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">pipeline</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">processors</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">json</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">operator</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> copy</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">path</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> content</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sarcasm</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">process_field</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">path</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sarcasm</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">result_type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> float</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">processors</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> how_sarcastic</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Run that config with some JSON documents:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">echo '{"id":"foo1","content":"this is totally sarcastic /s"}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  {"id":"foo2","content":"but this isnt sarcastic at all"}' |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  ./benthos -c ./config.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>You'll see some log events but also you should see your two modified documents:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">{"content":"this is totally sarcastic /s","id":"foo1","sarcasm":100}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">{"content":"but this isnt sarcastic at all","id":"foo2","sarcasm":0}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>That's much more useful, but this is just barely scratching the surface of what Benthos can do. For example, here's a config that calculates sarcasm with your processor and removes anything with a sarcasm level at or above 80:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">pipeline</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">processors</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> how_sarcastic</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">plugin</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">metadata_key</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sarcasm</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">filter_parts</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">operator</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> less_than</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">key</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sarcasm</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">arg</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Note that it makes use of your <code>metadata_key</code> field in order to filter the documents without changing their content.</p>
<p>Try experimenting with other Benthos processors, you can find the documentation at <a href="https://benthos.dev/docs/components/processors/about" target="_blank" rel="noopener noreferrer">benthos.dev/docs/components/processors/about</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="next-steps">Next Steps<a href="https://www.benthos.dev/blog/2019/08/20/write-a-benthos-plugin#next-steps" class="hash-link" aria-label="Direct link to Next Steps" title="Direct link to Next Steps">​</a></h2>
<p>After playing around with Benthos processors you should check out the various <a href="https://benthos.dev/docs/components/inputs/about" target="_blank" rel="noopener noreferrer">inputs</a>, <a href="https://benthos.dev/docs/components/outputs/about" target="_blank" rel="noopener noreferrer">outputs</a>, <a href="https://benthos.dev/docs/components/metrics/about" target="_blank" rel="noopener noreferrer">metrics aggregators</a> and <a href="https://benthos.dev/docs/components/tracers/about" target="_blank" rel="noopener noreferrer">tracers</a> that it's able to hook up with.</p>
<p>For example, here's a modified version of the previous config where we write from Kafka to an S3 bucket, sending our metrics to Prometheus:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">address</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 0.0.0.0</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">4195</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">input</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">kafka</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">addresses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> localhost</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">9092</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">consumer_group</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> foo_consumer_group</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">topics</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> foo_stream</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">pipeline</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">processors</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> how_sarcastic</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">plugin</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">metadata_key</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sarcasm</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">filter_parts</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">operator</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> less_than</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">key</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sarcasm</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">arg</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">output</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">s3</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">bucket</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> foo_bucket</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">content_type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> application/json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">path</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token tag" style="color:#00009f">!metadata:kafka_key</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">$</span><span class="token punctuation" style="color:#393A34">{</span><span class="token tag" style="color:#00009f">!timestamp_unix_nano</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">$</span><span class="token punctuation" style="color:#393A34">{</span><span class="token tag" style="color:#00009f">!count:files</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">.json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metrics</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># Endpoint hosted at both :4195/stats and :4195/metrics</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> prometheus</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>I'm sure you'll make great use of Benthos plugins with your extremely important work /s.</p>]]></content:encoded>
            <category>Plugins</category>
        </item>
        <item>
            <title><![CDATA[Introducing Benthos Lab]]></title>
            <link>https://www.benthos.dev/blog/2019/06/17/introducing-benthos-lab</link>
            <guid>https://www.benthos.dev/blog/2019/06/17/introducing-benthos-lab</guid>
            <pubDate>Mon, 17 Jun 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[Where you can build your very own monstrosities]]></description>
            <content:encoded><![CDATA[<p>After experimenting with innovative new ways to choke your browser to death I am
pleased to announce Benthos Lab, which lives at
<a href="https://lab.benthos.dev/" target="_blank" rel="noopener noreferrer">https://lab.benthos.dev</a>.</p>
<p>Benthos Lab is a website where users of the <a href="https://www.benthos.dev/" target="_blank" rel="noopener noreferrer">Benthos stream processor</a>
can write, format, execute and share their pipeline configurations. This was
made possible by compiling the entire service (written in Go) into Web Assembly
so that it can run directly in your browser.</p>
<p>Here's a video of it in action: <a href="https://youtu.be/1ZN-42A0sJU" target="_blank" rel="noopener noreferrer">https://youtu.be/1ZN-42A0sJU</a>.</p>
<p>Some technical details about how this was achieved can be found in
<a href="https://www.benthos.dev/blog/2019/05/27/compiling-benthos-to-wasm/">a previous post of mine</a>. The repo can be found at:
<a href="https://github.com/benthosdev/benthos-lab" target="_blank" rel="noopener noreferrer">https://github.com/benthosdev/benthos-lab</a>, feel free to clone it,
hack it and host your own version.</p>
<p><a href="https://lab.benthos.dev/" target="_blank" rel="noopener noreferrer"><img loading="lazy" alt="benthos-lab" src="https://www.benthos.dev/assets/images/banner-326be7857af0da51ae55257a875f9b21.svg" width="1850" height="300" class="img_ev3q"></a></p>
<p>Like every good laboratory it is scrappy and sometimes explodes. You need a
modern browser version and it doesn't currently support mobile. Regardless, I
think it's a good time to invite you try it out. Don't worry, I'll be watching
from a safe distance.</p>
<p>Also, if it does break on you then please remember that you don't pay me for
this, you vile parasite.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why">Why<a href="https://www.benthos.dev/blog/2019/06/17/introducing-benthos-lab#why" class="hash-link" aria-label="Direct link to Why" title="Direct link to Why">​</a></h2>
<p>At Meltwater we have many distributed teams using Benthos for a wide and ever
increasing list of use cases, which results in a lot of remote collaboration.</p>
<p>For the slower moving, asynchronous types of work we are usually fine with ye
olde git. However, sometimes it's nice to quickly hash stuff out, at which point
things would suddenly devolve into a barrage of files getting chaotically thrown
at a slack channel.</p>
<p><img loading="lazy" alt="slamming-slack" src="https://www.benthos.dev/assets/images/slamslack-4a1f578d9805562f26e82193082875ae.jpg" width="1800" height="750" class="img_ev3q"></p>
<p>By contrast, the lab is a civilised place where one can quickly and easily
create a pipeline concept, including sample input data, and share it directly
with a group. Opening up a shared lab provides all that same context, allows you
to make your own revisions to it, and even lets you execute it in order to see
the results it produces.</p>
<p><img loading="lazy" alt="genteel-lab" src="https://www.benthos.dev/assets/images/genteel-79cac79bb3722c269699ef43241be280.jpg" width="1800" height="750" class="img_ev3q"></p>
<p>For our teams this app dramatically reduced the time taken to create, prove and
demonstrate a pipeline concept. It's also much quicker for me to help teams that
have issues with their configs as they can make sure I have all the information
needed up front with a single URL.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="use-it-to-build-your-own-web-app">Use it to build your own web app<a href="https://www.benthos.dev/blog/2019/06/17/introducing-benthos-lab#use-it-to-build-your-own-web-app" class="hash-link" aria-label="Direct link to Use it to build your own web app" title="Direct link to Use it to build your own web app">​</a></h3>
<p>There's also plenty of unintended use cases for Benthos Lab as it basically
allows you to build your own custom web applications. Here's a session that
lower cases and normalises a JSON document, computes its sha256 hash and then
hex encodes the hash:
<a href="https://lab.benthos.dev/l/N-3sss3WPjj#input" target="_blank" rel="noopener noreferrer">https://lab.benthos.dev/l/N-3sss3WPjj#input</a>.</p>
<p>Pro tip: if you add the anchor <code>#input</code> to the end of the session URL then it
opens up at the input tab for quickly inserting stuff.</p>
<p>Since there's such a vast catalogue of Benthos
<a href="https://benthos.dev/docs/components/processors/about" target="_blank" rel="noopener noreferrer">processors available</a> I've already found myself bookmarking a
few lab sessions as general utilities.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="next-steps">Next Steps<a href="https://www.benthos.dev/blog/2019/06/17/introducing-benthos-lab#next-steps" class="hash-link" aria-label="Direct link to Next Steps" title="Direct link to Next Steps">​</a></h2>
<p>With this running within the sandbox of your browser there's lots of missing
functionality. For example, you can't create TCP/UDP connections (as of right
now) and you can't access a file system.</p>
<p>However, I don't plan to address this any time soon as the intention of the app
is to test snippets of config, not to execute your whole damn streaming
pipeline. You ought to learn to manage your expectations.</p>
<p>What I will do though is continue to improve the UI. If a feature you want is
missing (or broken, obviously) then please <a href="https://github.com/benthosdev/benthos-lab/issues" target="_blank" rel="noopener noreferrer">open an issue</a>.</p>]]></content:encoded>
            <category>Benthos Lab</category>
        </item>
        <item>
            <title><![CDATA[Compiling Benthos to Web Assembly]]></title>
            <link>https://www.benthos.dev/blog/2019/05/27/compiling-benthos-to-wasm</link>
            <guid>https://www.benthos.dev/blog/2019/05/27/compiling-benthos-to-wasm</guid>
            <pubDate>Mon, 27 May 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[Don't worry about why]]></description>
            <content:encoded><![CDATA[<p>Web assembly won't fix seasons 7 and 8, but it's still pretty cool. At a
<a href="https://underthehood.meltwater.com/blog/2019/06/17/benthos-lab-a-case-study-of-hackathon-innovation/" target="_blank" rel="noopener noreferrer">Meltwater hackathon</a> I had a project in mind (details soon to
follow) that would benefit hugely from Benthos running directly in the browser.
I therefore set out to compile it in wasm, this is my short and sweet journey.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-build">The Build<a href="https://www.benthos.dev/blog/2019/05/27/compiling-benthos-to-wasm#the-build" class="hash-link" aria-label="Direct link to The Build" title="Direct link to The Build">​</a></h2>
<p>The first thing I did and the first thing you ought to do if you are targeting
wasm yourself is skim through <a href="https://github.com/golang/go/wiki/WebAssembly" target="_blank" rel="noopener noreferrer">this section of the Go wiki</a>.</p>
<p>In short, I wrote a Go file:</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">package</span><span class="token plain"> main</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token string" style="color:#e3116c">"syscall/js"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token string" style="color:#e3116c">"github.com/Jeffail/benthos/lib/config"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token string" style="color:#e3116c">"gopkg.in/yaml.v3"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">func</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">normalise</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">this js</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Value</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> args </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">js</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Value</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">interface</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> configStr </span><span class="token builtin">string</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">args</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		configStr </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> args</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">String</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	conf </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> config</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">New</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">// Ignoring errors for brevity</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	yaml</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Unmarshal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token function" style="color:#d73a49">byte</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configStr</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">conf</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	sanit</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">_</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> conf</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Sanitised</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	sanitBytes</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">_</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> yaml</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Marshal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sanit</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">string</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sanitBytes</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">func</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	c </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">make</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">chan</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">struct</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	js</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Global</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Set</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"benthosNormaliseConfig"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> js</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">FuncOf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">normalise</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token operator" style="color:#393A34">&lt;-</span><span class="token plain">c</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>And compiled it:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">GOOS=js GOARCH=wasm go build -o main.wasm</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>I was pretty sure that this would be the end of the road for me. Benthos uses a
vast swathe of dependencies for its various connectors and so I was sure that I
would be immobilised with errors. However, to my surprise there were only three
(formatted for brevity):</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">lib/util/disk/check.go:29:11: undefined: syscall.Statfs_t</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">github.com/edsrzf/mmap-go@v1.0.0/mmap.go:77:9: undefined: mmap</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">github.com/lib/pq@v1.0.0/conn.go:321:13: undefined: userCurrent</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Which involved some calls for a buffer implementation using a memory-mapped file
library and the PostgreSQL driver for the SQL package. The errors themselves are
basically "this thing doesn't exist in Web Assembly", which usually means the
library has a feature behind build constraints but doesn't support wasm yet.</p>
<p>The solution for these problems in my case was as simple as to not to do the
call, and perhaps document that the feature doesn't work with a wasm build.</p>
<p>Obviously, we only want to disable these calls specifically when targeting wasm.
In Go that's easy, stick a cheeky
<a href="https://golang.org/pkg/go/build/#hdr-Build_Constraints" target="_blank" rel="noopener noreferrer">build constraint on there</a>. Here's the actual commit:
<a href="https://github.com/Jeffail/benthos/commit/9903b3d5d8519fcf7ecbce94c336e7f054a75942#diff-146b6fd87106d7f70f56facf7b1e7d98" target="_blank" rel="noopener noreferrer">9903b3d5d8519fcf7ecbce94c336e7f054a75942</a>, note that you can't
just constrain the feature, you also need to add an empty stub that has the
opposite constraint in order to satisfy your build.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="executing-go-from-javascript">Executing Go From JavaScript<a href="https://www.benthos.dev/blog/2019/05/27/compiling-benthos-to-wasm#executing-go-from-javascript" class="hash-link" aria-label="Direct link to Executing Go From JavaScript" title="Direct link to Executing Go From JavaScript">​</a></h2>
<p>The <a href="https://github.com/golang/go/wiki/WebAssembly" target="_blank" rel="noopener noreferrer">Go Wiki</a> shows you how to actually execute your wasm build
and I won't repeat it here, but I followed the steps and it was pretty straight
forward.</p>
<p>There was, however, one issue I came across. Some functions that I was calling
from JavaScript were causing my wasm runtime to panic and stop. The functions
all had channel blocking in common, something like this:</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">func</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">ashHasACoolBlog</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">this js</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Value</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> args </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">js</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Value</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">interface</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	someChan </span><span class="token operator" style="color:#393A34">&lt;-</span><span class="token plain"> args</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">String</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;-</span><span class="token plain">someOtherChanIHateNamingThings</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The function would sometimes execute successfully. Other times, specifically for
longer running calls, I would get a deadlock panic:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">fatal error: all goroutines are asleep - deadlock! wasm_exec.js:47:6</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">wasm_exec.js:47:6</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">goroutine 1 [chan receive]: wasm_exec.js:47:6</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">main.main() wasm_exec.js:47:6</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	/home/ash/tmp/wasm/main.go:20 +0x7</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Which was odd as they would be occasions where I would not expect a real
deadlock. I then found the relevant docs in the <a href="https://godoc.org/syscall/js#Func" target="_blank" rel="noopener noreferrer"><code>syscall/js</code></a>
package:</p>
<blockquote>
<p>Blocking operations in the wrapped function will block the event loop. As a
consequence, if one wrapped function blocks, other wrapped funcs will not be
processed. A blocking function should therefore explicitly start a new
goroutine.</p>
</blockquote>
<p>The consequences of blocking sound pretty harmless here, but in reality it
seemed to be the cause of my deadlock crash. I assume the odd error message is a
result of some nuanced mechanics within the wasm runtime.</p>
<p>I didn't investigate this crash any further as I was a lazy idiot back in those
dark days. I simply stopped writing blocking functions, and instead spawned
goroutines everywhere like they were losers at a Nickelback concert:</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">func</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">iJustWantToClarify</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">this js</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Value</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> args </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">js</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Value</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">interface</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">go</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">func</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		someChan </span><span class="token operator" style="color:#393A34">&lt;-</span><span class="token plain"> args</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">String</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		otherThing </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;-</span><span class="token plain">someOtherChanIHateNamingThings</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		js</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Global</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"thatActually"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Set</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token string" style="color:#e3116c">"textContent"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token string" style="color:#e3116c">"I quite enjoy and respect Knickelback as artists... "</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> otherThing</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="other-issues">Other Issues<a href="https://www.benthos.dev/blog/2019/05/27/compiling-benthos-to-wasm#other-issues" class="hash-link" aria-label="Direct link to Other Issues" title="Direct link to Other Issues">​</a></h2>
<p>There weren't any.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="final-words">Final Words<a href="https://www.benthos.dev/blog/2019/05/27/compiling-benthos-to-wasm#final-words" class="hash-link" aria-label="Direct link to Final Words" title="Direct link to Final Words">​</a></h2>
<p>It took a day for me to get a working application together and soon I'll be
blogging about the resulting product. Web assembly with Go is dope.</p>
<p>Kudos to both the W3C and the Go team for taking their time to build something
to completion without rushing the conclusion. Yes, I'm still bitter about Game
of Thrones.</p>]]></content:encoded>
            <category>Benthos Lab</category>
        </item>
    </channel>
</rss>