<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Bébhinn Egan</title>
    <description>The latest articles on Forem by Bébhinn Egan (@bbhnn).</description>
    <link>https://forem.com/bbhnn</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F203424%2F9cdf34cb-97b4-445a-9595-aaffabe06a07.jpg</url>
      <title>Forem: Bébhinn Egan</title>
      <link>https://forem.com/bbhnn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/bbhnn"/>
    <language>en</language>
    <item>
      <title>Pandora's Flask: Monitoring a Python web app with Prometheus</title>
      <dc:creator>Bébhinn Egan</dc:creator>
      <pubDate>Mon, 19 Aug 2019 11:08:37 +0000</pubDate>
      <link>https://forem.com/bbhnn/pandora-s-flask-monitoring-a-python-web-app-with-prometheus-540p</link>
      <guid>https://forem.com/bbhnn/pandora-s-flask-monitoring-a-python-web-app-with-prometheus-540p</guid>
      <description>&lt;p&gt;Originally posted on &lt;a href="https://www.metricfire.com/prometheus-tutorials/monitoring-python-web-app"&gt;Metricfire&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We eat lots of our &lt;a href="https://en.wikipedia.org/wiki/Eating_your_own_dog_food#Origin_of_the_term"&gt;own dogfood&lt;/a&gt; at &lt;a href="https://www.metricfire.com/"&gt;Metricfire&lt;/a&gt;, monitoring our services with a dedicated cluster running the same software.&lt;/p&gt;

&lt;p&gt;This has worked out really well for us over the years: as our own customer, we quickly spot issues in our various ingestion, storage and rendering services. It also drives the &lt;a href="https://www.atlassian.com/blog/statuspage/system-metrics-transparency"&gt;service status transparency&lt;/a&gt; our customers love.&lt;/p&gt;

&lt;p&gt;Recently we’ve been working on a new &lt;a href="https://prometheus.io/"&gt;Prometheus&lt;/a&gt; offering. Eating the right dogfood here means integrating Prometheus monitoring with our (mostly &lt;a href="https://www.hostedgraphite.com/blog/developing-and-deploying-python-in-private-repos"&gt;Python&lt;/a&gt;) backend stack.&lt;/p&gt;

&lt;p&gt;This post describes how we’ve done that in one instance, with a fully worked example of monitoring a simple &lt;a href="http://flask.pocoo.org/"&gt;Flask&lt;/a&gt; application running under &lt;a href="https://uwsgi-docs.readthedocs.io/"&gt;uWSGI&lt;/a&gt; + &lt;a href="https://www.nginx.com/"&gt;nginx&lt;/a&gt;. We’ll also discuss why it remains surprisingly involved to get this right.&lt;/p&gt;

&lt;h1&gt;
  
  
  A little history
&lt;/h1&gt;

&lt;p&gt;Prometheus' ancestor and main inspiration is &lt;a href="https://landing.google.com/sre/sre-book/chapters/practical-alerting/"&gt;Google's Borgmon&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In its native environment, Borgmon relies on ubiquitous and straightforward &lt;a href="https://en.wikipedia.org/wiki/Service_discovery"&gt;service discovery&lt;/a&gt;: monitored services are managed by &lt;a href="https://ai.google/research/pubs/pub43438"&gt;Borg&lt;/a&gt;, so it’s easy to find e.g. all jobs running on a cluster for a particular user; or for more complex deployments, all sub-tasks that together make up a job.&lt;/p&gt;

&lt;p&gt;Each of these might become a single target for Borgmon to scrape data from via /varz endpoints, analogous to Prometheus’ /metrics. Each is typically a multi-threaded server written in C++, Java, Go, or (less commonly) Python.&lt;/p&gt;

&lt;p&gt;Prometheus inherits many of Borgmon's assumptions about its environment. In particular, client libraries assume that metrics come from various libraries and subsystems, in multiple threads of execution, running in a shared address space. On the server side, Prometheus assumes that one target is one (probably) multi-threaded program.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why did it have to be snakes?
&lt;/h1&gt;

