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 user fields mapping to OTLP #431

Closed
wants to merge 5 commits into from

Conversation

ericywl
Copy link
Contributor

@ericywl ericywl commented Jan 24, 2025

❓ Why is this being changed

Related to elastic/apm-server#15254

πŸ§‘β€πŸ’» What is being changed

Map the following user fields from OTel attributes to APMEvent.User

  • user.id
  • user.name
  • user.email

The other user fields do not have equivalents in APMEvent.User, so they will still be under APMEvent.Labels.

βœ… How to validate the change

Run test on APM server with the changes

@@ -580,3 +580,19 @@ func replaceReservedRune(disallowedRunes string) func(r rune) rune {
return unicode.ToLower(r)
}
}

// NOTE: This will overwrite user fields set by `user.name=process.owner` from `otlp/metadata.go:translateResourceMetadata`.
Copy link
Contributor Author

@ericywl ericywl Jan 24, 2025

Choose a reason for hiding this comment

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

This requires some consideration, how should we handle it if the user.name was already set by process.owner?

ref:

case semconv.AttributeProcessOwner:
if out.User == nil {
out.User = &modelpb.User{}
}
out.User.Name = truncate(v.Str())

Copy link
Contributor Author

@ericywl ericywl Jan 24, 2025

Choose a reason for hiding this comment

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

See test cases at #431 (comment)

Copy link
Member

Choose a reason for hiding this comment

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

Raised in elastic/apm-server#15254 (comment) that process.owner mapping to user.name seems a bit out of place. I wonder it should actually be mapped to process.user.name instead.

Comment on lines +446 to +473
{
name: "process owner not overwritten",
processOwner: "i-am-the-owner",
input: userField{
userID: "123",
userName: "",
userEmail: "[email protected]",
},
expected: userField{
userID: "123",
userName: "i-am-the-owner",
userEmail: "[email protected]",
},
},
{
name: "overwrite process owner",
processOwner: "i-am-the-owner",
input: userField{
userID: "123",
userName: "hello",
userEmail: "[email protected]",
},
expected: userField{
userID: "123",
userName: "hello",
userEmail: "[email protected]",
},
},
Copy link
Contributor Author

@ericywl ericywl Jan 24, 2025

Choose a reason for hiding this comment

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

Here are the test cases for when the process.owner resource metadata attribute is set.

Copy link
Member

Choose a reason for hiding this comment

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

this is the case for record-level (log records, data points, spans) attributes overwriting resource level attributes, which is fine. But you may also need to test resource level User semconv fields competing with process.owner. However, I'm not sure if we should expect it at the resource level. See the above comment.

@@ -242,6 +242,8 @@ func translateResourceMetadata(resource pcommon.Resource, out *modelpb.APMEvent)
}
out.User.Name = truncate(v.Str())

// TODO(eric): Check if `user.*` fields are considered resource metadata?
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Need help to confirm if user.* attributes are:

  1. resource metadata only
  2. scope metadata only
  3. datapoints only
  4. resource metadata + datapoints
  5. scope metadata + datapoints
  6. resource metadata + scope metadata + datapoints

Copy link
Member

Choose a reason for hiding this comment

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

I see that you are currently only doing it for log records, data points and span events. imo it is missing for spans (see TranslateTransaction and TranslateSpan) which is most likely where these attributes are.

And you wonder if it should apply to resource and scope. I think it is unlikely for scope, but not too sure about resource. @axw may have a better idea here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks. From what I can tell, TranslateTransaction and TranslateSpan is also used by intake v2. Will this change overwrite the user fields that are set here?

Copy link
Member

Choose a reason for hiding this comment

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

I see that you are currently only doing it for log records, data points and span events. imo it is missing for spans (see TranslateTransaction and TranslateSpan) which is most likely where these attributes are.

++

And you wonder if it should apply to resource and scope. I think it is unlikely for scope, but not too sure about resource. @axw may have a better idea here.

I'm not aware of any cases where user would exist at the resource level. I guess there could be some kind of resource owner attributes, but I'm only aware of the need to represent users of the instrumented service, which would be at the operation level.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Got it, I will just add the change to TranslateTransaction and TranslateSpan.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks. From what I can tell, TranslateTransaction and TranslateSpan is also used by intake v2. Will this change overwrite the user fields that are set here?

