ddtrace 0.47.0 → 0.48.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +4 -2
  3. data/.circleci/images/primary/Dockerfile-2.0.0 +11 -1
  4. data/.circleci/images/primary/Dockerfile-2.1.10 +11 -1
  5. data/.circleci/images/primary/Dockerfile-2.2.10 +11 -1
  6. data/.circleci/images/primary/Dockerfile-2.3.8 +10 -0
  7. data/.circleci/images/primary/Dockerfile-2.4.6 +10 -0
  8. data/.circleci/images/primary/Dockerfile-2.5.6 +10 -0
  9. data/.circleci/images/primary/Dockerfile-2.6.4 +10 -0
  10. data/.circleci/images/primary/Dockerfile-2.7.0 +10 -0
  11. data/.circleci/images/primary/Dockerfile-jruby-9.2-latest +10 -0
  12. data/.gitlab-ci.yml +18 -18
  13. data/.rubocop.yml +19 -0
  14. data/.rubocop_todo.yml +44 -3
  15. data/Appraisals +55 -1
  16. data/CHANGELOG.md +47 -1
  17. data/Gemfile +10 -0
  18. data/Rakefile +9 -0
  19. data/bin/ddtracerb +15 -0
  20. data/ddtrace.gemspec +4 -2
  21. data/docs/GettingStarted.md +36 -53
  22. data/docs/ProfilingDevelopment.md +88 -0
  23. data/integration/README.md +1 -2
  24. data/integration/apps/rack/Dockerfile +3 -0
  25. data/integration/apps/rack/script/build-images +1 -1
  26. data/integration/apps/rack/script/ci +1 -1
  27. data/integration/apps/rails-five/script/build-images +1 -1
  28. data/integration/apps/rails-five/script/ci +1 -1
  29. data/integration/apps/ruby/script/build-images +1 -1
  30. data/integration/apps/ruby/script/ci +1 -1
  31. data/integration/images/include/http-health-check +1 -1
  32. data/integration/images/wrk/scripts/entrypoint.sh +1 -1
  33. data/integration/script/build-images +1 -1
  34. data/lib/ddtrace.rb +1 -0
  35. data/lib/ddtrace/configuration.rb +39 -13
  36. data/lib/ddtrace/configuration/components.rb +85 -3
  37. data/lib/ddtrace/configuration/settings.rb +31 -0
  38. data/lib/ddtrace/contrib/active_record/configuration/makara_resolver.rb +30 -0
  39. data/lib/ddtrace/contrib/active_record/configuration/resolver.rb +9 -3
  40. data/lib/ddtrace/contrib/resque/configuration/settings.rb +17 -1
  41. data/lib/ddtrace/contrib/resque/patcher.rb +4 -4
  42. data/lib/ddtrace/contrib/resque/resque_job.rb +22 -1
  43. data/lib/ddtrace/contrib/shoryuken/configuration/settings.rb +1 -0
  44. data/lib/ddtrace/contrib/shoryuken/tracer.rb +7 -3
  45. data/lib/ddtrace/diagnostics/environment_logger.rb +1 -1
  46. data/lib/ddtrace/error.rb +2 -0
  47. data/lib/ddtrace/ext/profiling.rb +52 -0
  48. data/lib/ddtrace/ext/transport.rb +1 -0
  49. data/lib/ddtrace/metrics.rb +4 -0
  50. data/lib/ddtrace/profiling.rb +54 -0
  51. data/lib/ddtrace/profiling/backtrace_location.rb +32 -0
  52. data/lib/ddtrace/profiling/buffer.rb +41 -0
  53. data/lib/ddtrace/profiling/collectors/stack.rb +253 -0
  54. data/lib/ddtrace/profiling/encoding/profile.rb +31 -0
  55. data/lib/ddtrace/profiling/event.rb +13 -0
  56. data/lib/ddtrace/profiling/events/stack.rb +102 -0
  57. data/lib/ddtrace/profiling/exporter.rb +23 -0
  58. data/lib/ddtrace/profiling/ext/cpu.rb +54 -0
  59. data/lib/ddtrace/profiling/ext/cthread.rb +134 -0
  60. data/lib/ddtrace/profiling/ext/forking.rb +97 -0
  61. data/lib/ddtrace/profiling/flush.rb +41 -0
  62. data/lib/ddtrace/profiling/pprof/builder.rb +121 -0
  63. data/lib/ddtrace/profiling/pprof/converter.rb +85 -0
  64. data/lib/ddtrace/profiling/pprof/message_set.rb +12 -0
  65. data/lib/ddtrace/profiling/pprof/payload.rb +18 -0
  66. data/lib/ddtrace/profiling/pprof/pprof.proto +212 -0
  67. data/lib/ddtrace/profiling/pprof/pprof_pb.rb +81 -0
  68. data/lib/ddtrace/profiling/pprof/stack_sample.rb +90 -0
  69. data/lib/ddtrace/profiling/pprof/string_table.rb +10 -0
  70. data/lib/ddtrace/profiling/pprof/template.rb +114 -0
  71. data/lib/ddtrace/profiling/preload.rb +3 -0
  72. data/lib/ddtrace/profiling/profiler.rb +28 -0
  73. data/lib/ddtrace/profiling/recorder.rb +87 -0
  74. data/lib/ddtrace/profiling/scheduler.rb +84 -0
  75. data/lib/ddtrace/profiling/tasks/setup.rb +77 -0
  76. data/lib/ddtrace/profiling/transport/client.rb +12 -0
  77. data/lib/ddtrace/profiling/transport/http.rb +122 -0
  78. data/lib/ddtrace/profiling/transport/http/api.rb +43 -0
  79. data/lib/ddtrace/profiling/transport/http/api/endpoint.rb +90 -0
  80. data/lib/ddtrace/profiling/transport/http/api/instance.rb +36 -0
  81. data/lib/ddtrace/profiling/transport/http/api/spec.rb +40 -0
  82. data/lib/ddtrace/profiling/transport/http/builder.rb +28 -0
  83. data/lib/ddtrace/profiling/transport/http/client.rb +33 -0
  84. data/lib/ddtrace/profiling/transport/http/response.rb +21 -0
  85. data/lib/ddtrace/profiling/transport/io.rb +30 -0
  86. data/lib/ddtrace/profiling/transport/io/client.rb +27 -0
  87. data/lib/ddtrace/profiling/transport/io/response.rb +16 -0
  88. data/lib/ddtrace/profiling/transport/parcel.rb +17 -0
  89. data/lib/ddtrace/profiling/transport/request.rb +15 -0
  90. data/lib/ddtrace/profiling/transport/response.rb +8 -0
  91. data/lib/ddtrace/runtime/container.rb +11 -3
  92. data/lib/ddtrace/sampling/rule_sampler.rb +3 -9
  93. data/lib/ddtrace/tasks/exec.rb +48 -0
  94. data/lib/ddtrace/tasks/help.rb +14 -0
  95. data/lib/ddtrace/tracer.rb +21 -0
  96. data/lib/ddtrace/transport/io/client.rb +15 -8
  97. data/lib/ddtrace/transport/parcel.rb +4 -0
  98. data/lib/ddtrace/version.rb +3 -1
  99. data/lib/ddtrace/workers/runtime_metrics.rb +14 -1
  100. metadata +70 -9
