Skip to content

[pkg/ottl] Add OTTL support for profiles #37574

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

Merged
merged 47 commits into from
Apr 14, 2025

Conversation

rockdaboot
Copy link
Contributor

@rockdaboot rockdaboot commented Jan 29, 2025

Fixes #36104

This is a first PR to get profiles support into OTTL. Follow-up PRs will add support for more sub-types of profiles like sample, mapping etc..

@rockdaboot rockdaboot force-pushed the ottl-profile branch 4 times, most recently from cd7d67e to 7a7b0dc Compare January 31, 2025 17:39
@rockdaboot rockdaboot changed the title Add minimal support of OTTL for profiles [pkg/ottl] Add support of OTTL for profiles Jan 31, 2025
@rockdaboot rockdaboot changed the title [pkg/ottl] Add support of OTTL for profiles [pkg/ottl] Add OTTL support for profiles Jan 31, 2025
@rockdaboot rockdaboot force-pushed the ottl-profile branch 3 times, most recently from 594f736 to a629ef0 Compare February 4, 2025 10:28
Copy link
Member

@dmathieu dmathieu left a comment

Choose a reason for hiding this comment

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

This is a lot of very similar code. But maybe that's how OTTL does things.

@rockdaboot rockdaboot marked this pull request as ready for review February 18, 2025 09:45
@rockdaboot rockdaboot requested a review from a team as a code owner February 18, 2025 09:45
_ internal.InstrumentationScopeContext = (*TransformContext)(nil)
_ internal.ProfileContext = TransformContext{}

// _ zapcore.ObjectMarshaler = (*TransformContext)(nil)
Copy link
Member

Choose a reason for hiding this comment

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

The TransformContext should implement the zapcore.ObjectMarshaler so that debug logging works.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Q: Would you like to see a meaningful marshalling, for example seeing the actual attributes for a sample? Or instead, see the attribute indices for a sample.
I would prefer the first, otherwise it takes a lot of mental load to translate the indices into attributes with the help of the attribute table. It is normally a human who does the debugging.

Copy link
Member

Choose a reason for hiding this comment

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

The original intent for this printout feature was to show the data exactly how OTTL sees it. This way when debugging a statement a user can see what the collector saw instead of what their mental model is of the data.

So I think it should printout indices and attributes separately, but if that is completely worthless to a user then we could do some manipulation. Can you provide a rough example of what the printout would look like for the 2 options you proposed?

@hfakar
Copy link

hfakar commented Apr 9, 2025

Is there any updates on this?

@rockdaboot
Copy link
Contributor Author

Is there any updates on this?

@hfakar This PR is waiting for #38928 to be merged 🤷🏻

TylerHelmuth pushed a commit that referenced this pull request Apr 10, 2025
…ssors (#38928)

<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue.
Ex. Adding a feature - Explain what this achieves.-->
#### Description

Currently, OTTL contexts setters can received different data type when
using slices, which might lead to unexpected outcomes, for example,
slice setters functions can receive the following value types:

-  `[]any` when set from literals: `set(string_table, ["foo", "bar"])`
    -   integer values within the `[]any` are parsed as `int64`
-  `[]T` when copied from another path: `set(slice_path, slice_path)`
- `pcommon.Slice` when set from an map's key value: `set(slice_path,
resource.attributes["slice"])`

Those different possibilities must be properly handled on the setter
assessors, and are not obvious since the value is any-wrapped. Failing
to handle all those possible types results in the path not being set or
errors.

This PR adds a set of functions that helps setting and getting slices
values, making it easier handling them until OTTL slice parsing is not
standardized. Those functions will be especially useful for the new
profile context
(#37574),
which needs to provide access to different pdata typed slices.

We've recently done something similar to maps
(#38434).

Usage examples:

```go
// tCtx.GetProfile().StringTable() -> pcommon.StringSlice
func accessStringTableKey[K ProfileContext](ctx context.Context, keys []ottl.Key[K]) ottl.StandardGetSetter[K] {
	return ottl.StandardGetSetter[K]{
		Getter: func(_ context.Context, tCtx K) (any, error) {
			return ctxutil.GetCommonTypedSliceValue[K, string](ctx, tCtx, tCtx.GetProfile().StringTable(), keys)
		},
		Setter: func(_ context.Context, tCtx K, val any) error {
			return ctxutil.SetCommonTypedSliceValue[K, string](ctx, tCtx, tCtx.GetProfile().StringTable(), keys, val)
		},
	}
}

