Wandering Thoughts archives


A note on using the Go Prometheus client package to exposed labeled metrics

For reasons beyond the scope of this blog entry, I have been recently playing around adding some Prometheus metrics to a Go program through the official Prometheus Go client packages. The particular metrics I wanted to add were going to have labels:

scripts_requests_total { script="ntpdate" } 58
scripts_requests_total { script="sntp" }    112

How to do this is not entirely clear in the Prometheus client package documentation. You start by creating, say, a CounterVec, then some magic happens involving methods with names like With and CurryWith, and you finally have metrics that you can set, increment, and so on. After some head scratching I have finally figured out a mental model of this, and now I'm going to write it down before I forget it.

When you create a metric with labels by using, say, NewCounterVec(), what you really create is a template for the actual metrics you will wind up with. Your template specifies what the names of the labels are, but obviously it doesn't (and can't) specify what values the labels have for any particular metric. In order to actually get a specific metric, you must fill in values for all of the labels in some way, which creates a specific metric from your template. With a specific metric in hand, you can now manipulate it to, for example, count things. If you're working with metrics that have labels, you always have to perform this specialization step, even if you're only ever going to generate a single metric (for example, a 'scripts_build_info' metric where the point is the label values).

The Go package offers two ways of doing this specialization. First, you can create a Labels map that maps all of the label names to specific values, and then use .With() or .GetMetricWith(). Second, you can simply use .WithLabelValues() or .GetWithLabelValues() to list off all of the label values in the same order as you specified the labels themselves when you created the *Vec metric template. Which one you use depends on which is more convenient.

These metrics templates can also be partially specified, filling in some but not all label values. This is done with the .CurryWith() and .MustCurryWith() methods, which return a 'narrower' *Vec metric template. I can imagine several situations where this might be useful, but since I haven't used this in code yet I'm not going to write out my speculations here.

(I suspect that Prometheus client packages for other languages follow a similar model, but I haven't looked at them yet.)

Sidebar: An unfortunate limitation of promhttp

The Prometheus Go client packages include promhttp, which can generate metrics related to the HTTP requests that your program handles (and also to any HTTP requests it makes, with a separate set of functions). Unfortunately the instrumentation it provides doesn't have any way to customize the labels of the metrics on a per-request basis, and re-implementing what it's doing requires duplicating a bunch of un-exported HTTP middleware functionality that it contains.

For a non-hypothetical example, promhttp goes through a large amount of work to be able to capture the HTTP reply's status code and other response information. When I started looking through that code, I decided that the HTTP status wasn't quite important enough to put in my own metrics.

(The problem here is that a concrete instance of the http.ResponseWriter may support additional interfaces, like http.Flusher or http.CloseNotifier, and this support may be important to either your HTTP server code or things that your code calls. It's easy to implement a plain http.ResponseWriter in middleware, but then downstream code loses access to these additional interfaces.)

programming/GoPrometheusMetricLabels written at 22:08:38; Add Comment

What I want out of my window manager

One answer to what I want out of my window manager is 'fvwm'. It's my current window manager and I'm not likely to switch to anything else because I'm perfectly satisfied with it. But that's not a good answer, because fvwm has a lot of features and I'm not using them all. As with everyone who uses a highly customizable thing, my important subset of fvwm is probably not quite the same as anyone else's important subset of it.

(I'm thinking about what I want out of my window manager because Wayland is coming someday, and that means I'm almost certainly going to need a new window manager at some time in, say, the next ten years.)

I can't tell for sure what's important to me, because I'm sort of a fish in water when it comes to fvwm and my fvwm configuration; I've been using it exclusively for so long that I'm not certain what I'd really miss if I moved and what's unusual. With that said, I think that the (somewhat) unusual features that I want go like this (on top of a straightforward 'floating layout' window manager):

  • Something like FvwmIconMan, which is central to how I manage terminal windows (which I tend to have a lot of).

  • The ability to iconify windows to icons on the root window and then place those icons in specific locations where they'll stay. I also want to be able to record the location of those icons and reposition them back, because I do that. Putting iconified windows in specific places is how I currently manage my plethora of Firefox windows, including keeping track of what I'm going to read soon. As usual, icons need to have both an icon and a little title string.

    (Perhaps I should figure out a better way to handle Firefox windows, one that involves less clutter. I have some thoughts there, although that's for another entry. But even with Firefox handled, there are various other windows I keep around in iconified form.)

  • Multiple virtual desktops or screens, with some sort of pager to show me a schematic view of what is on what screen or desktop and to let me switch between them by the mouse. I also need key bindings to flip around between screens. It has to be possible to easily move windows (in normal or iconified form) from screen to screen, including from the command line, and I should be able to set it so that some icons or windows are always present (ie, they float from screen to screen).

  • Window title bars that can be either present or absent, because some of my windows have them and some don't. I'd like the ability to customize what buttons a window titlebar has and what they do, but it's not really important; I could live with everything with a titlebar having a standard set.

  • User-defined menus that can be brought up with a wide variety of keys, because I have a lot of menus that are bound to a lot of different keys. My fvwm menus are one of my two major ways of launching programs, and I count on having a lot of different key bindings to make them accessible without having to go through multiple menu levels.

  • User-defined key bindings, including key bindings that still work when the keyboard focus is on a window. Key bindings need to be able to invoke both window manager functions (like raising and lowering windows) and to run user programs, especially dmenu.
  • User-defined bindings for mouse buttons, because I use a bunch of them.

  • Minimal or no clutter apart from things that I specifically want. I don't want the window manager insisting that certain interface elements must exist, such as a taskbar.

  • What fvwm calls 'focus follows mouse', where the keyboard focus is on the last window the mouse was in even if the mouse is then moved out to be over the root window. I don't want click to focus for various reasons and I now find strict mouse focus to be too limiting.

Fvwm allows me great power over customizing the fonts used, the exact width of window borders, and so on, but for the most part it's not something I care deeply about if the window manager does a competent job and makes good choices in general. It's convenient if the window manager has a command interface for testing and applying small configuration changes, like FvwmConsole; restarting the window manager when you have a lot of windows is kind of a pain.

(As you might guess from my priorities, my fvwm configuration file is almost entirely menu configurations, key and mouse button bindings, and making FvwmIconMan and fvwm's pager work right. I have in the past tried tricky things, but at this point I'm no longer really using any of them. All of my vaguely recent changes have been around keyboard bindings for things like moving windows and changing sound volume.)

PS: Command line interface and control of the window manager would be pretty handy. I may not use FvwmCommand very often, but I like that it's there. And I do use the Perl API for my hack.

Sidebar: Fvwm's virtual screens versus virtual desktops

Fvwm has both virtual screens and virtual desktops, and draws a distinction between them that is covered in the relevant section of its manpage. I use fvwm's virtual screens but not its desktops, and in practice I treat every virtual screen as a separate thing. It can sometimes be convenient that a window can spill over from virtual screen to virtual screen, since it often gives me a way of grabbing the corner of an extra-large window. On the other hand, it's also irritating when a window winds up protruding into another virtual screen.

All of this is leading up to saying that I wouldn't particularly object to a window manager that had only what fvwm would call virtual desktops, without virtual screens. This is good because I think that most modern window managers have adopted that model for their virtual things.

unix/WindowManagerWants written at 00:39:19; Add Comment

Page tools: See As Normal.
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.