-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DRAFT] custom: Go plugin support for custom plugins to support OTel extensions #9470
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#!/bin/bash | ||
|
||
# !! TODO: move to a Makefile | ||
|
||
CGO_CFLAGS="-I${HOME}/src/fluent-bit/include -I${HOME}/src/fluent-bit/lib/monkey/include -I${HOME}/src/fluent-bit/build/lib/monkey/include/monkey -I${HOME}/src/fluent-bit/lib/cfl/include -I${HOME}/src/fluent-bit/lib/cfl/lib/xxhash -I${HOME}/src/fluent-bit/lib/cmetrics/include -I${HOME}/src/fluent-bit/lib/flb_libco -I${HOME}/src/fluent-bit/lib/c-ares-1.33.1/include -I${HOME}/src/fluent-bit/lib/msgpack-c/include -I${HOME}/src/fluent-bit/lib/ctraces/include -I${HOME}/src/fluent-bit/lib/ctraces/lib/mpack/src" CGO_LDFLAGS="-L${HOME}/src/fluent-bit/build/lib -lfluent-bit" sh -c 'echo CGO_CFLAGS=${CGO_CFLAGS}; echo CGO_LDFLAGS=${CGO_LDFLAGS}; go build -buildmode=c-shared -o build/bin/custom_extensions_go.so github.com/fluent/fluent-bit/plugins/custom_extensions_go' | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module github.com/fluent/fluent-bit | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let's avoid adding extra dev files to the repo. |
||
|
||
go 1.23.0 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
// Fluent Bit Go! | ||
// ============== | ||
// Copyright (C) 2024 The Fluent Bit Go Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
|
||
package main | ||
|
||
// #include <stdlib.h> | ||
// #include "fluent-bit/flb_plugin.h" | ||
// #include "fluent-bit/flb_plugin_proxy.h" | ||
// #include "fluent-bit/flb_custom.h" | ||
import "C" | ||
|
||
import ( | ||
"fmt" | ||
"time" | ||
"unsafe" | ||
) | ||
|
||
// Define constants matching Fluent Bit core | ||
const ( | ||
FLB_ERROR = C.FLB_ERROR | ||
FLB_OK = C.FLB_OK | ||
FLB_RETRY = C.FLB_RETRY | ||
|
||
FLB_PROXY_CUSTOM_PLUGIN = C.FLB_CF_CUSTOM | ||
FLB_PROXY_GOLANG = C.FLB_PROXY_GOLANG | ||
) | ||
|
||
// Local type to define a plugin definition | ||
type ( | ||
FLBPluginProxyDef C.struct_flb_plugin_proxy_def | ||
FLBCustomInstance C.struct_flb_custom_instance | ||
) | ||
|
||
// When the FLBPluginInit is triggered by Fluent Bit, a plugin context | ||
// is passed and the next step is to invoke this FLBPluginRegister() function | ||
// to fill the required information: type, proxy type, flags name and | ||
// description. | ||
// | ||
//export FLBPluginRegister | ||
func FLBPluginRegister(def unsafe.Pointer, name, desc string) int { | ||
p := (*FLBPluginProxyDef)(def) | ||
p._type = FLB_PROXY_CUSTOM_PLUGIN | ||
p.proxy = FLB_PROXY_GOLANG | ||
p.flags = 0 | ||
p.name = C.CString(name) | ||
p.description = C.CString(desc) | ||
return 0 | ||
} | ||
|
||
// (fluentbit will call this) | ||
// plugin (context) pointer to fluentbit context (state/ c code) | ||
// | ||
//export FLBPluginInit | ||
func FLBPluginInit(plugin unsafe.Pointer) int { | ||
extensions := FLBPluginConfigKey(plugin, "extensions") | ||
fmt.Printf("[flb-go] extensions = '%s'\n", extensions) | ||
go func() { | ||
for { | ||
fmt.Printf("[flb-go] Go extensions alive %v\n", time.Now()) | ||
time.Sleep(10 * time.Second) | ||
} | ||
}() | ||
return FLB_OK | ||
} | ||
|
||
// Release resources allocated by the plugin initialization | ||
// | ||
//export FLBPluginUnregister | ||
func FLBPluginUnregister(def unsafe.Pointer) { | ||
p := (*FLBPluginProxyDef)(def) | ||
C.free(unsafe.Pointer(p.name)) | ||
C.free(unsafe.Pointer(p.description)) | ||
} | ||
|
||
//export FLBPluginExit | ||
func FLBPluginExit() int { | ||
return FLB_OK | ||
} | ||
|
||
func FLBPluginConfigKey(plugin unsafe.Pointer, key string) string { | ||
k := C.CString(key) | ||
p := plugin | ||
v := C.GoString(C.flb_custom_get_property(k, (*C.struct_flb_custom_instance)(p))) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need to implement flb_custom_get_property as an API here if we create custom plugin interface like as input and output: |
||
C.free(unsafe.Pointer(k)) | ||
return v | ||
} | ||
|
||
func main() { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ | |
#include <fluent-bit/flb_config.h> | ||
#include <fluent-bit/flb_plugin_proxy.h> | ||
#include <fluent-bit/flb_output.h> | ||
#include <fluent-bit/flb_custom.h> | ||
#include "./go.h" | ||
|
||
/* | ||
|
@@ -41,7 +42,7 @@ | |
* | ||
* - name: shortname of the plugin. | ||
* - description: plugin description. | ||
* - type: input, output, filter, whatever. | ||
* - type: input, output, filter, processor, custom. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure if processors can be written in Go today cc: @cosmo0920 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently, we can't do that. |
||
* - proxy: type of proxy e.g. GOLANG | ||
* - flags: optional flags, not used by Go plugins at the moment. | ||
* | ||
|
@@ -286,3 +287,87 @@ void proxy_go_input_unregister(void *data) { | |
flb_free(plugin->name); | ||
flb_free(plugin); | ||
} | ||
|
||
int proxy_go_custom_register(struct flb_plugin_proxy *proxy, | ||
struct flb_plugin_proxy_def *def) | ||
{ | ||
struct flbgo_custom_plugin *plugin; | ||
|
||
plugin = flb_malloc(sizeof(struct flbgo_custom_plugin)); | ||
if (!plugin) { | ||
return -1; | ||
} | ||
|
||
/* | ||
* Lookup the entry point function: | ||
* | ||
* - FLBPluginInit | ||
* - FLBPluginExit | ||
* | ||
* note: registration callback FLBPluginRegister() is resolved by the | ||
* parent proxy interface. | ||
*/ | ||
|
||
plugin->cb_init = flb_plugin_proxy_symbol(proxy, "FLBPluginInit"); | ||
if (!plugin->cb_init) { | ||
flb_error("[go proxy]: could not load FLBPluginInit symbol"); | ||
flb_free(plugin); | ||
return -1; | ||
} | ||
|
||
plugin->cb_exit = flb_plugin_proxy_symbol(proxy, "FLBPluginExit"); | ||
|
||
plugin->name = flb_strdup(def->name); | ||
|
||
/* This Go plugin context is an opaque data for the parent proxy */ | ||
proxy->data = plugin; | ||
|
||
return 0; | ||
} | ||
|
||
int proxy_go_custom_init(struct flb_plugin_proxy *proxy) | ||
{ | ||
int ret = 0; | ||
struct flbgo_custom_plugin *plugin = proxy->data; | ||
|
||
/* set the API */ | ||
plugin->api = proxy->api; | ||
plugin->i_ins = proxy->instance; | ||
// In order to avoid having the whole instance as part of the ABI we | ||
// copy the context pointer into the plugin. | ||
plugin->context = ((struct flb_custom_instance *)proxy->instance)->context; | ||
|
||
ret = plugin->cb_init(plugin); | ||
if (ret <= 0) { | ||
flb_error("[go proxy]: plugin '%s' failed to initialize", | ||
plugin->name); | ||
flb_free(plugin); | ||
return -1; | ||
} | ||
|
||
return ret; | ||
} | ||
|
||
int proxy_go_custom_destroy(struct flb_plugin_proxy_context *ctx) | ||
{ | ||
int ret = 0; | ||
struct flbgo_custom_plugin *plugin; | ||
|
||
plugin = (struct flbgo_custom_plugin *) ctx->proxy->data; | ||
flb_debug("[GO] running exit callback"); | ||
|
||
if (plugin->cb_exit) { | ||
ret = plugin->cb_exit(); | ||
} | ||
|
||
return ret; | ||
} | ||
|
||
void proxy_go_custom_unregister(void *data) { | ||
struct flbgo_custom_plugin *plugin; | ||
|
||
plugin = (struct flbgo_custom_plugin *) data; | ||
flb_free(plugin->name); | ||
flb_free(plugin); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's avoid adding extra dev files to the repo.