@@ -0,0 +1,41 @@
1
+ require 'ddtrace/runtime/identity'
2
+ require 'ddtrace/runtime/socket'
3
+
4
+ module Datadog
5
+ module Profiling
6
+ # Entity class used to represent metadata for a given profile
7
+ Flush = Struct.new(
8
+ :start,
9
+ :finish,
10
+ :event_groups,
11
+ :event_count,
12
+ :runtime_id,
13
+ :service,
14
+ :env,
15
+ :version,
16
+ :host,
17
+ :language,
18
+ :runtime_engine,
19
+ :runtime_platform,
20
+ :runtime_version,
21
+ :profiler_version
22
+ ) do
23
+ def initialize(*args)
24
+ super
25
+ self.runtime_id = runtime_id || Datadog::Runtime::Identity.id
26
+ self.service = service || Datadog.configuration.service
27
+ self.env = env || Datadog.configuration.env
28
+ self.version = version || Datadog.configuration.version
29
+ self.host = host || Datadog::Runtime::Socket.hostname
30
+ self.language = language || Datadog::Runtime::Identity.lang
31
+ self.runtime_engine = runtime_engine || Datadog::Runtime::Identity.lang_engine
32
+ self.runtime_platform = runtime_platform || Datadog::Runtime::Identity.lang_platform
33
+ self.runtime_version = runtime_version || Datadog::Runtime::Identity.lang_version
34
+ self.profiler_version = profiler_version || Datadog::Runtime::Identity.tracer_version
35
+ end
36
+ end
37
+
38
+ # Represents a collection of events of a specific type being flushed.
39
+ EventGroup = Struct.new(:event_class, :events).freeze
40
+ end
41
+ end
@@ -0,0 +1,121 @@
1
+ require 'ddtrace/profiling/flush'
2
+ require 'ddtrace/profiling/pprof/message_set'
3
+ require 'ddtrace/profiling/pprof/string_table'
4
+
5
+ module Datadog
6
+ module Profiling
7
+ module Pprof
8
+ # Accumulates profile data and produces a Perftools::Profiles::Profile
9
+ class Builder
10
+ DEFAULT_ENCODING = 'UTF-8'.freeze
11
+ DESC_FRAME_OMITTED = 'frame omitted'.freeze
12
+ DESC_FRAMES_OMITTED = 'frames omitted'.freeze
13
+
14
+ attr_reader \
15
+ :functions,
16
+ :locations,
17
+ :mappings,
18
+ :sample_types,
19
+ :samples,
20
+ :string_table
21
+
22
+ def initialize
23
+ @functions = MessageSet.new(1)
24
+ @locations = MessageSet.new(1)
25
+ @mappings = MessageSet.new(1)
26
+ @sample_types = MessageSet.new
27
+ @samples = []
28
+ @string_table = StringTable.new
29
+ end
30
+
31
+ def encode_profile(profile)
32
+ Perftools::Profiles::Profile.encode(profile).force_encoding(DEFAULT_ENCODING)
33
+ end
34
+
35
+ def build_profile
36
+ Perftools::Profiles::Profile.new(
37
+ sample_type: @sample_types.messages,
38
+ sample: @samples,
39
+ mapping: @mappings.messages,
40
+ location: @locations.messages,
41
+ function: @functions.messages,
42
+ string_table: @string_table.strings
43
+ )
44
+ end
45
+
46
+ def build_value_type(type, unit)
47
+ Perftools::Profiles::ValueType.new(
48
+ type: @string_table.fetch(type),
49
+ unit: @string_table.fetch(unit)
50
+ )
51
+ end
52
+
53
+ def build_locations(backtrace_locations, length)
54
+ locations = backtrace_locations.collect do |backtrace_location|
55
+ @locations.fetch(
56
+ # Filename
57
+ backtrace_location.path,
58
+ # Line number
59
+ backtrace_location.lineno,
60
+ # Function name
61
+ backtrace_location.base_label,
62
+ # Build function
63
+ &method(:build_location)
64
+ )
65
+ end
66
+
67
+ omitted = length - backtrace_locations.length
68
+
69
+ # Add placeholder stack frame if frames were truncated
70
+ if omitted > 0
71
+ desc = omitted == 1 ? DESC_FRAME_OMITTED : DESC_FRAMES_OMITTED
72
+ locations << @locations.fetch(
73
+ ''.freeze,
74
+ 0,
75
+ "#{omitted} #{desc}",
76
+ &method(:build_location)
77
+ )
78
+ end
79
+
80
+ locations
81
+ end
82
+
83
+ def build_location(id, filename, line_number, function_name = nil)
84
+ Perftools::Profiles::Location.new(
85
+ id: id,
86
+ line: [build_line(
87
+ @functions.fetch(
88
+ filename,
89
+ function_name,
90
+ &method(:build_function)
91
+ ).id,
92
+ line_number
93
+ )]
94
+ )
95
+ end
96
+
97
+ def build_line(function_id, line_number)
98
+ Perftools::Profiles::Line.new(
99
+ function_id: function_id,
100
+ line: line_number
101
+ )
102
+ end
103
+
104
+ def build_function(id, filename, function_name)
105
+ Perftools::Profiles::Function.new(
106
+ id: id,
107
+ name: @string_table.fetch(function_name),
108
+ filename: @string_table.fetch(filename)
109
+ )
110
+ end
111
+
112
+ def build_mapping(id, filename)
113
+ Perftools::Profiles::Mapping.new(
114
+ id: id,
115
+ filename: @string_table.fetch(filename)
116
+ )
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,85 @@
1
+ require 'ddtrace/ext/profiling'
2
+
3
+ module Datadog
4
+ module Profiling
5
+ module Pprof
6
+ # Base class for converters that convert profiling events to pprof
7
+ class Converter
8
+ attr_reader \
9
+ :builder
10
+
11
+ # Override in child class to define sample types
12
+ # this converter uses when building samples.
13
+ def self.sample_value_types
14
+ raise NotImplementedError
15
+ end
16
+
17
+ def initialize(builder, sample_type_mappings)
18
+ @builder = builder
19
+ @sample_type_mappings = sample_type_mappings
20
+ end
21
+
22
+ def group_events(events)
23
+ # Event grouping in format:
24
+ # [key, EventGroup]
25
+ event_groups = {}
26
+
27
+ events.each do |event|
28
+ key = yield(event)
29
+ values = build_sample_values(event)
30
+
31
+ unless key.nil?
32
+ if event_groups.key?(key)
33
+ # Update values for group
34
+ group_values = event_groups[key].values
35
+ group_values.each_with_index do |group_value, i|
36
+ group_values[i] = group_value + values[i]
37
+ end
38
+ else
39
+ # Add new group
40
+ event_groups[key] = EventGroup.new(event, values)
41
+ end
42
+ end
43
+ end
44
+
45
+ event_groups
46
+ end
47
+
48
+ def add_events!(events)
49
+ raise NotImplementedError
50
+ end
51
+
52
+ def sample_value_index(type)
53
+ index = @sample_type_mappings[type]
54
+ raise UnknownSampleTypeMappingError, type unless index
55
+
56
+ index
57
+ end
58
+
59
+ def build_sample_values(stack_sample)
60
+ # Build a value array that matches the length of the sample types
61
+ # Populate all values with "no value" by default
62
+ Array.new(@sample_type_mappings.length, Datadog::Ext::Profiling::Pprof::SAMPLE_VALUE_NO_VALUE)
63
+ end
64
+
65
+ # Represents a grouped event
66
+ # 'sample' is an example event object from the group.
67
+ # 'values' is the the summation of the group's sample values
68
+ EventGroup = Struct.new(:sample, :values)
69
+
70
+ # Error when the mapping of a sample type to value index is unknown
71
+ class UnknownSampleTypeMappingError < StandardError
72
+ attr_reader :type
73
+
74
+ def initialize(type)
75
+ @type = type
76
+ end
77
+
78
+ def message
79
+ "Mapping for sample value type '#{type}' to index is unknown."
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,12 @@
1
+ require 'ddtrace/utils/object_set'
2
+
3
+ module Datadog
4
+ module Profiling
5
+ module Pprof
6
+ # Acts as a unique dictionary of protobuf messages
7
+ class MessageSet < Utils::ObjectSet
8
+ alias_method :messages, :objects
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,18 @@
1
+ module Datadog
2
+ module Profiling
3
+ module Pprof
4
+ # Pprof output data.
5
+ # Includes encoded data and list of types.
6
+ Payload = Struct.new(:data, :types) do
7
+ def initialize(*args)
8
+ super
9
+ self.types = types || []
10
+ end
11
+
12
+ def to_s
13
+ data
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,212 @@
1
+ // Copyright 2016 Google Inc. All Rights Reserved.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ // Profile is a common stacktrace profile format.
16
+ //
17
+ // Measurements represented with this format should follow the
18
+ // following conventions:
19
+ //
20
+ // - Consumers should treat unset optional fields as if they had been
21
+ // set with their default value.
22
+ //
23
+ // - When possible, measurements should be stored in "unsampled" form
24
+ // that is most useful to humans. There should be enough
25
+ // information present to determine the original sampled values.
26
+ //
27
+ // - On-disk, the serialized proto must be gzip-compressed.
28
+ //
29
+ // - The profile is represented as a set of samples, where each sample
30
+ // references a sequence of locations, and where each location belongs
31
+ // to a mapping.
32
+ // - There is a N->1 relationship from sample.location_id entries to
33
+ // locations. For every sample.location_id entry there must be a
34
+ // unique Location with that id.
35
+ // - There is an optional N->1 relationship from locations to
36
+ // mappings. For every nonzero Location.mapping_id there must be a
37
+ // unique Mapping with that id.
38
+
39
+ syntax = "proto3";
40
+
41
+ package perftools.profiles;
42
+
43
+ option java_package = "com.google.perftools.profiles";
44
+ option java_outer_classname = "ProfileProto";
45
+
46
+ message Profile {
47
+ // A description of the samples associated with each Sample.value.
48
+ // For a cpu profile this might be:
49
+ // [["cpu","nanoseconds"]] or [["wall","seconds"]] or [["syscall","count"]]
50
+ // For a heap profile, this might be:
51
+ // [["allocations","count"], ["space","bytes"]],
52
+ // If one of the values represents the number of events represented
53
+ // by the sample, by convention it should be at index 0 and use
54
+ // sample_type.unit == "count".
55
+ repeated ValueType sample_type = 1;
56
+ // The set of samples recorded in this profile.
57
+ repeated Sample sample = 2;
58
+ // Mapping from address ranges to the image/binary/library mapped
59
+ // into that address range. mapping[0] will be the main binary.
60
+ repeated Mapping mapping = 3;
61
+ // Useful program location
62
+ repeated Location location = 4;
63
+ // Functions referenced by locations
64
+ repeated Function function = 5;
65
+ // A common table for strings referenced by various messages.
66
+ // string_table[0] must always be "".
67
+ repeated string string_table = 6;
68
+ // frames with Function.function_name fully matching the following
69
+ // regexp will be dropped from the samples, along with their successors.
70
+ int64 drop_frames = 7; // Index into string table.
71
+ // frames with Function.function_name fully matching the following
72
+ // regexp will be kept, even if it matches drop_functions.
73
+ int64 keep_frames = 8; // Index into string table.
74
+
75
+ // The following fields are informational, do not affect
76
+ // interpretation of results.
77
+
78
+ // Time of collection (UTC) represented as nanoseconds past the epoch.
79
+ int64 time_nanos = 9;
80
+ // Duration of the profile, if a duration makes sense.
81
+ int64 duration_nanos = 10;
82
+ // The kind of events between sampled ocurrences.
83
+ // e.g [ "cpu","cycles" ] or [ "heap","bytes" ]
84
+ ValueType period_type = 11;
85
+ // The number of events between sampled occurrences.
86
+ int64 period = 12;
87
+ // Freeform text associated to the profile.
88
+ repeated int64 comment = 13; // Indices into string table.
89
+ // Index into the string table of the type of the preferred sample
90
+ // value. If unset, clients should default to the last sample value.
91
+ int64 default_sample_type = 14;
92
+ }
93
+
94
+ // ValueType describes the semantics and measurement units of a value.
95
+ message ValueType {
96
+ int64 type = 1; // Index into string table.
97
+ int64 unit = 2; // Index into string table.
98
+ }
99
+
100
+ // Each Sample records values encountered in some program
101
+ // context. The program context is typically a stack trace, perhaps
102
+ // augmented with auxiliary information like the thread-id, some
103
+ // indicator of a higher level request being handled etc.
104
+ message Sample {
105
+ // The ids recorded here correspond to a Profile.location.id.
106
+ // The leaf is at location_id[0].
107
+ repeated uint64 location_id = 1;
108
+ // The type and unit of each value is defined by the corresponding
109
+ // entry in Profile.sample_type. All samples must have the same
110
+ // number of values, the same as the length of Profile.sample_type.
111
+ // When aggregating multiple samples into a single sample, the
112
+ // result has a list of values that is the elemntwise sum of the
113
+ // lists of the originals.
114
+ repeated int64 value = 2;
115
+ // label includes additional context for this sample. It can include
116
+ // things like a thread id, allocation size, etc
117
+ repeated Label label = 3;
118
+ }
119
+
120
+ message Label {
121
+ int64 key = 1; // Index into string table
122
+
123
+ // At most one of the following must be present
124
+ int64 str = 2; // Index into string table
125
+ int64 num = 3;
126
+
127
+ // Should only be present when num is present.
128
+ // Specifies the units of num.
129
+ // Use arbitrary string (for example, "requests") as a custom count unit.
130
+ // If no unit is specified, consumer may apply heuristic to deduce the unit.
131
+ // Consumers may also interpret units like "bytes" and "kilobytes" as memory
132
+ // units and units like "seconds" and "nanoseconds" as time units,
133
+ // and apply appropriate unit conversions to these.
134
+ int64 num_unit = 4; // Index into string table
135
+ }
136
+
137
+ message Mapping {
138
+ // Unique nonzero id for the mapping.
139
+ uint64 id = 1;
140
+ // Address at which the binary (or DLL) is loaded into memory.
141
+ uint64 memory_start = 2;
142
+ // The limit of the address range occupied by this mapping.
143
+ uint64 memory_limit = 3;
144
+ // Offset in the binary that corresponds to the first mapped address.
145
+ uint64 file_offset = 4;
146
+ // The object this entry is loaded from. This can be a filename on
147
+ // disk for the main binary and shared libraries, or virtual
148
+ // abstractions like "[vdso]".
149
+ int64 filename = 5; // Index into string table
150
+ // A string that uniquely identifies a particular program version
151
+ // with high probability. E.g., for binaries generated by GNU tools,
152
+ // it could be the contents of the .note.gnu.build-id field.
153
+ int64 build_id = 6; // Index into string table
154
+
155
+ // The following fields indicate the resolution of symbolic info.
156
+ bool has_functions = 7;
157
+ bool has_filenames = 8;
158
+ bool has_line_numbers = 9;
159
+ bool has_inline_frames = 10;
160
+ }
161
+
162
+ // Describes function and line table debug information.
163
+ message Location {
164
+ // Unique nonzero id for the location. A profile could use
165
+ // instruction addresses or any integer sequence as ids.
166
+ uint64 id = 1;
167
+ // The id of the corresponding profile.Mapping for this location.
168
+ // It can be unset if the mapping is unknown or not applicable for
169
+ // this profile type.
170
+ uint64 mapping_id = 2;
171
+ // The instruction address for this location, if available. It
172
+ // should be within [Mapping.memory_start...Mapping.memory_limit]
173
+ // for the corresponding mapping. A non-leaf address may be in the
174
+ // middle of a call instruction. It is up to display tools to find
175
+ // the beginning of the instruction if necessary.
176
+ uint64 address = 3;
177
+ // Multiple line indicates this location has inlined functions,
178
+ // where the last entry represents the caller into which the
179
+ // preceding entries were inlined.
180
+ //
181
+ // E.g., if memcpy() is inlined into printf:
182
+ // line[0].function_name == "memcpy"
183
+ // line[1].function_name == "printf"
184
+ repeated Line line = 4;
185
+ // Provides an indication that multiple symbols map to this location's
186
+ // address, for example due to identical code folding by the linker. In that
187
+ // case the line information above represents one of the multiple
188
+ // symbols. This field must be recomputed when the symbolization state of the
189
+ // profile changes.
190
+ bool is_folded = 5;
191
+ }
192
+
193
+ message Line {
194
+ // The id of the corresponding profile.Function for this line.
195
+ uint64 function_id = 1;
196
+ // Line number in source code.
197
+ int64 line = 2;
198
+ }
199
+
200
+ message Function {
201
+ // Unique nonzero id for the function.
202
+ uint64 id = 1;
203
+ // Name of the function, in human-readable form if available.
204
+ int64 name = 2; // Index into string table
205
+ // Name of the function, as identified by the system.
206
+ // For instance, it can be a C++ mangled name.
207
+ int64 system_name = 3; // Index into string table
208
+ // Source file containing the function.
209
+ int64 filename = 4; // Index into string table
210
+ // Line number in source file.
211
+ int64 start_line = 5;
212
+ }