@axw @carsonip Will this part be a concern?

Copy link
Member

Choose a reason for hiding this comment

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

As discussed in #431 (comment) , I think we should really fix user.name=process.owner in either this PR or a separate PR as a blocker. process.owner shouldn't be setting user.name in the first place. When that's fixed, this PR won't be overwriting user fields.

Copy link
Contributor

Choose a reason for hiding this comment

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

+1 on this suggestion. @ericywl can you put up a PR to changing the current user mapping as a bugfix and then get back to this PR?

@ericywl ericywl changed the title Add user fields mapping to otlp feat: Add user fields mapping to otlp Jan 27, 2025
@ericywl ericywl changed the title feat: Add user fields mapping to otlp feat: Add user fields mapping to OTLP Jan 27, 2025
@@ -242,6 +242,8 @@ func translateResourceMetadata(resource pcommon.Resource, out *modelpb.APMEvent)
}
out.User.Name = truncate(v.Str())

// TODO(eric): Check if `user.*` fields are considered resource metadata?
Copy link
Member

Choose a reason for hiding this comment

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

I see that you are currently only doing it for log records, data points and span events. imo it is missing for spans (see TranslateTransaction and TranslateSpan) which is most likely where these attributes are.

And you wonder if it should apply to resource and scope. I think it is unlikely for scope, but not too sure about resource. @axw may have a better idea here.

Comment on lines +446 to +473
{
name: "process owner not overwritten",
processOwner: "i-am-the-owner",
input: userField{
userID: "123",
userName: "",
userEmail: "[email protected]",
},
expected: userField{
userID: "123",
userName: "i-am-the-owner",
userEmail: "[email protected]",
},
},
{
name: "overwrite process owner",
processOwner: "i-am-the-owner",
input: userField{
userID: "123",
userName: "hello",
userEmail: "[email protected]",
},
expected: userField{
userID: "123",
userName: "hello",
userEmail: "[email protected]",
},
},
Copy link
Member

Choose a reason for hiding this comment

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

this is the case for record-level (log records, data points, spans) attributes overwriting resource level attributes, which is fine. But you may also need to test resource level User semconv fields competing with process.owner. However, I'm not sure if we should expect it at the resource level. See the above comment.

input/otlp/metadata.go Outdated Show resolved Hide resolved
}

allEvents := transformTraces(t, traces)
events := (*allEvents)[1:]
Copy link
Member

Choose a reason for hiding this comment

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

Why is the first event ignored? Is that the span itself?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes I believe so.

Copy link
Member

Choose a reason for hiding this comment

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

It shouldn't be ignored. We should ensure that the span document has user fields as well.

Copy link
Member

@carsonip carsonip left a comment

Choose a reason for hiding this comment

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

On the point about user fields being experimental, imo it is fine to handle them and map them to the most appropriate ECS fields, as we have been doing that in apm-server. The implication of this PR is that User semconv fields will be mapped differently, which makes it possibly a "breaking change".

For apm-server, if we're only doing that in a major version change, it is fine, but it also means an apm-data major release and any other apm-data changes to apm-server 8.x will require backport to the previous apm-data major.

For MIS, there's likely a different policy for breaking changes.

Therefore, I'd appreciate @simitt's views on whether this should really be considered a breaking change. It seems like a slippery slope to me.

@simitt
Copy link
Contributor

simitt commented Feb 3, 2025

For MIS, there's likely a different policy for breaking changes.

Therefore, I'd appreciate @simitt's views on whether this should really be considered a breaking change. It seems like a slippery slope to me.

Apologies for the late response. Correcting the current mapping of the user.* attributes is a bugfix which we should get in.
For the new mapping of user.* fields, we need alignment with @mlunadia on how to treat otel mappings in APM Server and MIS. Let's put this on hold for some more days until we have figured this out.

@simitt
Copy link
Contributor

simitt commented Feb 3, 2025

Let's close this PR, as we have closed the underlying issue as Won't fix. As raised by @lahsivjar , the currently mapped user fields are used in the Observability UIs with the current semantics of process owner. With the focus on otel native, let's not break this behaviour, but rather ensure the mapping is proper for the otel native solution.

@ericywl ericywl closed this Feb 4, 2025
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.

4 participants