— modern ops stuff —
Managing Wavefront Source Tags from the CLI
13 October 2016 // Wavefront

Once again I’ve been back into the Wavefront CLI and Ruby SDK, adding more functionality. This time, the work was driven by a wish to have our EC2 instances tag themselves with things like account, instance type, the repository from which they take their configuration management code, or maybe the version of that code.

The Ruby SDK didn’t give you any help in doing this, so the first job was to extend the class offering wrappers around the appropriate API calls.

Once that was done (including tests of course!), I added a new source command to the CLI. As we use docopt to parse input, the hardest part of the job was coming up with a sensible interface. After a lot of thought and a couple of rewrites, I ended up with this.

$ wavefront source --help
  wavefront source list [-f format] [-at] [-T tag ...] [-s source] [-l limit] <pattern>
  wavefront source show [-f format] <host> ...
  wavefront source describe <description> [<host>] ...
  wavefront source undescribe [<host>] ...
  wavefront source tag add [-H host ... ] <tag> ...
  wavefront source tag delete [-H host ... ] <tag> ...
  wavefront source untag [<host>] ...

  -a, --all            including hidden sources in 'human' output
  -t, --tags           show tag counts in 'human' output
  -s, --start=STRING   start the list after the named source
  -l, --limit=NUMBER   only list NUMBER sources
  -H, --host=STRING    source to manipulate
  -f, --format=STRING  output format (ruby, json, human)
                       [default: human]

For the sake of clarity I’ve removed the global options from the output. These let you define your Wavefront endpoint, authentication token and so-on. (The beauty of docopt is that you only have to write the help message shown above as a block of text in your code, and it all those options and subcommands get magically populated.)

The general principle of the source command is to have the things you are setting (tags and descriptions) be arguments, and the things you are setting them on (hosts, or, techinically, “sources”), options. This way you can set multiple tags on multiple hosts with a single command.

If, when manipulating a tag or description, you don’t specify a source (or sources), then the CLI will assume you wish to refer the machine on which it is running. That way automated “tagging myself” jobs don’t need to keep shelling out to uname(1) or whatever.

Let’s do a few examples.

In my home lab I have a Solaris server called shark. It has a number of zones on it, whose names all begin shark-. Let’s list everything with shark in the name.

$ wavefront source list shark
HOSTNAME                  DESCRIPTION                    TAGS

The argument shark, is a pattern, which is passed straight through to Wavefront. It seems that there it is matched as a general regex, because without having to put .* or similar on the end of it, I’ve got all the shark zones for free. It’s not clear from that what’s what, so let’s quickly describe them

$ wavefront source describe -H shark 'general-purpose server'
setting 'shark' description to 'general-purpose server'
$ wavefront source describe -H shark-media 'minidlna server'
setting 'shark-media' description to 'minidlna server'
$ wavefront source describe -H shark-wavefront 'wavefront proxy'
setting 'shark-wavefront' description to 'wavefront proxy'
$ wavefront source list shark
HOSTNAME                  DESCRIPTION                    TAGS
shark                     general-purpose server
shark-media               minidlna server
shark-wavefront           wavefront proxy

That’s fine, but descriptions aren’t particularly useful. As far as I know you can’t do anything with them in the timeseries language. Let’s do some tags.

$ wavefront source tag add -H shark physical solaris
Tagging 'shark' with 'physical'
Tagging 'shark' with 'solaris'
$ wavefront source tag add -H shark-media -H shark-wavefront -H
shark-ws zone
Tagging 'shark-media' with 'zone'
Tagging 'shark-wavefront' with 'zone'
Tagging 'shark-ws' with 'zone'
$ wavefront source list shark
HOSTNAME                  DESCRIPTION                    TAGS
shark                     general-purpose server         physical
shark-media               minidlna server                zone
shark-wavefront           wavefront proxy                zone
shark-ws                                                 zone

Now, we can filter our ts() queries. Putting tag=physical to any ts() statement (as the second argument, just before closing the brackets) will only show data for the physical host. Zones will be ignored. Sources can have as many tags as you want, so you can create all manner of ways to cross-reference.

We incorporate our host’s product, enviroment, and role into our metric paths, but you might feel tagging is a better way to do that. Also tag by AZ, instance-type and it’s trivial to pull out JVM stats just for t2-medium Cassandra boxes in the eu-west-1 production environment.

You can take tags away just as you added them, by swapping add for delete, or remove all a source’s tags in one go with untag. Similarly, there’s an undescribe command, which doesn’t technically remove a description (the API doesn’t provide a method for that) but does set it to an empty string.

To see everything Wavefront knows about a particular source, ask the CLI to show it to you.

$ wavefront source show shark
  description    general-purpose server
  tags           physical

Revisiting the list command, you are likely to have a lot of sources. (We have over 150,000.) So, if you’re listing, you likely want to be careful with your pattern, or paginate. To help you do this, the list command provides --limit, to limit the number of sources it returns, and --start. The latter takes requires a source name, and when it is used, the command will return sources starting with the one after that which you supplied.

Requesting a source list in raw or json format will include hidden sources, but human format will not, unless you supply the -a option. The same goes for the tag count summary included in list output: to turn that on in human-readable mode, add -t.

$ wavefront source list -at shark
HOSTNAME                  DESCRIPTION                    TAGS
shark                     general-purpose server         physical
shark-media               minidlna server                zone
shark-wavefront           wavefront proxy                zone
shark-ws                                                 zone
shark-wslab                                              hidden

TAG                      COUNT
hidden                   339
physical                 1
zone                     3

It’s also possible to have the human-readable output only display sources which have a particular tag, or tags. To do this, use -T.