func accessStringTable[K ProfileContext]() ottl.StandardGetSetter[K] {
	return ottl.StandardGetSetter[K]{
		Getter: func(_ context.Context, tCtx K) (any, error) {
			return tCtx.GetProfile().StringTable().AsRaw(), nil
		},
		Setter: func(_ context.Context, tCtx K, val any) error {
			return ctxutil.SetCommonTypedSliceValues[string](tCtx.GetProfile().StringTable(), val)
		},
	}
}

// *Int* function versions also handle type conversions and ensure returned values are compatible with OTTL defaults (int64).
// tCtx.GetProfile().LocationIndices() -> pcommon.Int32Slice
func accessLocationIndicesKey[K ProfileContext](ctx context.Context, keys []ottl.Key[K]) ottl.StandardGetSetter[K] {
	return ottl.StandardGetSetter[K]{
		Getter: func(_ context.Context, tCtx K) (any, error) {
			return ctxutil.GetCommonIntSliceValue[K, int32](ctx, tCtx, tCtx.GetProfile().LocationIndices(), keys)
		},
		Setter: func(_ context.Context, tCtx K, val any) error {
			return ctxutil.SetCommonIntSliceValue[K, int32](ctx, tCtx, tCtx.GetProfile().LocationIndices(), keys, val)
		},
	}
}

func accessLocationIndices[K ProfileContext]() ottl.StandardGetSetter[K] {
	return ottl.StandardGetSetter[K]{
		Getter: func(_ context.Context, tCtx K) (any, error) {
			return ctxutil.GetCommonIntSliceValues[int32](tCtx.GetProfile().LocationIndices()), nil
		},
		Setter: func(_ context.Context, tCtx K, val any) error {
			return ctxutil.SetCommonIntSliceValues[int32](tCtx.GetProfile().LocationIndices(), val)
		},
	}
}
```

<!--Describe what testing was performed and which tests were added.-->
#### Testing
- Unit tests

<!--Please delete paragraphs that you did not use before submitting.-->

---------

Co-authored-by: Tim Rühsen <[email protected]>
@atoulme
Copy link
Contributor

atoulme commented Apr 11, 2025

No longer waiting for a PR to be merged, but conflicts need to be resolved. Please attend to those and mark the PR ready as review again.

@atoulme atoulme marked this pull request as draft April 11, 2025 18:56
@atoulme
Copy link
Contributor

atoulme commented Apr 11, 2025

Removing waiting-for-code-owners as the PR was approved by @TylerHelmuth

@rockdaboot rockdaboot marked this pull request as ready for review April 13, 2025 17:56
@atoulme atoulme merged commit d0ffb46 into open-telemetry:main Apr 14, 2025
174 checks passed
@github-actions github-actions bot added this to the next release milestone Apr 14, 2025
akshays-19 pushed a commit to akshays-19/opentelemetry-collector-contrib that referenced this pull request Apr 23, 2025
…ssors (open-telemetry#38928)

<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue.
Ex. Adding a feature - Explain what this achieves.-->
#### Description

Currently, OTTL contexts setters can received different data type when
using slices, which might lead to unexpected outcomes, for example,
slice setters functions can receive the following value types:

-  `[]any` when set from literals: `set(string_table, ["foo", "bar"])`
    -   integer values within the `[]any` are parsed as `int64`
-  `[]T` when copied from another path: `set(slice_path, slice_path)`
- `pcommon.Slice` when set from an map's key value: `set(slice_path,
resource.attributes["slice"])`

Those different possibilities must be properly handled on the setter
assessors, and are not obvious since the value is any-wrapped. Failing
to handle all those possible types results in the path not being set or
errors.

This PR adds a set of functions that helps setting and getting slices
values, making it easier handling them until OTTL slice parsing is not
standardized. Those functions will be especially useful for the new
profile context
(open-telemetry#37574),
which needs to provide access to different pdata typed slices.

We've recently done something similar to maps
(open-telemetry#38434).

Usage examples:

```go
// tCtx.GetProfile().StringTable() -> pcommon.StringSlice
func accessStringTableKey[K ProfileContext](ctx context.Context, keys []ottl.Key[K]) ottl.StandardGetSetter[K] {
	return ottl.StandardGetSetter[K]{
		Getter: func(_ context.Context, tCtx K) (any, error) {
			return ctxutil.GetCommonTypedSliceValue[K, string](ctx, tCtx, tCtx.GetProfile().StringTable(), keys)
		},
		Setter: func(_ context.Context, tCtx K, val any) error {
			return ctxutil.SetCommonTypedSliceValue[K, string](ctx, tCtx, tCtx.GetProfile().StringTable(), keys, val)
		},
	}
}

