prometheus / prometheus/docs

Client library guidelines: Cannot enforce global state

Open
#506 8 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
717
Forks
1.2k
Avg merge
3d 15h
Merged PRs (30d)
19

Description

The client library guidelines contain the following sentence: "There MUST be a default CollectorRegistry, the standard metrics MUST by default implicitly register into it with no special work required by the user."

In most languages, that means to keep some global state or a singleton around. In other languages, it might be plainly impossible.

The real problem arises for languages that allow global state but it is highly frowned upon. Such a case is Go. The resistance against global state is very high (certainly higher than the resistance against dependencies, to draw a comparison, with the difference that it's mostly the whiners that are against dependencies, while the resistance against global state is lead by the most enlightened members of the community). While I find myself more in the "no global state" camp, I'm also a fan of giving options to the users, if need be let them chose their own poison. (One argument here is that they would anyway create wrappers to have global state again.) So the go client library allows both, work with the problematic global state and earn some convenience in exchange, or avoid the global state altogether. The library doesn't inflict any undue overhead on either camp. However, if auto-registration were the default, there would be special work required by the user to prevent interaction with the global state. That's a big no-no.

And then there is a completely different problem with Go: error handling. Registration can result in an error. The convenient way to create collector instances is in variable initialization. However in the var section, there cannot be any code to handle the error. The usual way out is MustRegister, i.e. panic in case of an error. That's fine for most. However, panicking in the var section is quite problematic (you won't even see one of your functions in the call stack), in particular because an unrelated change somewhere else (where another, but incompatible collector is registered) can suddenly cause a panic in the code that was fine so far. Panicking in this way is, as said, problematic, but doing so as default behavior, without calling it out (with the Must... idiom), is another big no-no.

We could go with a "MustRegister" method on the Collectors or a "MustRegisterWith" option, but even that would probably look weird for most experienced Go programmers, and it could still not do the registration by-default. (The default had to be to not register.)

Whatever the decision for the Go client will be, we have to soften the language in the quote above.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the quoted client library guideline and the discussion in this issue; compare it with the Go client's documented registration choices and error-handling constraints. Done when the guideline no longer mandates implicit global registration and clearly accommodates the Go behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
documentation
Issue type
Documentation
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.