Skip to content

Commit ddc1cfb

Browse files
authored
Adds option to delete extracted tag attributes (#78)
1 parent 661031f commit ddc1cfb

3 files changed

Lines changed: 87 additions & 0 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ As `fluent-plugin-datadog` is a buffered output plugin, you can set all of the b
102102
| **port** | Proxy port when logs are not directly forwarded to Datadog and ssl is not used | 80 |
103103
| **host** | Proxy endpoint when logs are not directly forwarded to Datadog | http-intake.logs.datadoghq.com |
104104
| **http_proxy** | HTTP proxy, only takes effect if HTTP forwarding is enabled (`use_http`). Defaults to `HTTP_PROXY`/`http_proxy` env vars. | nil |
105+
| **delete_extracted_tag_attributes** | When true, removes `kubernetes` and `docker` attributes from log records after extracting them as tags. Useful to avoid duplicate data in Datadog logs UI. | false |
105106

106107
### Docker and Kubernetes tags
107108

@@ -115,6 +116,8 @@ If your logs contain any of the following attributes, it will automatically be a
115116
* kubernetes.pod_name
116117
* docker.container_id
117118

119+
**Note:** By default, these values will appear twice in the Datadog logs UI, once as tags (e.g., `container_name:myapp`) and once as attributes (e.g., `@kubernetes.container_name`). If you prefer to avoid this duplication, set `delete_extracted_tag_attributes` to `true` in your configuration. This will remove the `kubernetes` and `docker` attributes from the log record after the tags have been extracted.
120+
118121
If the Datadog Agent collect them automatically, FluentD requires a plugin for this. We recommend using [fluent-plugin-kubernetes_metadata_filter](https://github.com/fabric8io/fluent-plugin-kubernetes_metadata_filter) to collect Docker and Kubernetes metadata.
119122

120123
Configuration example:

lib/fluent/plugin/out_datadog.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class RetryableError < StandardError;
4343
config_param :dd_source, :string, :default => nil
4444
config_param :dd_tags, :string, :default => nil
4545
config_param :dd_hostname, :string, :default => nil
46+
config_param :delete_extracted_tag_attributes, :bool, :default => false
4647

4748
# Connection settings
4849
config_param :host, :string, :default => DD_DEFAULT_HTTP_ENDPOINT
@@ -254,6 +255,12 @@ def enrich_record(tag, time, record)
254255
record["ddtags"] = record["ddtags"] + "," + container_tags
255256
end
256257
end
258+
259+
if @delete_extracted_tag_attributes
260+
record.delete('kubernetes')
261+
record.delete('docker')
262+
end
263+
257264
record
258265
end
259266

test/plugin/test_out_datadog.rb

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,83 @@ def create_valid_subject
150150
end
151151
end
152152

153+
sub_test_case "delete_extracted_tag_attributes" do
154+
test "should not delete kubernetes/docker attributes by default" do
155+
plugin = create_driver(%[
156+
api_key foo
157+
]).instance
158+
record = {
159+
"message" => "test",
160+
"kubernetes" => {
161+
"container_name" => "myapp",
162+
"namespace_name" => "default",
163+
"pod_name" => "myapp-abc123"
164+
},
165+
"docker" => {
166+
"container_id" => "abc123"
167+
}
168+
}
169+
result = plugin.enrich_record(nil, 12345, record)
170+
assert_not_nil result["kubernetes"]
171+
assert_not_nil result["docker"]
172+
end
173+
174+
test "should delete kubernetes/docker attributes when delete_extracted_tag_attributes is true" do
175+
plugin = create_driver(%[
176+
api_key foo
177+
delete_extracted_tag_attributes true
178+
]).instance
179+
record = {
180+
"message" => "test",
181+
"kubernetes" => {
182+
"container_name" => "myapp",
183+
"namespace_name" => "default",
184+
"pod_name" => "myapp-abc123"
185+
},
186+
"docker" => {
187+
"container_id" => "abc123"
188+
}
189+
}
190+
result = plugin.enrich_record(nil, 12345, record)
191+
assert_nil result["kubernetes"]
192+
assert_nil result["docker"]
193+
# Verify tags were still extracted
194+
assert_true result["ddtags"].include?("container_name:myapp")
195+
assert_true result["ddtags"].include?("kube_namespace:default")
196+
assert_true result["ddtags"].include?("pod_name:myapp-abc123")
197+
assert_true result["ddtags"].include?("container_id:abc123")
198+
end
199+
200+
test "should handle records without kubernetes/docker attributes when delete_extracted_tag_attributes is true" do
201+
plugin = create_driver(%[
202+
api_key foo
203+
delete_extracted_tag_attributes true
204+
]).instance
205+
record = {"message" => "test"}
206+
result = plugin.enrich_record(nil, 12345, record)
207+
assert_nil result["kubernetes"]
208+
assert_nil result["docker"]
209+
end
210+
211+
test "should preserve other record attributes when delete_extracted_tag_attributes is true" do
212+
plugin = create_driver(%[
213+
api_key foo
214+
delete_extracted_tag_attributes true
215+
]).instance
216+
record = {
217+
"message" => "test",
218+
"custom_field" => "custom_value",
219+
"kubernetes" => {
220+
"container_name" => "myapp"
221+
}
222+
}
223+
result = plugin.enrich_record(nil, 12345, record)
224+
assert_nil result["kubernetes"]
225+
assert_equal "custom_value", result["custom_field"]
226+
assert_equal "test", result["message"]
227+
end
228+
end
229+
153230
sub_test_case "truncation" do
154231
test "truncate messages of the given length" do
155232
plugin = create_valid_subject

0 commit comments

Comments
 (0)