Graphite dashboard system
Ruby JavaScript
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
bin Trailing whitespace Jun 8, 2012
lib Use module Pencil::Helpers in lieu of module Pencil ... module Helpers Jun 29, 2012
LICENSE Preliminary gem format Jun 18, 2011 Make a note about rewrite branch in current README Dec 20, 2012
Rakefile add Rakefile for helping with gem. Dec 7, 2011
pencil.gemspec Unpin sinatra dependency Jun 5, 2012


NOTE If you are checking out pencil for the first time you should check out the rewrite branch (in beta) which has lots of nice updates.

pencil is a monitoring frontend for graphite. It runs a webserver that dishes out pretty graphite urls in hopefully interesting and intuitive layouts.

Some features are:

  • Easy configuration

    Pretty much anything you'd want to do with the graphite composer can be coded into pencil configs using YAML syntax.

  • Implicit collection of host and cluster data

    pencil picks these up from graphite without you having to explicitly define them. You need only supply the metrics; see for configuration details.

  • Relative and absolute timespecs with auto-refresh

    Timeslices are measured in terms of a (possibly relative) starting time and a duration. Timespecs are parsed using the chronic and chronic_duration gems.

    You can use pencil in "tail-mode" (i.e. constant refresh, looking at last couple hours of data) or to view a particular timeslice in the past.

  • time-quantum support

    Requests can be mapped into discrete intervals (e.g.. 30 seconds) so that all requests within a window are treated as if they are the same request. This eases the burden on graphite to generate real-time images that are only slightly different than those generated by earlier requests. It also makes it easy to add some sort of caching layer.

  • permalinks

    Turn a relative timeslice (such as the last 8 hours) into an absolute one for placing in bug reports and all sorts of other useful things.

  • Lots of views and navigation UI for bouncing around them

    Global, cluster, dashboard, and host views!


gem install pencil

Dependencies are:

  • rack
  • sinatra
  • mongrel
  • json
  • chronic
  • chronic_duration
  • (fixme versions)


You should have a working graphite installation. Your metrics need to be composed of three pieces:

  • "%m", METRIC (the common part of each graphite path)
  • "%c", CLUSTER (cluster name, varies with query, must not contain periods)
  • "%h", HOST (host name, varies with query, must not contain periods)

The :metric_format string is specified in a configuration file (see below), and defaults to %m.%c.%h". It should contain only one %m, but is otherwise mostly unrestricted.

You need to set up YAML configuration files in order for pencil to work. Pencil searches the current directory (or, with -d DIR, DIR) for YAML files to load.

The important top-level configuration keys are:

  • :config:
  • :graphs:
  • :dashboards:

See examples/ for an example configuration directory. Here's an example pencil.yml, which contains general configuration options:

  :graphite_url URL # graphite URL
    :width: 1000
    :height: 400
    :fontSize: 15
    :start: "8 hours ago"  # in chronic timespec format
    :template: "noc"
    :yMin: 0
    :margin: 5
    :thickness: 2

  :refresh_rate: 60        # how often to refresh the view
  :host_sort: "numeric"    # add this if you want to sort hosts numerically
  :quantum: 30             # map requests to 30 second intervals
  :date_format: "%X %x"    # strftime
  :metric_format: "%m.%c.%h" #%m metric, %c cluster, %h host

A graph is a name, title, collection of targets, and some other options. A target is a metric => options map; see docs/ for details on supported options. It looks like (in YAML):

graph_name:             # name pencil references this graph by
  title: "graph_title"  # title displayed on graph
  targets:              # list of graphite targets
      :key: key         # key displayed on the legend for this metric
      :color: color     # color on the graph for this metric
      :key: key
      :color: color
  hosts: ["hosts1*", "test*_web", "hosts2*"] # filter on hosts
  areaMode: stacked

(Note that in any case where you would use a hash you may use an omap instead, to ensure the order in which options are applied)

Graph-level options are applied to the graph as a whole, where target-level options apply only to the specific target.

Similarly, a dashboard is a name, title, collection of graphs, and some other options. It looks like (in YAML):

  title: dash_title
    - graph1:
      hosts: ["sync*_web"] # hosts filter specific to this graph
      other_opt: val       # possibly other options in the future
    - graph2:
  hosts: ["filter1*", "*filter2"]

A graph is just a graph name => options hash. Options specified in a dashboard for a graph override the options in the original graph's definition when displaying the dashboard.

Pencil loads all the yaml files in its configuration directory and subdirectories. To facilitate organization of graphs and dashboards into multiple files the :graphs and :dashboards top-level keys are merged recursively during the load. The resulting pencil data structure will include all graphs and dashboards defined under these keys.

A few words on host filters: two wildcards are supported: "" and "#". "" consumes as /.*/ (like a shell wildcard) and "#" as /\d+/ (one or more digits). Be aware that "#" may require explicit enumeration in graphite URLs (and is currently implemented in this way) and you might have to configure Apache to accept longer URLs if you have many hosts that match a "#".

complex metrics and dashboard graph-level options

A simple target is just a metric => options map. Targets can also be complex, where the key is an ordered list of simple targets. This is useful, for example, if you want to graph the summation of a list of metrics (see docs/ for a list of supported transforms). Complex targets are denoted with the YAML's ? : complex-key syntax, and look like this:

  title: "memory usage"
    ? -
          opt1: value
      - system.memory.cached:
      - system.memory.shared:
      - system.memory.buffers:
      :key: "memory used"
      :color: green

As you can see, the memory used is computed by taking the difference of the total memory and its many uses.


Once you've set up the configs, you should be able to just run


and get something up on localhost:9292

From there you should be able to click around and see various interesting collections of graphs.

With no options, pencil looks in the current directory for YAML files and loads them.

You can bind to a specific port with -p PORT and specify a configuration directory with -d DIR. Other rack-related options will be added at some point in the future.