diff --git a/pkg/collector/python/datadog_agent.go b/pkg/collector/python/datadog_agent.go index 89dbca0a115df..9b321d40f4f4f 100644 --- a/pkg/collector/python/datadog_agent.go +++ b/pkg/collector/python/datadog_agent.go @@ -14,6 +14,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/config" "github.com/DataDog/datadog-agent/pkg/metadata/externalhost" + "github.com/DataDog/datadog-agent/pkg/metadata/inventories" "github.com/DataDog/datadog-agent/pkg/util" "github.com/DataDog/datadog-agent/pkg/util/kubernetes/clustername" "github.com/DataDog/datadog-agent/pkg/util/log" @@ -150,3 +151,14 @@ func SetExternalTags(hostname *C.char, sourceType *C.char, tags **C.char) { externalhost.SetExternalTags(hname, stype, tagsStrings) } + +// SetCheckMetadata updates a metadata value for one check instance in the cache. +// Indirectly used by the C function `set_check_metadata` that's mapped to `datadog_agent.set_check_metadata`. +//export SetCheckMetadata +func SetCheckMetadata(checkID, name, value *C.char) { + cid := C.GoString(checkID) + key := C.GoString(name) + val := C.GoString(value) + + inventories.SetCheckMetadata(cid, key, val) +} diff --git a/pkg/collector/python/init.go b/pkg/collector/python/init.go index 7716c2ad151b1..5b03eb26e5194 100644 --- a/pkg/collector/python/init.go +++ b/pkg/collector/python/init.go @@ -81,6 +81,7 @@ void GetConfig(char*, char **); void GetHostname(char **); void GetVersion(char **); void Headers(char **); +void SetCheckMetadata(char *, char *, char *); void SetExternalTags(char *, char *, char **); bool TracemallocEnabled(); @@ -90,6 +91,7 @@ void initDatadogAgentModule(rtloader_t *rtloader) { set_get_hostname_cb(rtloader, GetHostname); set_get_version_cb(rtloader, GetVersion); set_headers_cb(rtloader, Headers); + set_set_check_metadata_cb(rtloader, SetCheckMetadata); set_set_external_tags_cb(rtloader, SetExternalTags); set_tracemalloc_enabled_cb(rtloader, TracemallocEnabled); } diff --git a/releasenotes/notes/rtloader-api-for-check-metadata-bfa94b82c27d782d.yaml b/releasenotes/notes/rtloader-api-for-check-metadata-bfa94b82c27d782d.yaml new file mode 100644 index 0000000000000..a7bc798659281 --- /dev/null +++ b/releasenotes/notes/rtloader-api-for-check-metadata-bfa94b82c27d782d.yaml @@ -0,0 +1,5 @@ +--- +enhancements: + - | + Implement API that allows Python checks to send metadata using + the ``inventories`` provider. diff --git a/rtloader/common/builtins/datadog_agent.c b/rtloader/common/builtins/datadog_agent.c index fbe288ba391c3..54da30d249c0f 100644 --- a/rtloader/common/builtins/datadog_agent.c +++ b/rtloader/common/builtins/datadog_agent.c @@ -16,6 +16,7 @@ static cb_get_hostname_t cb_get_hostname = NULL; static cb_tracemalloc_enabled_t cb_tracemalloc_enabled = NULL; static cb_get_version_t cb_get_version = NULL; static cb_headers_t cb_headers = NULL; +static cb_set_check_metadata_t cb_set_check_metadata = NULL; static cb_set_external_tags_t cb_set_external_tags = NULL; // forward declarations @@ -26,6 +27,7 @@ static PyObject *tracemalloc_enabled(PyObject *self, PyObject *args); static PyObject *get_version(PyObject *self, PyObject *args); static PyObject *headers(PyObject *self, PyObject *args, PyObject *kwargs); static PyObject *log_message(PyObject *self, PyObject *args); +static PyObject *set_check_metadata(PyObject *self, PyObject *args); static PyObject *set_external_tags(PyObject *self, PyObject *args); static PyMethodDef methods[] = { @@ -36,6 +38,7 @@ static PyMethodDef methods[] = { { "get_version", get_version, METH_NOARGS, "Get Agent version." }, { "headers", (PyCFunction)headers, METH_VARARGS | METH_KEYWORDS, "Get standard set of HTTP headers." }, { "log", log_message, METH_VARARGS, "Log a message through the agent logger." }, + { "set_check_metadata", set_check_metadata, METH_VARARGS, "Send metadata for Checks." }, { "set_external_tags", set_external_tags, METH_VARARGS, "Send external host tags." }, { NULL, NULL } // guards }; @@ -82,6 +85,11 @@ void _set_get_clustername_cb(cb_get_clustername_t cb) cb_get_clustername = cb; } +void _set_set_check_metadata_cb(cb_set_check_metadata_t cb) +{ + cb_set_check_metadata = cb; +} + void _set_set_external_tags_cb(cb_set_external_tags_t cb) { cb_set_external_tags = cb; @@ -349,6 +357,41 @@ static PyObject *log_message(PyObject *self, PyObject *args) Py_RETURN_NONE; } +/*! \fn PyObject *set_check_metadata(PyObject *self, PyObject *args) + \brief This function implements the `datadog_agent.set_check_metadata` method, updating + the value in the cache. + \param self A PyObject* pointer to the `datadog_agent` module. + \param args A PyObject* pointer to a 3-ary tuple containing the unique ID of a check + instance, the name of the metadata entry, and the value of said entry. + \return A PyObject* pointer to `None`. + + This function is callable as the `datadog_agent.set_check_metadata` Python method and + uses the `cb_set_check_metadata()` callback to retrieve the value from the agent + with CGO. If the callback has not been set `None` will be returned. +*/ +static PyObject *set_check_metadata(PyObject *self, PyObject *args) +{ + // callback must be set + if (cb_set_check_metadata == NULL) { + Py_RETURN_NONE; + } + + char *check_id, *name, *value; + + PyGILState_STATE gstate = PyGILState_Ensure(); + + // datadog_agent.set_check_metadata(check_id, name, value) + if (!PyArg_ParseTuple(args, "sss", &check_id, &name, &value)) { + PyGILState_Release(gstate); + return NULL; + } + + PyGILState_Release(gstate); + cb_set_check_metadata(check_id, name, value); + + Py_RETURN_NONE; +} + // /*! \fn PyObject *set_external_tags(PyObject *self, PyObject *args) \brief This function implements the `datadog_agent.set_external_tags` method, diff --git a/rtloader/common/builtins/datadog_agent.h b/rtloader/common/builtins/datadog_agent.h index 2a45adb85cf7e..61f60ddcc84f7 100644 --- a/rtloader/common/builtins/datadog_agent.h +++ b/rtloader/common/builtins/datadog_agent.h @@ -74,6 +74,14 @@ The callback is expected to be provided by the rtloader caller - in go-context: CGO. */ +/*! \fn void _set_set_check_metadata_cb(cb_set_check_metadata_t) + \brief Sets a callback to be used by rtloader to allow setting metadata for a given + check instance. + \param object A function pointer with cb_set_check_metadata_t prototype to the callback + function. + + The callback is expected to be provided by the rtloader caller - in go-context: CGO. +*/ /*! \fn void _set_set_external_tags_cb(cb_set_external_tags_t) \brief Sets a callback to be used by rtloader to allow setting external tags for a given hostname. @@ -118,6 +126,7 @@ void _set_tracemalloc_enabled_cb(cb_tracemalloc_enabled_t); void _set_get_version_cb(cb_get_version_t); void _set_headers_cb(cb_headers_t); void _set_log_cb(cb_log_t); +void _set_set_check_metadata_cb(cb_set_check_metadata_t); void _set_set_external_tags_cb(cb_set_external_tags_t); PyObject *_public_headers(PyObject *self, PyObject *args, PyObject *kwargs); diff --git a/rtloader/include/datadog_agent_rtloader.h b/rtloader/include/datadog_agent_rtloader.h index 192cb925a7af0..12f6a366e1d11 100644 --- a/rtloader/include/datadog_agent_rtloader.h +++ b/rtloader/include/datadog_agent_rtloader.h @@ -461,6 +461,17 @@ DATADOG_AGENT_RTLOADER_API void set_tracemalloc_enabled_cb(rtloader_t *, cb_trac */ DATADOG_AGENT_RTLOADER_API void set_log_cb(rtloader_t *, cb_log_t); +/*! \fn void set_set_check_metadata_cb(rtloader_t *, cb_set_check_metadata_t) + \brief Sets a callback to be used by rtloader to allow setting metadata for a given + check instance. + \param rtloader_t A rtloader_t * pointer to the RtLoader instance. + \param object A function pointer with cb_set_check_metadata_t prototype to the callback + function. + + The callback is expected to be provided by the rtloader caller - in go-context: CGO. +*/ +DATADOG_AGENT_RTLOADER_API void set_set_check_metadata_cb(rtloader_t *, cb_set_check_metadata_t); + /*! \fn void set_set_external_tags_cb(rtloader_t *, cb_set_external_tags_t) \brief Sets a callback to be used by rtloader to allow setting external tags for a given hostname. diff --git a/rtloader/include/rtloader.h b/rtloader/include/rtloader.h index 24d7816bc0e6c..a2a6f5efd2d93 100644 --- a/rtloader/include/rtloader.h +++ b/rtloader/include/rtloader.h @@ -339,6 +339,15 @@ class RtLoader */ virtual void setLogCb(cb_log_t) = 0; + //! setCheckMetadataCb member. + /*! + \param A cb_set_check_metadata_t function pointer to the CGO callback. + + This allows us to set the relevant CGO callback that will allow adding metadata for + specific check instances to the go-land Inventories metadata provider cache. + */ + virtual void setSetCheckMetadataCb(cb_set_check_metadata_t) = 0; + //! setExternalTagsCb member. /*! \param A cb_set_external_tags_t function pointer to the CGO callback. diff --git a/rtloader/include/rtloader_types.h b/rtloader/include/rtloader_types.h index 924dcd0306f88..b7e1195d3bb3d 100644 --- a/rtloader/include/rtloader_types.h +++ b/rtloader/include/rtloader_types.h @@ -117,6 +117,8 @@ typedef void (*cb_get_clustername_t)(char **); typedef bool (*cb_tracemalloc_enabled_t)(void); // (message, level) typedef void (*cb_log_t)(const char *, int); +// (check_id, name, value) +typedef void (*cb_set_check_metadata_t)(char *, char *, char *); // (hostname, source_type_name, list of tags) typedef void (*cb_set_external_tags_t)(char *, char *, char **); diff --git a/rtloader/rtloader/api.cpp b/rtloader/rtloader/api.cpp index 45a4ec8daa803..07170d25fcc31 100644 --- a/rtloader/rtloader/api.cpp +++ b/rtloader/rtloader/api.cpp @@ -421,6 +421,11 @@ void set_log_cb(rtloader_t *rtloader, cb_log_t cb) AS_TYPE(RtLoader, rtloader)->setLogCb(cb); } +void set_set_check_metadata_cb(rtloader_t *rtloader, cb_set_check_metadata_t cb) +{ + AS_TYPE(RtLoader, rtloader)->setSetCheckMetadataCb(cb); +} + void set_set_external_tags_cb(rtloader_t *rtloader, cb_set_external_tags_t cb) { AS_TYPE(RtLoader, rtloader)->setSetExternalTagsCb(cb); diff --git a/rtloader/test/datadog_agent/datadog_agent.go b/rtloader/test/datadog_agent/datadog_agent.go index 27cf7de58508f..0fba762a5757a 100644 --- a/rtloader/test/datadog_agent/datadog_agent.go +++ b/rtloader/test/datadog_agent/datadog_agent.go @@ -26,6 +26,7 @@ import ( // extern bool getTracemallocEnabled(); // extern void getVersion(char **); // extern void headers(char **); +// extern void setCheckMetadata(char*, char*, char*); // extern void setExternalHostTags(char*, char*, char**); // // static void initDatadogAgentTests(rtloader_t *rtloader) { @@ -36,6 +37,7 @@ import ( // set_get_version_cb(rtloader, getVersion); // set_headers_cb(rtloader, headers); // set_log_cb(rtloader, doLog); +// set_set_check_metadata_cb(rtloader, setCheckMetadata); // set_set_external_tags_cb(rtloader, setExternalHostTags); // } import "C" @@ -163,6 +165,18 @@ func doLog(msg *C.char, level C.int) { ioutil.WriteFile(tmpfile.Name(), data, 0644) } +//export setCheckMetadata +func setCheckMetadata(checkID, name, value *C.char) { + cid := C.GoString(checkID) + key := C.GoString(name) + val := C.GoString(value) + + f, _ := os.OpenFile(tmpfile.Name(), os.O_APPEND|os.O_RDWR|os.O_CREATE, 0666) + defer f.Close() + + f.WriteString(strings.Join([]string{cid, key, val}, ",")) +} + //export setExternalHostTags func setExternalHostTags(hostname *C.char, sourceType *C.char, tags **C.char) { hname := C.GoString(hostname) diff --git a/rtloader/test/datadog_agent/datadog_agent_test.go b/rtloader/test/datadog_agent/datadog_agent_test.go index fd78da96aaac3..703ea1a0f550e 100644 --- a/rtloader/test/datadog_agent/datadog_agent_test.go +++ b/rtloader/test/datadog_agent/datadog_agent_test.go @@ -128,6 +128,19 @@ func TestLog(t *testing.T) { } } +func TestSetCheckMetadata(t *testing.T) { + code := ` + datadog_agent.set_check_metadata("redis:test:12345", "version.raw", "5.0.6") + ` + out, err := run(code) + if err != nil { + t.Fatal(err) + } + if out != "redis:test:12345,version.raw,5.0.6" { + t.Errorf("Unexpected printed value: '%s'", out) + } +} + func TestSetExternalTags(t *testing.T) { code := ` tags = [ diff --git a/rtloader/three/three.cpp b/rtloader/three/three.cpp index 31ac8c1197113..1386f8e0a891d 100644 --- a/rtloader/three/three.cpp +++ b/rtloader/three/three.cpp @@ -833,6 +833,11 @@ void Three::setLogCb(cb_log_t cb) _set_log_cb(cb); } +void Three::setSetCheckMetadataCb(cb_set_check_metadata_t cb) +{ + _set_set_check_metadata_cb(cb); +} + void Three::setSetExternalTagsCb(cb_set_external_tags_t cb) { _set_set_external_tags_cb(cb); diff --git a/rtloader/three/three.h b/rtloader/three/three.h index d9ab9fd5c1b21..a3515330acabf 100644 --- a/rtloader/three/three.h +++ b/rtloader/three/three.h @@ -99,6 +99,7 @@ class Three : public RtLoader void setGetClusternameCb(cb_get_clustername_t); void setGetTracemallocEnabledCb(cb_tracemalloc_enabled_t); void setLogCb(cb_log_t); + void setSetCheckMetadataCb(cb_set_check_metadata_t); void setSetExternalTagsCb(cb_set_external_tags_t); // _util API diff --git a/rtloader/two/two.cpp b/rtloader/two/two.cpp index 5beb886ef45bd..2b27c439424b3 100644 --- a/rtloader/two/two.cpp +++ b/rtloader/two/two.cpp @@ -838,6 +838,11 @@ void Two::setLogCb(cb_log_t cb) _set_log_cb(cb); } +void Two::setSetCheckMetadataCb(cb_set_check_metadata_t cb) +{ + _set_set_check_metadata_cb(cb); +} + void Two::setSetExternalTagsCb(cb_set_external_tags_t cb) { _set_set_external_tags_cb(cb); diff --git a/rtloader/two/two.h b/rtloader/two/two.h index 806c4ce9ab8d0..fe62a014c81f0 100644 --- a/rtloader/two/two.h +++ b/rtloader/two/two.h @@ -98,6 +98,7 @@ class Two : public RtLoader void setGetClusternameCb(cb_get_clustername_t); void setGetTracemallocEnabledCb(cb_tracemalloc_enabled_t); void setLogCb(cb_log_t); + void setSetCheckMetadataCb(cb_set_check_metadata_t); void setSetExternalTagsCb(cb_set_external_tags_t); // _util API