From 1bfc80755b1bf8a42fb0a9545e2fd5769643ef79 Mon Sep 17 00:00:00 2001 From: Jack Tysoe Date: Tue, 13 Aug 2024 09:48:21 +0100 Subject: [PATCH] feat(plugins)(datadog): add a datadog tag for the route name to each metric --- .../kong/datadog-plugin-route-name-tag.yml | 5 ++ kong/plugins/datadog/handler.lua | 10 ++- kong/plugins/datadog/schema.lua | 3 + spec/03-plugins/08-datadog/01-log_spec.lua | 89 +++++++++++++++++++ 4 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 changelog/unreleased/kong/datadog-plugin-route-name-tag.yml diff --git a/changelog/unreleased/kong/datadog-plugin-route-name-tag.yml b/changelog/unreleased/kong/datadog-plugin-route-name-tag.yml new file mode 100644 index 000000000000..9c28e7e03303 --- /dev/null +++ b/changelog/unreleased/kong/datadog-plugin-route-name-tag.yml @@ -0,0 +1,5 @@ +message: | + Added the route name to a built-in tag in the Datadog plugin, + to each of the output metrics. +type: feature +scope: Plugin diff --git a/kong/plugins/datadog/handler.lua b/kong/plugins/datadog/handler.lua index 4b68e8487a47..cebfba4b789d 100644 --- a/kong/plugins/datadog/handler.lua +++ b/kong/plugins/datadog/handler.lua @@ -28,10 +28,11 @@ local get_consumer_id = { } -local function compose_tags(service_name, status, consumer_id, tags, conf) +local function compose_tags(service_name, status, consumer_id, tags, conf, route_name) local result = { (conf.service_name_tag or "name") .. ":" .. service_name, - (conf.status_tag or "status") .. ":" .. status + (conf.status_tag or "status") .. ":" .. status, + route_name and route_name ~= "" and ((conf.route_name_tag or "route") .. ":" .. route_name) or nil } if consumer_id ~= nil then @@ -86,7 +87,10 @@ local function send_entries_to_datadog(conf, messages) message.service and gsub(message.service.name ~= null and message.service.name or message.service.host, "%.", "_") or "", message.response and message.response.status or "-", - consumer_id, metric_config.tags, conf) + consumer_id, metric_config.tags, + conf, + message.route and message.route.name and gsub(message.route.name ~= null and + message.route.name, "%.", "_") or "") logger:send_statsd(stat_name, stat_value, logger.stat_types[metric_config.stat_type], diff --git a/kong/plugins/datadog/schema.lua b/kong/plugins/datadog/schema.lua index e660f63e22c0..2bfd03e3be39 100644 --- a/kong/plugins/datadog/schema.lua +++ b/kong/plugins/datadog/schema.lua @@ -81,6 +81,9 @@ return { { service_name_tag = { description = "String to be attached as the name of the service.", type = "string", default = "name" }, }, + { + route_name_tag = { description = "String to be attached as the name of the route.", type = "string", + default = "route" }, }, { status_tag = { description = "String to be attached as the tag of the HTTP status.", type = "string", default = "status" }, }, diff --git a/spec/03-plugins/08-datadog/01-log_spec.lua b/spec/03-plugins/08-datadog/01-log_spec.lua index 214b7832961a..aa585b1eb831 100644 --- a/spec/03-plugins/08-datadog/01-log_spec.lua +++ b/spec/03-plugins/08-datadog/01-log_spec.lua @@ -99,6 +99,18 @@ describe("Plugin: datadog (log)", function() paths = { "/serviceless" }, no_service = true, } + + local route10 = bp.routes:insert { + name = "kong-sample_route", + hosts = { "datadog10.test" }, + service = bp.services:insert { name = "dd10" } + } + + local route11 = bp.routes:insert { + name = "kong-sample_route.11", + hosts = { "datadog11.test" }, + service = bp.services:insert { name = "dd11" } + } bp.plugins:insert { name = "key-auth", @@ -263,6 +275,35 @@ describe("Plugin: datadog (log)", function() } } + bp.plugins:insert { + name = "key-auth", + route = { id = route10.id }, + } + + bp.plugins:insert { + name = "datadog", + route = { id = route10.id }, + config = { + host = "127.0.0.1", + port = 9999, + }, + } + + bp.plugins:insert { + name = "key-auth", + route = { id = route11.id }, + } + + bp.plugins:insert { + name = "datadog", + route = { id = route11.id }, + config = { + host = "127.0.0.1", + port = 9999, + route_name_tag = "kong_route_name_tag", + }, + } + assert(helpers.start_kong({ database = strategy, nginx_conf = "spec/fixtures/custom_nginx.template", @@ -528,6 +569,54 @@ describe("Plugin: datadog (log)", function() assert.equal(DEFAULT_METRICS_COUNT, #gauges) end) + it("logs metrics with route name over UDP", function() + local thread = helpers.udp_server(9999, DEFAULT_METRICS_COUNT) + + local res = assert(proxy_client:send { + method = "GET", + path = "/status/200?apikey=kong", + headers = { + ["Host"] = "datadog10.test" + } + }) + assert.res_status(200, res) + + local ok, gauges = thread:join() + + assert.True(ok) + assert.equal(DEFAULT_METRICS_COUNT, #gauges) + assert.contains("kong.request.count:1|c|#name:dd10,status:200,route:kong-sample_route,consumer:bar,app:kong" , gauges) + assert.contains("kong.latency:%d*|ms|#name:dd10,status:200,route:kong-sample_route,consumer:bar,app:kong", gauges, true) + assert.contains("kong.request.size:%d*|ms|#name:dd10,status:200,route:kong-sample_route,consumer:bar,app:kong", gauges, true) + assert.contains("kong.response.size:%d*|ms|#name:dd10,status:200,route:kong-sample_route,consumer:bar,app:kong", gauges, true) + assert.contains("kong.upstream_latency:%d*|ms|#name:dd10,status:200,route:kong-sample_route,consumer:bar,app:kong", gauges, true) + assert.contains("kong.kong_latency:%d*|ms|#name:dd10,status:200,route:kong-sample_route,consumer:bar,app:kong", gauges, true) + end) + + it("logs metrics with different route name tag over UDP", function() + local thread = helpers.udp_server(9999, DEFAULT_METRICS_COUNT) + + local res = assert(proxy_client:send { + method = "GET", + path = "/status/200?apikey=kong", + headers = { + ["Host"] = "datadog11.test" + } + }) + assert.res_status(200, res) + + local ok, gauges = thread:join() + + assert.True(ok) + assert.equal(DEFAULT_METRICS_COUNT, #gauges) + assert.contains("kong.request.count:1|c|#name:dd11,status:200,kong_route_name_tag:kong-sample_route_11,consumer:bar,app:kong" , gauges) + assert.contains("kong.latency:%d+|ms|#name:dd11,status:200,kong_route_name_tag:kong-sample_route_11,consumer:bar,app:kong", gauges, true) + assert.contains("kong.request.size:%d+|ms|#name:dd11,status:200,kong_route_name_tag:kong-sample_route_11,consumer:bar,app:kong", gauges, true) + assert.contains("kong.response.size:%d+|ms|#name:dd11,status:200,kong_route_name_tag:kong-sample_route_11,consumer:bar,app:kong", gauges, true) + assert.contains("kong.upstream_latency:%d+|ms|#name:dd11,status:200,kong_route_name_tag:kong-sample_route_11,consumer:bar,app:kong", gauges, true) + assert.contains("kong.kong_latency:%d*|ms|#name:dd11,status:200,kong_route_name_tag:kong-sample_route_11,consumer:bar,app:kong", gauges, true) + end) + it("datadog plugin is triggered for serviceless routes", function() local thread = helpers.udp_server(9999, DEFAULT_METRICS_COUNT) local res = assert(proxy_client:send {