Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add kubernetes-metadata #8

Closed
wants to merge 2 commits into from

Conversation

csatib02
Copy link
Contributor

@csatib02 csatib02 commented Dec 4, 2024

Some tweaks and enhancements we did to fluentforwardexporter, we thought you might also find useful.

Copy link
Owner

@r0mdau r0mdau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To start, thank you for your contribution.

If you can (or next time), it is best for the reviewer if you split the skip_fail and the kubernetes changes in 2 separate MRs. Because it will take more time to review the k8s addition where I could have merged quickly the skip_fail one.

README.md Outdated Show resolved Hide resolved
config_test.go Outdated Show resolved Hide resolved
@csatib02 csatib02 requested a review from r0mdau December 5, 2024 12:38
@csatib02
Copy link
Contributor Author

csatib02 commented Dec 6, 2024

@r0mdau Added the changes!

@r0mdau
Copy link
Owner

r0mdau commented Dec 6, 2024

@csatib02 can you add the new ValidateTCPEndpoint property in the TestLoadConfigNewExporter test here : https://github.com/csatib02/fluentforwardexporter/blob/feat/improvements/config_test.go#L39

I want to ensure default value is false.

Otherwise, looks good to me.

@csatib02
Copy link
Contributor Author

csatib02 commented Dec 6, 2024

@r0mdau Done.

Comment on lines +126 to +172
if f.config.KubernetesMetadata != nil {
key := f.config.KubernetesMetadata.Key
if f.config.KubernetesMetadata.Key == "" {
key = "kubernetes"
}
var namespace, container, pod, node string
var labels map[string]string
res.Resource().Attributes().Range(func(k string, v pcommon.Value) bool {
if k == "k8s.namespace.name" {
namespace = v.AsString()
return true
}
if k == "k8s.container.name" {
container = v.AsString()
}
if k == "k8s.pod.name" {
pod = v.AsString()
}
if k == "k8s.node.name" {
node = v.AsString()
}
if f.config.KubernetesMetadata.IncludePodLabels && strings.HasPrefix(k, "k8s.pod.labels.") {
if labels == nil {
labels = make(map[string]string)
}
labelKey := strings.TrimPrefix(k, "k8s.pod.labels.")
labels[labelKey] = v.AsString()
}
return true
})

k8sMetadata := map[string]interface{}{
"namespace_name": namespace,
"container_name": container,
"pod_name": pod,
"host": node,
}

if f.config.KubernetesMetadata.IncludePodLabels {
k8sMetadata["labels"] = labels
}

m[key] = k8sMetadata
}

f.settings.Logger.Debug(fmt.Sprintf("message %+v", m))

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is for use only with processor/k8sattributesprocessor

I see 2 things:

  1. Put log Resources into a nested object, like from flat to a sub json document
  2. Rename fields, for example from k8s.namespace.name to namespace_name in the parent object key labeled by the Key property.

First idea for me is to not rename, if you want to rename, you must use the processor/attributesprocessor after the k8sattributesprocessor.

Second idea for me is to not be kubernetes specific. Whatever the ResourceLogs come from.

Example, to get the value in the log line as flat (not in a nested json object), you just need to add it to the default_labels_enabled property, example:

exporters:
  fluentforward:
    endpoint:
      tcp_addr: localhost:24224
    default_labels_enabled:
      k8s.namespace.name: true

I am wondering in which scenario on your side creating a sub json object is needed ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First idea for me is to not rename, if you want to rename, you must use the processor/attributesprocessor after the k8sattributesprocessor.

That is exactly what we are doing!
You can check it out here:

Also sharing with you an example configuration visualized using OtelBin.

  • I would also like to emphasize that the k8sattributesprocessor and the attributesprocessors in the pipelines generated by our operator are always present, and cannot be turned off. Mainly to be able to provide users with consistent metrics about their tenants.

Copy link
Owner

@r0mdau r0mdau Dec 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the renaming topic, taking one field for example for the discussion but it applies to the four fields.

Why extracting k8s.container.name and putting its value in the log field labeled: container_name ?

With my short configuration example above, you can keep the attribute labeled k8s.container.name and its value in the log.

And you can do the same with all the others k8s.pod.name etc...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The project I've sent the code-snippets from, soon will be available to use together, with one of our other operators: https://github.com/kube-logging/logging-operator

This operator historically used fluentbit for log-collection, which sent the logs in that structure. So we opted to use the same approach with otelcol aswell for compatibility reasons.
This also ensures we don't accidentally break components on other levels of the pipeline.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not checked all the log processors, but I think you can get the same log output from fluentforwardexporter using processors and adding a default_labels_enabled like I suggested above.

It is super important to me to not bake strongly kubernetes dependent logic and attributes within the exporter. Have you seen other otelcol exporters doing that (I am not sure) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I totally understand if you don't want to include this because of k8s dependent logic. It was just a proposal from our-side. Feel free to close this. :)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could change the exporter logic by using a denylist instead of an allowlist with the default_labels_enabled property. But works good like it is for now.

I am closing the PR.

Signed-off-by: Bence Csati <[email protected]>
@csatib02 csatib02 changed the title feat: improvementes feat: add kubernetes-metadata Dec 8, 2024
@r0mdau r0mdau closed this Dec 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants