Unikube Frontend

VueJS error tracking with Sentry

When it comes to error tracking in our Cloud Native applications Sentry has become our go-to solution. We do love the ease of use, the deep insights and the well-structured documentation. This blog post aims to provide you with our learnings on using Sentry on Unikube’s VueJS based frontend.

Header_Unikube-VueJS-Sentry.png


Sentry is simply a great piece of software we love to use in our everyday work and we want to share our learnings on using Sentry on Unikube’s VueJS based frontend with you. The code snippets are a bit simplified compared to the originals, however, they contain all necessary information.

General information & dependencies

Unikube’s frontend provides a UI to our many backend microservices. All our microservices are equipped with GraphQL interfaces which are then federated via Apollo Federation. This gives us the convenience of consuming the whole (external) graph through one endpoint. The frontend itself is a monolithic single page application, built with TypeScript on top of VueJS and Vuetify. We have included internationalisation via vue-i18n and frontend permission management through CASL.

When it comes to error tracking we have included Sentry’s SDK, which already includes a beautiful integration for VueJS.

Sentry Integration

The basic integration itself is as simple as it can be:
main.ts:

Wait - but what is this dsn-thing? It provides the SDK with the endpoint to which it will send any relevant events tracked by Sentry. To make sure we do not track any events from our local development environments we surround the initialisation with a simple if statement.
main.ts:

process.env contains certain environment variables and their values.

However, we do not stop here. To provide our developers with as much information ass possible, to ease the process of debugging, we add some more information at runtime. One very helpful thing is the integration of Sentry with Vue’s router.
router/index.ts:

Setting the label of the current route to Sentry’s transaction name immediately restricts the context in which our developers are „hunting“ the bug.

To provide our user’s with the best support possible we also enrich Sentry’s events with some user information. Our store's auth.ts modules handle the authentication tokens and states. As soon as the user information change (login, logout) we update Sentry’s context.
store/auth.ts:

This way we can filter the tracked errors for certain users and provide them with superb support and insights as well as super-quick bug fixes.

Sentry Source Maps and Release Health

Sentry comes with a fancy Webpack integration, which allows streamlining the creation of releases and linking source maps to those. This is an essential step to make sure our developers are not confronted with stack traces and errors from the minified JavaScript sources, but with the actual code from the repository.

We simply add the Sentry CLI Webpack plugin to our vue.config.js - and therefore to the Webpack configuration.
webpack.config.js:

We’re surrounding the release process with process.env.NODE_ENV === 'production' to make sure nothing from our development or CI test workflows lands as a release in Sentry.

If you take a closer look at the code you’ll notice that we work with an environment variable 'VUE_APP_VERSION' as well as with a file, which is located under '/run/secrets/SENTRY_AUTH_TOKEN'.

Let’s dive a bit deeper into the build process of the frontend.


Docker Arguments and Secrets

Since we make use of environment variables, which may differ from one environment to the other (compare development and production), those variables need to be set at build time. The 'dist' version of the frontend is served through a simple NGINX docker container. Therefore we leverage Docker’s arguments to pass in environment variables at build time (for the docker image as well as for the frontend).
Dockerfile:

If you wonder about the difference between docker ARG and ENV check it out here.

However, the SentryCLIPlugin sends something to our Sentry installation and therefore needs some kind of authentication. For that, the 'authToken' configuration parameter is used. Now - Unikube is an open-source project, which means our CI pipelines are open source as well. Nevertheless, we would like to keep our 'authToken' a secret, so that no one else can manipulate any release information on our Sentry installation. For that, we use Docker’s secret management. It allows us to inject secret information into the build process, which can only be used during build time. This is exactly what we need since the release information (including the source maps) only need to be generated once when the Docker image is built.

Docker injects the secret as a file, located under '/run/secrets/SENTRY_AUTH_TOKEN'. This file then is read by the 'SentryCLIPlugin'.

Github Actions

The last missing piece of the puzzle is the automated build of the Docker image in our CI pipeline. Since Unikube’s repositories are located on Github we leverage Github Actions.

Within the `docker.yaml` we define the steps to build the Docker images for our development and production environments.
.github/workflows/docker.yaml:

There are a few things to consider here:

  1. We use Github Action’s 'matrix' keyword to use the same job template for multiple environment builds.
  2. We log in to quay.io which is the service hosting our Docker images.
  3. Secret and Arguments are passed via 'docker/build-push-action@v2'.

The last thing to do here is set the secret information for the repository on its Github settings page:

Screenshot: Secret Actions GitHub


Done! This is how Unikube’s frontend currently integrates Sentry to better understand errors, fix bugs faster and provide better support for our users.


Let us know if you have any questions, feedback or maybe things we should consider to change. Thank you very much.