#include "dnsdist-lua-hooks.hh"
#include "dnsdist-lua.hh"
+#include "dnsdist-opentelemetry.hh"
#include "lock.hh"
#include "tcpiohandler.hh"
+#include <memory>
namespace dnsdist::lua::hooks
{
using ServerStateChangeCallback = std::function<void(const std::string&, bool)>;
static LockGuarded<std::vector<ExitCallback>> s_exitCallbacks;
-static LockGuarded<std::vector<MaintenanceCallback>> s_maintenanceHooks;
+static LockGuarded<std::vector<std::pair<std::string, MaintenanceCallback>>> s_maintenanceHooks;
static LockGuarded<std::vector<ServerStateChangeCallback>> s_serverStateChangeHooks;
-void runMaintenanceHooks(const LuaContext& context)
+void runMaintenanceHooks(const LuaContext& context, std::shared_ptr<pdns::trace::dnsdist::Tracer>& tracer)
{
(void)context;
for (const auto& callback : *(s_maintenanceHooks.lock())) {
- callback();
+ pdns::trace::dnsdist::getCloserForInternalSpan(tracer, callback.first);
+ callback.second();
}
}
-static void addMaintenanceCallback(const LuaContext& context, MaintenanceCallback callback)
+static void addMaintenanceCallback(const LuaContext& context, MaintenanceCallback callback, std::string name = "")
{
(void)context;
- s_maintenanceHooks.lock()->push_back(std::move(callback));
+ s_maintenanceHooks.lock()->push_back({"maintenanceCallback/" + name, std::move(callback)});
}
void clearMaintenanceHooks()
void setupLuaHooks(LuaContext& luaCtx)
{
- luaCtx.writeFunction("addMaintenanceCallback", [&luaCtx](const MaintenanceCallback& callback) {
+ luaCtx.writeFunction("addMaintenanceCallback", [&luaCtx](const MaintenanceCallback& callback, const std::optional<std::string> name) {
setLuaSideEffect();
- addMaintenanceCallback(luaCtx, callback);
+ addMaintenanceCallback(luaCtx, callback, name.value_or("unnamed"));
});
luaCtx.writeFunction("addExitCallback", [&luaCtx](const ExitCallback& callback) {
setLuaSideEffect();
*/
#pragma once
-#include <functional>
+#include "dnsdist-opentelemetry.hh"
+#include <memory>
#include <string>
class LuaContext;
namespace dnsdist::lua::hooks
{
-void runMaintenanceHooks(const LuaContext& context);
+void runMaintenanceHooks(const LuaContext& context, std::shared_ptr<pdns::trace::dnsdist::Tracer>& tracer);
void clearMaintenanceHooks();
void runExitCallbacks(const LuaContext& context);
void clearExitCallbacks();
:param function callback: The function to be called. It takes no parameter and returns no value.
-.. function:: addMaintenanceCallback(callback)
+.. function:: addMaintenanceCallback(callback[, name])
.. versionadded:: 1.9.0
+ .. versionchanged:: 2.2.0
+ ``name`` parameter added.
Register a Lua function to be called as part of the ``maintenance`` hook, which is executed roughly every second.
The function should not block for a long period of time, as it would otherwise delay the execution of the other functions registered for this hook, as well as the execution of the :func:`maintenance` function.
:param function callback: The function to be called. It takes no parameter and returns no value.
+ :param string name: The name of the callback, currently only exposed in :doc:`OpenTelemetry traces <ottrace>`.
.. code-block:: lua
import base64
import binascii
+import pprint
import threading
import time
return self.getFirstProtobufMessage(timeout=1)
def checkOTDataBase(self, otData):
+ pprint.pprint(otData)
self.assertEqual(len(otData["resource_spans"]), 1)
self.assertEqual(len(otData["resource_spans"][0]["resource"]["attributes"]), 1)
return result[0]
raise KeyError(f"{name} not found in OT Data")
- def checkMaintenanceSpanNames(self, all_span_name, extra_names=set()):
+ def checkMaintenanceSpanNames(self, all_span_name, extra_names=set(), callback_names=set()):
all_names = {
"maintenanceThread",
"maintenanceHooks",
"DynamicBlocks::runRegisteredGroups",
- }.union(extra_names)
+ }.union(extra_names).union({f"maintenanceCallback/{name}" for name in callback_names})
self.assertSetEqual(all_span_name, all_names)
{
"my-span",
},
+ {
+ "unnamed",
+ },
+ )
+
+ maintenanceFunction_span = self.getSpan(otData, "maintenanceHooks")
+ self.assertListEqual(
+ maintenanceFunction_span["attributes"],
+ [{"key": "outside", "value": {"string_value": "hello from the outside"}}],
+ )
+
+ my_span = self.getSpan(otData, "my-span")
+ self.assertListEqual(
+ my_span["attributes"],
+ [{"key": "inside", "value": {"string_value": "hello from the inside"}}],
+ )
+
+
+class TestOpenTelemetryTracingInternalWithFunctionsNamedCallbackLua(TestOpenTelemetryTracingInternalBase):
+ _config_template = """
+local function my_maintenance()
+ setSpanAttribute("outside", "hello from the outside")
+ withTraceSpan("my-span", function()
+ setSpanAttribute("inside", "hello from the inside")
+ os.execute("sleep 0.1")
+ end)
+end
+
+newServer{address="127.0.0.1:%d"}
+getServer(0):setUp()
+rl = newRemoteLogger('127.0.0.1:%d')
+setOpenTelemetryTracing(true)
+setOpenTelemetryInternalTrace('maintenance', {rl}, 60)
+
+addMaintenanceCallback(my_maintenance, "my_maintenance")
+"""
+
+ _config_params = [
+ "_testServerPort",
+ "_protobufServerPort",
+ ]
+
+ def testMaintenance(self):
+ otData = self.getFirstMaintenanceProtobufMessage()
+
+ msg_span_name = {v["name"] for v in otData["resource_spans"][0]["scope_spans"][0]["spans"]}
+
+ self.checkMaintenanceSpanNames(
+ msg_span_name,
+ {
+ "my-span",
+ },
+ {
+ "my_maintenance",
+ },
)
maintenanceFunction_span = self.getSpan(otData, "maintenanceHooks")