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

WIP: Implement Prometheus statser #355

Closed
wants to merge 6 commits into from

Conversation

0xYao
Copy link

@0xYao 0xYao commented Oct 31, 2020

Currently working on #284.

@atlassian-cla-bot
Copy link

atlassian-cla-bot bot commented Oct 31, 2020

Hooray! All contributors have signed the CLA.

)

// TODO: now I have setup the Prometheus metric objects, how do I integrate with gostatsd internal metrics measuring
// tools? How do I run this file, and start writing some tests for this. Need to adhere to the project testing styles.
Copy link
Collaborator

Choose a reason for hiding this comment

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

The expected interface is a stats.Statser (https://github.com/atlassian/gostatsd/blob/master/pkg/stats/statser.go), and you can embed a stats.flushNotifier to take care of the RegisterFlush and NotifyFlush calls.

You'll likely need to lazily create metrics on-demand and store them in a map - gostatsd doesn't have any arbitrary metrics, so you don't need to worry about removing things from the map. The map can be protected with an RWMutex, since after warmup, it will be very rare (if ever), that additional metrics are created.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also, there's basically no testing of the actual Statsers. There is a bit for pkg/web, but it's acceptable to just make sure you get a 200 return code when it's expected.

}
}

func (ps *PrometheusStatser) NotifyFlush(ctx context.Context, d time.Duration) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

You don't need to implement NotifyFlush and RegisterFlush, it's picked up implicitly from the embedded flushNotifier

Copy link
Author

Choose a reason for hiding this comment

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

How come the TaggedStatser implements those two functions or why does TaggedStatser not use a flushNotifier as one of its attributes?

Copy link
Collaborator

Choose a reason for hiding this comment

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

My bad, that comments from my personal account.

The TaggedStatser is a wrapper that explicitly calls to the wrapped Statser.

It shouldn't use a flushNotifier directly, because then the TaggedStatser and the underlying Statser would have different notification targets (and ultimately MetricFlusher.Run would only call NotifyFlush on the underlying Statser)

That being said, it could and probably should use an embedded Statser and remove the explicit implementation.

Copy link
Author

Choose a reason for hiding this comment

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

Oh, I see that now, what was the design process behind, is it because that they have different notification targets, so one such as TaggedStatser is a wrapper of Statser but InternalStatser is not a wrapper because they have the same notification targets?

I am using the GoLand IDE, and I am trying to find the usage of NotifyFlush, for some reason I cannot see any call to this method outside of the statsers and the flush_notifer.

Copy link
Collaborator

Choose a reason for hiding this comment

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

There was no special design considerations behind TaggedStatser not embedding the Statser, it's possible at the time that I thought you could only embed a struct in a struct, and an interface in an interface, but not an interface in a struct, I don't recall for sure though.

InternalStatser does explicitly implement NotifyFlush however, as it needs to take action on the flush before returning. Flush notification is an asynchronous, best effort action, and any metrics triggered by it are processed in the next flush cycle.

The InternalStatser however explicitly needs to process the metrics in the current flush cycle, so it takes action (dispatching internal metrics) before returning.

I'm not sure why GoLand doesn't detect usage - it does in my setup. You could try rebuilding the index through File -> Invalidatae Caches / Restart, but I don't know if it will help.

The only place it's called is at https://github.com/atlassian/gostatsd/blob/master/pkg/statsd/flusher.go#L69

Copy link
Author

Choose a reason for hiding this comment

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

My problem was I was not aware that the Statser interface also has a NotifyFlush method, I was only trying to find the usage of NotifyFlush from the flsuhNotifier struct.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ahhh, that would do it :)

type PrometheusStatser struct {
flushNotifier

// collector of gauges that stores the internal gauge metrics of gostatsd
Copy link
Collaborator

Choose a reason for hiding this comment

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

Each GaugeVec and CounterVec is a single metric name, they need to be lazily created.

Copy link
Author

Choose a reason for hiding this comment

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

Does it make sense to use the Gauges and Counter structs gostatsd already provides or would using the structs provided from the prometheus package be better?

Copy link
Collaborator

Choose a reason for hiding this comment

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

You'd need to use the ones from the prometheus packages, because they're ultimately added to the prometheus registry.


// TODO: how do I use tags here, same for the Count and the TimingMS methods
func (ps *PrometheusStatser) Gauge(name string, value float64, tags gostatsd.Tags) {
ps.gaugeVec.WithLabelValues(name).Add(value)
Copy link
Collaborator

Choose a reason for hiding this comment

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

The tags map to labels

@tiedotguy
Copy link
Collaborator

Just as an aside, I believe prom uses snake_case to name its metric, not dotted.case - you should have a place where there's a basic strings.Replace to change . to _

@0xYao 0xYao closed this Oct 1, 2021
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