Skip to content

Commit 57a5849

Browse files
christos68kfelixge
andauthored
Profiles: simplify profile stack trace representation (ASCII fix, conflicts resolved) (#708)
* Simplify profile stack trace representation - Introduce a first-class Stack message type and lookup table. - Replace location index range based stack trace encoding on Sample with a single stack_index reference. - Remove the location_indices lookup table. The primary motivation is laying the ground work for [timestamp based profiling][timestamp proposal] where the same stack trace needs to be referenced much more frequently compared to aggregation based on low cardinality attributes. Timestamp based profiling is also expected to be used with the the upcoming [Off-CPU profiling][off-cpu pr] feature in the eBPF profiler. Off-CPU stack traces have a different distribution compared to CPU samples. In particular stack traces are much more repetitive because they only occur at call sites such as syscalls. For the same reason it is also uncommon to see a stack trace are a root-prefix of a previously observed stack trace. We might need to revisit the previous [previous benchmarks][benchmarks] to confirm these claims. The secondary motivation is simplicitly. Arguably the proposed change here will make it easier to write exporters, processors as well as receivers. It seems like we had rough consensus around this change in previous SIG meetings, and it seems like a good incremental step to make progress on the timestamp proposal. [timestamp proposal]: #594 [off-cpu pr]: open-telemetry/opentelemetry-ebpf-profiler#196 [benchmarks]: https://docs.google.com/spreadsheets/d/1Q-6MlegV8xLYdz5WD5iPxQU2tsfodX1-CDV1WeGzyQ0/edit?gid=2069300294#gid=2069300294 Modified-by: Christos Kalkanis <[email protected]> * Update ASCII diagram for new Stack message * Move leaf frame explanation to field inside Stack message * Update field number * Update ASCII diagram (Sample->Stack n-1 instead of 1-1) --------- Co-authored-by: Felix Geisendörfer <[email protected]>
1 parent f4bf875 commit 57a5849

File tree

1 file changed

+47
-36
lines changed

1 file changed

+47
-36
lines changed

opentelemetry/proto/profiles/v1development/profiles.proto

Lines changed: 47 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,18 @@ option go_package = "go.opentelemetry.io/proto/otlp/profiles/v1development";
7070
// ┌──────────────────┐ 1-n ┌─────────────────┐ ┌──────────┐
7171
// │ Sample │ ──────▷ │ KeyValueAndUnit │ │ Link │
7272
// └──────────────────┘ └─────────────────┘ └──────────┘
73-
// │ 1-n △ △
74-
// │ 1-n ┌─────────────────┘ │ 1-n
75-
// ▽ │ │
76-
// ┌──────────────────┐ n-1 ┌──────────────┐
77-
// │ Location │ ──────▷ │ Mapping │
78-
// └──────────────────┘ └──────────────┘
73+
// │ △ △
74+
// │ n-1 │ │ 1-n
75+
// ▽ │ │
76+
// ┌──────────────────┐ │ │
77+
// │ Stack │ │ │
78+
// └──────────────────┘ │ │
79+
// │ 1-n │ │
80+
// │ 1-n ┌────────────────┘ │
81+
// ▽ │ │
82+
// ┌──────────────────┐ n-1 ┌─────────────┐
83+
// │ Location │ ──────▷ │ Mapping │
84+
// └──────────────────┘ └─────────────┘
7985
// │
8086
// │ 1-n
8187
// ▼
@@ -102,7 +108,7 @@ message ProfilesDictionary {
102108
// into that address range referenced by locations via Location.mapping_index.
103109
repeated Mapping mapping_table = 1;
104110

105-
// Locations referenced by samples via Profile.location_indices.
111+
// Locations referenced by samples via Stack.location_indices.
106112
repeated Location location_table = 2;
107113

108114
// Functions referenced by locations via Line.function_index.
@@ -134,6 +140,9 @@ message ProfilesDictionary {
134140
// The restrictions take origin from the OpenTelemetry specification:
135141
// https://github.com/open-telemetry/opentelemetry-specification/blob/v1.47.0/specification/common/README.md#attribute.
136142
repeated KeyValueAndUnit attribute_table = 6;
143+
144+
// Stacks referenced by samples via Sample.stack_index.
145+
repeated Stack stack_table = 7;
137146
}
138147

139148
// ProfilesData represents the profiles data that can be stored in persistent storage,
@@ -214,18 +223,19 @@ message ScopeProfiles {
214223
// information present to determine the original sampled values.
215224
//
216225
// - The profile is represented as a set of samples, where each sample
217-
// references a sequence of locations, and where each location belongs
226+
// references a stack trace which is a list of locations, each belonging
218227
// to a mapping.
219-
// - There is a N->1 relationship from sample.location_id entries to
220-
// locations. For every sample.location_id entry there must be a
228+
// - There is a N->1 relationship from Stack.location_indices entries to
229+
// locations. For every Stack.location_indices entry there must be a
221230
// unique Location with that index.
222231
// - There is an optional N->1 relationship from locations to
223232
// mappings. For every nonzero Location.mapping_id there must be a
224233
// unique Mapping with that index.
225234

226-
// Represents a complete profile, including sample types, samples,
227-
// mappings to binaries, locations, functions, string table, and additional metadata.
228-
// It modifies and annotates pprof Profile with OpenTelemetry specific fields.
235+
// Represents a complete profile, including sample types, samples, mappings to
236+
// binaries, stacks, locations, functions, string table, and additional
237+
// metadata. It modifies and annotates pprof Profile with OpenTelemetry
238+
// specific fields.
229239
//
230240
// Note that whilst fields in this message retain the name and field id from pprof in most cases
231241
// for ease of understanding data migration, it is not intended that pprof:Profile and
@@ -240,54 +250,51 @@ message Profile {
240250
// The set of samples recorded in this profile.
241251
repeated Sample sample = 2;
242252

243-
// References to locations in ProfilesDictionary.location_table.
244-
repeated int32 location_indices = 3;
245-
246-
// The following fields 4-14 are informational, do not affect
253+
// The following fields 3-12 are informational, do not affect
247254
// interpretation of results.
248255

249256
// Time of collection (UTC) represented as nanoseconds past the epoch.
250-
fixed64 time_unix_nano = 4;
257+
fixed64 time_unix_nano = 3;
251258
// Duration of the profile, if a duration makes sense.
252-
uint64 duration_nano = 5;
259+
uint64 duration_nano = 4;
253260
// The kind of events between sampled occurrences.
254261
// e.g [ "cpu","cycles" ] or [ "heap","bytes" ]
255-
ValueType period_type = 6;
262+
ValueType period_type = 5;
256263
// The number of events between sampled occurrences.
257-
int64 period = 7;
264+
int64 period = 6;
258265
// Free-form text associated with the profile. The text is displayed as is
259266
// to the user by the tools that read profiles (e.g. by pprof). This field
260267
// should not be used to store any machine-readable information, it is only
261268
// for human-friendly content. The profile must stay functional if this field
262269
// is cleaned.
263-
repeated int32 comment_strindices = 8; // Indices into ProfilesDictionary.string_table.
270+
repeated int32 comment_strindices = 7; // Indices into ProfilesDictionary.string_table.
264271

265272
// A globally unique identifier for a profile. The ID is a 16-byte array. An ID with
266273
// all zeroes is considered invalid. It may be used for deduplication and signal
267274
// correlation purposes. It is acceptable to treat two profiles with different values
268275
// in this field as not equal, even if they represented the same object at an earlier
269276
// time.
270277
// This field is optional; an ID may be assigned to an ID-less profile in a later step.
271-
bytes profile_id = 9;
278+
bytes profile_id = 8;
272279

273280
// dropped_attributes_count is the number of attributes that were discarded. Attributes
274281
// can be discarded because their keys are too long or because there are too many
275282
// attributes. If this value is 0, then no attributes were dropped.
276-
uint32 dropped_attributes_count = 10;
283+
uint32 dropped_attributes_count = 9;
277284

278285
// Specifies format of the original payload. Common values are defined in semantic conventions. [required if original_payload is present]
279-
string original_payload_format = 11;
286+
string original_payload_format = 10;
280287

281288
// Original payload can be stored in this field. This can be useful for users who want to get the original payload.
282289
// Formats such as JFR are highly extensible and can contain more information than what is defined in this spec.
283290
// Inclusion of original payload should be configurable by the user. Default behavior should be to not include the original payload.
284291
// If the original payload is in pprof format, it SHOULD not be included in this field.
285292
// The field is optional, however if it is present then equivalent converted data should be populated in other fields
286293
// of this message as far as is practicable.
287-
bytes original_payload = 12;
294+
bytes original_payload = 11;
288295

289296
// References to attributes in attribute_table. [optional]
290-
repeated int32 attribute_indices = 13;
297+
repeated int32 attribute_indices = 12;
291298
}
292299

293300
// A pointer from a profile Sample to a trace Span.
@@ -400,23 +407,20 @@ message ValueType {
400407
// values: [2, 2, 3, 3]
401408
// timestamps_unix_nano: [1, 2, 3, 4]
402409
message Sample {
403-
// locations_start_index along with locations_length refers to to a slice of locations in Profile.location_indices.
404-
int32 locations_start_index = 1;
405-
// locations_length along with locations_start_index refers to a slice of locations in Profile.location_indices.
406-
// Supersedes location_index.
407-
int32 locations_length = 2;
410+
// Reference to stack in ProfilesDictionary.stack_table.
411+
int32 stack_index = 1;
408412
// The type and unit of each value is defined by Profile.sample_type.
409-
repeated int64 values = 3;
413+
repeated int64 values = 2;
410414
// References to attributes in ProfilesDictionary.attribute_table. [optional]
411-
repeated int32 attribute_indices = 4;
415+
repeated int32 attribute_indices = 3;
412416

413417
// Reference to link in ProfilesDictionary.link_table. [optional]
414418
// It can be unset / set to 0 if no link exists, as link_table[0] is always a 'null' default value.
415-
int32 link_index = 5;
419+
int32 link_index = 4;
416420

417421
// Timestamps associated with Sample represented in nanoseconds. These
418422
// timestamps should fall within the Profile's time range.
419-
repeated fixed64 timestamps_unix_nano = 6;
423+
repeated fixed64 timestamps_unix_nano = 5;
420424
}
421425

422426
// Describes the mapping of a binary in memory, including its address range,
@@ -436,6 +440,13 @@ message Mapping {
436440
repeated int32 attribute_indices = 5;
437441
}
438442

443+
// A Stack represents a stack trace as a list of locations.
444+
message Stack {
445+
// References to locations in ProfilesDictionary.location_table.
446+
// The first location is the leaf frame.
447+
repeated int32 location_indices = 1;
448+
}
449+
439450
// Describes function and line table debug information.
440451
message Location {
441452
// Reference to mapping in ProfilesDictionary.mapping_table.

0 commit comments

Comments
 (0)