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

Adds method and optional status Labels to PrometheusBackend #1651

Merged
merged 15 commits into from
Jan 9, 2023

Conversation

kevinmeredith
Copy link
Contributor

@kevinmeredith kevinmeredith commented Dec 4, 2022

Adds method and optional status labels to PrometheusBackend. At work, I was missing these labels out of the box. Having worked on-call in production for 3.5 years, I've found HTTP Methods and Status Codes to be valuable to understand running web services.

As a result, I opened this PR.

I completed the following for the observability/prometheus-backend project. I'm assuming CI/CD will run the overall compile and test.

Before submitting pull request:

  • Check if the project compiles by running sbt compile
  • Verify docs compilation by running sbt compileDocs
  • Check if tests pass by running sbt test
  • Format code by running sbt scalafmt

It's easier to understand explicit field names with a class than via the hard-to-follow _.X methods.
@kevinmeredith kevinmeredith marked this pull request as draft December 4, 2022 04:32
@kevinmeredith kevinmeredith marked this pull request as ready for review December 4, 2022 04:54
@kevinmeredith kevinmeredith changed the title draft/WIP: Prometheus addition Adds method and optional status Labels to PrometheusBackend Dec 4, 2022
(r: (Request[_, _], Throwable)) => requestToFailureCounterMapper(r._1, r._2),
requestToSizeSummaryMapper,
(rr: (Request[_, _], Response[_])) => responseToSizeSummaryMapper(rr._1, rr._2),
(req: Request[_, _]) => requestToHistogramNameMapper(req).map(addLabelPairs(_, req, None)),
Copy link
Member

Choose a reason for hiding this comment

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

as I understand, this will always add the labels (if they are not present). So it's not possible not to add them - if somebody, for some reason would want that.

Maybe, instead we could modify the default values of parameters in apply so that the user has chance to fully override the behavior?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

as I understand, this will always add the labels (if they are not present)

Correct

Maybe, instead we could modify the default values of parameters in apply so that the user has chance to fully override the behavior?

In my 3.5 years of prod on-call, I always found method and status labels to be helpful.

That being said, I'll defer to you and implement this change, i.e. update the default's to consist of method and, optionally, status.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done - ec2ca4a

* BaseCollectorConfig sub-type. Note that PrometheusBackend#apply and PrometheusListener's constructor reference
* the sub-types of BaseCollectorConfig.
*/
def addLabelPairs(config: BaseCollectorConfig, req: Request[_, _], maybeResp: Option[Response[_]]): config.T = {
Copy link
Member

Choose a reason for hiding this comment

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

Maybe a better name would be sth like addMethodStatusLabels? It would reflect more clearly what it does

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good call - will add.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done - d802a5d

@@ -90,7 +143,7 @@ object PrometheusBackend {
cache.getOrElseUpdate(collectorRegistry, new ConcurrentHashMap[String, T]())
}

type RequestCollectors = (Option[Histogram.Timer], Option[Gauge.Child])
final class RequestCollectors(val maybeTimer: Option[Histogram.Timer], val maybeGauge: Option[Gauge.Child])
Copy link
Member

Choose a reason for hiding this comment

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

maybe a case class? also, the optionality is already expressed in the types, so I'd just use timer / gauge

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Side comment: I tend to avoid case if there's no need for equality, i.e. class w/ val's meets the bare minimum.

But, adding case is a trivial addition, so I'm happy to add.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done - 7870222

* BaseCollectorConfig sub-type. Note that PrometheusBackend#apply and PrometheusListener's constructor reference
* the sub-types of BaseCollectorConfig.
*/
def addLabelPairs(config: BaseCollectorConfig, req: Request[_, _], maybeResp: Option[Response[_]]): config.T = {
Copy link
Member

Choose a reason for hiding this comment

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

also, maybe a different signature, without the type member: def addLabelPairs[T <: BaseCollectorConfig](cfg: T, ...)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep - let me add that. config.T is a bit ugly, I agree.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done - 2e97286. Not sure the T#T is any better. Let me know, please.

@adamw
Copy link
Member

adamw commented Dec 7, 2022

Thanks! I left some comments inline. We should probably make similar changes to the opentelemetry backend (either here or in a separate follow-up issue)

@kevinmeredith
Copy link
Contributor Author

A few tests are still failing locally for me:

[info] PrometheusBackendTest:
[info] prometheus
[info] - should use default histogram name (120 milliseconds)
[info] - should allow creating two prometheus backends (2 milliseconds)
[info] - should use mapped request to histogram name (4 milliseconds)
[info] - should use mapped request to histogram name with labels and buckets (5 milliseconds)
[info] - should use mapped request to gauge name with labels (6 milliseconds)
[info] - should disable histograms (1 millisecond)
[info] - should use default gauge name *** FAILED *** (15 seconds, 111 milliseconds)
[info]   The code passed to eventually never returned normally. Attempted 107 times over 15.070412125 seconds. Last failure message: The Option on which value was invoked was not defined.. (PrometheusBackendTest.scala:165)
[info] - should use mapped request to gauge name *** FAILED *** (15 seconds, 95 milliseconds)
[info]   The code passed to eventually never returned normally. Attempted 106 times over 15.081156 seconds. Last failure message: The Option on which value was invoked was not defined.. (PrometheusBackendTest.scala:196)
[info] - should disable gauge *** FAILED *** (15 seconds, 94 milliseconds)
[info]   The code passed to eventually never returned normally. Attempted 107 times over 15.075386708 seconds. Last failure message: The Option on which value was invoked was not defined.. (PrometheusBackendTest.scala:228)
[info] - should use default counter name (46 milliseconds)
[info] - should not override user-supplied 'method' and 'status' labels (9 milliseconds)
[info] - should use default summary name (14 milliseconds)
[info] - should use error counter when http error is thrown (23 milliseconds)
[info] - should use failure counter when other exception is thrown (4 milliseconds)
[info] - should use success counter on success response (1 millisecond)

I'm suspicious that they are flaky, but I'll review again another day.

@kevinmeredith
Copy link
Contributor Author

If anything stands out to you, @adamw, on the cause(s) of the failures on #1651 (comment), let me know, please! Thanks

@adamw adamw merged commit 212a79c into softwaremill:master Jan 9, 2023
@adamw
Copy link
Member

adamw commented Jan 9, 2023

@kevinmeredith thanks!

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.

2 participants