# Seshat

Seshat is a counters registry that maintains counter references with associated
meta data about what each counter refers to. Makes it easy to export counters
in a format suitable for external export to, e.g. [prometheus](

Seshat is a foundation for the future metrics subsystem in RabbitMQ.

## Project Maturity


## Documentation

### First create a new seshat group

A group in seshat is some logical partitioning of counters. E.g. you may have
a group per erlang application, or some subcomponent of your system.
    GroupRef = seshat:new_group(pets),

A group is essentially en ETS table where counters and their meta data will be
stored. The `GroupRef` is an opaque type (but really it is an `ets:tid()`. The 
group can be any `term()` but it makes sense to just use atoms. Keep stuff tidy folks.

Now we're ready to register some counters. 

    -define(C_CARROTS_EATEN, 1),
    -define(C_HOLES_DUG, 2),
    Fields = [{carrots_eaten_total, ?C_CARROTS_EATEN, counter,
                "Total number of carrots eaten on a meal"},
              {holes_dug_total, ?C_HOLES_DUG, counter,
               "Total number of holes dug in an afternoon"}],
    Name = rabbit,
    CountersRef = seshat:new(pets, Name, Fields),

The `CountersRef` is a `counters:counters_ref()` type and can use used as usual
with the counters module. The `CountersRef` can be stored in the state of a
stateful erlang module or be retrieved using `sesaht:fetch(Group, Name)`

    counters:add(CountersRef, ?C_CARROTS_EATEN, 3),

To inspect the counters on the system for a given group do:

    Overview = seshat:overview(pets),

Overview is a map of `#{Name => #{FieldName, Count}}`. E.g. for the above
it would look like:

    #{rabbit => #{carrots_eaten_total => 3, holes_dug_total => 0}}

There is also `seshat:format(Groups)` which for the above case will return:

    #{carrots_eaten_total =>
        #{help => "Total number of carrots eaten on a meal",
          type => counter,
          values => #{rabbit => 3}},
      holes_dug_total =>
        #{help => "Total number of holes dug in an afternoon",
          type => counter,
          values => #{rabbit => 0}}}

This format uses the counter `Name` as a unique value label for the metrics.
This formatting is more suitable for e.g. prometheus export. The counter name
doesn't have to be an atom. It can also be a list of two-tuples or
a pre-formatted binary.

## Copyright and License

(c) 2022, VMware Inc or its affiliates.

Double licensed under the ASL2 and MPL2.0.
See [LICENSE](./LICENSE) for details.