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

Support duration and float metrics #223

Merged
merged 2 commits into from
Apr 19, 2024
Merged

Conversation

cretz
Copy link
Member

@cretz cretz commented Apr 16, 2024

What was changed

  • Allow MetricMeter.CreateHistogram to provide floating point types or TimeSpan in addition to already-supported integer types
  • Allow MetricMeter.CreateGauge to provide floating point types in addition to already-supported integer types
  • Added OpenTelemetryOptions.UseSecondsForDuration option to have OTel metrics use float seconds instead of ms
  • Added PrometheusOptions.UseSecondsForDuration option to have Prom metrics use float seconds instead of ms
  • ICustomMetricMeter.CreateHistogram now supports double and TimeSpan (for those creating custom meter impls)
    • Minor 💥 compat break, but only if the caller starts creating histograms for floats/durations or sets non-default duration format option
  • ICustomMetricMeter.CreateGauge now supports double (for those creating custom meter impls)
    • Minor 💥 compat break, but only if the caller starts creating gauges for floats
  • Added MetricsOptions.CustomMetricMeterOptions which accepts an option type whose only field is HistogramDurationFormat to specify whether meter impls will get duration metrics as integer milliseconds, float seconds, or time spans
  • Tests

Checklist

  1. Closes [Feature Request] Support metric option for using seconds (and other recent core metric changes) #209

@cretz cretz requested a review from a team April 16, 2024 20:44
@cretz cretz force-pushed the metric-duration branch from 24e8346 to 54687c5 Compare April 16, 2024 20:56
Copy link
Member

@Sushisource Sushisource left a comment

Choose a reason for hiding this comment

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

Looking good. Dang C# has some nice bits but it is verboooooossseeee.

{
// Have to convert TimeSpan to something .NET meter can work with. For this to even
// happen, a user would have had to set custom options to report as time span.
if (typeof(T) == typeof(TimeSpan))
Copy link
Member

Choose a reason for hiding this comment

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

This whole non-erased generic type check thing feels deeply illegal to me 😆

Copy link
Member Author

Choose a reason for hiding this comment

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

Reified generics are so nice in .NET compared to Java's type erasure. This is why you can call AddWorkflow<MyWorkflowClass>() and similar. But there are some downsides.

@@ -51,18 +51,44 @@ internal class MetricInteger : SafeHandle
/// </summary>
/// <param name="value">Value to record.</param>
/// <param name="attributes">Attributes to set.</param>
public void Record(ulong value, MetricAttributes attributes)
public void RecordInteger(ulong value, MetricAttributes attributes)
Copy link
Member

Choose a reason for hiding this comment

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

Rather than allowing all record kinds on one Metric type it seems like it'd be pretty easy to hand out specialized versions with only one record method each corresponding to the kind passed in when created

Copy link
Member Author

Choose a reason for hiding this comment

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

This is not public user-facing code. We do it in a .NET idiomatic way when it comes to the actual user-facing code. But it is nice for the C FFI if we do combine these into fewer calls and expect the caller be smart.

let meter = &*(self.meter_impl.0);
(meter.metric_record_duration)(
self.metric,
value.as_millis().try_into().unwrap_or(u64::MAX),
Copy link
Member

Choose a reason for hiding this comment

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

I can't decide in the rare case that this happens if it's better to record this max or simply not record anything at all

Copy link
Member Author

@cretz cretz Apr 18, 2024

Choose a reason for hiding this comment

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

I was stuck a bit here too and just settled on this. Hopefully the issue never arises. But if we think it's enough of an issue, we can look info logging instead.

This gets even worse when we convert back to .NET types because. E.g. for .NET a ulong (i.e. u64) is "not CLS-compliant", so it's best to use long (i.e. i64) instead, so I limit to max there too (default unchecked cast wraps into negative). This is much more likely of a problem, but I can't currently think of a case where Core side will go over max-i64.

@cretz cretz merged commit 1573d3a into temporalio:main Apr 19, 2024
6 checks passed
@cretz cretz deleted the metric-duration branch April 19, 2024 12:51
@cretz
Copy link
Member Author

cretz commented Apr 19, 2024

@Sushisource - merged based on approval (waited a day after my most recent comment responses), but we can revisit any of the pieces if you think they are important.

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.

[Feature Request] Support metric option for using seconds (and other recent core metric changes)
2 participants