&lt;p&gt;These assumptions break in many non-Google deployments, particularly in the Python world. Here it is common (e.g. using &lt;a href="https://www.djangoproject.com/"&gt;Django&lt;/a&gt; or &lt;a href="http://flask.pocoo.org/"&gt;Flask&lt;/a&gt; to run under a &lt;a href="https://wsgi.readthedocs.io/en/latest/what.html"&gt;WSGI&lt;/a&gt; application server that spreads requests across multiple workers, each of which is a process rather than a thread.&lt;/p&gt;

&lt;p&gt;In a naive deployment of the Prometheus &lt;a href="https://github.com/prometheus/client_python"&gt;Python client&lt;/a&gt; for a Flask app running under uWSGI, each request from the Prometheus server to /metrics can hit a different worker process, each of which exports its own counters, histograms, etc. The resulting monitoring data is garbage.&lt;/p&gt;

&lt;p&gt;For example, each scrape of a specific counter will return the value for one worker rather than the whole job: the value jumps all over the place and tells you nothing useful about the application as a whole.&lt;/p&gt;

&lt;h1&gt;
  
  
  A solution
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://echorand.me/"&gt;Amit Saha&lt;/a&gt; discusses the same problems and various solutions in a &lt;a href="https://echorand.me/your-options-for-monitoring-multi-process-python-applications-with-prometheus.html"&gt;detailed writeup&lt;/a&gt;. We follow option #2: the Prometheus Python client includes a &lt;a href="https://github.com/prometheus/client_python#multiprocess-mode-gunicorn"&gt;multiprocess mode&lt;/a&gt; intended to handle this situation, with &lt;a href="https://gunicorn.org/"&gt;gunicorn&lt;/a&gt; being the motivating example of an application server.&lt;/p&gt;

&lt;p&gt;This works by sharing a directory of &lt;a href="https://github.com/prometheus/client_python/blob/624bb61e6f15e0c3739fec853edaea2b91d1674f/prometheus_client/mmap_dict.pyhttps://github.com/prometheus/client_python/blob/624bb61e6f15e0c3739fec853edaea2b91d1674f/prometheus_client/mmap_dict.py"&gt;mmap()'d dictionaries&lt;/a&gt; across all the processes in an application. Each process then does the maths to return a shared view of the whole application's metrics when it is scraped by Prometheus.&lt;/p&gt;

&lt;p&gt;This has some "headline" &lt;a href="https://github.com/prometheus/client_python#multiprocess-mode-gunicorn"&gt;disadvantages listed in the docs&lt;/a&gt;: no per-process Python metrics for free, lack of full support for certain metric types, a slightly complicated Gauge type, etc.&lt;/p&gt;

&lt;p&gt;It's also difficult to configure end-to-end. Here's what's necessary &amp;amp; how we achieved each part in our environment; hopefully this &lt;a href="https://github.com/hostedgraphite/pandoras_flask"&gt;full example&lt;/a&gt; will help anyone doing similar work in the future.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The shared directory must be passed to the process as an environment variable, &lt;em&gt;prometheus_multiproc_dir&lt;/em&gt;. No problem: we use uWSGI's &lt;a href="https://uwsgi-docs.readthedocs.io/en/latest/Options.html#env"&gt;env&lt;/a&gt; option to pass it in: see &lt;a href="https://github.com/hostedgraphite/pandoras_flask/blob/master/conf/uwsgi.ini#L13"&gt;uwsgi.ini&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The client’s shared directory must be cleared across application restarts. This was a little tricky to figure out. We use one of uWSGI's &lt;a href="https://uwsgi-docs.readthedocs.io/en/latest/Hooks.html#the-hookable-uwsgi-phases"&gt;hardcoded hooks&lt;/a&gt;, exec-asap, to &lt;a href="https://uwsgi-docs.readthedocs.io/en/latest/Hooks.html#exec-run-shell-commands"&gt;exec a shell script&lt;/a&gt; right after reading the configuration file and before doing anything else. See &lt;a href="https://github.com/hostedgraphite/pandoras_flask/blob/master/conf/uwsgi.ini#L14"&gt;uwsgi.ini&lt;/a&gt;. Our script &lt;a href="https://github.com/hostedgraphite/pandoras_flask/blob/master/bin/clear_prometheus_multiproc"&gt;removes &amp;amp; recreates&lt;/a&gt; the Prometheus client's shared data directory. In order to be sure of the right permissions, we run uwsgi under &lt;a href="http://supervisord.org/"&gt;supervisor&lt;/a&gt; as root and &lt;a href="https://github.com/hostedgraphite/pandoras_flask/blob/master/conf/uwsgi.ini#L18"&gt;drop privs&lt;/a&gt; within uwsgi.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The application must set up the Python client’s multiprocess mode. This is mostly a matter of &lt;a href="https://github.com/prometheus/client_python#multiprocess-mode-gunicorn"&gt;following the docs&lt;/a&gt;, which we did via &lt;a href="https://echorand.me/your-options-for-monitoring-multi-process-python-applications-with-prometheus.html"&gt;Saha's post&lt;/a&gt;: see &lt;a href="https://github.com/hostedgraphite/pandoras_flask/blob/master/pandoras_flask/metrics.py"&gt;metrics.py&lt;/a&gt;. Note that this includes some neat &lt;a href="https://github.com/hostedgraphite/pandoras_flask/blob/master/pandoras_flask/metrics.py#L17"&gt;middleware&lt;/a&gt; exporting Prometheus metrics for response status and latency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;uWSGI must set up the application environment so that applications load after &lt;em&gt;fork()&lt;/em&gt;. By default, uWSGI attempts to save memory by loading the application and then &lt;em&gt;fork()'ing&lt;/em&gt;. This indeed has &lt;a href="https://en.wikipedia.org/wiki/Copy-on-write"&gt;copy-on-write&lt;/a&gt; advantages and might save a significant amount of memory. However, it appears to interfere with the operation of the client's multiprocess mode - possibly because there's some &lt;a href="https://rachelbythebay.com/w/2011/06/07/forked/"&gt;locking prior to fork()&lt;/a&gt; this way? uWSGI's &lt;a href="https://uwsgi-docs.readthedocs.io/en/latest/articles/TheArtOfGracefulReloading.html?highlight=lazy-apps#preforking-vs-lazy-apps-vs-lazy"&gt;lazy-apps option&lt;/a&gt; allows us to load the application after forking, which gives us a cleaner environment.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So altogether, this results in a working &lt;em&gt;/metrics&lt;/em&gt; endpoint for our Flask app running under uWSGI. You can try out the full worked example in our &lt;a href="https://github.com/hostedgraphite/pandoras_flask/"&gt;pandoras_flask demo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Note that in our demo we expose the metrics endpoint on a &lt;a href="https://github.com/hostedgraphite/pandoras_flask/blob/master/conf/nginx.conf#L28"&gt;different port&lt;/a&gt; to the app proper - this makes it easy to allow access for our monitoring without users being able to hit it.&lt;/p&gt;

&lt;p&gt;In our deployments, we also use the &lt;a href="https://github.com/timonwong/uwsgi_exporter"&gt;uwsgi_exporter&lt;/a&gt; to get more stats out of uWSGI itself.&lt;/p&gt;

&lt;h1&gt;
  
  
  Futures
&lt;/h1&gt;

&lt;p&gt;Saha's &lt;a href="https://echorand.me/your-options-for-monitoring-multi-process-python-applications-with-prometheus.html"&gt;blog post&lt;/a&gt; lays out a series of alternatives, with pushing metrics via a local &lt;a href="https://github.com/etsy/statsd"&gt;statsd&lt;/a&gt; as the favoured solution. That’s not really a hop we prefer to take.&lt;/p&gt;

&lt;p&gt;Ultimately, running everything under container orchestration like &lt;a href="https://kubernetes.io/"&gt;kubernetes&lt;/a&gt; would provide the native environment in which Prometheus shines, but that’s a big step just to get its other advantages in an existing Python application stack.&lt;/p&gt;

&lt;p&gt;Probably the most Promethean intermediate step is to register each sub-process separately as a scraping target. This is the approach taken by &lt;a href="https://github.com/korfuri/django-prometheus/blob/master/documentation/exports.md#exporting-metrics-in-a-wsgi-application-with-multiple-processes-per-process"&gt;django-prometheus&lt;/a&gt;, though the suggested “port range” approach is a bit hacky.&lt;/p&gt;

&lt;p&gt;In our environment, we could (and may yet) implement this idea with something like:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Running a webserver inside a thread in each process, listening on an ephemeral port and serving &lt;em&gt;/metrics&lt;/em&gt; queries;&lt;/li&gt;
&lt;li&gt;Having the webserver register and regularly refresh its address (e.g. hostname:32769) in a short-TTL &lt;em&gt;etcd&lt;/em&gt; path—we use &lt;a href="https://github.com/etcd-io/etcd"&gt;etcd&lt;/a&gt; already for most of our service discovery needs;&lt;/li&gt;
&lt;li&gt;Using &lt;a href="https://prometheus.io/docs/guides/file-sd/"&gt;file-based service discovery&lt;/a&gt; in Prometheus to locate these targets and scrape them as individuals.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We think this approach is less involved than using the Python client’s multiprocess mode, but it comes with its own complexities.&lt;/p&gt;

&lt;p&gt;It’s worth noting that having one target per worker contributes to something of a time series explosion. For example, in this case a single default Histogram metric to track response times from the Python client across 8 workers would produce around 140 individual time series, before multiplying by other labels we might include. That’s not a problem for Prometheus to handle, but it does add up (or likely, multiply) as you scale, so be careful!&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;For now, exporting metrics to Prometheus from a standard Python web app stack is a bit involved no matter which road you take. We hope this post will help people who just want to get going with their existing nginx + uwsgi + &lt;em&gt;Flask&lt;/em&gt; apps.&lt;/p&gt;

&lt;p&gt;As we run more services under container orchestration—something we intend to do—we expect it will become easier to integrate Prometheus monitoring with them.&lt;/p&gt;

&lt;p&gt;Established Prometheus users might like to look at our &lt;a href="https://www.metricfire.com/hosted-prometheus"&gt;Hosted Prometheus&lt;/a&gt; offering—if you’d like a demo, please &lt;a href="https://www.metricfire.com"&gt;get in touch&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Written by Cian Synnott, Programmer at &lt;a href="https://www.metricfire.com"&gt;Metricfire&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>python</category>
    </item>
    <item>
      <title>Continuous self-testing at Hosted Graphite — why we send external canaries, every second</title>
      <dc:creator>Bébhinn Egan</dc:creator>
      <pubDate>Wed, 31 Jul 2019 09:43:20 +0000</pubDate>
      <link>https://forem.com/bbhnn/continuous-self-testing-at-hosted-graphite-why-we-send-external-canaries-every-second-4hh7</link>
      <guid>https://forem.com/bbhnn/continuous-self-testing-at-hosted-graphite-why-we-send-external-canaries-every-second-4hh7</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on the &lt;a href="https://www.hostedgraphite.com/blog/continuous-self-testing-at-hosted-graphite-why-we-send-external-canaries-every-second"&gt;Hosted Graphite blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;At Hosted Graphite, internal system monitoring is something our engineers are always concerned about. To detect any degradation we continuously self-test all our endpoints — every second, every day. It gives us an early warning sign of small changes that could be an indicator of larger problems and lets us know how well our service is running. We try to measure what our customers are actually experiencing and this is one of the main metrics of service quality that we grade ourselves on.&lt;/p&gt;

&lt;h1&gt;
  
  
  How does it work?
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Each canary service sends a value of '1' once per second with the appropriate timestamp to each endpoint that we accept metric traffic on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the case of any TCP connections we re-establish a new connection each time (and record the time taken) to allow measurement of network delays and services being overloaded.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We can then continuously monitor these metrics for any drop in value.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This system lets us know if something’s wrong: when the amount of traffic we record drops below an acceptable loss amount for a particular service, our alerting tools raise the alarm. We can then check on the exact number of failed data-points by looking at our &lt;a href="https://www.hostedgraphite.com/docs/advanced/data-views.html"&gt;sum dataviews&lt;/a&gt; presented on a dashboard. These figures are aggregated and grouped by protocol and source network, allowing us to determine the extent of the degradation at a glance. We can answer the "Just one AWS zone?" or "All UDP services?" questions extremely quickly because of this continuous, distributed monitoring.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UJclhCfH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/l8s9jv3t8zsehhldysmn.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UJclhCfH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/l8s9jv3t8zsehhldysmn.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  ‍A snippet of the canaries dashboard — all green right now!
&lt;/h6&gt;

&lt;h2&gt;
  
  
  The juicy details
&lt;/h2&gt;

&lt;p&gt;We test all our endpoints. That includes TCP, TCP w/ TLS, UDP, Pickle, Pickle w/ TLS, and HTTPS. Our test sends a datapoint every second to make sure we pick up on any degradation of service. To make sure we're not falsely covering-up a delay in accepting the data or establishing a connection, the canary has been carefully engineered to send one datapoint per second and to abandon the attempt if it takes longer than a second, ensuring a very reliable continuous rate of one value per second no matter what.&lt;/p&gt;

&lt;p&gt;If it takes longer than a second to connect and submit a datapoint, we'd record that as a dropped datapoint, because we care about the data delivery rate as well as how long it takes for us to accept it.&lt;/p&gt;

&lt;p&gt;A single datapoint gets sent for each protocol and these go to our Graphite-compatible endpoints. The sum rate of these metrics is then rendered in our alerting service and if the value drops below acceptable loss for a particular service, an on-call engineer is paged.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wqtFU8ke--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/oc1sdiv6qegpe8r51pmb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wqtFU8ke--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/oc1sdiv6qegpe8r51pmb.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Canary sumrates dashboard — we offset the line at 2.0 from 1.0 for a clear view of both on the same graph
&lt;/h6&gt;

&lt;h1&gt;
  
  
  Locations
&lt;/h1&gt;

&lt;p&gt;Our canary services are located in three places:&lt;/p&gt;

&lt;h2&gt;
  
  
  External
&lt;/h2&gt;

&lt;p&gt;The external canaries are all located outside of the main Hosted Graphite architecture/pipeline. They’re tagged and sent from different places, all over the world. We do this so that we can understand if, for example, there’s a problem with traffic from a specific region.&lt;/p&gt;

&lt;h2&gt;
  
  
  Internal
&lt;/h2&gt;

&lt;p&gt;We run more canaries that sit within our own data centre. This allows us to test our local network so we can differentiate a failure that is likely due to some mishap in our own service as opposed to external connectivity issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  On-machine
&lt;/h2&gt;

&lt;p&gt;While we send canary data from many locations outside and inside our network, we also send a continuous stream of canary data locally from each of our ingestion services to itself so failures of a single machine or service are immediately apparent. This data is also used automatically by our clustering and service discovery tools, allowing auto-remediation of most common individual machine failure types.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qTxdvQ6x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/tm0d41ew2gwhrpjyyfsp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qTxdvQ6x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/tm0d41ew2gwhrpjyyfsp.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Status page (includes full incident history)
&lt;/h6&gt;

&lt;p&gt;For transparency, &lt;a href="https://status.hostedgraphite.com/"&gt;we publish all the details on our status page&lt;/a&gt; so our customers have full visibility of any blip in our service and real time status information. We include a full breakdown of what caused the issue, who it affected, and how the issue has been resolved.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Written by Dan Fox, SRE at Hosted Graphite.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>sre</category>
      <category>saas</category>
      <category>devops</category>
    </item>
    <item>
      <title>Why we’re teaching our staff how to get a pay rise</title>
      <dc:creator>Bébhinn Egan</dc:creator>
      <pubDate>Tue, 30 Jul 2019 18:59:04 +0000</pubDate>
      <link>https://forem.com/bbhnn/why-we-re-teaching-our-staff-how-to-get-a-pay-rise-54i8</link>
      <guid>https://forem.com/bbhnn/why-we-re-teaching-our-staff-how-to-get-a-pay-rise-54i8</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on the &lt;a href="https://www.hostedgraphite.com/blog/surviving-on-call-tips-from-a-hosted-graphite-sre"&gt;Hosted Graphite blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;At Hosted Graphite, we’re open about how we do things: both internally and externally. We publish the &lt;a href="https://status.hostedgraphite.com/"&gt;status of our internal systems&lt;/a&gt; (and &lt;a href="https://status.hostedgraphite.com/history"&gt;share a full history of all incidents&lt;/a&gt;), we share our weekly &lt;a href="https://baremetrics.com/"&gt;Baremetrics&lt;/a&gt; reports on revenue and churn rate with everyone in the company and, most recently, we told all our staff how to ask for a pay rise.&lt;/p&gt;

&lt;p&gt;For us, being transparent about pay doesn’t mean publishing everyone’s salary (&lt;a href="https://open.buffer.com/introducing-open-salaries-at-buffer-including-our-transparent-formula-and-all-individual-salaries/"&gt;though some companies do go that far&lt;/a&gt;). It’s more about making sure everyone has an understanding about how salary increases are decided on and what steps to take to prepare for a review. Every company periodically reviews and adjust salaries. We just make it clear to everyone what our approach is and how to best prepare.&lt;/p&gt;

&lt;p&gt;To do this, we laid out a clear process for salary reviews and wrote down the steps involved to make sure everyone gets the best deal. It includes:&lt;/p&gt;

&lt;p&gt;Preparing a list in advance with points on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What went well this year, and the impact this had on the company.&lt;/li&gt;
&lt;li&gt;What went badly, and what you learned from it.&lt;/li&gt;
&lt;li&gt;The salary range you think is fair, and why.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remembering every project you've contributed to and every bit of impact you've had over a whole year is impossible. To help with this, we encourage everyone to write "snippets"— a short daily or weekly note about what you've done and what decisions were made. When it's time for an annual review, often the only source of data needed is these short activity logs. The key is doing it at regular intervals.&lt;/p&gt;

&lt;p&gt;Then we meet, discuss what’s been written, and talk about the proposal. The intention here is to teach every employee how to critically review what they've done in the last year, to identify weak spots, to think about how to counter those, and how to use this data to justify the salary they deserve.&lt;/p&gt;

&lt;p&gt;Learning to negotiate a salary is a very difficult thing, and nobody is going to go out of their way to teach you. That’s why being clear on how to ask for an increase fits in with our goal of making sure we develop the people we have, especially those who come to us early in their careers. Most people learn to negotiate by getting a raw deal a few times early in their career, and that’s something we’d like to avoid.&lt;/p&gt;

&lt;p&gt;It also ties in to our commitment to tackling &lt;a href="https://www.newyorker.com/business/currency/why-cant-silicon-valley-solve-its-diversity-problem"&gt;the tech diversity problem&lt;/a&gt; (in our own small way). We think that just saying we’re committed to equality and diversity isn’t enough and have put considerable energy into being &lt;a href="https://www.hostedgraphite.com/blog/no-brogrammers-practical-tips-for-writing-inclusive-job-ads"&gt;more inclusive in our hiring process&lt;/a&gt; and the way we operate. Being open about salary negotiations is another way we battle inequality. It’s our way of subverting the current system &lt;a href="https://www.payscale.com/career-news/2015/02/why-women-dont-negotiate-salary-and-what-to-do-about-it"&gt;where women and minorities are more likely to be uncomfortable negotiating salary&lt;/a&gt; and therefore tend to be paid less. It’s about having systems in place to make sure everyone gets a fair deal.&lt;/p&gt;

&lt;p&gt;Of course, it works in our interest too. If we don't adjust salaries correctly, people will feel undervalued and will leave. We could be sneaky or strict about this process like other companies are, but that just leads to an odd and adversarial environment where people can feel undervalued for a long time, or where people who aren't sure about the right way to justify their new salary won't get a good deal. A very happy team is worth a lot more than shaving a bit off everyone's salary and being Grinches about it. We're convinced that if we teach our staff this skill, and generally work on developing the already fantastic people we work with, they’ll be happier, produce better work, stick around longer and invite their talented friends to work with us too. It's not selfless, but we think being nicer and more human than other companies is going to benefit everyone in the long run, even if in the short term we're basically telling our employees how to get more money out of us.&lt;/p&gt;

</description>
      <category>hiring</category>
      <category>inclusion</category>
      <category>saas</category>
    </item>
    <item>
      <title>Surviving On-Call: Tips from a Hosted Graphite SRE</title>
      <dc:creator>Bébhinn Egan</dc:creator>
      <pubDate>Mon, 29 Jul 2019 18:23:28 +0000</pubDate>
      <link>https://forem.com/bbhnn/surviving-on-call-tips-from-a-hosted-graphite-sre-32hk</link>
      <guid>https://forem.com/bbhnn/surviving-on-call-tips-from-a-hosted-graphite-sre-32hk</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on the &lt;a href="https://www.hostedgraphite.com/blog/surviving-on-call-tips-from-a-hosted-graphite-sre"&gt;Hosted Graphite blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;On-call is pain, and anyone who says otherwise is trying to sell you something. That said, there are lots of ways to make on-call a better experience, necessary evil that it is.  I’ve been an SRE at &lt;a href="https://www.hostedgraphite.com/"&gt;Hosted Graphite&lt;/a&gt; since 2016, so have done my fair share of on-call. A lot has already been written about how companies can make on-call a better experience for teams, and lucky for us we get a mandatory day-off after an oncall shift, flexible working hours and a remote friendly office that goes a long way to making the on-call experience suck less. These are obviously organisation specific, but for the purposes of this post I’d like to focus on things that you can do to make your individual experience better, based on what I’ve learned.&lt;/p&gt;

&lt;h1&gt;
  
  
  Notification Hygiene
&lt;/h1&gt;

&lt;p&gt;‍&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“It's important to practice good hygiene&lt;br&gt;
At least if you wanna run with my team”&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Del The Funky Homosapien (If you Must)&lt;/em&gt;&lt;br&gt;
‍&lt;/p&gt;

&lt;p&gt;Notification hygiene is something that most of us are pretty terrible at – in and outside of work. Cleaning up your notifications is a very useful tactic for on-call, as chances are you'll be answering the pager and spending more time looking at screens than you normally would. If you use &lt;a href="https://www.pagerduty.com/"&gt;Pagerduty&lt;/a&gt;, I’d recommend grabbing a relevant &lt;a href="https://support.pagerduty.com/docs/notification-phone-numbers"&gt;Pagerduty V-Card&lt;/a&gt; for your region. Next you’ll want to set up your Do Not Disturbs: for me that is close family, my team-mates’ phone numbers and all of the numbers relevant to the Pagerduty V-Card. After that, I turn off all other push notifications and pop my phone into Do Not Disturb mode. This setup makes sure the only audible notifications I get are either from close family, phone alarms, Pagerduty notifications or emergency work calls. We use &lt;a href="https://slack.com/intl/en-ie/"&gt;Slack&lt;/a&gt; at Hosted Graphite, so I also enable Slack notifications between working hours and generally allow all calls from 7am-9pm to account for things like doctor’s appointments, package deliveries, or most importantly, takeaway deliveries.&lt;/p&gt;

&lt;p&gt;This might seem like a lot of effort, particularly if you use your phone pretty much as is (where you’re inundated with a barrage of notifications). If that works for you, that’s cool, but the goal I have during on-call shifts is to reduce the time I’m actively thinking about getting paged, unless the pager is currently yelling at me.&lt;/p&gt;

&lt;p&gt;Bonus tip: When you’re setting up Pagerduty notification channels, make sure to leave a minute or two delay before your first notification. This means that if you see a page happen in real time while you’re working, you can acknowledge it through the web app before it blows up your phone.&lt;/p&gt;

&lt;p&gt;Note: This is going to depend entirely on your response times for the services you are on call for. If it’s an incredibly high priority service, that requires response times in the seconds, this strategy isn’t going to work. However, if your services are resilient enough, and allow for longer response times for incidents, this strategy can make your incident management more effective, as you’re able to properly deal with issues without your phone constantly going off.&lt;/p&gt;

&lt;p&gt;In that case I’d recommend just making your initial notifications be a push notification directly to your laptop, combined with one going to your phone–then you’ll get instant feedback before your phone goes off, because you’re looking directly at the screen and can acknowledge it from there.&lt;/p&gt;

&lt;h1&gt;
  
  
  Personal Care
&lt;/h1&gt;

&lt;p&gt;‍&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“I know you've had a rough time&lt;br&gt;
Here I've come to hijack you (hijack you), I'll love you while&lt;br&gt;
I'm making the most of the night”&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Carly Rae Jepsen (Making the Most of the Night)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Like it or not, most on-call shifts are going to tire you out. The exception is when absolutely nothing happens at all, which we aspire to by doing proper incident follow-up, post-mortems, and focusing on infrastructure and software improvements to make on-call suck less. That said, the best laid plans of mice and men are nothing when faced with a faulty router in a data-centre at 3am.&lt;/p&gt;

&lt;p&gt;So you’ve been woken up at 3am, you’ve sorted your incident, but now you’re awake and can’t get back to sleep. The temptation is to get up, power through, finish work early, and try to grab some sleep later. However that way lies danger, as it’s easy to get stuck in the pattern of staying up late, and missing most of the first half of the day. Prioritising regular sleep is vital, as is trying to stick to a reasonable routine. I’m a night owl, and because we have flexible hours at Hosted Graphite, my hours tend to be something like 11am to 7pm, and I usually fall asleep around 2am. So even if I get paged at 8am and I could just get up and start my day, I’m always going to take that sleep.&lt;/p&gt;

&lt;p&gt;When I first started doing on-call I didn’t do this, and tried to power through...exactly once. You would not think that an hour or two of extra sleep makes that much difference, but it does. I remember spending that day making tonnes of small mistakes and felt my brain was working at quarter-speed (and for the people who know me, that’s definitely saying something).&lt;/p&gt;

&lt;p&gt;An incident heavy week can also reach its tendrils into other aspects of your personal life – if you find yourself working late into the evening, the temptation emerges to order in some food or grab a pizza on your way home. I’ve found that if I don’t do some prep in advance of being on-call I end up mostly eating trash for the week, and feeling way worse than I would otherwise. When combined with potentially disturbed sleep, the temptation to skip breakfast so you can spend a little longer in bed is another decision which will likely put a damper on your on-call week. &lt;/p&gt;

&lt;p&gt;To avoid this, before going on-call I’ll buy a box of some sort of cereal/breakfast bar and whatever fruit I feel like eating and set myself the rule that I’m not leaving the house til I eat breakfast. If I make it as easy as possible to eat a decent breakfast, there’s no excuse not to. I have the usual work lunch, and at dinner time make twice as much as I normally would, to cover me for the next day in case I get hit with a page. As for those extreme incident-laden weeks, anything you can set and forget til it’s done cooking is ideal, and it means you’ll still be eating well even if you’re dealing with a lot of incidents.&lt;/p&gt;

&lt;p&gt;The last, and probably most important aspect of looking after yourself on-call is to take stock of your mental health. You need to do whatever it is that lets you relax, be it video games, quiet time with a book, or a trip to the gym. Whatever it is, you need to make time for something that isn’t thinking about work, so you can recharge your batteries. You may be on-call for the week, but the pager isn’t your life.&lt;/p&gt;

&lt;p&gt;It’s always good to remember is that you have a team behind you to support you and back you up. At Hosted Graphite, the company wants well rested and happy engineers, because well rested and happy engineers make fewer mistakes, do better work, and make for a much stronger team.&lt;br&gt;
‍&lt;/p&gt;

&lt;h1&gt;
  
  
  Out and About on Call
&lt;/h1&gt;

&lt;p&gt;‍&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“If you go down in the woods today&lt;br&gt;
You're sure of a big surprise”&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Anne Murray (Teddy Bear’s Picnic)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There’s a perception that when you’re doing an on-call shift, you need to be at home, bound to your phone and laptop, hunched over in anticipation for the next notification so you can spring into action. This is not the case. Although I’d generally advise against to the cinema or an evening at a fancy French restaurant, you can pretty much go about your regular routine–so long as you have a couple of things prepared:&lt;/p&gt;

&lt;h2&gt;
  
  
  A good 4G/LTE connection and phone to use as a hotspot
&lt;/h2&gt;

&lt;p&gt;If you’re doing on-call, you should be provided with this. At Hosted Graphite, our phone bills are covered by the office and we have a choice between using our own devices, or a company provided phone. Whatever way your company does it, you’re going to need ready access to the internet for both notification delivery and actual incident response time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your laptop
&lt;/h2&gt;

&lt;p&gt;Obviously, you’ll need a way to respond to incidents and you probably don’t have much choice here. If you’re lucky enough to be able to pick and choose the device you use for your on-call purposes, I’d recommend the 13” macbook air for most SRE type work that is heavily biased towards work on remote servers. It's lightweight and easily portable. Excellent battery life is also a big plus. For the windows inclined (or if you just want to run some straight up linux with no faff) I’ve also heard very good things about the Thinkpad X Series.&lt;/p&gt;

&lt;h2&gt;
  
  
  A power bank and assorted chargers
&lt;/h2&gt;

&lt;p&gt;You don’t want to get caught with a dead phone or laptop, so a beefy power bank is worth picking up, for both peace of mind and to fill up any devices you may have if you’re caught somewhere without plug access, like a bus or train.&lt;/p&gt;

&lt;h2&gt;
  
  
  A solid backpack to hold all your on-call related stuff
&lt;/h2&gt;

&lt;p&gt;The ideal here is something that's big enough to comfortably hold all of the above, but not too big to leave you hauling around a huge backpack everywhere. When I’m on-call I tend to use a simple leather messenger bag for trips to and from work, and for everywhere else I use &lt;a href="https://www.amazon.co.uk/gp/product/B076LQ8WT8/ref=oh_aui_search_detailpage?ie=UTF8&amp;amp;psc=1"&gt;this MATEIN backpack (amazon uk)&lt;/a&gt;. It holds everything I need and collapses down fairly thin when all the space isn’t in use. It also has a handy usb port on the side, so you can plug in your power bank without needing to take it out.&lt;/p&gt;

&lt;p&gt;You’ll probably have other specific needs, like a yubikey for auth or maybe a swipe card reader for vpn access or other similar things, so I tried to just focus on the bare minimum here. The most important thing is to do your best to just forget the pager is a thing until it pages out and go about your life.&lt;/p&gt;

&lt;h1&gt;
  
  
  Final note
&lt;/h1&gt;

&lt;p&gt;If you only take one thing away from this post, it’s that you need to put your own well-being first, and once you do that other aspects of on-call will become easier. These mobile meat sacks we inhabit are fragile at best, and it is both the responsibility of the person on-call and also the company’s leadership to ensure that people who are doing on-call on a regular basis are given the resources they need to succeed, and the time they need to stay well-rested, healthy and happy.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Written by Dave Fennell, SRE at Hosted Graphite.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>sre</category>
      <category>mentalhealth</category>
      <category>saas</category>
    </item>
  </channel>
</rss>
