diff --git a/changelog/unreleased/kong/serviceless-routes-still-trigger-datalog-plugin.yml b/changelog/unreleased/kong/serviceless-routes-still-trigger-datalog-plugin.yml new file mode 100644 index 00000000000..71df7dd33bc --- /dev/null +++ b/changelog/unreleased/kong/serviceless-routes-still-trigger-datalog-plugin.yml @@ -0,0 +1,3 @@ +message: "**Datadog**: Fix a bug that datadog plugin is not triggered for serviceless routes. In this fix, datadog plugin is always triggered, and the value of tag `name`(service_name) is set as an empty value." +type: bugfix +scope: Plugin \ No newline at end of file diff --git a/kong/plugins/datadog/handler.lua b/kong/plugins/datadog/handler.lua index 3158a9e45e8..4b68e8487a4 100644 --- a/kong/plugins/datadog/handler.lua +++ b/kong/plugins/datadog/handler.lua @@ -56,10 +56,6 @@ local function send_entries_to_datadog(conf, messages) end for _, message in ipairs(messages) do - local name = gsub(message.service.name ~= null and - message.service.name or message.service.host, - "%.", "_") - local stat_name = { request_size = "request.size", response_size = "response.size", @@ -87,8 +83,10 @@ local function send_entries_to_datadog(conf, messages) local get_consumer_id = get_consumer_id[metric_config.consumer_identifier] local consumer_id = get_consumer_id and get_consumer_id(message.consumer) or nil local tags = compose_tags( - name, message.response and message.response.status or "-", - consumer_id, metric_config.tags, conf) + 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) logger:send_statsd(stat_name, stat_value, logger.stat_types[metric_config.stat_type], @@ -107,12 +105,7 @@ local DatadogHandler = { VERSION = kong_meta.version, } - function DatadogHandler:log(conf) - if not ngx.ctx.service then - return - end - local ok, err = Queue.enqueue( Queue.get_plugin_params("datadog", conf), send_entries_to_datadog, diff --git a/spec/03-plugins/08-datadog/01-log_spec.lua b/spec/03-plugins/08-datadog/01-log_spec.lua index 8ec13a9a7c8..90b9e2f9f26 100644 --- a/spec/03-plugins/08-datadog/01-log_spec.lua +++ b/spec/03-plugins/08-datadog/01-log_spec.lua @@ -1,8 +1,10 @@ local helpers = require "spec.helpers" local cjson = require "cjson" +local stringx = require "pl.stringx" describe("Plugin: datadog (log)", function() + local DEFAULT_METRICS_COUNT = 6 lazy_setup(function() helpers.setenv('KONG_DATADOG_AGENT_HOST', 'localhost') @@ -93,6 +95,11 @@ describe("Plugin: datadog (log)", function() } } + local route9 = bp.routes:insert { + paths = { "/serviceless" }, + no_service = true, + } + bp.plugins:insert { name = "key-auth", route = { id = route1.id }, @@ -237,6 +244,25 @@ describe("Plugin: datadog (log)", function() }, } + bp.plugins:insert { + name = "datadog", + route = { id = route9.id }, + config = { + host = "127.0.0.1", + port = 9999, + queue_size = 2, + }, + } + + bp.plugins:insert { + name = "request-termination", + route = { id = route9.id }, + config = { + status_code = 200, + message = "OK", + } + } + assert(helpers.start_kong({ database = strategy, nginx_conf = "spec/fixtures/custom_nginx.template", @@ -245,17 +271,23 @@ describe("Plugin: datadog (log)", function() proxy_client = helpers.proxy_client() end) + lazy_teardown(function() + helpers.stop_kong() + end) + + before_each(function() + proxy_client = helpers.proxy_client() + end) + + after_each(function() if proxy_client then proxy_client:close() end - - - helpers.stop_kong() end) it("logs metrics over UDP", function() - local thread = helpers.udp_server(9999, 6) + local thread = helpers.udp_server(9999, DEFAULT_METRICS_COUNT) local res = assert(proxy_client:send { method = "GET", @@ -268,7 +300,7 @@ describe("Plugin: datadog (log)", function() local ok, gauges = thread:join() assert.True(ok) - assert.equal(6, #gauges) + assert.equal(DEFAULT_METRICS_COUNT, #gauges) assert.contains("kong.request.count:1|c|#name:dd1,status:200,consumer:bar,app:kong" , gauges) assert.contains("kong.latency:%d+|ms|#name:dd1,status:200,consumer:bar,app:kong", gauges, true) assert.contains("kong.request.size:%d+|ms|#name:dd1,status:200,consumer:bar,app:kong", gauges, true) @@ -278,7 +310,7 @@ describe("Plugin: datadog (log)", function() end) it("logs metrics over UDP #grpc", function() - local thread = helpers.udp_server(9999, 6) + local thread = helpers.udp_server(9999, DEFAULT_METRICS_COUNT) local grpc_cleint = assert(helpers.proxy_client_grpc()) @@ -293,7 +325,7 @@ describe("Plugin: datadog (log)", function() local ok, gauges = thread:join() assert.True(ok) - assert.equal(6, #gauges) + assert.equal(DEFAULT_METRICS_COUNT, #gauges) assert.contains("kong.request.count:1|c|#name:grpc,status:200,consumer:bar,app:kong" , gauges) assert.contains("kong.latency:%d+|ms|#name:grpc,status:200,consumer:bar,app:kong", gauges, true) assert.contains("kong.request.size:%d+|ms|#name:grpc,status:200,consumer:bar,app:kong", gauges, true) @@ -303,7 +335,7 @@ describe("Plugin: datadog (log)", function() end) it("logs metrics over UDP with custom prefix", function() - local thread = helpers.udp_server(9999, 6) + local thread = helpers.udp_server(9999, DEFAULT_METRICS_COUNT) local res = assert(proxy_client:send { method = "GET", @@ -316,7 +348,7 @@ describe("Plugin: datadog (log)", function() local ok, gauges = thread:join() assert.True(ok) - assert.equal(6, #gauges) + assert.equal(DEFAULT_METRICS_COUNT, #gauges) assert.contains("prefix.request.count:1|c|#name:dd4,status:200,consumer:bar,app:kong",gauges) assert.contains("prefix.latency:%d+|ms|#name:dd4,status:200,consumer:bar,app:kong", gauges, true) assert.contains("prefix.request.size:%d+|ms|#name:dd4,status:200,consumer:bar,app:kong", gauges, true) @@ -326,7 +358,7 @@ describe("Plugin: datadog (log)", function() end) it("logs metrics over UDP with custom tag names", function() - local thread = helpers.udp_server(9999, 6) + local thread = helpers.udp_server(9999, DEFAULT_METRICS_COUNT) local res = assert(proxy_client:send { method = "GET", @@ -339,7 +371,7 @@ describe("Plugin: datadog (log)", function() local ok, gauges = thread:join() assert.True(ok) - assert.equal(6, #gauges) + assert.equal(DEFAULT_METRICS_COUNT, #gauges) assert.contains("kong.request.count:1|c|#upstream:dd6,http_status:200,user:bar,app:kong",gauges) assert.contains("kong.latency:%d+|ms|#upstream:dd6,http_status:200,user:bar,app:kong", gauges, true) assert.contains("kong.request.size:%d+|ms|#upstream:dd6,http_status:200,user:bar,app:kong", gauges, true) @@ -387,7 +419,7 @@ describe("Plugin: datadog (log)", function() end) it("logs metrics to host/port defined via environment variables", function() - local thread = helpers.udp_server(9999, 6) + local thread = helpers.udp_server(9999, DEFAULT_METRICS_COUNT) local res = assert(proxy_client:send { method = "GET", @@ -400,7 +432,7 @@ describe("Plugin: datadog (log)", function() local ok, gauges = thread:join() assert.True(ok) - assert.equal(6, #gauges) + assert.equal(DEFAULT_METRICS_COUNT, #gauges) assert.contains("kong.request.count:1|c|#name:dd5,status:200,consumer:bar,app:kong" , gauges) assert.contains("kong.latency:%d+|ms|#name:dd5,status:200,consumer:bar,app:kong", gauges, true) assert.contains("kong.request.size:%d+|ms|#name:dd5,status:200,consumer:bar,app:kong", gauges, true) @@ -410,7 +442,7 @@ describe("Plugin: datadog (log)", function() end) it("logs metrics in several batches", function() - local thread = helpers.udp_server(9999, 6) + local thread = helpers.udp_server(9999, DEFAULT_METRICS_COUNT) local res = assert(proxy_client:send { method = "GET", @@ -423,7 +455,7 @@ describe("Plugin: datadog (log)", function() local ok, gauges = thread:join() assert.True(ok) - assert.equal(6, #gauges) + assert.equal(DEFAULT_METRICS_COUNT, #gauges) assert.contains("kong.request.count:1|c|#name:dd7,status:200,consumer:bar,app:kong" , gauges) assert.contains("kong.latency:%d+|ms|#name:dd7,status:200,consumer:bar,app:kong", gauges, true) assert.contains("kong.request.size:%d+|ms|#name:dd7,status:200,consumer:bar,app:kong", gauges, true) @@ -448,7 +480,7 @@ describe("Plugin: datadog (log)", function() local ok, gauges = thread:join() assert.True(ok) - assert.equal(6, #gauges) + assert.equal(DEFAULT_METRICS_COUNT, #gauges) end) it("should not return a runtime error (regression)", function() @@ -476,9 +508,9 @@ describe("Plugin: datadog (log)", function() thread:join() end) - + it("referenceable fields works", function() - local thread = helpers.udp_server(9999, 6, 6) + local thread = helpers.udp_server(9999, DEFAULT_METRICS_COUNT, 6) local another_proxy_client = helpers.proxy_client() local res = assert(another_proxy_client:send { @@ -493,7 +525,32 @@ describe("Plugin: datadog (log)", function() local ok, gauges = thread:join() assert.True(ok) - assert.equal(6, #gauges) + assert.equal(DEFAULT_METRICS_COUNT, #gauges) + 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 { + method = "GET", + path = "/serviceless", + }) + + local body = assert.res_status(200, res) + assert.equals(body, '{"message":"OK"}') + + local ok, gauges = thread:join() + assert.True(ok) + assert.equals(DEFAULT_METRICS_COUNT, #gauges) + + for _, g in ipairs(gauges) do + -- tags start with `#` + local tmp = stringx.split(g, '#') + local tag_idx = #tmp + assert(tag_idx == 2, "Error: missing tags") + local tags = tmp[tag_idx] + assert(tags, "Error: missing tags") + assert(string.match(tags, "name:,"), "Error: the value of `name` must be an empty string for serviceless routes") + end end) end) end