func accessStringTable[K ProfileContext]() ottl.StandardGetSetter[K] {
	return ottl.StandardGetSetter[K]{
		Getter: func(_ context.Context, tCtx K) (any, error) {
			return tCtx.GetProfile().StringTable().AsRaw(), nil
		},
		Setter: func(_ context.Context, tCtx K, val any) error {
			return ctxutil.SetCommonTypedSliceValues[string](tCtx.GetProfile().StringTable(), val)
		},
	}
}

// *Int* function versions also handle type conversions and ensure returned values are compatible with OTTL defaults (int64).
// tCtx.GetProfile().LocationIndices() -> pcommon.Int32Slice
func accessLocationIndicesKey[K ProfileContext](ctx context.Context, keys []ottl.Key[K]) ottl.StandardGetSetter[K] {
	return ottl.StandardGetSetter[K]{
		Getter: func(_ context.Context, tCtx K) (any, error) {
			return ctxutil.GetCommonIntSliceValue[K, int32](ctx, tCtx, tCtx.GetProfile().LocationIndices(), keys)
		},
		Setter: func(_ context.Context, tCtx K, val any) error {
			return ctxutil.SetCommonIntSliceValue[K, int32](ctx, tCtx, tCtx.GetProfile().LocationIndices(), keys, val)
		},
	}
}

