<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Falco – Falco Plugins</title><link>https://v0-43--falcosecurity.netlify.app/docs/reference/plugins/</link><description>Recent content in Falco Plugins on Falco</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="https://v0-43--falcosecurity.netlify.app/docs/reference/plugins/feed.xml" rel="self" type="application/rss+xml"/><item><title>Docs: Falco Plugins API Reference</title><link>https://v0-43--falcosecurity.netlify.app/docs/reference/plugins/plugin-api-reference/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://v0-43--falcosecurity.netlify.app/docs/reference/plugins/plugin-api-reference/</guid><description>
&lt;h2 id="introduction"&gt;Introduction&lt;/h2&gt;
&lt;p&gt;This page documents the functions that make up the Falco plugins API. In most cases, you will not need to implement these functions directly. There are &lt;a href="https://github.com/falcosecurity/plugin-sdk-go"&gt;Go&lt;/a&gt; and &lt;a href="https://github.com/falcosecurity/plugin-sdk-cpp"&gt;C++&lt;/a&gt; SDKs that provide an easier-to-use interface for plugin authors.&lt;/p&gt;
&lt;p&gt;At a high level, the API functions are grouped as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Functions that are commons to all plugins&lt;/li&gt;
&lt;li&gt;Functions that implement one specific capability&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The C header files &lt;a href="https://github.com/falcosecurity/libs/blob/0.17.2/userspace/plugin/plugin_types.h"&gt;plugin_api.h&lt;/a&gt; numerate all the API functions and associated structs/types as they are used by the plugins framework. The whole plugin API and the loader used in Falco are implemented in C in a standalone module located inside &lt;a href="https://github.com/falcosecurity/libs/tree/master/userspace/plugin"&gt;falcosecurity/libs/userspace/plugin&lt;/a&gt;, and can be imported and reused in other projects using the falcosecurity plugin system (e.g. we have a &lt;a href="https://github.com/falcosecurity/plugin-sdk-go/tree/main/pkg/loader"&gt;plugin loader written in Go&lt;/a&gt; developed on top of the C one).&lt;/p&gt;
&lt;p&gt;Remember, however, that from the perspective of the plugin, each function name has a prefix &lt;code&gt;plugin_&lt;/code&gt; e.g. &lt;code&gt;plugin_get_required_api_version&lt;/code&gt;, &lt;code&gt;plugin_get_name&lt;/code&gt;, etc.&lt;/p&gt;
&lt;p&gt;Since &lt;a href="https://v0-43--falcosecurity.netlify.app/blog/falco-0-33-0/"&gt;Falco v0.33.0&lt;/a&gt;, some function symbols of &lt;strong&gt;the plugin API started supporting concurrent invocations&lt;/strong&gt; from multiple threads. If not explicitly specified in each symbol's API reference, the plugin API assumes that functions are invoked always from the same thread with no concurrency.&lt;/p&gt;
&lt;h3 id="plugin-api-versioning"&gt;Plugin API Versioning&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;The current version of the plugin API is &lt;code&gt;3.6.0&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The plugin API is a formal contract between the framework and the plugins, and it is versioned using &lt;a href="https://semver.org/"&gt;semantic versioning&lt;/a&gt;. The framework exposes the plugin API version it supports, and each plugin expresses a required plugin API version. If the version required by a plugin does not pass the semantic check with the one supported by the framework, then the plugin cannot be loaded. See the section about &lt;a href="https://v0-43--falcosecurity.netlify.app/docs/reference/plugins/plugin-api-reference/#get-required-api-version"&gt;&lt;code&gt;plugin_get_required_api_version&lt;/code&gt;&lt;/a&gt; for more details.&lt;/p&gt;
&lt;h3 id="conventions"&gt;Conventions&lt;/h3&gt;
&lt;p&gt;The following conventions apply for all of the below API functions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Every function that returns a &lt;code&gt;const char* &lt;/code&gt; must return a null-terminated C string.&lt;/li&gt;
&lt;li&gt;All string values returned across the API are considered owned by the plugin and must remain valid for use by the plugin framework. Specifically, this means:
&lt;ul&gt;
&lt;li&gt;For demographic functions like &lt;code&gt;plugin_get_name&lt;/code&gt;, &lt;code&gt;plugin_get_description&lt;/code&gt;, the returned strings must remain valid until the plugin is destroyed.&lt;/li&gt;
&lt;li&gt;When returning events via &lt;code&gt;plugin_next_batch&lt;/code&gt;, both the array of structs and the data payloads inside each struct must remain valid until the next call to &lt;code&gt;plugin_next_batch&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;When returning extracted string values via &lt;code&gt;plugin_extract_fields&lt;/code&gt;, every extracted string must remain valid until the next call to &lt;code&gt;plugin_extract_fields&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;For every function that returns an error, the plugin should save a meaningful error string that the framework can retrieve via a call to &lt;code&gt;plugin_get_last_error&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="inversion-of-control-and-callbacks-to-the-plugin-s-owner"&gt;Inversion of Control and Callbacks to the Plugin's Owner&lt;/h2&gt;
&lt;p&gt;All functions from the plugin API define functionalities that the plugin offers to the framework. In the default execution path, the plugin is always the &amp;quot;passive&amp;quot; actor, with the framework being the orchestrator determining when and how often a given plugin function gets invoked.&lt;/p&gt;
&lt;p&gt;The plugin API also supports an occasional inversion of control in which plugins can actively invoke functions exposed by the framework that owns it. For those cases, the execution flow generally proceeds as follows. First, the framework invokes a function exported by the plugin according its supported version of the plugin API. As one of the function arguments the framework passes to the plugin a vtable struct allocated and owned by the framework itself, containing one or more function pointers referring to code functions of the framework that the plugin is allowed to invoke. Permissions about retaining such function pointers inside the plugin's state after the execution of the plugin API symbol may vary depending on the API symbol itself and its related capabilities. Alongside the function pointers, the framework also provides the plugin with a &lt;code&gt;ss_plugin_owner_t*&lt;/code&gt; opaque handle, which the plugin must pass to the framework's functions. The opaque handle represents an instance of the plugin's &lt;em&gt;owner&lt;/em&gt;, which is an abstract component that the framework allocates for managing the plugin's requests. If the framework passes one of the function pointers defined in the vtable structs as &lt;code&gt;NULL&lt;/code&gt;, then the plugin must assume that the related piece of functionality is not supported by the framework in that context. Plugins must always check whether the function pointers passed by the framework are &lt;code&gt;NULL&lt;/code&gt; or not.&lt;/p&gt;
&lt;p&gt;An example of functionality provided in the form of inversion of control is the access to &lt;a href="https://v0-43--falcosecurity.netlify.app/docs/reference/plugins/plugin-api-reference/#state-tables-api"&gt;state tables&lt;/a&gt;. The C++ example below shows how a plugin can interact with its owner during the execution of its &lt;code&gt;init&lt;/code&gt; function. In this case, the plugin iterates over the list of state tables registered in the framework and catches errors arising during the invocations of the owner's callbacks:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-CPP" data-lang="CPP"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;extern&lt;/span&gt; &lt;span style="color:#b44"&gt;&amp;#34;C&amp;#34;&lt;/span&gt; ss_plugin_t&lt;span style="color:#666"&gt;*&lt;/span&gt; plugin_init(&lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; ss_plugin_init_input&lt;span style="color:#666"&gt;*&lt;/span&gt; in, ss_plugin_rc&lt;span style="color:#666"&gt;*&lt;/span&gt; rc)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#666"&gt;*&lt;/span&gt;rc &lt;span style="color:#666"&gt;=&lt;/span&gt; SS_PLUGIN_SUCCESS;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; my_plugin &lt;span style="color:#666"&gt;*&lt;/span&gt;ret &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;new&lt;/span&gt; my_plugin();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt; (&lt;span style="color:#666"&gt;!&lt;/span&gt;in &lt;span style="color:#666"&gt;||&lt;/span&gt; &lt;span style="color:#666"&gt;!&lt;/span&gt;in&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;tables)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#666"&gt;*&lt;/span&gt;rc &lt;span style="color:#666"&gt;=&lt;/span&gt; SS_PLUGIN_FAILURE;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ret&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;lasterr &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#b44"&gt;&amp;#34;access to the state tables is not supported by the owner&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt; ret;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;uint32_t&lt;/span&gt; ntables &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#666"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;auto&lt;/span&gt; tables &lt;span style="color:#666"&gt;=&lt;/span&gt; in&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;tables&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;list_tables(in&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;owner, &lt;span style="color:#666"&gt;&amp;amp;&lt;/span&gt;ntables);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt; (&lt;span style="color:#666"&gt;!&lt;/span&gt;tables)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#666"&gt;*&lt;/span&gt;rc &lt;span style="color:#666"&gt;=&lt;/span&gt; SS_PLUGIN_FAILURE;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ret&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;lasterr &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#b44"&gt;&amp;#34;can&amp;#39;t list state tables: &amp;#34;&lt;/span&gt; &lt;span style="color:#666"&gt;+&lt;/span&gt; std&lt;span style="color:#666"&gt;::&lt;/span&gt;string(in&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;get_owner_last_error(in&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;owner));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt; ret;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;for&lt;/span&gt; (&lt;span style="color:#0b0;font-weight:bold"&gt;uint32_t&lt;/span&gt; i &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#666"&gt;0&lt;/span&gt;; i &lt;span style="color:#666"&gt;&amp;lt;&lt;/span&gt; ntables; i&lt;span style="color:#666"&gt;++&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;auto&lt;/span&gt;&lt;span style="color:#666"&gt;&amp;amp;&lt;/span&gt; ti &lt;span style="color:#666"&gt;=&lt;/span&gt; tables[i];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; printf(&lt;span style="color:#b44"&gt;&amp;#34;table=&amp;#39;%s&amp;#39;, key_type=%d&lt;/span&gt;&lt;span style="color:#b62;font-weight:bold"&gt;\n&lt;/span&gt;&lt;span style="color:#b44"&gt;&amp;#34;&lt;/span&gt;, ti.name, ti.key_type);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt; ret;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="logging"&gt;Logging&lt;/h3&gt;
&lt;p&gt;Another functionality that makes use of inversion of control is &lt;strong&gt;logging&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The framework provides a log function during the plugin initialization, which the plugin can use to invoke the framework-provided logger at any time during the plugin life-cycle.&lt;/p&gt;
&lt;p&gt;The following C++ example shows how a plugin can retain the owner's handle and the log function to invert control and invoke the framework logger:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-CPP" data-lang="CPP"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;struct&lt;/span&gt; &lt;span style="color:#00f"&gt;my_plugin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_owner_t&lt;span style="color:#666"&gt;*&lt;/span&gt; owner;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_log_fn_t log;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;extern&lt;/span&gt; &lt;span style="color:#b44"&gt;&amp;#34;C&amp;#34;&lt;/span&gt; ss_plugin_t&lt;span style="color:#666"&gt;*&lt;/span&gt; plugin_init(&lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; ss_plugin_init_input&lt;span style="color:#666"&gt;*&lt;/span&gt; in, ss_plugin_rc&lt;span style="color:#666"&gt;*&lt;/span&gt; rc)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#666"&gt;*&lt;/span&gt;rc &lt;span style="color:#666"&gt;=&lt;/span&gt; SS_PLUGIN_SUCCESS;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; my_plugin &lt;span style="color:#666"&gt;*&lt;/span&gt;ret &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;new&lt;/span&gt; my_plugin();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ret&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;log &lt;span style="color:#666"&gt;=&lt;/span&gt; in&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;log_fn;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ret&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;owner &lt;span style="color:#666"&gt;=&lt;/span&gt; in&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;owner;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ret&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;log(ret&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;owner, &lt;span style="color:#a2f"&gt;NULL&lt;/span&gt;, &lt;span style="color:#b44"&gt;&amp;#34;initializing plugin...&amp;#34;&lt;/span&gt;, SS_PLUGIN_LOG_SEV_INFO);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt; ret;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;extern&lt;/span&gt; &lt;span style="color:#b44"&gt;&amp;#34;C&amp;#34;&lt;/span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;void&lt;/span&gt; plugin_destroy(ss_plugin_t&lt;span style="color:#666"&gt;*&lt;/span&gt; s)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; my_plugin &lt;span style="color:#666"&gt;*&lt;/span&gt;ps &lt;span style="color:#666"&gt;=&lt;/span&gt; (my_plugin &lt;span style="color:#666"&gt;*&lt;/span&gt;) s;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ps&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;log(ps&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;owner, &lt;span style="color:#a2f"&gt;NULL&lt;/span&gt;, &lt;span style="color:#b44"&gt;&amp;#34;destroying plugin...&amp;#34;&lt;/span&gt;, SS_PLUGIN_LOG_SEV_INFO);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;delete&lt;/span&gt; ((my_plugin &lt;span style="color:#666"&gt;*&lt;/span&gt;) s);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The signature of the log function is:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;void log(ss_plugin_owner_t* owner, const char* component, const char* msg, ss_plugin_log_severity sev);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;where &lt;code&gt;owner&lt;/code&gt; is the handle of the owner, &lt;code&gt;component&lt;/code&gt; is a string representing the plugin's component name that is invoking the logger (falls back to the plugin name when &lt;code&gt;NULL&lt;/code&gt;), &lt;code&gt;msg&lt;/code&gt; is the log message and &lt;code&gt;sev&lt;/code&gt; is the log &lt;a href="https://github.com/falcosecurity/libs/blob/0.17.2/userspace/plugin/plugin_types.h#L285-L296"&gt;severity&lt;/a&gt; as defined in API.&lt;/p&gt;
&lt;h2 id="common-plugin-api"&gt;Common Plugin API&lt;/h2&gt;
&lt;h3 id="get-required-api-version"&gt;get_required_api_version&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;const char* plugin_get_required_api_version() [Required: yes]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function returns a string containing a &lt;a href="https://semver.org/"&gt;semver&lt;/a&gt; version number e.g. &amp;quot;3.0.0&amp;quot;, reflecting the version of the plugin API framework that this plugin requires. This is different than the version of the plugin itself, and should only have to change when the plugin API changes.&lt;/p&gt;
&lt;p&gt;This is the first function the framework calls when loading a plugin. If the returned value is not semver-compatible with the version of the plugin API framework, the plugin will not be loaded.&lt;/p&gt;
&lt;p&gt;For example, if the code implementing the plugin framework has version 1.1.0, and a plugin's &lt;code&gt;plugin_get_required_api_version&lt;/code&gt; function returns 1.0.0, the plugin API is compatible and the plugin will be loaded. If the code implementing the plugin framework has version 3.0.0, and a plugin's &lt;code&gt;plugin_get_required_api_version&lt;/code&gt; function returns 1.0.0, the API is not compatible and the plugin will not be loaded.&lt;/p&gt;
&lt;h3 id="get-name-description-contact-version"&gt;get_{name,description,contact,version}&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;const char* plugin_get_name() [Required: yes]
const char* plugin_get_description() [Required: yes]
const char* plugin_get_contact() [Required: yes]
const char* plugin_get_version() [Required: yes]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;These functions all return an C string, with memory owned by the plugin, that describe the plugin:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;plugin_get_name&lt;/code&gt;: Return the name of the plugin.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;plugin_get_description&lt;/code&gt;: Return a short description of the plugin.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;plugin_get_contact&lt;/code&gt;: Return a contact url/email/twitter account for the plugin authors.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;plugin_get_version&lt;/code&gt;: Return the version of the plugin itself.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For &lt;code&gt;get_version&lt;/code&gt;, note that increasing the major version signals breaking changes in the plugin implementation but must not change the serialization format of the event data. For example, events written in pre-existing capture files must always be readable by newer versions of the plugin.&lt;/p&gt;
&lt;h3 id="init"&gt;init&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ss_plugin_t* plugin_init(const ss_plugin_init_input *input, ss_plugin_rc *rc) [Required: yes]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function passes plugin-level configuration to the plugin to create its plugin-level state. The plugin then returns a pointer to that state, as a &lt;code&gt;ss_plugin_t *&lt;/code&gt; handle. The handle is never examined by the plugin framework and is never freed. It is only provided as the argument to later API functions.&lt;/p&gt;
&lt;p&gt;When managing plugin-level state, keep the following in mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It is the plugin's responsibility to allocate plugin state (memory, open files, etc) and free that state later in &lt;code&gt;plugin_destroy&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The plugin state should be the &lt;em&gt;only&lt;/em&gt; location for state (e.g. no globals, no per-thread state). Although unlikely, the framework may choose to call &lt;code&gt;plugin_init&lt;/code&gt; multiple times for the same plugin, and this should be supported by the plugin.&lt;/li&gt;
&lt;li&gt;The returned rc value should be &lt;code&gt;SS_PLUGIN_SUCCESS&lt;/code&gt; (0) on success, &lt;code&gt;SS_PLUGIN_FAILURE&lt;/code&gt; (1) on failure.&lt;/li&gt;
&lt;li&gt;On failure, make sure to return a meaningful error message in the next call to &lt;code&gt;plugin_get_last_error&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;On failure, plugins can decide whether to return an allocated state or not. In the first case, the plugin framework will use the allocated state to retrieve the failure error with &lt;code&gt;plugin_get_last_error&lt;/code&gt;, and will then free the state with &lt;code&gt;plugin_destroy&lt;/code&gt;. In the second case, &lt;code&gt;plugin_destroy&lt;/code&gt; will not be called and the plugin framework will return a generic error.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The format of the config string is entirely determined by the plugin author, and by default is passed unchanged from Falco/the application using the plugin framework to the plugin. However, semi-structured formats like JSON/YAML are preferable to free-form text. In those cases, the plugin author can provide a schema describing the config string contents by implementing the optional &lt;code&gt;get_init_schema&lt;/code&gt; function. If so, the &lt;code&gt;init&lt;/code&gt; function can assume the passed-in configuration string to always be well-formed, and can avoid performing any error handling. The plugin framework will take care of automatically parsing it against the provided schema and generating ad-hoc errors accordingly. Please refer to the documentation of &lt;code&gt;get_init_schema&lt;/code&gt; for more details.&lt;/p&gt;
&lt;p&gt;If a non-NULL ss_plugin_t* state is returned, then subsequent invocations of &lt;code&gt;init&lt;/code&gt; must not return the same &lt;code&gt;ss_plugin_t *&lt;/code&gt; value again, unless it has been disposed with &lt;code&gt;destroy&lt;/code&gt; first.&lt;/p&gt;
&lt;h3 id="destroy"&gt;destroy&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;void plugin_destroy(ss_plugin_t *s) [Required: yes]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function frees any resources held in the &lt;code&gt;ss_plugin_t&lt;/code&gt; struct. Afterwards, the handle should be considered destroyed and no further API functions will be called with that handle.&lt;/p&gt;
&lt;h3 id="get-last-error"&gt;get_last_error&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;const char* plugin_get_last_error(ss_plugin_t* s) [Required: yes]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function is called by the framework after a prior call returned an error. The plugin should return a meaningful error string providing more information about the most recent error.&lt;/p&gt;
&lt;h3 id="get-init-schema"&gt;get_init_schema&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;const char* plugin_get_init_schema(ss_plugin_schema_type* schema_type) [Required: no]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function returns a schema that describes the configuration to be passed to &lt;code&gt;init&lt;/code&gt; during plugin initialization. The return value is a C string, with memory owned by the plugin, representing the configuration schema. The type of schema returned is compliant with the &lt;code&gt;ss_plugin_schema_type&lt;/code&gt; enumeration, and is written inside the &lt;code&gt;schema_type&lt;/code&gt; output argument.&lt;/p&gt;
&lt;p&gt;Although this function is non-required, it is common to implement it due to the benefits it brings. If &lt;code&gt;get_init_schema&lt;/code&gt; is correctly implemented, the &lt;code&gt;init&lt;/code&gt; function can assume the passed-in configuration string to always be well-formed. The plugin framework will take care of automatically parsing it against the provided schema and generating ad-hoc errors accordingly. This also serves as a piece of documentation for users about how the plugin needs to be configured.&lt;/p&gt;
&lt;p&gt;Currently, the plugin framework only supports the &lt;a href="https://json-schema.org/"&gt;JSON Schema format&lt;/a&gt;, which is represented by the &lt;code&gt;SS_PLUGIN_SCHEMA_JSON&lt;/code&gt; enum value. If a plugin defines a JSON Schema, the framework will require the init configuration string to be a valid json-formatted string.&lt;/p&gt;
&lt;p&gt;Writing the dummy enum value &lt;code&gt;SS_PLUGIN_SCHEMA_NONE&lt;/code&gt; inside &lt;code&gt;schema_type&lt;/code&gt; is equivalent to avoiding implementing the &lt;code&gt;get_init_schema&lt;/code&gt; function itself, which ends up with the framework treating the init configuration as an opaque string with no additional checks.&lt;/p&gt;
&lt;h3 id="set-config"&gt;set_config&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ss_plugin_rc plugin_set_config(ss_plugin_t* s, const ss_plugin_set_config_input* i) [Required: no]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Sets a new plugin configuration when provided by the framework.
The new configuration is provided by &lt;code&gt;config&lt;/code&gt; as a string in &lt;code&gt;ss_plugin_set_config_input* i&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This function should return:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SS_PLUGIN_SUCCESS&lt;/code&gt; (0) if the config is accepted&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SS_PLUGIN_FAILURE&lt;/code&gt; (1) if the config is rejected&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If rejected, the plugin should provide context in the string returned by &lt;code&gt;get_last_error()&lt;/code&gt; before returning.&lt;/p&gt;
&lt;h3 id="get-metrics"&gt;get_metrics&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ss_plugin_metric* plugin_get_metrics(ss_plugin_t* s, uint32_t* num_metrics) [Required: no]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function returns the pointer to the first element of an array containing plugin-provided custom metrics.&lt;/p&gt;
&lt;p&gt;Each element of the array is a &lt;code&gt;ss_plugin_metric&lt;/code&gt; which is &lt;a href="https://github.com/falcosecurity/libs/blob/0.17.2/userspace/plugin/plugin_types.h#L331-L345"&gt;defined&lt;/a&gt; in the plugin API as follows:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-CPP" data-lang="CPP"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;typedef&lt;/span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;struct&lt;/span&gt; &lt;span style="color:#00f"&gt;ss_plugin_metric&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;char&lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt; name; &lt;span style="color:#080;font-style:italic"&gt;//Opaque string representing the metric name.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_metric_type type; &lt;span style="color:#080;font-style:italic"&gt;// Metric type, indicates whether the metric value is monotonic or non-monotonic.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_metric_value value; &lt;span style="color:#080;font-style:italic"&gt;// Metric numeric value.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_metric_value_type value_type; &lt;span style="color:#080;font-style:italic"&gt;// Metric value data type, e.g. `uint64_t`.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} ss_plugin_metric;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Each metric defines its own name, value, type (monotonic or non-monotonic) and value type (data type of its numeric value).&lt;/p&gt;
&lt;p&gt;The argument &lt;code&gt;num_metrics&lt;/code&gt; is a return argument and must be set to the length of the array before returning. It can be set to &lt;code&gt;0&lt;/code&gt; if no metrics are provided.&lt;/p&gt;
&lt;h2 id="event-sourcing-capability-api"&gt;Event Sourcing Capability API&lt;/h2&gt;
&lt;h3 id="get-id"&gt;get_id&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;uint32_t plugin_get_id() [Required: varies]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This should return the &lt;a href="https://v0-43--falcosecurity.netlify.app/docs/plugins#plugin-event-ids"&gt;event ID&lt;/a&gt; allocated to your plugin. During development and before receiving an official event ID, you can use the &amp;quot;Test&amp;quot; value of 999.&lt;/p&gt;
&lt;p&gt;This function is required if &lt;code&gt;get_event_source&lt;/code&gt; is defined and returns a non-empty string, otherwise it is considered optional. Returning zero is equivalent to not implementing the function. If the plugin has a non-zero ID and a non-empty event source, then its &lt;code&gt;next_batch&lt;/code&gt; function is allowed to only return events of plugin type (code 322) with its own plugin ID and event source.&lt;/p&gt;
&lt;h3 id="get-event-source"&gt;get_event_source&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;const char* plugin_get_event_source() [Required: varies]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function returns a C string, with memory owned by the plugin, containing the plugin's &lt;a href="https://v0-43--falcosecurity.netlify.app/docs/plugins/#plugin-event-sources-and-interoperability"&gt;event source&lt;/a&gt;. This event source is used for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Associating Falco rules with plugin events--A Falco rule with a &lt;code&gt;source: gizmo&lt;/code&gt; property will run on all events returned by the gizmo plugin's &lt;code&gt;next_batch&lt;/code&gt; function.&lt;/li&gt;
&lt;li&gt;Linking together plugins with field extraction capability and plugins with event sourcing capability. The first can list a given event source like &lt;code&gt;gizmo&lt;/code&gt; in its &lt;code&gt;get_extract_event_sources&lt;/code&gt; function, and they will get an opportunity to extract fields from all events returned by the &amp;quot;gizmo&amp;quot; plugin.&lt;/li&gt;
&lt;li&gt;Ensuring that only one plugin at a time is loaded for a given source.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When defining a source, make sure it accurately describes the events from your plugin (e.g. use &lt;code&gt;aws_cloudtrail&lt;/code&gt; for AWS CloudTrail events, not &lt;code&gt;json&lt;/code&gt; or &lt;code&gt;logs&lt;/code&gt;) and doesn't overlap with the source of any other plugin with event sourcing capability.&lt;/p&gt;
&lt;p&gt;The only time where duplicate sources make sense are when a group of plugins can use a standard data format for a given event. For example, plugins might extract &lt;code&gt;k8s_audit&lt;/code&gt; events from multiple cloud sources like gcp, azure, aws, etc. If they all format their events as json objects that have identical formats as one could obtain by using &lt;a href="https://kubernetes.io/docs/tasks/debug-application-cluster/audit/"&gt;K8s Audit&lt;/a&gt; hooks, then it would make sense for the plugins to use the same source.&lt;/p&gt;
&lt;p&gt;This function is required if &lt;code&gt;get_id&lt;/code&gt; is defined and returns a non-zero ID, otherwise it is considered optional. Returning an empty string is equivalent to not implementing the function. If the plugin has a non-zero ID and a non-empty event source, then its &lt;code&gt;next_batch&lt;/code&gt;
function is allowed to only return events of plugin type (code 322) with its own plugin ID and event source.&lt;/p&gt;
&lt;h3 id="open"&gt;open&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ss_instance_t* plugin_open(ss_plugin_t* s, const char* params, int32_t* rc) [Required: yes]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function is called to &amp;quot;open&amp;quot; a stream of events. The interpretation of a stream of events is up to the plugin author, but think of &lt;code&gt;plugin_init&lt;/code&gt; as initializing the plugin software, and &lt;code&gt;plugin_open&lt;/code&gt; as configuring the software to return events. Using a streaming audio analogy, &lt;code&gt;plugin_init&lt;/code&gt; turns on the app, and &lt;code&gt;plugin_open&lt;/code&gt; starts a streaming audio channel.&lt;/p&gt;
&lt;p&gt;The same general guidelines apply for &lt;code&gt;plugin_open&lt;/code&gt; as do for &lt;code&gt;plugin_init&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All state related to sourcing a stream of events should be in the returned &lt;code&gt;ss_instance_t&lt;/code&gt; pointer.&lt;/li&gt;
&lt;li&gt;Return 0 on success, 1 on error. Be ready to return an error via &lt;code&gt;plugin_get_last_error&lt;/code&gt; on error.&lt;/li&gt;
&lt;li&gt;The plugin should support concurrent open sessions at once. Unlike plugin-level state, it's very likely that the plugin framework might call &lt;code&gt;plugin_open&lt;/code&gt; multiple times for a given plugin.&lt;/li&gt;
&lt;li&gt;On error, do not return any instance struct, as the plugin framework will not call &lt;code&gt;plugin_close&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If a non-NULL &lt;code&gt;ss_instance_t*&lt;/code&gt; instance is returned, then subsequent invocations of &lt;code&gt;open&lt;/code&gt; must not return the same &lt;code&gt;ss_instance_t*&lt;/code&gt; value again, unless it has been disposed with &lt;code&gt;close&lt;/code&gt; first.&lt;/p&gt;
&lt;h3 id="close"&gt;close&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;void plugin_close(ss_plugin_t* s, ss_instance_t* h) [Required: yes]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function closes a stream of events previously started via a call to &lt;code&gt;plugin_open&lt;/code&gt;. Afterwards, the stream should be considered closed and the framework will not call &lt;code&gt;plugin_next_batch&lt;/code&gt;/&lt;code&gt;plugin_extract_fields&lt;/code&gt; with the same &lt;code&gt;ss_instance_t&lt;/code&gt; pointer.&lt;/p&gt;
&lt;h3 id="next-batch"&gt;next_batch&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;int32_t plugin_next_batch(ss_plugin_t* s, ss_instance_t* h, uint32_t *nevts, ss_plugin_event ***evts) [Required: yes]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function is used to return a set of next events to the plugin framework, given a plugin state and open instance.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;*evts&lt;/code&gt; should be updated to an allocated contiguous array of &lt;code&gt;ss_plugin_event&lt;/code&gt; pointers. The memory for the structs array is owned by the plugin and should be held until the next call to &lt;code&gt;plugin_next_batch&lt;/code&gt;. &lt;code&gt;*nevts&lt;/code&gt; should be updated with the number of events returned.&lt;/p&gt;
&lt;p&gt;An event is represented by a &lt;code&gt;ss_plugin_event&lt;/code&gt; struct, which observes the same format of the &lt;a href="https://v0-43--falcosecurity.netlify.app/docs/reference/plugins/plugin-api-reference/#libscap-event-block-specification"&gt;libscap event block specification&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This function should return:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SS_PLUGIN_SUCCESS&lt;/code&gt; (0) on success&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SS_PLUGIN_FAILURE&lt;/code&gt; (1) on failure&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SS_PLUGIN_TIMEOUT&lt;/code&gt; (-1) on non-error but there are no events to return.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SS_PLUGIN_EOF&lt;/code&gt; (6) when the stream of events is complete.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the plugin receives a &lt;code&gt;SS_PLUGIN_FAILURE&lt;/code&gt;, it will close the stream of events by calling &lt;code&gt;plugin_close&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If a plugin implements a specific event source (&lt;code&gt;get_id&lt;/code&gt; is non-zero and &lt;code&gt;get_event_source&lt;/code&gt; is non-empty), then, it is only allowed to produce events of type plugin (code 322) containing its own plugin ID (as returned by &lt;code&gt;get_id&lt;/code&gt;). In such a case, when an event contains a zero plugin ID, the framework automatically sets the plugin ID of the event to the one of the plugin. If a plugin does not implement a specific event source, it is allowed to produce events of any of the types supported by the &lt;a href="https://v0-43--falcosecurity.netlify.app/docs/reference/plugins/plugin-api-reference/#libscap-event-block-specification"&gt;libscap specific&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;SS_PLUGIN_TIMEOUT&lt;/code&gt; should be returned whenever no events can be returned immediately. This ensures that the plugin framework is not stalled waiting for a response from &lt;code&gt;plugin_next_batch&lt;/code&gt;. When the framework receives a &lt;code&gt;SS_PLUGIN_TIMEOUT&lt;/code&gt;, it will keep the stream of events open and call &lt;code&gt;plugin_next_batch&lt;/code&gt; again later.&lt;/p&gt;
&lt;p&gt;This function can be invoked concurrently by multiple threads, each with distinct and unique parameter values. The value of the &lt;code&gt;ss_plugin_event***&lt;/code&gt; output parameter must be uniquely attached to the ss_instance_t* parameter value. The pointer must not be shared across multiple distinct &lt;code&gt;ss_instance_t*&lt;/code&gt; values.&lt;/p&gt;
&lt;h3 id="get-progress"&gt;get_progress&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;const char* plugin_get_progress(ss_plugin_t* s, ss_instance_t* h, uint32_t* progress_pct) [Required: no]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If the plugin exports this function, the framework will periodically call it after open to return how much of the event stream has been read. If a plugin does not provide a bounded stream of events (for example, events coming from a file or other source that has an ending), it should not export this function.&lt;/p&gt;
&lt;p&gt;If not exported, the plugin framework will not print meaningful process indicators while processing event streams.&lt;/p&gt;
&lt;p&gt;When called, the &lt;code&gt;progress_pct&lt;/code&gt; pointer should be updated with the read progress, as a number between 0 (no data has been read) and 10000 (100% of the data has been read). This encoding allows the engine to print progress decimals without requiring to deal with floating point numbers (which could cause incompatibility problems with some languages).&lt;/p&gt;
&lt;p&gt;The return value is an string representation of the read progress, with the memory owned by the plugin. This might include the progress percentage combined with additional context added by the plugin. The plugin can return &lt;code&gt;NULL&lt;/code&gt;. In this case, the framework will use the &lt;code&gt;progress_pct&lt;/code&gt; value instead.&lt;/p&gt;
&lt;p&gt;This function can be invoked concurrently by multiple threads, each with distinct and unique parameter values. If the returned pointer is non-NULL, then it must be uniquely attached to the &lt;code&gt;ss_instance_t*&lt;/code&gt; parameter value. The pointer must not be shared across multiple distinct &lt;code&gt;ss_instance_t*&lt;/code&gt; values.&lt;/p&gt;
&lt;h3 id="event-to-string"&gt;event_to_string&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;const char* plugin_event_to_string(ss_plugin_t *s, const ss_plugin_event_input *evt) [Required: no]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function is used to return a printable representation of an event. The memory is owned by the plugin and can be freed on the next call to &lt;code&gt;plugin_event_to_string&lt;/code&gt;. It is used in filtering/output expressions as the built-in field &lt;code&gt;evt.plugininfo&lt;/code&gt;. Even if implemented, this function is ignored if a plugin does not implement a specific event source (&lt;code&gt;get_id&lt;/code&gt; is undefined or returns zero, and &lt;code&gt;get_event_source&lt;/code&gt; is undefined or returns an empty string).&lt;/p&gt;
&lt;p&gt;The string representation should be on a single line and contain important information about the event. It is not necessary to return all information from the event. Simply return the most important fields/properties of the event that provide a useful default representation.&lt;/p&gt;
&lt;p&gt;Here is an example output, from the &lt;a href="https://github.com/falcosecurity/plugins/blob/master/plugins/cloudtrail"&gt;cloudtrail&lt;/a&gt; plugin:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;us-east-1 masters.some-demo.k8s.local s3 GetObject Size=0 URI=s3://some-demo-env/some-demo.k8s.local/backups/etcd/events/control/etcd-cluster-created
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function can be invoked concurrently by multiple threads, each with distinct and unique parameter values. If the returned pointer is non-NULL, then it must be uniquely attached to the &lt;code&gt;ss_plugin_t*&lt;/code&gt; parameter value. The pointer must not be shared across multiple distinct &lt;code&gt;ss_plugin_t*&lt;/code&gt; values.&lt;/p&gt;
&lt;h3 id="list-open-params"&gt;list_open_params&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;const char* plugin_list_open_params(ss_plugin_t* s, ss_plugin_rc* rc) [Required: no]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function returns a list of suggested values that are valid parameters for the &lt;code&gt;open&lt;/code&gt; plugin function.
Although non-required, this function is useful to instruct users about potential valid parameters for opening a stream of events. Implementing this function also brings additional usage documentation for the plugin, and allows makes it more usable with automated tools.&lt;/p&gt;
&lt;p&gt;The returned value is a json string, with memory owned by the plugin, which contains an array of objects. Each object describes one suggested value for the &lt;code&gt;open&lt;/code&gt; function. Here's an example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#008000;font-weight:bold"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;: &lt;span style="color:#b44"&gt;&amp;#34;resource1&amp;#34;&lt;/span&gt;, &lt;span style="color:#008000;font-weight:bold"&gt;&amp;#34;desc&amp;#34;&lt;/span&gt;: &lt;span style="color:#b44"&gt;&amp;#34;An example of openable resource&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#008000;font-weight:bold"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;: &lt;span style="color:#b44"&gt;&amp;#34;resource2&amp;#34;&lt;/span&gt;, &lt;span style="color:#008000;font-weight:bold"&gt;&amp;#34;desc&amp;#34;&lt;/span&gt;: &lt;span style="color:#b44"&gt;&amp;#34;Another example of openable resource&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#008000;font-weight:bold"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;: &lt;span style="color:#b44"&gt;&amp;#34;res1;res2;res3&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#008000;font-weight:bold"&gt;&amp;#34;desc&amp;#34;&lt;/span&gt;: &lt;span style="color:#b44"&gt;&amp;#34;Some names&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#008000;font-weight:bold"&gt;&amp;#34;separator&amp;#34;&lt;/span&gt;: &lt;span style="color:#b44"&gt;&amp;#34;;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Each object has the following properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;value&lt;/code&gt;: a string usable as a parameter for &lt;code&gt;open&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;desc&lt;/code&gt;: (optional) a string with that describes the meaning of &lt;code&gt;value&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;separator&lt;/code&gt;: (optional) a string representing a separator string in case &lt;code&gt;value&lt;/code&gt; represents a list of concatenated values. This can be used by plugins to specify an open param that represents more than one source, in which case they can be separated by the separator substring. It's a plugin responsibility to specify the separator string.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="field-extraction-capability-api"&gt;Field Extraction Capability API&lt;/h2&gt;
&lt;h3 id="get-fields"&gt;get_fields&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;const char* plugin_get_fields() [Required: yes]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function should return the set of fields supported by the plugin. Remember, a field is a name (e.g. &lt;code&gt;proc.name&lt;/code&gt;) that can extract a value (e.g. &lt;code&gt;nginx&lt;/code&gt;) from an event (e.g. a syscall event involving a process). The return value is a string whose memory is owned by the plugin. The string is json formatted and contains an array of objects. Each object describes one field. Here's an example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#008000;font-weight:bold"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#b44"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;, &lt;span style="color:#008000;font-weight:bold"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#b44"&gt;&amp;#34;gizmo.field1&amp;#34;&lt;/span&gt;, &lt;span style="color:#008000;font-weight:bold"&gt;&amp;#34;arg&amp;#34;&lt;/span&gt;: {&lt;span style="color:#008000;font-weight:bold"&gt;&amp;#34;isRequired&amp;#34;&lt;/span&gt;: &lt;span style="color:#a2f;font-weight:bold"&gt;true&lt;/span&gt;, &lt;span style="color:#008000;font-weight:bold"&gt;&amp;#34;isKey&amp;#34;&lt;/span&gt;: &lt;span style="color:#a2f;font-weight:bold"&gt;true&lt;/span&gt;}, &lt;span style="color:#008000;font-weight:bold"&gt;&amp;#34;desc&amp;#34;&lt;/span&gt;: &lt;span style="color:#b44"&gt;&amp;#34;Describing field 1&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#008000;font-weight:bold"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#b44"&gt;&amp;#34;uint64&amp;#34;&lt;/span&gt;, &lt;span style="color:#008000;font-weight:bold"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#b44"&gt;&amp;#34;gizmo.field2&amp;#34;&lt;/span&gt;, &lt;span style="color:#008000;font-weight:bold"&gt;&amp;#34;desc&amp;#34;&lt;/span&gt;: &lt;span style="color:#b44"&gt;&amp;#34;Describing field 2&amp;#34;&lt;/span&gt;, &lt;span style=""&gt;properties:&lt;/span&gt; &lt;span style=""&gt;[&lt;/span&gt;&lt;span style="color:#008000;font-weight:bold"&gt;&amp;#34;hidden&amp;#34;&lt;/span&gt;&lt;span style=""&gt;]&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Each object has the following properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;type&lt;/code&gt;: one of &amp;quot;string&amp;quot;, &amp;quot;uint64&amp;quot;, &amp;quot;bool&amp;quot;, &amp;quot;reltime&amp;quot;, &amp;quot;abstime&amp;quot;, &amp;quot;ipaddr&amp;quot;, &amp;quot;ipnet&amp;quot;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;name&lt;/code&gt;: a string with a name for the field. By convention, this is a dot-separated path of names. Use a consistent first name e.g. &amp;quot;ct.xxx&amp;quot; to help filter authors associate the field with a given plugin.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isList&lt;/code&gt;: (optional) If present and set to true, notes that the field extracts a list of values. Fields of this kind can only be used with the &lt;code&gt;in&lt;/code&gt; and &lt;code&gt;intersects&lt;/code&gt; filtering operators. For list fields, extracting single values means extracting lists of length equal to 1.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;arg&lt;/code&gt;: (optional) if present, notes that the field can accept an argument e.g. field[arg]. More precisely, the following flags could be specified:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;isRequired&lt;/code&gt;: if true, the argument is required.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isIndex&lt;/code&gt;: if true, the field is numeric.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isKey&lt;/code&gt;: if true, the field is a string. If &lt;code&gt;isRequired&lt;/code&gt; is true, one between &lt;code&gt;isIndex&lt;/code&gt; and &lt;code&gt;isKey&lt;/code&gt; must be true, to specify the argument type. If &lt;code&gt;isRequired&lt;/code&gt; is false, but one between &lt;code&gt;isIndex&lt;/code&gt; and &lt;code&gt;isKey&lt;/code&gt; is true, the argument is allowed but not required.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;display&lt;/code&gt;: (optional) If present, a string that will be used to display the field instead of the name. Used in tools like wireshark.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;desc&lt;/code&gt;: a string with a short description of the field. This will be used in help output so be concise and descriptive.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;properties&lt;/code&gt;: (optional) If present, an array of additional properties that apply to the field. The value is an array of strings that can be one of the following:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;hidden&lt;/code&gt;: Do not display the field when using programs like &lt;code&gt;falco --list&lt;/code&gt; to list the set of supported fields.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conversation&lt;/code&gt;: This field is applicable for use in &lt;a href="https://www.wireshark.org/docs/wsug_html_chunked/ChStatConversations.html"&gt;wireshark conversations&lt;/a&gt;, and denotes that the field represents one half of a &amp;quot;conversation&amp;quot; that can be shown in the conversations or endpoints view.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;info&lt;/code&gt;: Also applicable for use in wireshark, and denotes that it should be appended to the &amp;quot;info&amp;quot; column in the wireshark event list.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When defining fields, keep the following guidelines in mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Field names should generally have the plugin name/event source as the first component, and usually have one or two additional components. For example, &lt;code&gt;gizmo.pid&lt;/code&gt; is preferred over &lt;code&gt;gizmo.process.id.is&lt;/code&gt;. If a plugin has a moderately large set of fields, using components to group fields may make sense (e.g. &lt;code&gt;cloudtrail.s3.bytes.in&lt;/code&gt; and &lt;code&gt;cloudtrail.s3.bytes.out&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Fields should be idempotent: for a given event, the value for a field should be the same regardless of when/where the event was generated.&lt;/li&gt;
&lt;li&gt;Fields should be neutral: define fields that extract properties of the event (e.g. &amp;quot;source ip address&amp;quot;) rather than judgements (e.g. &amp;quot;source ip address is associated with a botnet&amp;quot;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="extract-fields"&gt;extract_fields&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;int32_t plugin_extract_fields(ss_plugin_t *s, const ss_plugin_event_input *evt, const ss_plugin_field_extract_input* in) [Required: yes]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function is used to return the value for one or more field names that were returned in &lt;code&gt;plugin_get_fields&lt;/code&gt;. The framework provides an event and an input containing an array of &lt;code&gt;ss_plugin_extract_field&lt;/code&gt; structs. Each struct has one field name/type, and the plugin fills in each struct with the corresponding value for that field.&lt;/p&gt;
&lt;p&gt;The format of the &lt;code&gt;ss_plugin_extract_field&lt;/code&gt; struct is the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-CPP" data-lang="CPP"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// The noncontiguous numbers are to maintain equality with underlying
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// falcosecurity/libs types.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;typedef&lt;/span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;enum&lt;/span&gt; &lt;span style="color:#00f"&gt;ss_plugin_field_type&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// A 64bit unsigned integer.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; FTYPE_UINT64 &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#666"&gt;8&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// A printable buffer of bytes, NULL terminated
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; FTYPE_STRING &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#666"&gt;9&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// A relative time. Seconds * 10^9 + nanoseconds. 64bit.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; FTYPE_RELTIME &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#666"&gt;20&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// An absolute time interval. Seconds from epoch * 10^9 + nanoseconds. 64bit.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; FTYPE_ABSTIME &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#666"&gt;21&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// A boolean value, 4 bytes.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; FTYPE_BOOL &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#666"&gt;25&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Either an IPv4 or IPv6 address. The length indicates which one it is.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; FTYPE_IPADDR &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#666"&gt;40&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Either an IPv4 or IPv6 network. The length indicates which one it is.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// The field encodes only the IP address, so this differs from FTYPE_IPADDR,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// from the way the framework perform runtime checks and comparisons.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; FTYPE_IPNET &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#666"&gt;41&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}ss_plugin_field_type;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;typedef&lt;/span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;struct&lt;/span&gt; &lt;span style="color:#00f"&gt;ss_plugin_extract_field&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;union&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;char&lt;/span&gt;&lt;span style="color:#666"&gt;**&lt;/span&gt; str;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;uint64_t&lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt; u64;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;uint32_t&lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt; u32;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_bool&lt;span style="color:#666"&gt;*&lt;/span&gt; boolean;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_byte_buffer&lt;span style="color:#666"&gt;*&lt;/span&gt; buf;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } res;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;uint64_t&lt;/span&gt; res_len;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;uint32_t&lt;/span&gt; field_id;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;char&lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt; field;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;char&lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt; arg_key;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;uint64_t&lt;/span&gt; arg_index;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;bool&lt;/span&gt; arg_present;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;uint32_t&lt;/span&gt; ftype;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;bool&lt;/span&gt; flist;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} ss_plugin_extract_field;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For each struct, the plugin fills in &lt;code&gt;field_id&lt;/code&gt;/&lt;code&gt;field&lt;/code&gt;/&lt;code&gt;arg&lt;/code&gt;/&lt;code&gt;ftype&lt;/code&gt; with the field. &lt;code&gt;field_id&lt;/code&gt; is the index into the original list of fields returned by &lt;code&gt;plugin_get_fields&lt;/code&gt;, and allows for faster mapping to a plugin's set of fields. The plugin should fill in &lt;code&gt;res_len&lt;/code&gt; and &lt;code&gt;res&lt;/code&gt; with a pointer to an array of values of appropriate type for the field, depending on the field type &lt;code&gt;ftype&lt;/code&gt;. If the field type is &lt;code&gt;FTYPE_STRING&lt;/code&gt;, res should be updated to point to an string with the string value, with memory owned by the plugin. The plugin should retain this memory until the next call to &lt;code&gt;plugin_extract_fields&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If &lt;code&gt;res_len&lt;/code&gt; is set to zero, the plugin framework assumes that &lt;code&gt;res&lt;/code&gt; is undefined and will not use it. Setting a &lt;code&gt;res_len&lt;/code&gt; value grater than 1 is allowed only for fields for which &lt;code&gt;isList&lt;/code&gt; is defined as true.&lt;/p&gt;
&lt;p&gt;This function can be invoked concurrently by multiple threads, each with distinct and unique parameter values. The value of the &lt;code&gt;ss_plugin_extract_field*&lt;/code&gt; output parameter must be uniquely attached to the &lt;code&gt;ss_plugin_t*&lt;/code&gt; parameter value. The pointer must not be shared across multiple distinct &lt;code&gt;ss_plugin_t*&lt;/code&gt; values.&lt;/p&gt;
&lt;h3 id="get-extract-event-sources"&gt;get_extract_event_sources&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;const char* plugin_get_extract_event_sources() [Required: no]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function allows the plugin to restrict the kinds of events where the plugin's &lt;code&gt;extract_fields&lt;/code&gt; method will be called. Valid event source names are the ones returned by the &lt;code&gt;get_event_source&lt;/code&gt; function of plugins with event sourcing capability, or &lt;code&gt;syscall&lt;/code&gt; for indicating support to non-plugin events. The return value should be a string containing a json array of compatible event sources, with memory owned by the plugin. Here's an example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[&lt;span style="color:#b44"&gt;&amp;#34;aws_cloudtrail&amp;#34;&lt;/span&gt;, &lt;span style="color:#b44"&gt;&amp;#34;gcp_cloudtrail&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This implies that the plugin can potentially extract values from events that have a source &lt;code&gt;aws_cloudtrail&lt;/code&gt; or &lt;code&gt;gcp_cloudtrail&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This function is optional. If the plugin does not export this function or if it returns an empty array (or &lt;code&gt;NULL&lt;/code&gt;), then if the plugin has sourcing capability, and implements a specific event source, it will only receive events matching its event source, otherwise the framework will assume the plugin can receive events from all event sources.&lt;/p&gt;
&lt;h3 id="get-extract-event-types"&gt;get_extract_event_types&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;uint16_t* plugin_get_extract_event_types(uint32_t* numtypes) [Required: no]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function allows the plugin to restrict the kinds of events where the plugin's &lt;code&gt;extract_fields&lt;/code&gt; method will be called. The return value is an array of integers representing the event types that the plugin is capable of processing for field extraction. Events with types that are not present in the returned list will not be received by the plugin. The event types follow the enumeration from the &lt;a href="https://v0-43--falcosecurity.netlify.app/docs/reference/plugins/plugin-api-reference/#libscap-event-block-specification"&gt;libscap specific&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This function is optional. If the plugin does not export this function or if it returns an empty array (or &lt;code&gt;NULL&lt;/code&gt;), the plugin will receive every event type if the result of &lt;code&gt;get_extract_event_sources&lt;/code&gt; (either default or custom) is compatible with the &lt;code&gt;syscall&lt;/code&gt; event source, otherwise the plugin will only receive events of plugin type (code 322).&lt;/p&gt;
&lt;h2 id="event-parsing-capability-api"&gt;Event Parsing Capability API&lt;/h2&gt;
&lt;h3 id="parse-event"&gt;parse_event&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ss_plugin_rc plugin_parse_event(ss_plugin_t *s, const ss_plugin_event_input *evt, const ss_plugin_event_parse_input* in) [Required: yes]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Receives an event from the current capture and parses its content. The plugin is guaranteed to receive an event at most once, after any operation related the event sourcing capability, and before any other operation related to the field extraction capability. The returned rc value should be &lt;code&gt;SS_PLUGIN_SUCCESS&lt;/code&gt; (0) on success, &lt;code&gt;SS_PLUGIN_FAILURE&lt;/code&gt; (1) on failure.&lt;/p&gt;
&lt;p&gt;The framework provides an event and an input. The event pointer is allocated and owner by the framework, and it is not guaranteed that to refer to the same memory or data returned by the last &lt;code&gt;next_batch&lt;/code&gt; call (in case the same plugin also supports the event sourcing capability). The input is a vtable containing callbacks towards the plugin's owner that can be used by the plugin for performing read/write operations on state tables not owned by itself, for which it obtained accessors at initialization time. The plugin does not need to go through this vtable in order to read and write from a table it owns.&lt;/p&gt;
&lt;p&gt;This function can be invoked concurrently by multiple threads, each with distinct and unique parameter values. The value of the ss_plugin_event_parse_input* output parameter must be uniquely attached to the ss_plugin_t* parameter value. The pointer must not be shared across multiple distinct ss_plugin_t* values.&lt;/p&gt;
&lt;h3 id="get-parse-event-sources"&gt;get_parse_event_sources&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;const char* plugin_get_parse_event_sources() [Required: no]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function allows the plugin to restrict the kinds of events where the plugin's &lt;code&gt;parse_event&lt;/code&gt; method will be called. Valid event source names are the ones returned by the &lt;code&gt;get_event_source&lt;/code&gt; function of plugins with event sourcing capability, or &lt;code&gt;syscall&lt;/code&gt; for indicating support to non-plugin events. The return value should be a string containing a json array of compatible event sources, with memory owned by the plugin.&lt;/p&gt;
&lt;p&gt;This function is optional. If the plugin does not export this function or if it returns an empty array (or &lt;code&gt;NULL&lt;/code&gt;), then if the plugin has sourcing capability, and implements a specific event source, it will only receive events matching its event source, otherwise the framework will assume the plugin can receive events from all event sources.&lt;/p&gt;
&lt;h3 id="get-parse-event-types"&gt;get_parse_event_types&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;uint16_t* plugin_get_parse_event_types(uint32_t* numtypes) [Required: no]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This function allows the plugin to restrict the kinds of events where the plugin's &lt;code&gt;parse_event&lt;/code&gt; method will be called. The return value is an array of integers representing the event types that the plugin is capable of processing for field extraction. Events with types that are not present in the returned list will not be received by the plugin. The event types follow the enumeration from the &lt;a href="https://v0-43--falcosecurity.netlify.app/docs/reference/plugins/plugin-api-reference/#libscap-event-block-specification"&gt;libscap specific&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This function is optional. If the plugin does not export this function or if it returns an empty array (or &lt;code&gt;NULL&lt;/code&gt;), the plugin will receive every event type if the result of &lt;code&gt;get_parse_event_sources&lt;/code&gt; (either default or custom) is compatible with the &lt;code&gt;syscall&lt;/code&gt; event source, otherwise the plugin will only receive events of plugin type (code 322).&lt;/p&gt;
&lt;h2 id="async-events-capability-api"&gt;Async Events Capability API&lt;/h2&gt;
&lt;h3 id="get-async-event-sources"&gt;get_async_event_sources&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;const char* plugin_get_async_event_sources() [Required: no]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The return value should be a string containing a json array of compatible event sources, with memory owned by the plugin. The list describes the event sources for which this plugin is capable of injecting async events in the event stream of a capture.&lt;/p&gt;
&lt;p&gt;This function is optional. If the plugin does not export this function or if it returns an empty array (or &lt;code&gt;NULL&lt;/code&gt;), then the async
events produced by a plugin will be injected in the event stream of any source.&lt;/p&gt;
&lt;h3 id="get-async-events"&gt;get_async_events&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;const char* plugin_get_async_events() [Required: yes]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Return a string describing the name list of all asynchronous events that this plugin is capable of pushing into a live event stream. The framework can reject async events produced by a plugin if their name is not on the name list returned by this function. The return value should be a string containing a json array of compatible event sources, with memory owned by the plugin.&lt;/p&gt;
&lt;h3 id="set-async-event-handler"&gt;set_async_event_handler&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ss_plugin_rc plugin_set_async_event_handler(ss_plugin_t* s, ss_plugin_owner_t* owner, const ss_plugin_async_event_handler_t handler) [Required: yes]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Sets a function handler that allows the plugin to send events asynchronously to its owner during a live event capture. The handler is a thread-safe function that can be invoked concurrently by multiple threads. The asynchronous events must be encoded as an async event type (code 402) as for the &lt;a href="https://v0-43--falcosecurity.netlify.app/docs/reference/plugins/plugin-api-reference/#libscap-event-block-specification"&gt;libscap specific&lt;/a&gt;. The returned rc value should be &lt;code&gt;SS_PLUGIN_SUCCESS&lt;/code&gt; (0) on success, &lt;code&gt;SS_PLUGIN_FAILURE&lt;/code&gt; (1) on failure.&lt;/p&gt;
&lt;p&gt;The memory of events sent to the async event handler function must be owned by the plugin and is not retained by the owner after the event handler returns. The async event handler function is defined as follows:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-CPP" data-lang="CPP"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// Function handler used by plugin for sending asynchronous events to the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// Falcosecurity libs during a live event capture. The asynchronous events
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// must be encoded as an async event type (code 402) as for the libscap specific.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// The function returns SS_PLUGIN_SUCCESS in case of success, or
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// SS_PLUGIN_FAILURE otherwise. If a non-NULL char pointer is passed for
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// the &amp;#34;err&amp;#34; argument, it will be filled with an error message string
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// in case the handler function returns SS_PLUGIN_FAILURE. The error string
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// has a max length of PLUGIN_MAX_ERRLEN (termination char included) and its
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// memory must be allocated and owned by the plugin.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;typedef&lt;/span&gt; &lt;span style="color:#00a000"&gt;ss_plugin_rc&lt;/span&gt; (&lt;span style="color:#666"&gt;*&lt;/span&gt;ss_plugin_async_event_handler_t)(ss_plugin_owner_t&lt;span style="color:#666"&gt;*&lt;/span&gt; o, &lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; ss_plugin_event &lt;span style="color:#666"&gt;*&lt;/span&gt;evt, &lt;span style="color:#0b0;font-weight:bold"&gt;char&lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt; err);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The plugin can start sending async events through the passed-in handler right from the moment this function is invoked. &lt;code&gt;set_async_event_handler&lt;/code&gt; can be invoked multiple times during the lifetime of a plugin. In that case, the registered function handler remains valid up until the next invocation of &lt;code&gt;set_async_event_handler&lt;/code&gt; on the same plugin, after which the new handler set must replace any already-set one. If the handler is set to a &lt;code&gt;NULL&lt;/code&gt; function pointer, the plugin is instructed about disabling or stopping the production of async events. If a &lt;code&gt;NULL&lt;/code&gt; handler is set, and an asynchronous job has been started by the plugin before, the plugin should stop the job and wait for it to be finished before returning from this function. Although the event handler is thread-safe and can be invoked concurrently, this function is still invoked by the framework sequentially from the same thread.&lt;/p&gt;
&lt;p&gt;The C++ example below shows how an async event handler can be correctly used from an asynchronous thread with proper start and stop conditions:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-CPP" data-lang="CPP"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;typedef&lt;/span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;struct&lt;/span&gt; &lt;span style="color:#00f"&gt;my_plugin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#666"&gt;::&lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;thread&lt;/span&gt; async_thread;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#666"&gt;::&lt;/span&gt;atomic&lt;span style="color:#666"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;bool&lt;/span&gt;&lt;span style="color:#666"&gt;&amp;gt;&lt;/span&gt; async_thread_run;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} my_plugin;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;extern&lt;/span&gt; &lt;span style="color:#b44"&gt;&amp;#34;C&amp;#34;&lt;/span&gt; ss_plugin_t&lt;span style="color:#666"&gt;*&lt;/span&gt; plugin_init(&lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; ss_plugin_init_input&lt;span style="color:#666"&gt;*&lt;/span&gt; in, ss_plugin_rc&lt;span style="color:#666"&gt;*&lt;/span&gt; rc)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; my_plugin &lt;span style="color:#666"&gt;*&lt;/span&gt;ret &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;new&lt;/span&gt; my_plugin();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ret&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;async_thread_run &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#a2f"&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#666"&gt;*&lt;/span&gt;rc &lt;span style="color:#666"&gt;=&lt;/span&gt; SS_PLUGIN_SUCCESS;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt; ret;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;extern&lt;/span&gt; &lt;span style="color:#b44"&gt;&amp;#34;C&amp;#34;&lt;/span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;void&lt;/span&gt; plugin_destroy(ss_plugin_t&lt;span style="color:#666"&gt;*&lt;/span&gt; s)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// stop the async thread if it&amp;#39;s running
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; my_plugin &lt;span style="color:#666"&gt;*&lt;/span&gt;ps &lt;span style="color:#666"&gt;=&lt;/span&gt; (my_plugin &lt;span style="color:#666"&gt;*&lt;/span&gt;) s;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt; (ps&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;async_thread_run)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ps&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;async_thread_run &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#a2f"&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt; (ps&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;async_thread.joinable())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ps&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;async_thread.join();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;delete&lt;/span&gt; ps;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;extern&lt;/span&gt; &lt;span style="color:#b44"&gt;&amp;#34;C&amp;#34;&lt;/span&gt; ss_plugin_rc plugin_set_async_event_handler(ss_plugin_t&lt;span style="color:#666"&gt;*&lt;/span&gt; s, ss_plugin_owner_t&lt;span style="color:#666"&gt;*&lt;/span&gt; owner, &lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; ss_plugin_async_event_handler_t handler)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; my_plugin &lt;span style="color:#666"&gt;*&lt;/span&gt;ps &lt;span style="color:#666"&gt;=&lt;/span&gt; (my_plugin &lt;span style="color:#666"&gt;*&lt;/span&gt;) s;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// stop the async thread if it&amp;#39;s running
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt; (ps&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;async_thread_run)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ps&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;async_thread_run &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#a2f"&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt; (ps&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;async_thread.joinable())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ps&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;async_thread.join();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// if an handler is provided, launch an async worker
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt; (handler)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ps&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;async_thread_run &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#a2f"&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ps&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;async_thread &lt;span style="color:#666"&gt;=&lt;/span&gt; std&lt;span style="color:#666"&gt;::&lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;thread&lt;/span&gt;([ps, owner, handler]()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;char&lt;/span&gt; err[PLUGIN_MAX_ERRLEN];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;while&lt;/span&gt; (ps&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;async_thread_run;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_event&lt;span style="color:#666"&gt;*&lt;/span&gt; evt &lt;span style="color:#666"&gt;=&lt;/span&gt; ps&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;do_some_work();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt; (handler(owner, evt, err) &lt;span style="color:#666"&gt;!=&lt;/span&gt; SS_PLUGIN_SUCCESS)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// report the error somehow
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt; SS_PLUGIN_SUCCESS;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Async events encode a plugin ID that defines its event source. However, this value is set by the framework when the async event is received, and is set to the ID associated to the plugin-defined event source currently open during a live capture, or zero in case of the &lt;code&gt;syscall&lt;/code&gt; event source. The event source assigned by the framework to the async event can only be among the ones compatible with the list returned by &lt;code&gt;get_async_event_sources&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Async events encode a string representing their event name, which is used for runtime matching and define the encoded data payload. Plugins are allowed to only send async events with one of the names expressed in the list returned by &lt;code&gt;get_async_events&lt;/code&gt;. The name of an async event acts as a contract on the encoding of the data payload of all async events with the same name.&lt;/p&gt;
&lt;h2 id="libscap-event-block-specification"&gt;Libscap Event Block Specification&lt;/h2&gt;
&lt;p&gt;Libscap, the Falcosecurity libs component responsible of event captures and control, proposes and supports a specification that regulates the way system, kernel, and plugin events are encoded. The same specification also defines the encoding of SCAP capture files, that can be used by the Falcosecurity libs to record and replay event streams. In the specification, events are defined as a specific block type of the &lt;a href="https://pcapng.com/"&gt;pcap-ng file format&lt;/a&gt;. All the event types and the associated parameters supported by libscap are defined by &lt;a href="https://github.com/falcosecurity/libs/blob/0.11.0/driver/event_table.c"&gt;the libscap's event table&lt;/a&gt;. The plugin API fully shares and observes the libscap's event definitions, and uses them for both reading and writing events from/to the framework.&lt;/p&gt;
&lt;p&gt;As for the libscap specific, an event is represented as a contiguous region of memory composed by a header and a list of parameters appended to it, in the form of:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-CPP" data-lang="CPP"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// | evt header | len param 1 (2B/4B) | ... | len param N (2B/4B) | data param 1 | ... | data param N |
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;typedef&lt;/span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;struct&lt;/span&gt; &lt;span style="color:#00f"&gt;ss_plugin_event&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;uint64_t&lt;/span&gt; ts; &lt;span style="color:#080;font-style:italic"&gt;/* timestamp, in nanoseconds from epoch */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;uint64_t&lt;/span&gt; tid; &lt;span style="color:#080;font-style:italic"&gt;/* the tid of the thread that generated this event */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;uint32_t&lt;/span&gt; len; &lt;span style="color:#080;font-style:italic"&gt;/* the event len, including the header */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;uint16_t&lt;/span&gt; type; &lt;span style="color:#080;font-style:italic"&gt;/* the event type */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;uint32_t&lt;/span&gt; nparams; &lt;span style="color:#080;font-style:italic"&gt;/* the number of parameters of the event */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} ss_plugin_event;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The event header is composed of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ts&lt;/code&gt;: the event timestamp, in nanoseconds since the epoch. Can be (uint64_t)-1, in which case the framework will automatically fill the event time with the current time.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tid&lt;/code&gt;: the tid of the thread that generated this event. Can be (uint64_t)-1 in case no thread is specified, such as when generating a plugin event (type code 322).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;len&lt;/code&gt;: the event len, including the header&lt;/li&gt;
&lt;li&gt;&lt;code&gt;type&lt;/code&gt;: the code of the event, as per the ones supported by the &lt;a href="https://v0-43--falcosecurity.netlify.app/docs/reference/plugins/plugin-api-reference/#libscap-event-block-specification"&gt;libscap specific&lt;/a&gt;. This dictates the number and kind of parameters, and whether the length is encoded as a 2 bytes or 4 bytes integer.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nparams&lt;/code&gt;: the number of parameters of the event&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Further and more formal documentation will be available in the future...&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="state-tables-api"&gt;State Tables API&lt;/h2&gt;
&lt;p&gt;In the plugin framework, &lt;strong&gt;state tables&lt;/strong&gt; are simple key-value mappings representing a piece of state owned by a component of the Falcosecurity libs or defined by a plugin. The plugin API declares formal abstract definitions for state tables and provides means for plugins to access the state owned by other components of the framework, define and own their own state, and make it accessible externally. In this context, a component of the framework is an abstract entity that could represent a given piece of machinery within the Falco libraries or any other plugin loaded at runtime.&lt;/p&gt;
&lt;h3 id="basic-concepts"&gt;Basic Concepts&lt;/h3&gt;
&lt;p&gt;A state table is a key-value map that can be used for storing pieces of state within the plugin framework. State tables are an abstract concept, and the plugin API does not enforce any specific implementation. Instead, the API specifies interface boundaries in the form of C virtual tables of methods representing the behavior of state tables. This allows the plugin API to remain flexible, abstract, and multi-language by nature. The model by which state tables work is defined by the notions of ownership, registration, and discovery.&lt;/p&gt;
&lt;p&gt;Every state table must have an owner, which is responsible of managing the table's memory and of implementing all the functions of the state tables API. Owners can either be plugins or any of the other actors that are part of the Falcosecurity libraries. For example, libsinsp is the owner of the &lt;code&gt;threads&lt;/code&gt; table, which is a key-value store where the key is a thread ID of a Linux machine and the value is a set of information describing a Linux thread. Plugins can access the &lt;code&gt;threads&lt;/code&gt; table of libsinsp for retrieving thread information given a thread ID, reading and writing the info fields, extending the info with additional metadata, and do much more. However, plugins are never responsible of managing the memory and the implementation of the &lt;code&gt;threads&lt;/code&gt; table, as it is owned by libsinsp only. Instead, plugins can do the same by defining their own stateful components and implementing the required interface functions to register them as &amp;quot;state tables&amp;quot;. Stateful components must be registered in the framework in order to be considered &amp;quot;state tables&amp;quot;. Libsinsp, which owns the plugins loaded at runtime, also holds a &amp;quot;table registry&amp;quot; that is the source of truth for all the state tables known at runtime. Once a state table is registered in the table registry, it is discoverable by all the actors and plugins running in the context of the same Falcosecurity libs instance.&lt;/p&gt;
&lt;p&gt;The way plugins can interact with state tables is through discovery and the usage of accessors. At initialization time (in the &lt;code&gt;init&lt;/code&gt; function), plugins are provided interface functions that allow them to list all the state tables available at runtime and obtaining &amp;quot;accessors&amp;quot; for later usage. An &lt;em&gt;accessor&lt;/em&gt; is an opaque pointers obtained at initialization time and that can be used later (e.g. when parsing an event or when extracting a field) for accessing a given table or the fields of its entries. Considering the example of the &lt;code&gt;threads&lt;/code&gt; table, in its &lt;code&gt;init&lt;/code&gt; function a given plugin could obtain an accessor to the table and to some of the fields of each thread info (such as the &lt;code&gt;pid&lt;/code&gt; or the &lt;code&gt;comm&lt;/code&gt;) and store them in its plugin state. Later, when extracting a field, the same plugin would be available to query the &lt;code&gt;threads&lt;/code&gt; table for a given thread ID (perhaps obtained by reading the event payload of a syscall) by using the table accessor, and then reading the &lt;code&gt;pid&lt;/code&gt; of the obtained thread by using the field accessor.&lt;/p&gt;
&lt;p&gt;Inherently, the plugin API also enable plugins to define their own state tables and register them in the table registry. Once that's done, the registered state table will be visible to all other plugins just like the &lt;code&gt;threads&lt;/code&gt; table, without knowing nor caring about which actor is owning it. The state table owned by the plugin will be discoverable through the table registry by the plugin itself too. However, plugins owning a given table are not forced to go through the state tables interface in order to operate on it (conversely, this could also be the less efficient choice). Plugins can implement their own state as they prefer, whereas the purpose of the state tables interface is solely to make that state available to other actors in the framework. Coherently, table owners can also decide &amp;quot;how much&amp;quot; of a table they want the other components to have visibility of. For example, libsinsp can access more info and functionalities on the &lt;code&gt;threads&lt;/code&gt; table than what it makes available through the state table interface, which is also natural considering that its implementation is hidden and can be arbitrary.&lt;/p&gt;
&lt;p&gt;The set of state tables made available by a given plugin or Falcosecurity libs actor, and the set of fields and operations available for each of those table, &lt;strong&gt;take part of the semantic versioned UX contract of that plugin or actor&lt;/strong&gt;. For example, removing a given table or table field from libsinsp can be considered a breaking change that must reflected by the version number of the Falcosecurity libs. The same applies for the version of each plugin and the state tables declared by them.&lt;/p&gt;
&lt;h3 id="access-and-consistency"&gt;Access and Consistency&lt;/h3&gt;
&lt;p&gt;State tables are dynamic structures. Each table is defined by a given key type, which can be any of the types supported by the &lt;code&gt;ss_plugin_state_type&lt;/code&gt; enumeration. Then, the each key-value mappings contained in the table are referred to as &lt;em&gt;table entries&lt;/em&gt;. Each entry has a specific set of information fields, which is shared across all the entries of the same table. Each field is named and has a specific type. The set of fields for the entries of a given table is defined dynamically at runtime and can be extended by different actors. For example, libsinsp populates the &lt;code&gt;threads&lt;/code&gt; table with a given set of information fields for each table's entry (representing a given thread info), and plugins can read and write the value of those fields by obtaining accessors for those. However, plugins also have the opportunity of defining new fields inside the &lt;code&gt;threads&lt;/code&gt; table, with a new unique name and a specific type, and libsinsp will be responsible of hosting that new piece of information for each thread and make it available to all actors in the framework. The same can happen for tables defined by any plugin.&lt;/p&gt;
&lt;p&gt;Given that state tables can get modified by different actors at runtime, there has to be a deterministic disambiguation about consistency of table edits and visibility of those changes. The plugin API implements this by guaranteeing a deterministic and non-changing total ordering of all the actors in the system. Considering a given ordering, an actor will have visibility only over the changes applied by actors coming before it in the given ordering. In the Falcosecurity libs and the plugin framework, the guaranteed order is the one by which plugins are loaded at runtime. The first actor in the order is always libsinsp itself, which means that all plugins will always see all the table modifications authored by libsinsp at a given point in time. Then, plugins are ordered by following their loading order at runtime. This means that if Plugin B is loaded in Falco after Plugin A, then Plugin B will see all the table changes performed by Plugin A at runtime, but not the contrary (however, they'll both have visibility over the changes performed by libsinsp). As such &lt;a href="https://v0-43--falcosecurity.netlify.app/docs/plugins/usage/#loading-plugins-in-falco"&gt;the plugins loading order in Falco&lt;/a&gt; can be functionally relevant.&lt;/p&gt;
&lt;h3 id="subtables-and-complex-data-types"&gt;Subtables and complex data types&lt;/h3&gt;
&lt;p&gt;The plugin framework supports a special table field type which is the &lt;code&gt;table&lt;/code&gt; type.
Table entries can use this field to store the handle to another table, which means each entry can have its own subtables.&lt;/p&gt;
&lt;p&gt;For example, the &lt;code&gt;threads&lt;/code&gt; table has a field named &lt;code&gt;file_descriptors&lt;/code&gt;. This field allows accessing the file descriptor table of every thread, making it possible to access useful information about a specific open file descriptor like file &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;pid&lt;/code&gt;, and much more.&lt;/p&gt;
&lt;p&gt;This also unlocks the ability for tables to store/access arrays, maps or even more complex data types. The plugin can &amp;quot;wrap&amp;quot; the complex type in a table by implementing the interface functions for that type, allowing the complex data types to be stored as a subtable.&lt;/p&gt;
&lt;h3 id="obtaining-accessors"&gt;Obtaining Accessors&lt;/h3&gt;
&lt;p&gt;Before performing any operation over state tables, plugins must first obtain accessors for each of them. This can happen only at initialization time through a vtable that is passed only to the &lt;code&gt;init&lt;/code&gt; plugin function. The vtable allows plugins to discover all the tables registered in the framework, get accessors for them, and &lt;a href="https://v0-43--falcosecurity.netlify.app/docs/reference/plugins/plugin-api-reference/#registering-state-tables"&gt;register their own tables&lt;/a&gt;. Once an accessor is obtained, plugins must maintain it up until they are destroyed, and use it during functions related to specific capabilities (e.g. field extraction, event parsing). The vtable passed to &lt;code&gt;init&lt;/code&gt; is reported below.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-CPP" data-lang="CPP"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// Vtable for controlling and the fields for the entries of a state table.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// This allows discovering the fields available in the table, defining new ones,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// and obtaining accessors usable at runtime for reading and writing the fields&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// data from each entry of a given state table.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;typedef&lt;/span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;struct&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Returns a pointer to an array containing info about all the fields
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// available in the entries of the table. nfields will be filled with the number
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// of elements of the returned array. The array&amp;#39;s memory is owned by the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// tables&amp;#39;s owner. Returns NULL in case of error.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_table_fieldinfo&lt;span style="color:#666"&gt;*&lt;/span&gt; (&lt;span style="color:#666"&gt;*&lt;/span&gt;list_table_fields)(ss_plugin_table_t&lt;span style="color:#666"&gt;*&lt;/span&gt; t, &lt;span style="color:#0b0;font-weight:bold"&gt;uint32_t&lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt; nfields);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Returns an opaque pointer representing an accessor to a data field
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// present in all entries of the table, given its name and type.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// This can later be used for read and write operations for all entries of
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// the table. The pointer is owned by the table&amp;#39;s owner.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Returns NULL in case of issues (including when the field is not defined
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// or it has a type different than the specified one).
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_table_field_t&lt;span style="color:#666"&gt;*&lt;/span&gt; (&lt;span style="color:#666"&gt;*&lt;/span&gt;get_table_field)(ss_plugin_table_t&lt;span style="color:#666"&gt;*&lt;/span&gt; t, &lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;char&lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt; name, ss_plugin_state_type data_type);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Defines a new field in the table given its name and data type,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// which will then be available in all entries contained in the table.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Returns an opaque pointer representing an accessor to the newly-defined
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// field. This can later be used for read and write operations for all entries of
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// the table. The pointer is owned by the table&amp;#39;s owner.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Returns NULL in case of issues (including when a field is defined multiple
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// times with different data types).
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_table_field_t&lt;span style="color:#666"&gt;*&lt;/span&gt; (&lt;span style="color:#666"&gt;*&lt;/span&gt;add_table_field)(ss_plugin_table_t&lt;span style="color:#666"&gt;*&lt;/span&gt; t, &lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;char&lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt; name, ss_plugin_state_type data_type);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} ss_plugin_table_fields_vtable;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;typedef&lt;/span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;struct&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Returns a pointer to an array containing info about all the tables
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// registered in the plugin&amp;#39;s owner. ntables will be filled with the number
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// of elements of the returned array. The array&amp;#39;s memory is owned by the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// plugin&amp;#39;s owner. Returns NULL in case of error.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_table_info&lt;span style="color:#666"&gt;*&lt;/span&gt; (&lt;span style="color:#666"&gt;*&lt;/span&gt;list_tables)(ss_plugin_owner_t&lt;span style="color:#666"&gt;*&lt;/span&gt; o, &lt;span style="color:#0b0;font-weight:bold"&gt;uint32_t&lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt; ntables);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Returns an opaque accessor to a state table registered in the plugin&amp;#39;s
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// owner, given its name and key type. Returns NULL if an case of error.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_table_t&lt;span style="color:#666"&gt;*&lt;/span&gt; (&lt;span style="color:#666"&gt;*&lt;/span&gt;get_table)(ss_plugin_owner_t&lt;span style="color:#666"&gt;*&lt;/span&gt; o, &lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;char&lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt; name, ss_plugin_state_type key_type);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Registers a new state table in the plugin&amp;#39;s owner. Returns
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// SS_PLUGIN_SUCCESS in case of success, and SS_PLUGIN_FAILURE otherwise.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// The state table is owned by the plugin itself, and the input will be used
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// by other actors of the plugin&amp;#39;s owner to interact with the state table.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_rc (&lt;span style="color:#666"&gt;*&lt;/span&gt;add_table)(ss_plugin_owner_t&lt;span style="color:#666"&gt;*&lt;/span&gt; o, &lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; ss_plugin_table_input&lt;span style="color:#666"&gt;*&lt;/span&gt; in);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Vtable for controlling operations related to fields on the state tables
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// registered in the plugin&amp;#39;s owner.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_table_fields_vtable fields;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} ss_plugin_init_tables_input;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="obtaining-subtables-accessors"&gt;Obtaining subtables accessors&lt;/h3&gt;
&lt;p&gt;Obtaining table accessors is a bit different for subtables.&lt;/p&gt;
&lt;p&gt;Table accessors can be only obtained at initialization time, however tables may be empty at this time, which means subtables may not yet exist.
The solution to this problem is to create a table entry just to get its subtables.&lt;/p&gt;
&lt;p&gt;Please note that this newly created entry is temporary and it should be used only at initialization time to obtain subtable accessors.&lt;/p&gt;
&lt;p&gt;The following example shows how to obtain accessors for the file descriptor subtable:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-CPP" data-lang="CPP"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;struct&lt;/span&gt; &lt;span style="color:#00f"&gt;plugin_state&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_table_t&lt;span style="color:#666"&gt;*&lt;/span&gt; thread_table;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_table_field_t&lt;span style="color:#666"&gt;*&lt;/span&gt; table_field_fdtable;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_table_field_t&lt;span style="color:#666"&gt;*&lt;/span&gt; table_field_fdtable_name;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;static&lt;/span&gt; ss_plugin_t&lt;span style="color:#666"&gt;*&lt;/span&gt; &lt;span style="color:#00a000"&gt;plugin_init&lt;/span&gt;(&lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; ss_plugin_init_input&lt;span style="color:#666"&gt;*&lt;/span&gt; in, ss_plugin_rc&lt;span style="color:#666"&gt;*&lt;/span&gt; rc)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; plugin_state &lt;span style="color:#666"&gt;*&lt;/span&gt;ret &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;new&lt;/span&gt; plugin_state();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// get the accessor to the threads table
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ret&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;thread_table &lt;span style="color:#666"&gt;=&lt;/span&gt; in&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;tables&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;get_table(in&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;owner, &lt;span style="color:#b44"&gt;&amp;#34;threads&amp;#34;&lt;/span&gt;, ss_plugin_state_type&lt;span style="color:#666"&gt;::&lt;/span&gt;SS_PLUGIN_ST_INT64);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// get an accessor to the subtable field
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ret&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;table_field_fdtable &lt;span style="color:#666"&gt;=&lt;/span&gt; in&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;tables&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;fields.get_table_field(ret&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;thread_table, &lt;span style="color:#b44"&gt;&amp;#34;file_descriptors&amp;#34;&lt;/span&gt;, ss_plugin_state_type&lt;span style="color:#666"&gt;::&lt;/span&gt;SS_PLUGIN_ST_TABLE);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// create a new table entry
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;auto&lt;/span&gt; entry &lt;span style="color:#666"&gt;=&lt;/span&gt; in&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;tables&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;writer_ext&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;create_table_entry(ret&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;thread_table);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// read the subtable handle from the new entry
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_state_data data;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; in&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;tables&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;reader_ext&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;read_entry_field(ret&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;thread_table, entry, ret&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;table_field_fdtable, &lt;span style="color:#666"&gt;&amp;amp;&lt;/span&gt;data);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;auto&lt;/span&gt; fdtable &lt;span style="color:#666"&gt;=&lt;/span&gt; data.table;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;//obtain the accessor to one of the subtable fields
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ret&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;table_field_fdtable_name &lt;span style="color:#666"&gt;=&lt;/span&gt; in&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;tables&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;fields_ext&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;get_table_field(fdtable, &lt;span style="color:#b44"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;, ss_plugin_state_type&lt;span style="color:#666"&gt;::&lt;/span&gt;SS_PLUGIN_ST_STRING);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;//destroy the temporary entry
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; in&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;tables&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;writer_ext&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;destroy_table_entry(ret&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;thread_table, entry);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="accessing-tables"&gt;Accessing Tables&lt;/h3&gt;
&lt;p&gt;After obtaining accessors for all the tables and fields a given plugin is interested into, they can be used for performing operations over tables at runtime. Table operations are split in the two &amp;quot;reading&amp;quot; and &amp;quot;writing&amp;quot; categories, each having their own vtable and set of functions. The &amp;quot;reader&amp;quot; and the &amp;quot;writer&amp;quot; vtables are passed to the interested plugin functions for different capabilities, depending on their scope. For example, the &lt;code&gt;extract_fields&lt;/code&gt; function of the field extraction capability gets passed the state tables reader vtable, whereas the &lt;code&gt;parse_event&lt;/code&gt; function of the event parsing capability has access to both the reader and writer vtables. This enforces users to only apply state tables modifications at event parsing time, leaving field extraction a &amp;quot;stateless&amp;quot; code path. The reader and writer vtables and their respective functions are reported below.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-CPP" data-lang="CPP"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// Vtable for controlling a state table for read operations.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;typedef&lt;/span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;struct&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Returns the table&amp;#39;s name, or NULL in case of error.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// The returned pointer is owned by the table&amp;#39;s owner.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;char&lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt; (&lt;span style="color:#666"&gt;*&lt;/span&gt;get_table_name)(ss_plugin_table_t&lt;span style="color:#666"&gt;*&lt;/span&gt; t);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Returns the number of entries in the table, or ((uint64_t) -1) in
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// case of error.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;uint64_t&lt;/span&gt; (&lt;span style="color:#666"&gt;*&lt;/span&gt;get_table_size)(ss_plugin_table_t&lt;span style="color:#666"&gt;*&lt;/span&gt; t);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Returns an opaque pointer to an entry present in the table at the given
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// key, or NULL in case of issues (including if no entry is found at the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// given key). The returned pointer is owned by the table&amp;#39;s owner.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_table_entry_t&lt;span style="color:#666"&gt;*&lt;/span&gt; (&lt;span style="color:#666"&gt;*&lt;/span&gt;get_table_entry)(ss_plugin_table_t&lt;span style="color:#666"&gt;*&lt;/span&gt; t, &lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; ss_plugin_state_data&lt;span style="color:#666"&gt;*&lt;/span&gt; key);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Reads the value of an entry field from a table&amp;#39;s entry.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// The field accessor must be obtained during plugin_init().
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// The read value is stored in the &amp;#34;out&amp;#34; parameter.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Returns SS_PLUGIN_SUCCESS if successful, and SS_PLUGIN_FAILURE otherwise.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_rc (&lt;span style="color:#666"&gt;*&lt;/span&gt;read_entry_field)(ss_plugin_table_t&lt;span style="color:#666"&gt;*&lt;/span&gt; t, ss_plugin_table_entry_t&lt;span style="color:#666"&gt;*&lt;/span&gt; e, &lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; ss_plugin_table_field_t&lt;span style="color:#666"&gt;*&lt;/span&gt; f, ss_plugin_state_data&lt;span style="color:#666"&gt;*&lt;/span&gt; out);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} ss_plugin_table_reader_vtable;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// Vtable for controlling a state table for write operations.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;typedef&lt;/span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;struct&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Erases all the entries of the table.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Returns SS_PLUGIN_SUCCESS if successful, and SS_PLUGIN_FAILURE otherwise.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_rc (&lt;span style="color:#666"&gt;*&lt;/span&gt;clear_table)(ss_plugin_table_t&lt;span style="color:#666"&gt;*&lt;/span&gt; t);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Erases an entry from a table at the given key.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Returns SS_PLUGIN_SUCCESS if successful, and SS_PLUGIN_FAILURE otherwise.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_rc (&lt;span style="color:#666"&gt;*&lt;/span&gt;erase_table_entry)(ss_plugin_table_t&lt;span style="color:#666"&gt;*&lt;/span&gt; t, &lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; ss_plugin_state_data&lt;span style="color:#666"&gt;*&lt;/span&gt; key);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Creates a new entry that can later be added to the same table it was
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// created from. The entry is represented as an opaque pointer owned
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// by the plugin. Once obtained, the plugin can either add the entry
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// to the table through add_table_entry(), or destroy it through
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// destroy_table_entry(). Returns an opaque pointer to the newly-created
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// entry, or NULL in case of error.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_table_entry_t&lt;span style="color:#666"&gt;*&lt;/span&gt; (&lt;span style="color:#666"&gt;*&lt;/span&gt;create_table_entry)(ss_plugin_table_t&lt;span style="color:#666"&gt;*&lt;/span&gt; t);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Destroys a table entry obtained by from previous invocation of create_table_entry().
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;void&lt;/span&gt; (&lt;span style="color:#666"&gt;*&lt;/span&gt;destroy_table_entry)(ss_plugin_table_t&lt;span style="color:#666"&gt;*&lt;/span&gt; t, ss_plugin_table_entry_t&lt;span style="color:#666"&gt;*&lt;/span&gt; e);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Adds a new entry to a table obtained by from previous invocation of
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// create_table_entry() on the same table. The entry is inserted in the table
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// with the given key. If another entry is already present with the same key,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// it gets replaced. After insertion, table will be come the owner of the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// entry&amp;#39;s pointer. Returns an opaque pointer to the newly-added table&amp;#39;s entry,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// or NULL in case of error.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_table_entry_t&lt;span style="color:#666"&gt;*&lt;/span&gt; (&lt;span style="color:#666"&gt;*&lt;/span&gt;add_table_entry)(ss_plugin_table_t&lt;span style="color:#666"&gt;*&lt;/span&gt; t, &lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; ss_plugin_state_data&lt;span style="color:#666"&gt;*&lt;/span&gt; key, ss_plugin_table_entry_t&lt;span style="color:#666"&gt;*&lt;/span&gt; entry);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Updates a table&amp;#39;s entry by writing a value for one of its fields.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// The field accessor must be obtained during plugin_init().
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// The written value is read from the &amp;#34;in&amp;#34; parameter.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Returns SS_PLUGIN_SUCCESS if successful, and SS_PLUGIN_FAILURE otherwise.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_rc (&lt;span style="color:#666"&gt;*&lt;/span&gt;write_entry_field)(ss_plugin_table_t&lt;span style="color:#666"&gt;*&lt;/span&gt; t, ss_plugin_table_entry_t&lt;span style="color:#666"&gt;*&lt;/span&gt; e, &lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; ss_plugin_table_field_t&lt;span style="color:#666"&gt;*&lt;/span&gt; f, &lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; ss_plugin_state_data&lt;span style="color:#666"&gt;*&lt;/span&gt; in);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} ss_plugin_table_writer_vtable;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="accessing-subtables"&gt;Accessing subtables&lt;/h3&gt;
&lt;p&gt;Subtables handles can be obtained just like any other field, by reading the &lt;code&gt;table&lt;/code&gt; type field of an entry.&lt;/p&gt;
&lt;p&gt;After obtaining subtables handles and &lt;a href="https://v0-43--falcosecurity.netlify.app/docs/reference/plugins/plugin-api-reference/#obtaining-subtables-accessors"&gt;fields accessors&lt;/a&gt;, accessing subtables is the same as accessing regular tables.&lt;/p&gt;
&lt;p&gt;The following example shows how to access fields from the &lt;code&gt;file_descriptors&lt;/code&gt; subtable from one of the entries of the &lt;code&gt;threads&lt;/code&gt; table:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-CPP" data-lang="CPP"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ss_plugin_rc &lt;span style="color:#00a000"&gt;plugin_parse_event&lt;/span&gt;(ss_plugin_t &lt;span style="color:#666"&gt;*&lt;/span&gt;s, &lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; ss_plugin_event_input &lt;span style="color:#666"&gt;*&lt;/span&gt;ev, &lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; ss_plugin_event_parse_input&lt;span style="color:#666"&gt;*&lt;/span&gt; in)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; plugin_state &lt;span style="color:#666"&gt;*&lt;/span&gt;ps &lt;span style="color:#666"&gt;=&lt;/span&gt; (plugin_state &lt;span style="color:#666"&gt;*&lt;/span&gt;) s;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_state_data tmp;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// get an entry from the thread table
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tmp.s64 &lt;span style="color:#666"&gt;=&lt;/span&gt; ev&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;evt&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;tid;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_table_entry_t&lt;span style="color:#666"&gt;*&lt;/span&gt; thread_entry &lt;span style="color:#666"&gt;=&lt;/span&gt; in&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;table_reader_ext&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;get_table_entry(ps&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;thread_table, &lt;span style="color:#666"&gt;&amp;amp;&lt;/span&gt;tmp);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// read the file_descriptors field from the entry
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; in&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;table_reader_ext&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;read_entry_field(ps&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;thread_table, thread_entry, ps&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;table_field_fdtable, &lt;span style="color:#666"&gt;&amp;amp;&lt;/span&gt;tmp);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_table_t&lt;span style="color:#666"&gt;*&lt;/span&gt; fdtable &lt;span style="color:#666"&gt;=&lt;/span&gt; tmp.table;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// get an entry from the file descriptors table of the previously read thread
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tmp.s64 &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#666"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_table_entry_t&lt;span style="color:#666"&gt;*&lt;/span&gt; fd_entry &lt;span style="color:#666"&gt;=&lt;/span&gt; in&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;table_reader_ext&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;get_table_entry(fdtable, &lt;span style="color:#666"&gt;&amp;amp;&lt;/span&gt;tmp);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// read a field from the entry in the file descriptors table
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; in&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;table_reader_ext&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;read_entry_field(fdtable, fd_entry, ps&lt;span style="color:#666"&gt;-&amp;gt;&lt;/span&gt;table_field_fdtable_name, &lt;span style="color:#666"&gt;&amp;amp;&lt;/span&gt;tmp);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="registering-state-tables"&gt;Registering State Tables&lt;/h3&gt;
&lt;p&gt;On top of accessing tables owned by the framework or other plugins, each plugin can also make part (or all) of its state available to other actors in the framework in the form of state tables. In this case, the plugin is responsible of providing all the necessary vtables and their respective functions, just like the Falcosecurity libraries do for the tables owned by them (e.g. the &lt;code&gt;threads&lt;/code&gt; table). Plugins have total freedom towards how the table is actually implemented, as long as they respect the API functions in the vtables and they own all the memory related to the table and its entries. Plugins also have the freedom of not supporting some of the functions of the vtables, however they are not allowed to pass NULL-pointing function references. The struct by which plugins register their state table and the related vtable functions is reported below.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-CPP" data-lang="CPP"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// Plugin-provided input passed to the add_table() callback of
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// ss_plugin_init_tables_input, that can be used by the plugin to inform its
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// owner about one of the state tables owned by the plugin. The plugin
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// is responsible of owning all the memory pointed by this struct and
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// of implementing all the API functions. These will be used by other
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// plugins loaded by the falcosecurity libraries to interact with the state
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// of a given plugin to implement cross-plugin state access.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;typedef&lt;/span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;struct&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// The name of the state table.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt; &lt;span style="color:#0b0;font-weight:bold"&gt;char&lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt; name;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// The type of the sta table&amp;#39;s key.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_state_type key_type;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// A non-NULL opaque pointer to the state table.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// This will be passed as parameters to all the callbacks defined below.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_table_t&lt;span style="color:#666"&gt;*&lt;/span&gt; table;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Vtable for controlling read operations on the state table.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_table_reader_vtable reader;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Vtable for controlling write operations on the state table.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_table_writer_vtable writer;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;// Vtable for controlling operations related to fields on the state table.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ss_plugin_table_fields_vtable fields;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} ss_plugin_table_input;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="thread-safety-and-reproducibility"&gt;Thread-safety and Reproducibility&lt;/h3&gt;
&lt;p&gt;State access is not thread-safe. Operations related to either discovery, reading, or writing, must all be executed in the synchronous context and within the thread in which the framework invokes the given plugin function that is capable of accessing tables. For example, plugins are only allowed to read from a table during the execution of &lt;code&gt;extract_fields&lt;/code&gt; or &lt;code&gt;parse_event&lt;/code&gt;, but they are not allowed to launch an asynchronous thread that reuses the same accessors to read from a table after any of those functions have returned.&lt;/p&gt;
&lt;p&gt;Also, the previous sections imply that state tables can be operated on during the execution of various plugin functions, but that however only the &lt;code&gt;parse_event&lt;/code&gt; function of the event parsing capability can perform write operations. This is by purpose and design due to the architecture of the Falcosecurity libraries themselves.&lt;/p&gt;
&lt;p&gt;There may be use cases when the state update results of some asynchronous job and computation. For example, the Falcosecurity libraries implement the container metadata enrichment support by connecting to one or more container runtime sockets and fetching information asynchronously using a separate thread of the main event processing loop. In those cases, state updates must still happen synchronously. The &lt;a href="https://v0-43--falcosecurity.netlify.app/docs/reference/plugins/plugin-api-reference/#async-events-capability-api"&gt;async events capability&lt;/a&gt; is the strategy provided by the plugin framework. With that, plugins are provided with a thread-safe callback that they can use to inject asynchronous events in the currently-open event stream, and the framework will guarantee those events to be later received by functions such as &lt;code&gt;parse_event&lt;/code&gt; or &lt;code&gt;extract_fields&lt;/code&gt; just like any other events. Plugins can only safely utilize asynchronously-obtained information for state updates and field extraction through this messaging-like communication mode.&lt;/p&gt;
&lt;p&gt;An additional effect of injecting asynchronous events in an event stream is that they can so be recorded in SCAP capture files, thus being reproducible when reading events later from that capture files. By having the asynchronous information recorded in the event stream, the event parsing and field extraction plugin functions will be able to work just like in live capture mode by also making all the state transitions reproducible and deterministic.&lt;/p&gt;</description></item><item><title>Docs: Falco Plugins Go SDK Walkthrough</title><link>https://v0-43--falcosecurity.netlify.app/docs/reference/plugins/go-sdk-walkthrough/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://v0-43--falcosecurity.netlify.app/docs/reference/plugins/go-sdk-walkthrough/</guid><description>
&lt;h2 id="introduction"&gt;Introduction&lt;/h2&gt;
&lt;p&gt;The &lt;a href="https://github.com/falcosecurity/plugin-sdk-go"&gt;Go SDK&lt;/a&gt; provides prebuilt constructs and definitions that help developing plugins by abstracting all the complexities related to the bridging between the C and the Go runtimes. The Go SDK takes care of satisfying all the plugin framework requirements without having to deal with the low-level details, by also optimizing the most critical code paths.&lt;/p&gt;
&lt;p&gt;The SDK allows developers to choose either from a low-level set of abstractions, or from a more high-level set of packages designed for simplicity and ease of use. The best way to approach the Go SDK is to start by importing a few high-level packages, which is enough to satisfy the majority of use cases.&lt;/p&gt;
&lt;p&gt;This section documents the Go SDK at a high-level, please refer to the &lt;a href="https://github.com/falcosecurity/plugin-sdk-go"&gt;official Go SDK documentation&lt;/a&gt; for deeper details.&lt;/p&gt;
&lt;h3 id="architecture-of-the-go-sdk"&gt;Architecture of the Go SDK&lt;/h3&gt;
&lt;p&gt;Since Falcosecurity plugins run in a C runtime, the Go SDK has been designed to abstract most of the complexity related to writing C-compliant code acceptable by the plugin framework, so that developers can focus on writing Go code only.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://v0-43--falcosecurity.netlify.app/docs/images/plugin_sdk_go_architecture.png" alt="plugin_sdk_go_architecture" loading="lazy" /&gt;
&lt;/p&gt;
&lt;p&gt;At a high level, the SDK is on top of three fundamental packages with different levels of abstractions:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Package &lt;code&gt;sdk&lt;/code&gt; is a container for all the basic types, definitions, and helpers that are reused across all the SDK parts.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Package &lt;code&gt;sdk/symbols&lt;/code&gt; contains prebuilt implementations for all the C symbols that plugins must export to be accepted by the framework. The prebuilt C symbols are divided in many subpackages, so that each of them can be imported individually to opt-in/opt-out each symbol.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Package &lt;code&gt;sdk/plugins&lt;/code&gt; provide high-level definition and base types for implementing plugin capabilities. This uses &lt;code&gt;sdk/symbols&lt;/code&gt; internally and takes care of importing all the prebuilt C symbols required each plugin capability respectively. This is the main entrypoint for developers to write plugins in Go.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Two additional packages &lt;code&gt;ptr&lt;/code&gt; and &lt;code&gt;cgo&lt;/code&gt; are used internally to simplify and optimize the state management and the usage of C-allocated memory pointers.&lt;/p&gt;
&lt;p&gt;For some use cases, developers can consider using the SDK layers selectively. This is meaningful only if developers wish to manually write part of the low-level C details of the framework in their plugins, but still want to use some parts of the SDK. However, this is discouraged if not for advanced use cases only. Developers are encouraged to use the &lt;code&gt;sdk/plugins&lt;/code&gt; to build Falcosecurity plugins, which is easier to use and will have less frequent breaking changes.&lt;/p&gt;
&lt;p&gt;Further details can be found in the documentation of each package: &lt;a href="https://pkg.go.dev/github.com/falcosecurity/plugin-sdk-go/pkg/sdk"&gt;&lt;code&gt;sdk&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://pkg.go.dev/github.com/falcosecurity/plugin-sdk-go/pkg/sdk/symbols"&gt;&lt;code&gt;sdk/symbols&lt;/code&gt;&lt;/a&gt;, and &lt;a href="https://pkg.go.dev/github.com/falcosecurity/plugin-sdk-go/pkg/sdk/plugins"&gt;&lt;code&gt;sdk/plugins&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="getting-started"&gt;Getting Started&lt;/h3&gt;
&lt;p&gt;The SDK is built on top of a set of minimal composable interfaces describing the behavior of plugins and plugin instances. As such, developing plugins is as easy as defining a struct type representing the plugin itself, ensuring that the mandatory interface methods are defined on it, and then registering it to the SDK.&lt;/p&gt;
&lt;p&gt;To use the Go SDK, all you need to import are the &lt;code&gt;sdk&lt;/code&gt; and &lt;code&gt;sdk/plugins&lt;/code&gt; packages. The first contains all the core types and definitions used across the rest of the SDK packages, whereas the latter contains built-in constructs to develop plugins. The subpackages &lt;code&gt;sdk/plugins/source&lt;/code&gt; and &lt;code&gt;sdk/plugins/extractor&lt;/code&gt; contain specialized definitions for the event sourcing and the field extraction capabilities respectively.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;dummy&lt;/code&gt; plugin, documented in the &lt;a href="https://v0-43--falcosecurity.netlify.app/docs/reference/plugins/go-sdk-walkthrough/#example-go-plugin-dummy"&gt;next sections&lt;/a&gt;, is a simple example that helps understand how to start writing Go plugins with this SDK. The SDK also provides a set of &lt;a href="https://github.com/falcosecurity/plugin-sdk-go/tree/main/examples"&gt;base examples&lt;/a&gt; to get you started with plugin development.&lt;/p&gt;
&lt;h3 id="defining-a-plugin-with-field-extraction-capability"&gt;Defining a Plugin with Field Extraction Capability&lt;/h3&gt;
&lt;p&gt;In the Go SDK, a plugin with field extraction capability is a type implementing the following interface:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// sdk/plugins/extractor&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Plugin&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;interface&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;...&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Info&lt;/span&gt;()&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt;sdk.Info&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Init&lt;/span&gt;(config&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;string&lt;/span&gt;)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;error&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Fields&lt;/span&gt;()&lt;span style="color:#bbb"&gt; &lt;/span&gt;[]sdk.FieldEntry&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Extract&lt;/span&gt;(req&lt;span style="color:#bbb"&gt; &lt;/span&gt;sdk.ExtractRequest,&lt;span style="color:#bbb"&gt; &lt;/span&gt;evt&lt;span style="color:#bbb"&gt; &lt;/span&gt;sdk.EventReader)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;error&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Info()&lt;/code&gt; returns all the info about the plugin. The returned &lt;code&gt;plugins.Info&lt;/code&gt; struct should be filled in by the plugin author and contains fields such as the plugin ID, name, description, etc.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Init()&lt;/code&gt; method is called to initialize a plugin when the framework allocates it. A user-defined configuration string is passed by the framework. This is where the plugin can initialize its internal state and acquire all the resources it needs.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Fields()&lt;/code&gt; returns an array of &lt;code&gt;sdk.FieldEntry&lt;/code&gt; representing all the fields supported by a plugin for extraction. The order of the fields is relevant, as their index is used as an identifier during extraction.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Extract()&lt;/code&gt; extracts the value of one of the supported fields from a given event passed in by the framework. The &lt;code&gt;sdk.ExtractRequest&lt;/code&gt; argument should be used to set the extracted value.&lt;/p&gt;
&lt;h4 id="optional-interfaces"&gt;Optional Interfaces&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Destroyer&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;interface&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Destroy&lt;/span&gt;()&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;InitSchema&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;interface&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;InitSchema&lt;/span&gt;()&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt;SchemaInfo&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Plugins with field extraction capability can optionally implement the &lt;code&gt;sdk.Destroyer&lt;/code&gt; interface. In that case, &lt;code&gt;Destroy()&lt;/code&gt; will be called when the plugin gets destroyed and can be used to release any allocated resource. they can also also optionally implement the &lt;code&gt;sdk.InitSchema&lt;/code&gt; interface. In that case, &lt;code&gt;InitSchema()&lt;/code&gt; will be used to to return a schema describing the data expected to be passed as a configuration during the plugin initialization. This follows the semantics documented for &lt;a href="https://v0-43--falcosecurity.netlify.app/docs/reference/plugins/plugin-api-reference/#get-init-schema"&gt;&lt;code&gt;get_init_schema&lt;/code&gt;&lt;/a&gt;. Currently, the schema must follow the &lt;a href="https://json-schema.org/"&gt;JSON Schema specific&lt;/a&gt;, which in Go can also be easily auto-generated with external packages (e.g. &lt;a href="https:/github.com/alecthomas/jsonschema"&gt;alecthomas/jsonschema&lt;/a&gt;).&lt;/p&gt;
&lt;h3 id="defining-a-plugin-with-event-sourcing-capability"&gt;Defining a Plugin with Event Sourcing Capability&lt;/h3&gt;
&lt;p&gt;In the Go SDK, a plugin with event sourcing capability must specify two types, one of the plugin itself and one for the plugin instances, implementing the following interfaces respectively:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// sdk/plugins/source&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Plugin&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;interface&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;...&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Info&lt;/span&gt;()&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt;sdk.Info&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Init&lt;/span&gt;(config&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;string&lt;/span&gt;)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;error&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Open&lt;/span&gt;(params&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;string&lt;/span&gt;)&lt;span style="color:#bbb"&gt; &lt;/span&gt;(Instance,&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;error&lt;/span&gt;)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// sdk/plugins/source&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Instance&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;interface&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;...&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;NextBatch&lt;/span&gt;(pState&lt;span style="color:#bbb"&gt; &lt;/span&gt;PluginState,&lt;span style="color:#bbb"&gt; &lt;/span&gt;evts&lt;span style="color:#bbb"&gt; &lt;/span&gt;EventWriters)&lt;span style="color:#bbb"&gt; &lt;/span&gt;(&lt;span style="color:#0b0;font-weight:bold"&gt;int&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;error&lt;/span&gt;)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;source.Plugin&lt;/code&gt; interface has many functions in common with &lt;code&gt;extractor.Plugin&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Open()&lt;/code&gt; creates a new plugin instance to open a new stream of events. The framework provides the user-defined open parameters to customize the event source. The return value must implement the &lt;code&gt;source.Instance&lt;/code&gt; interface, and its lifecycle ends when the event stream is closed.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;source.Instance&lt;/code&gt; interface represents plugin instances for an opened event stream, and has one mandatory method and a few optional ones.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;NextBatch&lt;/code&gt; creates a new batch of events to be pushed in the event stream. The SDK provides a pre-allocated batch to write events into, in order to manage the used memory optimally.&lt;/p&gt;
&lt;h4 id="optional-interfaces-1"&gt;Optional Interfaces&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Destroyer&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;interface&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Destroy&lt;/span&gt;()&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Closer&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;interface&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Close&lt;/span&gt;()&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;InitSchema&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;interface&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;InitSchema&lt;/span&gt;()&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt;SchemaInfo&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;OpenParams&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;interface&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;OpenParams&lt;/span&gt;()&lt;span style="color:#bbb"&gt; &lt;/span&gt;([]OpenParam,&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;error&lt;/span&gt;)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Progresser&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;interface&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Progress&lt;/span&gt;(pState&lt;span style="color:#bbb"&gt; &lt;/span&gt;sdk.PluginState)&lt;span style="color:#bbb"&gt; &lt;/span&gt;(&lt;span style="color:#0b0;font-weight:bold"&gt;float64&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;string&lt;/span&gt;)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Stringer&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;interface&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;String&lt;/span&gt;(evt&lt;span style="color:#bbb"&gt; &lt;/span&gt;sdk.EventReader)&lt;span style="color:#bbb"&gt; &lt;/span&gt;(&lt;span style="color:#0b0;font-weight:bold"&gt;string&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;error&lt;/span&gt;)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Plugins with event sourcing capabilities can optionally implement the &lt;code&gt;sdk.Destroyer&lt;/code&gt; and &lt;code&gt;sdk.InitSchema&lt;/code&gt; interfaces, just like mentioned in the section above.&lt;/p&gt;
&lt;p&gt;Additionally, they can also implement the &lt;code&gt;sdk.OpenParams&lt;/code&gt; interface. If requested by the application, the framework may call &lt;code&gt;OpenParams()&lt;/code&gt; before opening the event stream to obtains some suggested values that would valid parameters for &lt;code&gt;Open()&lt;/code&gt;. For more details, see the documentation of &lt;a href="https://v0-43--falcosecurity.netlify.app/docs/reference/plugins/plugin-api-reference/#list-open-params"&gt;&lt;code&gt;list_open_params&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Plugin instances can optionally implement the &lt;code&gt;sdk.Closer&lt;/code&gt;, &lt;code&gt;sdk.Progresser&lt;/code&gt;, and &lt;code&gt;sdk.Stringer&lt;/code&gt; interfaces. If &lt;code&gt;sdk.Closer&lt;/code&gt; is implemented, the &lt;code&gt;Close()&lt;/code&gt; method is called while closing the event stream and can be used to release the resources used by the plugin instance. If &lt;code&gt;sdk.Progresser&lt;/code&gt; is implemented, the &lt;code&gt;Progress()&lt;/code&gt; method is called by the SDK when the framework requests progress data about the event stream of the plugin instance. &lt;code&gt;Progress()&lt;/code&gt; must return a &lt;code&gt;float64&lt;/code&gt; with a value between 0 and 1 representing the current progress percentage, and a string representation of the same progress value. If &lt;code&gt;sdk.Stringer&lt;/code&gt; is implemented, the &lt;code&gt;String()&lt;/code&gt; method must return a string representation of an event created by the plugin, which is used by the framework as an extraction value of the &lt;code&gt;evt.plugininfo&lt;/code&gt; field. The string representation should be on a single line and contain important information about the event.&lt;/p&gt;
&lt;h4 id="best-practices-and-go-sdk-prebuilts-for-source-instances"&gt;Best Practices and Go SDK Prebuilts for Source Instances&lt;/h4&gt;
&lt;p&gt;Although the Go SDK gives developers high control and flexibility, in the general case implementing the &lt;code&gt;sdk.NextBatcher&lt;/code&gt; interface is not trivial. Custom definitions of &lt;code&gt;source.Instance&lt;/code&gt; require developers to be mindful of the following while implementing the &lt;code&gt;NextBatch()&lt;/code&gt; function:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It should return as fast as possible and should try to fill-up event batch up to its maximum capacity&lt;/li&gt;
&lt;li&gt;Listen for a timeout of few milliseconds and return the batch in its current state once the timeout is expired&lt;/li&gt;
&lt;li&gt;Conceive the case in which &lt;code&gt;Close()&lt;/code&gt; is called before &lt;code&gt;NextBatch()&lt;/code&gt; has returned. This can potentially happen if the plugin framework receives signals such as SIGINT or SIGTERM&lt;/li&gt;
&lt;li&gt;Minimize the number of memory allocations&lt;/li&gt;
&lt;li&gt;Keep returning &lt;code&gt;sdk.ErrEOF&lt;/code&gt; after returning it the first time&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Considering the above, the SDK provides prebuilt implementations of &lt;code&gt;source.Instance&lt;/code&gt; that satisfy a broad range of use cases, so that developers need to define their own type only if they have advanced or custom requirements.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// sdk/plugins/source&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;NewPullInstance&lt;/span&gt;(pull&lt;span style="color:#bbb"&gt; &lt;/span&gt;source.PullFunc,&lt;span style="color:#bbb"&gt; &lt;/span&gt;options&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;...&lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;(&lt;span style="color:#666"&gt;*&lt;/span&gt;&amp;lt;unexported&lt;span style="color:#666"&gt;-&lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&amp;gt;))&lt;span style="color:#bbb"&gt; &lt;/span&gt;(source.Instance,&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;error&lt;/span&gt;)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;NewPushInstance&lt;/span&gt;(evtC&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;&amp;lt;-&lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;chan&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;source.PushEvent,&lt;span style="color:#bbb"&gt; &lt;/span&gt;options&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;...&lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;(&lt;span style="color:#666"&gt;*&lt;/span&gt;&amp;lt;unexported&lt;span style="color:#666"&gt;-&lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&amp;gt;))&lt;span style="color:#bbb"&gt; &lt;/span&gt;(source.Instance,&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;error&lt;/span&gt;)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;source.NewPullInstance&lt;/code&gt; and &lt;code&gt;source.NewPushInstance&lt;/code&gt; are two constructors for SDK-provided &lt;code&gt;source.Instance&lt;/code&gt; implementations that cover the following use cases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pull Model&lt;/strong&gt;: for when the event source can be implemented sequentially and the time required to generate a sequence of event is deterministic. This is implemented with a functional design, where the passed-in callback is expected to be non-suspensive and to return quickly&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Push Model&lt;/strong&gt;: for when the event source can be suspensive and there is no time guarantee regarding when an event gets produced. For instance, this applies for all event sources that generate events from webhook events. Given the event-driven nature of this use case, this is implemented by passing event data in the form of byte slices through a channel&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The prebuilt &lt;code&gt;source.Instance&lt;/code&gt;s can be configured in the function constructors by using the Go &lt;em&gt;options pattern&lt;/em&gt;. The SDK provides options for configuring and overriding all the default values:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// sdk/plugins/source&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;WithInstanceContext&lt;/span&gt;(ctx&lt;span style="color:#bbb"&gt; &lt;/span&gt;context.Context)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;(&lt;span style="color:#666"&gt;*&lt;/span&gt;&amp;lt;unexported&lt;span style="color:#666"&gt;-&lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&amp;gt;)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;WithInstanceTimeout&lt;/span&gt;(timeout&lt;span style="color:#bbb"&gt; &lt;/span&gt;time.Duration)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;(&lt;span style="color:#666"&gt;*&lt;/span&gt;&amp;lt;unexported&lt;span style="color:#666"&gt;-&lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&amp;gt;)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;WithInstanceClose&lt;/span&gt;(close&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;())&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;(&lt;span style="color:#666"&gt;*&lt;/span&gt;&amp;lt;unexported&lt;span style="color:#666"&gt;-&lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&amp;gt;)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;WithInstanceBatchSize&lt;/span&gt;(size&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;uint32&lt;/span&gt;)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;(&lt;span style="color:#666"&gt;*&lt;/span&gt;&amp;lt;unexported&lt;span style="color:#666"&gt;-&lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&amp;gt;)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;WithInstanceEventSize&lt;/span&gt;(size&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;uint32&lt;/span&gt;)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;(&lt;span style="color:#666"&gt;*&lt;/span&gt;&amp;lt;unexported&lt;span style="color:#666"&gt;-&lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&amp;gt;)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;WithInstanceProgress&lt;/span&gt;(progress&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;()&lt;span style="color:#bbb"&gt; &lt;/span&gt;(&lt;span style="color:#0b0;font-weight:bold"&gt;float64&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;string&lt;/span&gt;))&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;(&lt;span style="color:#666"&gt;*&lt;/span&gt;&amp;lt;unexported&lt;span style="color:#666"&gt;-&lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&amp;gt;)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here's an example of how the &lt;em&gt;Pull Model&lt;/em&gt; prebuilt can be used to implement an event source:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;(m&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt;MyPlugin)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Open&lt;/span&gt;(params&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;string&lt;/span&gt;)&lt;span style="color:#bbb"&gt; &lt;/span&gt;(source.Instance,&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;error&lt;/span&gt;)&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;counter&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;:=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f"&gt;uint64&lt;/span&gt;(&lt;span style="color:#666"&gt;0&lt;/span&gt;)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;pull&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;:=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;(ctx&lt;span style="color:#bbb"&gt; &lt;/span&gt;context.Context,&lt;span style="color:#bbb"&gt; &lt;/span&gt;evt&lt;span style="color:#bbb"&gt; &lt;/span&gt;sdk.EventWriter)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;error&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;counter&lt;span style="color:#666"&gt;++&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;:=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;gob.&lt;span style="color:#00a000"&gt;NewEncoder&lt;/span&gt;(evt.&lt;span style="color:#00a000"&gt;Writer&lt;/span&gt;()).&lt;span style="color:#00a000"&gt;Encode&lt;/span&gt;(counter);&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;!=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;nil&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;evt.&lt;span style="color:#00a000"&gt;SetTimestamp&lt;/span&gt;(&lt;span style="color:#a2f"&gt;uint64&lt;/span&gt;(time.&lt;span style="color:#00a000"&gt;Now&lt;/span&gt;().&lt;span style="color:#00a000"&gt;UnixNano&lt;/span&gt;()))&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;nil&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;source.&lt;span style="color:#00a000"&gt;NewPullInstance&lt;/span&gt;(pull)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="registering-a-plugin-in-the-sdk"&gt;Registering a Plugin in the SDK&lt;/h3&gt;
&lt;p&gt;After defining proper types for the plugin, the only thing remaining is to register it in the SDK so that it can be used in the plugin framework.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// sdk/plugins&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;FactoryFunc&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;()&lt;span style="color:#bbb"&gt; &lt;/span&gt;plugins.Plugin&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// sdk/plugins&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;SetFactory&lt;/span&gt;(plugins.FactoryFunc)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// sdk/plugins/extractor&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Register&lt;/span&gt;(extractor.Plugin)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// sdk/plugins/source&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Register&lt;/span&gt;(source.Plugin)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The newly created plugin type need to be registered to the SDK in a Go &lt;code&gt;init&lt;/code&gt; function and through the &lt;code&gt;plugins.SetFactory()&lt;/code&gt; function. &lt;code&gt;plugins.FactoryFunc&lt;/code&gt; is a function type that is used by the SDK to create plugins when requested by the plugin framework. Then, the &lt;code&gt;source.Register()&lt;/code&gt; and &lt;code&gt;extractor.Register()&lt;/code&gt; functions should be invoked inside the body of &lt;code&gt;plugins.FactoryFunc&lt;/code&gt; functions to implement the event sourcing and the field extraction capabilities respectively.&lt;/p&gt;
&lt;p&gt;The defined plugin types are expected to implement a given set of methods. Compilation will fail at the &lt;code&gt;Register()&lt;/code&gt; functions if any of the required methods is not defined. Developers are encouraged to compose their structs with &lt;code&gt;plugins.BasePlugin&lt;/code&gt;, and &lt;code&gt;source.BaseInstance&lt;/code&gt;, which provide prebuilt boilerplate for many of those methods. In this way, developers just need to focus on implementing the few plugin-specific methods remaining.&lt;/p&gt;
&lt;p&gt;Besides the interface requirements, the defined types can contain arbitrary fields and methods. State variable that must be maintained during the plugin lifecycle (or in the lifecycle of an opened event stream) must be contained in the defined types. In this way, the SDK can guarantee that the state variables are not disposed by the garbage collector.&lt;/p&gt;
&lt;h3 id="interacting-with-events"&gt;Interacting with Events&lt;/h3&gt;
&lt;p&gt;Generating new events, and extracting field values from them, are the hottest path in the plugin framework and can happen at a very high rate. For this reason, the Go SDK optimizes the memory usage as much as possible, avoiding reallocations and copies wherever possible. Internally, this sometimes means reading and writing on C-allocated memory from Go code directly, which is efficient but also very unsafe and can lead to unstable code.&lt;/p&gt;
&lt;p&gt;As such, the SDK provides the two &lt;code&gt;sdk.EventReader&lt;/code&gt; and &lt;code&gt;sdk.EventWriter&lt;/code&gt; interfaces, which enable developers to safely read and write from events while still fully leveraging the underlying memory optimizations. &lt;code&gt;sdk.EventReader&lt;/code&gt; gives a read-only view of an event, with accessor methods for all the internal fields, and &lt;code&gt;sdk.EventWriter&lt;/code&gt; does the same in read-only mode.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;EventReader&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;interface&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;EventNum&lt;/span&gt;()&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;uint64&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Timestamp&lt;/span&gt;()&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;uint64&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Reader&lt;/span&gt;()&lt;span style="color:#bbb"&gt; &lt;/span&gt;io.ReadSeeker&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;EventWriter&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;interface&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;SetTimestamp&lt;/span&gt;(value&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;uint64&lt;/span&gt;)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Writer&lt;/span&gt;()&lt;span style="color:#bbb"&gt; &lt;/span&gt;io.Writer&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Event data can either be read or written through the standard &lt;code&gt;io.SeekReader&lt;/code&gt; and &lt;code&gt;io.Writer&lt;/code&gt; interfaces, returned by the &lt;code&gt;Reader()&lt;/code&gt; and &lt;code&gt;Writer()&lt;/code&gt; methods respectively. The SDK hides behind these interfaces all the safety and optimization mechanisms.&lt;/p&gt;
&lt;p&gt;For plugins with event sourcing capability, a reusable batch of &lt;code&gt;sdk.EventWriter&lt;/code&gt;s is automatically allocated in each plugin source instance after the &lt;code&gt;Open()&lt;/code&gt; method returns. This slab-allocator creates reusable event data by using the default &lt;code&gt;sdk.DefaultBatchSize&lt;/code&gt; and &lt;code&gt;sdk.DefaultEvtSize&lt;/code&gt; constants. Developers can override the automatic allocation to define batches of arbitrary sizes in the &lt;code&gt;Open()&lt;/code&gt; method, by calling the &lt;code&gt;SetEvents()&lt;/code&gt; method on the newly opened plugin instance before returning it. The reusable event batch can be created with the &lt;code&gt;sdk.NewEventWriters&lt;/code&gt; function, that takes the event data size and batch size as arguments.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;NewEventWriters&lt;/span&gt;(size,&lt;span style="color:#bbb"&gt; &lt;/span&gt;dataSize&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;int64&lt;/span&gt;)&lt;span style="color:#bbb"&gt; &lt;/span&gt;(EventWriters,&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;error&lt;/span&gt;)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that the size of the reusable event batch defines the maximum size of each event batch created by the plugin in &lt;code&gt;NextBatch&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="compiling-plugins"&gt;Compiling Plugins&lt;/h3&gt;
&lt;p&gt;After successfully writing a plugin, all you need is to compile it. Go allows compiling binaries as a C-compliant shared library with the &lt;code&gt;-buildmode=c-shared&lt;/code&gt; flag. The build command will be something looking like:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;go build -buildmode=c-shared -o &amp;lt;outname&amp;gt;.so *.go
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The SDK takes care of generating all the required C exported functions that the plugin framework needs to load the plugin. Once built, your plugin is ready to be used in the Falcosecurity plugin system.&lt;/p&gt;
&lt;h2 id="example-go-plugin-dummy"&gt;Example Go Plugin: &lt;code&gt;dummy&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;This section walks through the implementation of the &lt;code&gt;dummy&lt;/code&gt;. This plugin returns events that are just a number value that increases with each event generated. Each increase is 1 plus a random &amp;quot;jitter&amp;quot; value that ranges from [0:jitter]. The jitter value is provided as configuration to the plugin in &lt;code&gt;plugin_init&lt;/code&gt;. The starting value and the maximum number of events are provided as open parameters to the plugin in &lt;code&gt;plugin_open&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This will show how the above API functions are actually used in a functional plugin. The source code for this plugin can be found at &lt;a href="https://github.com/falcosecurity/plugins/blob/master/plugins/dummy/plugin/dummy.go"&gt;dummy.go&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="initial-imports"&gt;Initial Imports&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;package&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;main&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;import&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;(&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;...&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b44"&gt;&amp;#34;github.com/falcosecurity/plugin-sdk-go/pkg/sdk&amp;#34;&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b44"&gt;&amp;#34;github.com/falcosecurity/plugin-sdk-go/pkg/sdk/plugins&amp;#34;&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b44"&gt;&amp;#34;github.com/falcosecurity/plugin-sdk-go/pkg/sdk/plugins/extractor&amp;#34;&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b44"&gt;&amp;#34;github.com/falcosecurity/plugin-sdk-go/pkg/sdk/plugins/source&amp;#34;&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Importing the &lt;code&gt;sdk&lt;/code&gt; and &lt;code&gt;sdk/plugins&lt;/code&gt; packages is the first step for developing a Falcosecurity plugin in Go. The &lt;code&gt;sdk&lt;/code&gt; package contains all the core types and definitions used across the other packages of the SDK. The &lt;code&gt;sdk/plugins&lt;/code&gt; package contains prebuilt constructs for defining new plugins.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;sdk/plugins/source&lt;/code&gt; and &lt;code&gt;sdk/plugins/extractor&lt;/code&gt; packages are required to register the event sourcing and field extraction capabilities. &lt;code&gt;dummy&lt;/code&gt; implements both of them.&lt;/p&gt;
&lt;p&gt;The Go module &lt;code&gt;falcosecurity/plugin-sdk-go&lt;/code&gt; has its own &lt;a href="https://pkg.go.dev/github.com/falcosecurity/plugin-sdk-go"&gt;documentation&lt;/a&gt;, which gives deeper insights about the internal architecture of the SDK.&lt;/p&gt;
&lt;h3 id="defining-the-plugin"&gt;Defining the Plugin&lt;/h3&gt;
&lt;p&gt;In the Go SDK, plugins are defined by a set of composable tiny interfaces. To define a new plugin, the first step is to define a new &lt;code&gt;struct&lt;/code&gt; type representing the plugin itself, and then register it to the SDK. Plugins with event sourcing capability, like &lt;code&gt;dummy&lt;/code&gt;, must define an additional type representing the opened instance of the plugin event stream.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;PluginConfig&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;struct&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// This reflects potential internal state for the plugin. In&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// this case, the plugin is configured with a jitter.&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Jitter&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;uint64&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b44"&gt;`json:&amp;#34;jitter&amp;#34; jsonschema:&amp;#34;description=A random amount added to the sample of each event (Default: 10)&amp;#34;`&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Plugin&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;struct&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;plugins.BasePlugin&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// Will be used to randomize samples&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;rand&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt;rand.Rand&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// Contains the init configuration values&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;config&lt;span style="color:#bbb"&gt; &lt;/span&gt;PluginConfig&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;type&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;PluginInstance&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;struct&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;source.BaseInstance&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// Copy of the init params from plugin_open()&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;initParams&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;string&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// The number of events to return before EOF&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;maxEvents&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;uint64&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// A count of events returned. Used to count against maxEvents.&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;counter&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;uint64&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// A semi-random numeric value, derived from this value and&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// jitter. This is put in every event as the data property.&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;sample&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;uint64&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;init&lt;/span&gt;()&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;plugins.&lt;span style="color:#00a000"&gt;SetFactory&lt;/span&gt;(&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;()&lt;span style="color:#bbb"&gt; &lt;/span&gt;plugins.Plugin&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;p&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;:=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;&amp;amp;&lt;/span&gt;Plugin{}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;source.&lt;span style="color:#00a000"&gt;Register&lt;/span&gt;(p)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;extractor.&lt;span style="color:#00a000"&gt;Register&lt;/span&gt;(p)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;p&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;})&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="plugin-info"&gt;Plugin Info&lt;/h3&gt;
&lt;p&gt;An &lt;code&gt;Info()&lt;/code&gt; method is needed to return a data struct containing all the plugin info. &lt;code&gt;Info()&lt;/code&gt; is a required method for the defined plugin struct type. This plugin defined its info as a set of constants for simplicity, but it's not a requirement.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;const&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;(&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;PluginID&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;uint32&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;=&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;3&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;PluginName&lt;span style="color:#bbb"&gt; &lt;/span&gt;=&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b44"&gt;&amp;#34;dummy&amp;#34;&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;PluginDescription&lt;span style="color:#bbb"&gt; &lt;/span&gt;=&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b44"&gt;&amp;#34;Reference plugin for educational purposes&amp;#34;&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;PluginContact&lt;span style="color:#bbb"&gt; &lt;/span&gt;=&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b44"&gt;&amp;#34;github.com/falcosecurity/plugins&amp;#34;&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;PluginVersion&lt;span style="color:#bbb"&gt; &lt;/span&gt;=&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b44"&gt;&amp;#34;0.4.0&amp;#34;&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;PluginEventSource&lt;span style="color:#bbb"&gt; &lt;/span&gt;=&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b44"&gt;&amp;#34;dummy&amp;#34;&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt;...&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;(m&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt;Plugin)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Info&lt;/span&gt;()&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt;plugins.Info&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;&amp;amp;&lt;/span&gt;plugins.Info{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;ID:&lt;span style="color:#bbb"&gt; &lt;/span&gt;PluginID,&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Name:&lt;span style="color:#bbb"&gt; &lt;/span&gt;PluginName,&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Description:&lt;span style="color:#bbb"&gt; &lt;/span&gt;PluginDescription,&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Contact:&lt;span style="color:#bbb"&gt; &lt;/span&gt;PluginContact,&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Version:&lt;span style="color:#bbb"&gt; &lt;/span&gt;PluginVersion,&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;RequiredAPIVersion:&lt;span style="color:#bbb"&gt; &lt;/span&gt;PluginRequiredApiVersion,&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;EventSource:&lt;span style="color:#bbb"&gt; &lt;/span&gt;PluginEventSource,&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666"&gt;...&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="initializing-destroying-the-plugin"&gt;Initializing/Destroying the Plugin&lt;/h3&gt;
&lt;p&gt;The mandatory &lt;code&gt;Init()&lt;/code&gt; method serves as an initialization entrypoint for plugins. This is where the user-defined configuration string is passed in by the framework. The internal state of the plugin should be initialized at this level. An error can be returned to abort the plugin initialization.&lt;/p&gt;
&lt;p&gt;Defining the &lt;code&gt;Destroy()&lt;/code&gt; method is optional but can be useful if some resource needs to be released before the plugin gets destroyed. The &lt;code&gt;InitSchema()&lt;/code&gt; method is optional too, but it allows the framework to parse the init config automatically, thus avoiding the need of doing it manually inside &lt;code&gt;Init()&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// Set the config default values.&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;(p&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt;PluginConfig)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;setDefault&lt;/span&gt;()&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;p.Jitter&lt;span style="color:#bbb"&gt; &lt;/span&gt;=&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;10&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// This returns a schema representing the configuration expected by the&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// plugin to be passed to the Init() method. Defining InitSchema() allows&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// the framework to automatically validate the configuration, so that the&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// plugin can assume that it to be always be well-formed when passed to Init().&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;(p&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt;Plugin)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;InitSchema&lt;/span&gt;()&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt;sdk.SchemaInfo&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// We leverage the jsonschema package to autogenerate the&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// JSON Schema definition using reflection from our config struct.&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;reflector&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;:=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;jsonschema.Reflector{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// all properties are optional by default&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;RequiredFromJSONSchemaTags:&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;true&lt;/span&gt;,&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// unrecognized properties don&amp;#39;t cause a parsing failures&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;AllowAdditionalProperties:&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;true&lt;/span&gt;,&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;schema,&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;:=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;reflector.&lt;span style="color:#00a000"&gt;Reflect&lt;/span&gt;(&lt;span style="color:#666"&gt;&amp;amp;&lt;/span&gt;PluginConfig{}).&lt;span style="color:#00a000"&gt;MarshalJSON&lt;/span&gt;();&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;==&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;nil&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;&amp;amp;&lt;/span&gt;sdk.SchemaInfo{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Schema:&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f"&gt;string&lt;/span&gt;(schema),&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;nil&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// Since this plugin defines the InitSchema() method, we can assume&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// that the configuration is pre-validated by the framework and&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;// always well-formed according to the provided schema.&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;(m&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt;Plugin)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Init&lt;/span&gt;(cfg&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;string&lt;/span&gt;)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;error&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// initialize state&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;m.rand&lt;span style="color:#bbb"&gt; &lt;/span&gt;=&lt;span style="color:#bbb"&gt; &lt;/span&gt;rand.&lt;span style="color:#00a000"&gt;New&lt;/span&gt;(rand.&lt;span style="color:#00a000"&gt;NewSource&lt;/span&gt;(time.&lt;span style="color:#00a000"&gt;Now&lt;/span&gt;().&lt;span style="color:#00a000"&gt;UnixNano&lt;/span&gt;()))&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// The format of cfg is a json object with a single param&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// &amp;#34;jitter&amp;#34;, e.g. {&amp;#34;jitter&amp;#34;: 10}&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// Empty configs are allowed, in which case the default is used.&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// Since we provide a schema through InitSchema(), the framework&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// guarantees that the config is always well-formed json.&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;m.config.&lt;span style="color:#00a000"&gt;setDefault&lt;/span&gt;()&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;json.&lt;span style="color:#00a000"&gt;Unmarshal&lt;/span&gt;([]&lt;span style="color:#a2f"&gt;byte&lt;/span&gt;(cfg),&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;&amp;amp;&lt;/span&gt;m.config)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;nil&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;(m&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt;Plugin)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Destroy&lt;/span&gt;()&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// nothing to do here&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="opening-closing-a-stream-of-events"&gt;Opening/Closing a Stream of Events&lt;/h3&gt;
&lt;p&gt;A plugin instance is created when the plugin event stream is opened, which can happen more than once during the plugin lifecycle. Plugins with event sourcing capability are required to define an &lt;code&gt;Open()&lt;/code&gt; method that creates a returns a new plugin instance. This is where the framework passes in the user-defined open parameters string.&lt;/p&gt;
&lt;p&gt;The plugin instance type returned by &lt;code&gt;Open()&lt;/code&gt; can define an optional &lt;code&gt;Close()&lt;/code&gt; method bundling any additional deinitialization logic to run while closing the event stream.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;(m&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt;Plugin)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Open&lt;/span&gt;(prms&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;string&lt;/span&gt;)&lt;span style="color:#bbb"&gt; &lt;/span&gt;(source.Instance,&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;error&lt;/span&gt;)&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// The format of params is a json object with two params:&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// - &amp;#34;start&amp;#34;, which denotes the initial value of sample&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// - &amp;#34;maxEvents&amp;#34;: which denotes the number of events to return before EOF.&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// Example:&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// {&amp;#34;start&amp;#34;: 1, &amp;#34;maxEvents&amp;#34;: 1000}&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;var&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;obj&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;map&lt;/span&gt;[&lt;span style="color:#0b0;font-weight:bold"&gt;string&lt;/span&gt;]&lt;span style="color:#0b0;font-weight:bold"&gt;uint64&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;:=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;json.&lt;span style="color:#00a000"&gt;Unmarshal&lt;/span&gt;([]&lt;span style="color:#a2f"&gt;byte&lt;/span&gt;(prms),&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;&amp;amp;&lt;/span&gt;obj)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;!=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;nil&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;nil&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;fmt.&lt;span style="color:#00a000"&gt;Errorf&lt;/span&gt;(&lt;span style="color:#b44"&gt;&amp;#34;params %s could not be parsed: %v&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;prms,&lt;span style="color:#bbb"&gt; &lt;/span&gt;err)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;_,&lt;span style="color:#bbb"&gt; &lt;/span&gt;ok&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;:=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;obj[&lt;span style="color:#b44"&gt;&amp;#34;start&amp;#34;&lt;/span&gt;];&lt;span style="color:#bbb"&gt; &lt;/span&gt;!ok&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;nil&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;fmt.&lt;span style="color:#00a000"&gt;Errorf&lt;/span&gt;(&lt;span style="color:#b44"&gt;&amp;#34;params %s did not contain start property&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;prms)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;_,&lt;span style="color:#bbb"&gt; &lt;/span&gt;ok&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;:=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;obj[&lt;span style="color:#b44"&gt;&amp;#34;maxEvents&amp;#34;&lt;/span&gt;];&lt;span style="color:#bbb"&gt; &lt;/span&gt;!ok&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;nil&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;fmt.&lt;span style="color:#00a000"&gt;Errorf&lt;/span&gt;(&lt;span style="color:#b44"&gt;&amp;#34;params %s did not contain maxEvents property&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;prms)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;&amp;amp;&lt;/span&gt;PluginInstance{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;initParams:&lt;span style="color:#bbb"&gt; &lt;/span&gt;prms,&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;maxEvents:&lt;span style="color:#bbb"&gt; &lt;/span&gt;obj[&lt;span style="color:#b44"&gt;&amp;#34;maxEvents&amp;#34;&lt;/span&gt;],&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;counter:&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;0&lt;/span&gt;,&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;sample:&lt;span style="color:#bbb"&gt; &lt;/span&gt;obj[&lt;span style="color:#b44"&gt;&amp;#34;start&amp;#34;&lt;/span&gt;],&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;},&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;nil&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;(m&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt;PluginInstance)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Close&lt;/span&gt;()&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// nothing to do here&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="returning-new-events"&gt;Returning new Events&lt;/h3&gt;
&lt;p&gt;New events are generated in batch by the &lt;code&gt;NextBatch&lt;/code&gt; function. The function is mandatory for plugins with event sourcing capability and must be defined as a method of the plugin instance struct type. The &lt;code&gt;pState&lt;/code&gt; argument is the plugin struct type initialized in &lt;code&gt;Init()&lt;/code&gt;, passed in by the framework for ease of access. The plugin state is passed as an instance of the &lt;code&gt;sdk.PluginState&lt;/code&gt; interface, so a manual cast is required to access the internal state variables defined in the struct type.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;evts&lt;/code&gt; parameter is a sdk-managed batch of events to be used for creating new events. For that, the SDK uses a slab allocator and reuses the same event batch at every iteration to improve performance. The length of the &lt;code&gt;evts&lt;/code&gt; list represents the maximum size of each event batch.
Each element of the batch is an instance of &lt;code&gt;sdk.EventWriter&lt;/code&gt; that provides handy methods to write the event info and data. Event data can be written with the Go &lt;code&gt;io.Writer&lt;/code&gt; interface.&lt;/p&gt;
&lt;p&gt;If an error is returned, the SDK returns a failure to the framework and invalidates the current batch. The special errors &lt;code&gt;sdk.ErrTimeout&lt;/code&gt; and &lt;code&gt;sdk.ErrEOF&lt;/code&gt; have a special meaning, and are used to either advise the framework that no new events are currently available, or that the event stream is terminated.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;(m&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt;PluginInstance)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;NextBatch&lt;/span&gt;(pState&lt;span style="color:#bbb"&gt; &lt;/span&gt;sdk.PluginState,&lt;span style="color:#bbb"&gt; &lt;/span&gt;evts&lt;span style="color:#bbb"&gt; &lt;/span&gt;sdk.EventWriters)&lt;span style="color:#bbb"&gt; &lt;/span&gt;(&lt;span style="color:#0b0;font-weight:bold"&gt;int&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;error&lt;/span&gt;)&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// Return EOF if reached maxEvents&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;m.counter&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;&amp;gt;=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;m.maxEvents&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;0&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;sdk.ErrEOF&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// access the plugin state&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;plugin&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;:=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;pState.(&lt;span style="color:#666"&gt;*&lt;/span&gt;Plugin)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;var&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;n&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;int&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;var&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;evt&lt;span style="color:#bbb"&gt; &lt;/span&gt;sdk.EventWriter&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;for&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;n&lt;span style="color:#bbb"&gt; &lt;/span&gt;=&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;0&lt;/span&gt;;&lt;span style="color:#bbb"&gt; &lt;/span&gt;m.counter&lt;span style="color:#bbb"&gt; &lt;/span&gt;&amp;lt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;m.maxEvents&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;n&lt;span style="color:#bbb"&gt; &lt;/span&gt;&amp;lt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;evts.&lt;span style="color:#00a000"&gt;Len&lt;/span&gt;();&lt;span style="color:#bbb"&gt; &lt;/span&gt;n&lt;span style="color:#666"&gt;++&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;evt&lt;span style="color:#bbb"&gt; &lt;/span&gt;=&lt;span style="color:#bbb"&gt; &lt;/span&gt;evts.&lt;span style="color:#00a000"&gt;Get&lt;/span&gt;(n)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;m.counter&lt;span style="color:#666"&gt;++&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// Increment sample by 1, also add a jitter of [0:jitter]&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;m.sample&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;+=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;1&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;+&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f"&gt;uint64&lt;/span&gt;(plugin.rand.&lt;span style="color:#00a000"&gt;Int63n&lt;/span&gt;(&lt;span style="color:#a2f"&gt;int64&lt;/span&gt;(plugin.config.Jitter&lt;span style="color:#666"&gt;+&lt;/span&gt;&lt;span style="color:#666"&gt;1&lt;/span&gt;)))&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// The representation of a dummy event is the sample as a string.&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;str&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;:=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;strconv.&lt;span style="color:#00a000"&gt;Itoa&lt;/span&gt;(&lt;span style="color:#a2f"&gt;int&lt;/span&gt;(m.sample))&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// It is not mandatory to set the Timestamp of the event (it&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// would be filled in by the framework if set to uint_max),&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// but it&amp;#39;s a good practice.&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;evt.&lt;span style="color:#00a000"&gt;SetTimestamp&lt;/span&gt;(&lt;span style="color:#a2f"&gt;uint64&lt;/span&gt;(time.&lt;span style="color:#00a000"&gt;Now&lt;/span&gt;().&lt;span style="color:#00a000"&gt;UnixNano&lt;/span&gt;()))&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;_,&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;:=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;evt.&lt;span style="color:#00a000"&gt;Writer&lt;/span&gt;().&lt;span style="color:#00a000"&gt;Write&lt;/span&gt;([]&lt;span style="color:#a2f"&gt;byte&lt;/span&gt;(str))&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;!=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;nil&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;0&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;n,&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;nil&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="printing-events-as-strings"&gt;Printing Events As Strings&lt;/h3&gt;
&lt;p&gt;Plugins with event sourcing capability can optionally have a &lt;code&gt;String()&lt;/code&gt; method to format the contents of events created with a previous call to &lt;code&gt;NextBatch()&lt;/code&gt;. The event data is readable through an instance of &lt;code&gt;sdk.EventReader&lt;/code&gt; provided by the SDK. Internally, this allows safe memory access and an optimal reusage of the same buffer to maximize the performance of hot framework paths.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;(m&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt;Plugin)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;String&lt;/span&gt;(evt&lt;span style="color:#bbb"&gt; &lt;/span&gt;sdk.EventReader)&lt;span style="color:#bbb"&gt; &lt;/span&gt;(&lt;span style="color:#0b0;font-weight:bold"&gt;string&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;error&lt;/span&gt;)&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;evtBytes,&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;:=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;ioutil.&lt;span style="color:#00a000"&gt;ReadAll&lt;/span&gt;(evt.&lt;span style="color:#00a000"&gt;Reader&lt;/span&gt;())&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;!=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;nil&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b44"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;evtStr&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;:=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f"&gt;string&lt;/span&gt;(evtBytes)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// The string representation of an event is a json object with the sample&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;fmt.&lt;span style="color:#00a000"&gt;Sprintf&lt;/span&gt;(&lt;span style="color:#b44"&gt;&amp;#34;{\&amp;#34;sample\&amp;#34;: \&amp;#34;%s\&amp;#34;}&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;evtStr),&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;nil&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="defining-fields"&gt;Defining Fields&lt;/h3&gt;
&lt;p&gt;This dummy plugin has field extraction capability and exports 3 fields:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dummy.value&lt;/code&gt;: the value in the event, as a uint64&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dummy.strvalue&lt;/code&gt;: the value in the event, as a string&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dummy.divisible&lt;/code&gt;: this field takes an argument and returns 1 if the value in the event is divisible by the argument (a numeric divisor). For example, if the value was 12, &lt;code&gt;dummy.divisible[3]&lt;/code&gt; would return 1 for that event.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;Fields()&lt;/code&gt; method returns a slice of &lt;code&gt;sdk.FieldEntry&lt;/code&gt; representing all the supported fields.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;(m&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt;Plugin)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Fields&lt;/span&gt;()&lt;span style="color:#bbb"&gt; &lt;/span&gt;[]sdk.FieldEntry&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;[]sdk.FieldEntry{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Type:&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b44"&gt;&amp;#34;uint64&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Name:&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b44"&gt;&amp;#34;dummy.divisible&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Desc:&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b44"&gt;&amp;#34;Return 1 if the value is divisible by the provided divisor, 0 otherwise&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Arg:&lt;span style="color:#bbb"&gt; &lt;/span&gt;sdk.FieldEntryArg{IsRequired:&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;true&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;IsKey:&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;true&lt;/span&gt;},&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;},&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Type:&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b44"&gt;&amp;#34;uint64&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Name:&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b44"&gt;&amp;#34;dummy.value&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Desc:&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b44"&gt;&amp;#34;The sample value in the event&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;},&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Type:&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b44"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Name:&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b44"&gt;&amp;#34;dummy.strvalue&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Desc:&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b44"&gt;&amp;#34;The sample value in the event, as a string&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;},&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="extracting-fields"&gt;Extracting Fields&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;Extract&lt;/code&gt; method extracts all of the supported fields. The &lt;code&gt;req&lt;/code&gt; parameter allows accessing all the info regarding the field request, such as the field id or name, and the optional user-passed argument. The &lt;code&gt;evt&lt;/code&gt; parameter is an interface that helps reading the event info and data.&lt;/p&gt;
&lt;p&gt;The extracted field value must be set through the &lt;code&gt;SetValue&lt;/code&gt; method of &lt;code&gt;sdk.ExtractRequest&lt;/code&gt;. Returning from &lt;code&gt;Extract&lt;/code&gt; without calling &lt;code&gt;SetValue&lt;/code&gt; will signal the SDK that the requested field is not present in the given event.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;(m&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;*&lt;/span&gt;Plugin)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#00a000"&gt;Extract&lt;/span&gt;(req&lt;span style="color:#bbb"&gt; &lt;/span&gt;sdk.ExtractRequest,&lt;span style="color:#bbb"&gt; &lt;/span&gt;evt&lt;span style="color:#bbb"&gt; &lt;/span&gt;sdk.EventReader)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#0b0;font-weight:bold"&gt;error&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;evtBytes,&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;:=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;ioutil.&lt;span style="color:#00a000"&gt;ReadAll&lt;/span&gt;(evt.&lt;span style="color:#00a000"&gt;Reader&lt;/span&gt;())&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;!=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;nil&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;evtStr&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;:=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f"&gt;string&lt;/span&gt;(evtBytes)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;evtVal,&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;:=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;strconv.&lt;span style="color:#00a000"&gt;Atoi&lt;/span&gt;(evtStr)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;!=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;nil&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;switch&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;req.&lt;span style="color:#00a000"&gt;FieldID&lt;/span&gt;()&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;case&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;0&lt;/span&gt;:&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// dummy.divisible&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;divisor,&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;:=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;strconv.&lt;span style="color:#00a000"&gt;Atoi&lt;/span&gt;(req.&lt;span style="color:#00a000"&gt;ArgKey&lt;/span&gt;())&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;!=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;nil&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;fmt.&lt;span style="color:#00a000"&gt;Errorf&lt;/span&gt;(&lt;span style="color:#b44"&gt;&amp;#34;argument to dummy.divisible %s could not be converted to number&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;req.&lt;span style="color:#00a000"&gt;ArgKey&lt;/span&gt;())&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;evtVal&lt;span style="color:#666"&gt;%&lt;/span&gt;divisor&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;==&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;0&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;req.&lt;span style="color:#00a000"&gt;SetValue&lt;/span&gt;(&lt;span style="color:#a2f"&gt;uint64&lt;/span&gt;(&lt;span style="color:#666"&gt;1&lt;/span&gt;))&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;}&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;else&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;req.&lt;span style="color:#00a000"&gt;SetValue&lt;/span&gt;(&lt;span style="color:#a2f"&gt;uint64&lt;/span&gt;(&lt;span style="color:#666"&gt;0&lt;/span&gt;))&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;case&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;1&lt;/span&gt;:&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// dummy.value&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;req.&lt;span style="color:#00a000"&gt;SetValue&lt;/span&gt;(&lt;span style="color:#a2f"&gt;uint64&lt;/span&gt;(evtVal))&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;case&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;2&lt;/span&gt;:&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#080;font-style:italic"&gt;// dummy.strvalue&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;req.&lt;span style="color:#00a000"&gt;SetValue&lt;/span&gt;(evtStr)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;default&lt;/span&gt;:&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;fmt.&lt;span style="color:#00a000"&gt;Errorf&lt;/span&gt;(&lt;span style="color:#b44"&gt;&amp;#34;no known field: %s&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;req.&lt;span style="color:#00a000"&gt;Field&lt;/span&gt;())&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;nil&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="running-the-plugin"&gt;Running the Plugin&lt;/h3&gt;
&lt;p&gt;This plugin can be configured in Falco by adding the following to &lt;code&gt;falco.yaml&lt;/code&gt; file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#008000;font-weight:bold"&gt;plugins&lt;/span&gt;:&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;- &lt;span style="color:#008000;font-weight:bold"&gt;name&lt;/span&gt;:&lt;span style="color:#bbb"&gt; &lt;/span&gt;dummy&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#008000;font-weight:bold"&gt;library_path&lt;/span&gt;:&lt;span style="color:#bbb"&gt; &lt;/span&gt;/tmp/my-plugins/dummy/libdummy.so&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#008000;font-weight:bold"&gt;init_config&lt;/span&gt;:&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#008000;font-weight:bold"&gt;jitter&lt;/span&gt;:&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#666"&gt;10&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#008000;font-weight:bold"&gt;open_params&lt;/span&gt;:&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b44"&gt;&amp;#39;{&amp;#34;start&amp;#34;: 1, &amp;#34;maxEvents&amp;#34;: 20}&amp;#39;&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;## Optional&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#008000;font-weight:bold"&gt;load_plugins&lt;/span&gt;:&lt;span style="color:#bbb"&gt; &lt;/span&gt;[dummy]&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This simple rule prints a Falco alert any time the event number is between 0 and 10, and the sample value is divisible by 3:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#008000;font-weight:bold"&gt;rule&lt;/span&gt;:&lt;span style="color:#bbb"&gt; &lt;/span&gt;My Dummy Rule&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#008000;font-weight:bold"&gt;desc&lt;/span&gt;:&lt;span style="color:#bbb"&gt; &lt;/span&gt;My Desc&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#008000;font-weight:bold"&gt;condition&lt;/span&gt;:&lt;span style="color:#bbb"&gt; &lt;/span&gt;evt.num &amp;gt; 0 and evt.num &amp;lt; 10 and dummy.divisible[3] = 1&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#008000;font-weight:bold"&gt;output&lt;/span&gt;:&lt;span style="color:#bbb"&gt; &lt;/span&gt;A dummy event | event=%evt.plugininfo sample=%dummy.value sample_str=%dummy.strvalue num=%evt.num&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#008000;font-weight:bold"&gt;priority&lt;/span&gt;:&lt;span style="color:#bbb"&gt; &lt;/span&gt;INFO&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#008000;font-weight:bold"&gt;source&lt;/span&gt;:&lt;span style="color:#bbb"&gt; &lt;/span&gt;dummy&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here's what it looks like when run:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ ./falco -r ../falco-files/dummy_rules.yaml -c ../falco-files/falco.yaml
Wed Feb 2 16:26:35 2022: Falco version 0.31.0 (driver version 319368f1ad778691164d33d59945e00c5752cd27)
Wed Feb 2 16:26:35 2022: Falco initialized with configuration file ../falco-files/falco.yaml
Wed Feb 2 16:26:35 2022: Loading plugin (dummy) from file /tmp/my-plugins/dummy/libdummy.so
Wed Feb 2 16:26:35 2022: Loading rules from file ../rules/dummy_rules.yaml:
Wed Feb 2 16:26:35 2022: Starting internal webserver, listening on port 8765
16:26:35.527827816: Notice A dummy event (event={&amp;#34;sample&amp;#34;: &amp;#34;6&amp;#34;} sample=6 sample_str=6 num=1)
16:26:35.527829658: Notice A dummy event (event={&amp;#34;sample&amp;#34;: &amp;#34;18&amp;#34;} sample=18 sample_str=18 num=3)
16:26:35.527831048: Notice A dummy event (event={&amp;#34;sample&amp;#34;: &amp;#34;33&amp;#34;} sample=33 sample_str=33 num=8)
Events detected: 3
Rule counts by severity:
INFO: 3
Triggered rules by rule name:
My Dummy Rule: 3
Syscall event drop monitoring:
- event drop detected: 0 occurrences
- num times actions taken: 0
&lt;/code&gt;&lt;/pre&gt;</description></item></channel></rss>