Backend Chart Rendering
Sentry's frontend provides users with detailed and interactive charts of various types, highly tailored to the look and feel of the Sentry product. Historically these charts have been something we only have in the web application.
There are however, cases where it would be very valuable to show a chart in some context onside of the application. For example
Slack unfurling of Discover charts, Metric Alert notifications, Issue details, or any other link in Sentry where it may be useful to see a chart in Slack.
Notification and summary emails. Having trends visualized as charts.
Fortunately, Sentry has built-in functionality for the internal Chartcuterie NodeJS service, which can produce graphs in an image format via an HTTP API. The charts are generated using the same ECharts library that is used on the frontend. Chartcuterie shares code with Sentry's frontend, meaning the look-and-feel of the charts can be easily maintained between the frontend, and charts generated by Chartcuterie on the backend.
Generating charts using Chartcuterie is dead simple.
Import the generate_chart
function, provided a chart type and data object, get a public image URL.
from sentry.charts import generate_chart, ChartType
# The shape of data is determined by the RenderDescriptor in the
# configuration module for the ChartType being rendered.
data = {}
chart_url = generate_chart(ChartType.MY_CHART_TYPE, data)
Chartcuterie loads an external JavaScirpt module from sentry.io which determines how it renders charts. This module directly configures EChart's options
object, including transformations on the series data provided to Chartcuterie upon a POST /render
call.
This module lives as part of getsentry/sentry, and can be found in static/app/chartcuterie/config.tsx.
It is possible to configure an optional initialization function init
that runs when the service starts. This function has access to Chartcuterie's global echarts object and can be used register utilites to it (registerMaps
, for example).
Chart rendering is configured on a per "chart type" basis. For each type of chart you will need to declare a well-known name in the frontend application as well as in the backend charts module.
On the frontend add a
ChartType
in static/app/charctuerie/types.tsx.Register the
RenderDescriptor
for the chart, which describes the look and feel, as well as series transformations, in static/app/chartcuterie/config.tsx. You can use theregister
function for this.In the backend add a matching
ChartType
in thesentry.charts.types
module.Deploy your changes in Sentry. The configuration module will automatically propagate to Chartcuterie within a 5 minute window.
You do not need to deploy Chartcuterie.
Do NOT deploy functionality that uses your new chart type at the same time as the configuration module. Because there is a propagation delay, the new chart type is not guaranteed to be available immediately after a deployment.
The configuration module includes the deployed sentry.io commit SHA, which allows Chartcuterie to check if it has received a new configuration module upon each poll tick.
To enable Chartcuterie in your local developer environment first enable it in your config.yml
:
# Enable charctuerie
chart-rendering.enabled: true
Currently you need to manually build the configuration module in your development environment.
yarn build-chartcuterie-config
You can then boot the Chartcuterie devservice. If the devservice doesn't start check that the chart-render.enabled key is correctly set to true
(Use sentry config get chart-rendering.enabled
).
sentry devservices up chartcuterie
You can validate that the service has successfully started by checking the logs
docker logs -f sentry_chartcuterie
Which should look something like this
info: Using polling strategy to resolve configuration...
info: Polling every 5s for config...
info: Server listening for render requests on port 9090
info: Resolved new config via polling: n styles available. {"version":"xxx"}
info: Config polling switching to idle mode
info: Polling every 300s for config...
Your development environment is now ready make calls to a local instance of Chartcuterie.
Currently you need to rebuild the configuration module using yarn build-chartcuterie-config
on every change. This may be improved in the future.
Here are a couple service diagrams for the Chartcuterie service and how it interacts with the Sentry application server.
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").