Error Tracking

mit Sentry

Puzzle Tech Kafi, 29.05.2019

Mathis Hofer & Thomas Philipona

Bugs fixen bevor die User sich melden

Weshalb Error Tracking?

Reaching production is only the first step...

The 3 Pillars of Observability

Logging

Metrics

Tracing

While there are many good tools that make development easier, the post-deployment process of discovery, investigation, and remediation is still painful, confusing, annoying, and lengthy.

Adhiraj Somani, Sentry

Errbit 😃

errbit.puzzle.ch

  • Airbrake API kompatible Open Source Implementation
  • Im Einsatz bei
    Rails-Projekten
    seit ~2012 (Hitobito)
  • Frontend-Integration über airbrake-js
    seit 2016 (socialweb)

Errbit 😭

  • Nicht sehr aktive Entwicklung
  • Java-Integration problematisch
  • Featureumfang begrenzt

Sentry @ Puzzle

EST. 21. März 2019

Stand

sentry.puzzle.ch wurde vom Techboard eingerichtet

 

Erste Projekte verwenden Sentry

(Acrevis, B4U, Marina, PuzzleTime, socialweb, Zeus etc.)

 

Erfahrungen sammeln

 

Best Practices erarbeiten

Ziele

Ablösung von Errbit bei allen Ruby Projekten bis Ende Jahr

 

Für Java Projekte und im Frontend als Standard etablieren

Wichtig zu wissen

pitc als Organization ID verwenden:

sentry.puzzle.ch/pitc/

 

Oder bei der Loginmaske →

Und: Gewünschte Teams joinen, damit die Projekte sichtbar werden

Best Practices

Es gibt eine Organization: pitc

 

Pro Projekt ein Team erstellen mit Projektkürzel:
z.B. pofi-b4u

 

Im Team pro (Micro-)Service ein Project erstellen:
z.B. b4u-backend, b4u-frontend

 

Umgebungen (Integration, Produktion etc.) als Environment im gleichen Project abbilden:
environment im SDK konfigurieren

Was ist Sentry?

SDKs

JavaScript, Browser JavaScript CDN, Java, Node.js, .NET, PHP, Ruby, Vue, Angular, Ember, React, React Native, Cordova, Electron, Python, Django, Flask, Sanic, Celery, AWS Lambda (Python), Serverless (Python), Pyramid, RQ (Redis Queue), WSGI, AIOHTTP, Tornado, Bottle, Rust, actix-web, Minidump, Elixir, Cocoa, Go

Sentry-supported:

Community-supported:

C++, Clojure, Crystal, Dart, Grails, Kubernetes, Lua, Nuxt, OCaml, Scrapy, Terraform, Wordpress, Zend

Workflow

Triage

Fehlersuche

Problem gelöst

Ziel soll sein:

0 Issues

 

Irrelevante Fehler in Applikation handeln

Organisatorisch: Wochenverantwortung

Features

Wichtige Informationen

Exception, Stack Trace

Umgebung, Version

Request URL, Parameter, Headers

Benutzer, Browser, Betriebssystem

 

Verlauf

Auf einen Blick:

Wie häufig tritt der Fehler auf?

Erstes Ereignis, letztes Ereignis

E-Mail Notifications

Fehler werden per E-Mail notifiziert
(kann auch global deaktiviert werden)

 

Häufigkeit kann pro Projekt/Umgebung konfiguriert werden:

Weekly Report Mail

Breadcrumbs

User Feedback

Releases

Mit SDK den release konfigurieren
(z.B. Commit Hash oder Versionsnummer)

 

Manche SDKs unterstützen automatisches Guessing

Releases (cont. 1)

Issues werden einem Release zugeordnet (getagged):

Releases (cont. 2)

Release erstellen:

entweder implizit (durch Issue)

oder explizit (via CLI/API/Webhook)

 

Weitere Funktionen:

Artefakte (Sourcen/Sourcemaps) anhängen

Verknüpfung mit Commit → Gitlab/Github Plugin konfigurieren

Demo

Integrationen

Java

  • java.util.logging
  • Log4j
  • Logback
  • Spring
compile 'io.sentry:sentry-spring:1.7.16'


@Bean
public HandlerExceptionResolver sentryExceptionResolver() {
    return new io.sentry.spring.SentryExceptionResolver();
}


@Bean
public ServletContextInitializer sentryServletContextInitializer() {
    return new io.sentry.spring.SentryServletContextInitializer();
}

Ruby/Rails

Konfiguration in Initializers:

gem "sentry-raven"
Rails.application.config.filter_parameters += [:password, :token]

Raven.configure do |config|
  config.sanitize_fields =
    Rails.application.config.filter_parameters.map(&:to_s)
  config.release = ENV['OPENSHIFT_BUILD_COMMIT']
end

Environment als SENTRY_CURRENT_ENV setzen

Ruby/Rails (cont. 1)

class ApplicationController < ActionController::API

  before_action :set_sentry_request_context
  before_action :set_sentry_user_context

  private

  def set_sentry_request_context
    Raven.extra_context(
      params: params.to_unsafe_h,
      url: request.url
    )
  end

  def set_sentry_user_context
    Raven.user_context(
      id: current_user.try(:id),
      name: current_user.try(:username)
    )
  end

end

Ruby/Rails (cont. 2)

class ApplicationJob < ActiveJob::Base

  rescue_from(Exception) do |e|
    Raven.capture_exception(e, logger: 'delayed_job')
  end

  def deserialize(job_data)
    super(job_data)
    Raven.extra_context(active_job: job_data)
  end

end

JavaScript/Frontend

(bietet neue unified API, raven-js ist veraltet)

 

Konfiguration:

npm install @sentry/browser
import * as Sentry from '@sentry/browser';

Sentry.init({
  dsn: 'https://<key>@sentry.io/<project>'
  environment: 'integration',
  release: '1.23'
});

Erfasst automatisch global alle Exceptions

JavaScript/Frontend (cont. 1)

SourceMaps:

  • //# sourceMappingURL=foo.js.map im JS-File
  • oder JS Files mit SourceMap Header ausliefern

JavaScript/Frontend (cont. 2)

Bei Angular ErrorHandler implementieren:

@Injectable()
export class SentryErrorHandler implements ErrorHandler {
  constructor() {
    Sentry.init({
      dsn: 'https://<key>@sentry.puzzle.ch/<project>',
      environment: 'integration',
      release: '1.23'
    });
  }

  handleError(error: any) {
    Sentry.configureScope(scope => {
      scope.setUser({ id: myUserId, username: myUserName });
    });
    const eventId = Sentry.captureException(error.originalError || error);
    Sentry.showReportDialog({ eventId });
  }
}

Fragen?

Anlaufstellen:

sentry.puzzle.ch

Sentry User Guide im Wiki

docs.sentry.io

#puzzle-ask

#puzzle-techboard

Made with Slides.com