func accessLocationIndices[K ProfileContext]() ottl.StandardGetSetter[K] {
	return ottl.StandardGetSetter[K]{
		Getter: func(_ context.Context, tCtx K) (any, error) {
			return ctxutil.GetCommonIntSliceValues[int32](tCtx.GetProfile().LocationIndices()), nil
		},
		Setter: func(_ context.Context, tCtx K, val any) error {
			return ctxutil.SetCommonIntSliceValues[int32](tCtx.GetProfile().LocationIndices(), val)
		},
	}
}
```

<!--Describe what testing was performed and which tests were added.-->
#### Testing
- Unit tests

<!--Please delete paragraphs that you did not use before submitting.-->

---------

Co-authored-by: Tim Rühsen <[email protected]>
akshays-19 pushed a commit to akshays-19/opentelemetry-collector-contrib that referenced this pull request Apr 23, 2025
Fixes
open-telemetry#36104

This is a first PR to get profiles support into OTTL. Follow-up PRs will
add support for more sub-types of profiles like `sample`, `mapping`
etc..
Fiery-Fenix pushed a commit to Fiery-Fenix/opentelemetry-collector-contrib that referenced this pull request Apr 24, 2025
…ssors (open-telemetry#38928)

<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue.
Ex. Adding a feature - Explain what this achieves.-->
#### Description

Currently, OTTL contexts setters can received different data type when
using slices, which might lead to unexpected outcomes, for example,
slice setters functions can receive the following value types:

-  `[]any` when set from literals: `set(string_table, ["foo", "bar"])`
    -   integer values within the `[]any` are parsed as `int64`
-  `[]T` when copied from another path: `set(slice_path, slice_path)`
- `pcommon.Slice` when set from an map's key value: `set(slice_path,
resource.attributes["slice"])`

Those different possibilities must be properly handled on the setter
assessors, and are not obvious since the value is any-wrapped. Failing
to handle all those possible types results in the path not being set or
errors.

This PR adds a set of functions that helps setting and getting slices
values, making it easier handling them until OTTL slice parsing is not
standardized. Those functions will be especially useful for the new
profile context
(open-telemetry#37574),
which needs to provide access to different pdata typed slices.

We've recently done something similar to maps
(open-telemetry#38434).

Usage examples:

```go
// tCtx.GetProfile().StringTable() -> pcommon.StringSlice
func accessStringTableKey[K ProfileContext](ctx context.Context, keys []ottl.Key[K]) ottl.StandardGetSetter[K] {
	return ottl.StandardGetSetter[K]{
		Getter: func(_ context.Context, tCtx K) (any, error) {
			return ctxutil.GetCommonTypedSliceValue[K, string](ctx, tCtx, tCtx.GetProfile().StringTable(), keys)
		},
		Setter: func(_ context.Context, tCtx K, val any) error {
			return ctxutil.SetCommonTypedSliceValue[K, string](ctx, tCtx, tCtx.GetProfile().StringTable(), keys, val)
		},
	}
}

func accessStringTable[K ProfileContext]() ottl.StandardGetSetter[K] {
	return ottl.StandardGetSetter[K]{
		Getter: func(_ context.Context, tCtx K) (any, error) {
			return tCtx.GetProfile().StringTable().AsRaw(), nil
		},
		Setter: func(_ context.Context, tCtx K, val any) error {
			return ctxutil.SetCommonTypedSliceValues[string](tCtx.GetProfile().StringTable(), val)
		},
	}
}

// *Int* function versions also handle type conversions and ensure returned values are compatible with OTTL defaults (int64).
// tCtx.GetProfile().LocationIndices() -> pcommon.Int32Slice
func accessLocationIndicesKey[K ProfileContext](ctx context.Context, keys []ottl.Key[K]) ottl.StandardGetSetter[K] {
	return ottl.StandardGetSetter[K]{
		Getter: func(_ context.Context, tCtx K) (any, error) {
			return ctxutil.GetCommonIntSliceValue[K, int32](ctx, tCtx, tCtx.GetProfile().LocationIndices(), keys)
		},
		Setter: func(_ context.Context, tCtx K, val any) error {
			return ctxutil.SetCommonIntSliceValue[K, int32](ctx, tCtx, tCtx.GetProfile().LocationIndices(), keys, val)
		},
	}
}

func accessLocationIndices[K ProfileContext]() ottl.StandardGetSetter[K] {
	return ottl.StandardGetSetter[K]{
		Getter: func(_ context.Context, tCtx K) (any, error) {
			return ctxutil.GetCommonIntSliceValues[int32](tCtx.GetProfile().LocationIndices()), nil
		},
		Setter: func(_ context.Context, tCtx K, val any) error {
			return ctxutil.SetCommonIntSliceValues[int32](tCtx.GetProfile().LocationIndices(), val)
		},
	}
}
```

<!--Describe what testing was performed and which tests were added.-->
#### Testing
- Unit tests

<!--Please delete paragraphs that you did not use before submitting.-->

---------

Co-authored-by: Tim Rühsen <[email protected]>
Fiery-Fenix pushed a commit to Fiery-Fenix/opentelemetry-collector-contrib that referenced this pull request Apr 24, 2025
Fixes
open-telemetry#36104

This is a first PR to get profiles support into OTTL. Follow-up PRs will
add support for more sub-types of profiles like `sample`, `mapping`
etc..
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[pkg/ottl] Add support for profiles
10 participants