-
Notifications
You must be signed in to change notification settings - Fork 230
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
Record stats for serialization time #1628
Conversation
@@ -382,6 +382,17 @@ | |||
_(result).must_equal(SUCCESS) | |||
end | |||
|
|||
it 'records metrics' do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of mocking the metrics reporter, we could move InMemoryMetricsReporter
from https://github.com/open-telemetry/opentelemetry-ruby/blob/2bcb4643b144300b0e18cba6ae61e93eb75bc5b0/exporter/zipkin/test/test_helper.rb#L43-L42 to opentelemetry-test-helpers
if reviewers would like.
@@ -77,7 +77,9 @@ def initialize(endpoint: nil, | |||
def export(span_data, timeout: nil) | |||
return FAILURE if @shutdown | |||
|
|||
send_bytes(encode(span_data), timeout: timeout) | |||
send_bytes( | |||
measure_encode_duration { encode(span_data) }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should inline measure_encode_duration
into the encode
method. We didn't do that with measure_request_duration
because the block it wraps is a stdlib method (@http.request(request)
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure thing
) | ||
end | ||
measure_encode_duration do | ||
Opentelemetry::Proto::Collector::Trace::V1::ExportTraceServiceRequest.encode( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just an indentation change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I was unclear in my earlier comment. I don't think we need measure_encode_duration
. We just need to ... measure the duration of the encode
method. I.e.
def encode(span_data) # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
Opentelemetry::Proto::Collector::Trace::V1::ExportTraceServiceRequest.encode(
Opentelemetry::Proto::Collector::Trace::V1::ExportTraceServiceRequest.new(
resource_spans: span_data
.group_by(&:resource)
.map do |resource, span_datas|
Opentelemetry::Proto::Trace::V1::ResourceSpans.new(
resource: Opentelemetry::Proto::Resource::V1::Resource.new(
attributes: resource.attribute_enumerator.map { |key, value| as_otlp_key_value(key, value) }
),
scope_spans: span_datas
.group_by(&:instrumentation_scope)
.map do |il, sds|
Opentelemetry::Proto::Trace::V1::ScopeSpans.new(
scope: Opentelemetry::Proto::Common::V1::InstrumentationScope.new(
name: il.name,
version: il.version
),
spans: sds.map { |sd| as_otlp_span(sd) }
)
end
)
end
)
)
rescue StandardError => e
OpenTelemetry.handle_error(exception: e, message: 'unexpected error in OTLP::Exporter#encode')
nil
ensure
stop = Process.clock_gettime(Process::CLOCK_MONOTONIC)
duration_ms = 1000.0 * (stop - start)
@metrics_reporter.record_value('otel.otlp_exporter.encode_duration',
value: duration_ms)
end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this makes more sense; I was on autopilot. Will make change.
220baee
to
e80c46d
Compare
e80c46d
to
e166308
Compare
ensure | ||
stop = Process.clock_gettime(Process::CLOCK_MONOTONIC) | ||
duration_ms = 1000.0 * (stop - start) | ||
@metrics_reporter.record_value('otel.otlp_exporter.encode_duration', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would y'all feel about adding a helper that accepts a block:
@metrics_reporter.record_duration(name, labels: labels) do
# your code we want to measure goes here
end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we do this one more time, it's worth a refactor. I am not super keen on the block-based approach if all our callsites are full methods. I think I'd prefer:
def foo
probe = start_probe('otel.otlp_exporter.foo')
...
ensure
probe.finish
end
over:
def foo
@metrics_reporter.record_duration('otel.otlp_exporter.foo') do
...
end
end
simply because it avoids deeper indentation as we add instrumentation to existing methods. The latter is better for measurements of small chunks of code within a larger method.
Serialization takes place during export and is a resource-intensive process; users may want to see how long it takes.
Remnants of earlier approach
I had to prove to myself that the value returned from a block passed to a block-handling function will be returned from the block-handling function even when there's anensure
in that function (I was worried that something from theensure
block would be returned). For documentation, I'll reproduce that experiment here:Given the RubyYields output: