opentelemetry-collector-contrib icon indicating copy to clipboard operation
opentelemetry-collector-contrib copied to clipboard

[processor/transform]: Allow transformation of Trace attribute keys

Open EddieEldridge opened this issue 3 years ago • 10 comments

Is your feature request related to a problem? Please describe. I want to able to rename Trace attribute keys with the transform processor.

Describe the solution you'd like

 transform/key_rename:
    traces:
      queries:
        - replace_all_patterns(attributes.keys, "^prefix_+", "prefix.")

Describe alternatives you've considered None as I know of no other alternatives.

Additional context Regex named capture groups don't allow for . characters in the capture group and I want my attribute keys to follow the Otel naming standard of using .s.

Attempted Implementation

attributes/extract:
    actions:
      - key: http.url
        pattern: ^(?P<prefix_http_protocol>.*):\/\/(?P<prefix_http_domain>.*)\/(?P<prefix_http_path>.*)
        action: extract
transform/key_rename:
    traces:
      queries:
        - replace_all_patterns(attributes.keys, "^prefix_+", "prefix.")

Code Change Required https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/processor/transformprocessor/internal/traces/traces.go#L147

EddieEldridge avatar Jul 21 '22 13:07 EddieEldridge

Instead of changing key names you should be able to use the "set" function to create a new attribute with the existing attribute and then use the "delete" function to remove the old attribute. I think you need 0.56.0 to access the delete function.

TylerHelmuth avatar Jul 21 '22 14:07 TylerHelmuth

Oh but I see that you want to change potentially all the keys, not specific ones. Ya I don't think we support that yet.

TylerHelmuth avatar Jul 21 '22 15:07 TylerHelmuth

Regex named capture groups don't allow for . characters in the capture group and I want my attribute keys to follow the Otel naming standard of using .s.

Are you referring to the attributes processor with this comment? This is why you can't do pattern: ^(?P<prefix.http.protocol>.*):\/\/(?P<prefix.http.domain>.*)\/(?P<prefix.http.path>.*) ?

TylerHelmuth avatar Jul 21 '22 15:07 TylerHelmuth

If it is only those three you could do

transform/key_rename:
    traces:
      queries:
        - set(attributes["prefix.http.protocol"], attributes["prefix_http_protocol"])
        - set(attributes["prefix.http.domain"], attributes["prefix_http_domain"])
        - set(attributes["prefix.http.path"], attributes["prefix_http_path"])
        - delete_matching_keys(attributes, "^prefix_+")

But I agree that we cannot currently change keys dynamically. I'm not sure if we would support that via a new path accessor (attributes.keys) or a specific function.

TylerHelmuth avatar Jul 21 '22 15:07 TylerHelmuth

Regex named capture groups don't allow for . characters in the capture group and I want my attribute keys to follow the Otel naming standard of using .s.

Are you referring to the attributes processor with this comment? This is why you can't do pattern: ^(?P<prefix.http.protocol>.*):\/\/(?P<prefix.http.domain>.*)\/(?P<prefix.http.path>.*) ?

Yes that's correct.

If it is only those three you could do

transform/key_rename:
    traces:
      queries:
        - set(attributes["prefix.http.protocol"], attributes["prefix_http_protocol"])
        - set(attributes["prefix.http.domain"], attributes["prefix_http_domain"])
        - set(attributes["prefix.http.path"], attributes["prefix_http_path"])
        - delete_matching_keys(attributes, "^prefix_+")

But I agree that we cannot currently change keys dynamically. I'm not sure if we would support that via a new path accessor (attributes.keys) or a specific function.

I would still like to see the functionality to dynamically change keys without having to call set on every attribute but what you suggested is perfect and seems to be working well for now :)

Final Working Solution

# 1. From the http.url attribute, using RegEx named capture groups, create three new attributes:
# 
# - temp_http_protocol
# - temp_http_domain
# - temp_http_path
# 
# 2. Set the name of the new attributes to the following:
# 
# - temp_http_protocol -> prefix.http_protcol
# - temp_http_domain -> prefix.http_hostname (using http.host and net.peer.name instead if they exist)
# - temp_http_path -> prefix.http_path
# 
# 3. Delete the temp attributes as we don't need them anymore
# 
# 4. For Span's that have a name like HTTP(S) {{ HTTP_METHOD }}, set the name to the following:
# 
# - {{ HTTP_METHOD }} {{ HTTP_HOSTNAME}}

  attributes/extract:
    actions:
      - key: http.url
        pattern: ^(?P<temp_http_protocol>.*):\/\/(?P<temp_http_domain>.*)\/(?P<temp_http_path>.*)
        action: extract
  transform/url:
    traces:
      queries:
        - set(attributes["prefix.http_protocol"], attributes["temp_http_protocol"]) where attributes["temp_http_protocol"] != nil
        - set(attributes["prefix.http_path"], attributes["temp_http_path"]) where attributes["temp_http_path"] != nil
        - set(attributes["prefix.hostname"], attributes["temp_http_domain"]) where attributes["temp_http_domain"] != nil
        - set(attributes["prefix.hostname"], attributes["net.peer.name"]) where attributes["net.peer.name"] != nil
        - set(attributes["prefix.hostname"], attributes["http.host"]) where attributes["http.host"] != nil
        # 0.56 Only
        # - delete_matching_keys(attributes, "^temp_+")

  attributes/cleanup:
    actions:
      - key: temp_http_protocol
        action: delete
      - key: temp_http_domain
        action: delete
      - key: temp_http_path
        action: delete
  span/rename:
    include:
      match_type: regexp
      span_names: ["^(HTTP(S)*?) ((GET)|(POST)|(PUT)|(DELETE)|(PATCH)|(UPDATE)|(OPTIONS)*?)$"]
    name:
      separator: " "
      from_attributes: ['http.method', 'prefix.hostname']

EddieEldridge avatar Jul 21 '22 15:07 EddieEldridge

IIUC, for now, we should design a new function which could change the key's name that matches the regex expression dynamically, such as replace_all_key_patterns ? @TylerHelmuth

fatsheep9146 avatar Jul 28 '22 05:07 fatsheep9146

Yes a new function could do it. It would be very similar to replace_all_patterns.

TylerHelmuth avatar Jul 28 '22 15:07 TylerHelmuth

Yes a new function could do it. It would be very similar to replace_all_patterns.

I'd love to try this, could you assign to me? @TylerHelmuth

fatsheep9146 avatar Jul 28 '22 15:07 fatsheep9146

@fatsheep9146 its yours. Forewarned, accepting the function will probably be depended on some of the PRs in #11751 being merged first.

TylerHelmuth avatar Jul 28 '22 16:07 TylerHelmuth

@fatsheep9146 the issue is closed. You should add the new function to pkg/telemetryquerylanguage

TylerHelmuth avatar Aug 04 '22 22:08 TylerHelmuth