Sentry, l'alternative crédible à Firebase et AppInsight ?

Vous êtes arrivé sur cette page peut-être par curiosité ou via une recherche un peu plus spécifique dans le but d'en apprendre davantage sur Sentry ? Excellente nouvelle ! C'est là tout l'objectif de cet article dans lequel nous découvrirons ce qu'est Sentry, son utilité, les fonctionnalités principales qu'il propose, comment l'installer en local sur une machine de développement puis comment l'implémenter dans divers projets. Vous êtes prêt ? C'est parti !
AXOPEN, L'équipe Tech Mis à jour le 29 Oct 2024
sentry.png

Qu'est-ce que Sentry ?

Sentry est un outil de MonitoringTechnique qui permet d'analyser et de surveiller le comportement et les réactions d'une application. gratuit et open source destiné à la surveillance des erreurs et des performances de vos applications. Il permet de suivre, enregistrer et analyser les erreurs (bugs, exceptions) rencontrées par les utilisateurs en temps réel. Créé en 2015, plusieurs grandes entreprises utilisent cette solution comme Github, Atlassian, Disney, Microsoft ou encore Cloudflare.

En tant que développeur, l'intérêt de cette solution est d'identifier et corriger les problèmes plus efficacement et rapidement, améliorant ainsi la qualité des applications web, mobiles et backend, suivant le projet sur lequel vous souhaitez l'implémenter.

En d'autres termes, Sentry permet 3 choses principales, Débogage, Profilage, Traçage.

Voici une définition générale de ces termes :

  • Débogage : Sentry capture et affiche les erreurs rencontrées dans une application avec des informations détaillées : type d'erreur, message, pile d'appel, et environnement utilisateur. Cela permet de connaitre et localiser les bugs rapidement pour une correction plus efficace.
  • Profilage : Le profilage permet de suivre l'utilisation des ressources (CPU, mémoire) et d'analyser le temps d'exécution des fonctions. Cela aide à identifier les parties du code qui ralentissent l'application pour nous permettre d'améliorer les performances globales en retravaillant les parties pertinentes.
  • Traçage : Le traçage suit les étapes d'une requête ou transaction à travers différents services de l'application. Il aide à comprendre les interactions entre composants et à identifier les ralentissements dans le flux, pour une optimisation plus globale.

Fonctionnalités principales

Si vous faites du développement mobile, Firebase Crashlytics doit probablement vous être familier. Outil développé par Google et destiné au reporting d'erreurs et de crash d'application Android ou iOS, il est très utilisé par les entreprises de développement comme AXOPEN, mais manque à mon sens de clartés et de certaines fonctionnalités bien pratiques proposées par Sentry.

Si le mobile n'est pas votre tasse de thé ou que vous faites également du développement d'APIUne API est un programme permettant à deux applications distinctes de communiquer entre elles et d’échanger des données., AzureAzure est la plateforme de Cloud de Microsoft. propose AppInsight pour monitorer et fournir une vision globale des performances et bug de vos endpoints (si vous travaillez en cloud Azure).

Sentry pour sa part, en plus d'être indépendant, regroupe les arguments de ces deux solutions en ajoutant plus de détails afin de permettre une identification du contexte, ce qui manque cruellement dans les solutions précédentes, par l'intermédiaire d'une interface claire et intuitive.

Pour parvenir à ce résultat, plusieurs fonctionnalités complémentaires sont intégrées, traçabilité des actions avec un breadcrumb (Fil d'Ariane), intégration aux outils de versioning (git, gitlab, etc.) pour la création d'issues automatique avec le code concerné, création de tickets Jira, session replay pour un extrait vidéo ou capture d'écran des actions précédant un bug ou un crash, profilage front et API pour l'analyse des performances, le tout en étant compatible avec énormément de langage de programmation et sans exclusivité avec la plateforme.

Il supporte les projets mobiles tout comme les front-end et back-end/API suivant : 

307d835e-bba8-4514-8200-d6ef1b279419.png

Installation de Sentry en Self-Hosted

L'une des forces de Sentry en complément de sa disponibilité en SaaS (Software-as-a-Service) est sa mise à disposition en Self-Hosted, vous laissant le choix d'utiliser le service cloud préféré et répondant aux exigences de votre entreprise (zone géographique pour le stockage des données, ressources attribuées, etc.). Sa licence vous permet son utilisation dans un cadre commercial, tant que vous ne le revendez pas.

Téléchargement et installation de Sentry

Dans un premier temps, prenons connaissance du tag de la dernière release disponible sur le repository https://github.com/getsentry/sentry/releases. À cet instant, il s'agit de la 24.9.0.

Modifier la commande suivante avec le dernier numéro de version, puis dans un environnement docker valide, exécuter le clonage et l'installation du repo pour procéder à la création des containers et l'initialisation.

Pour ma part, je travaille sous WSL (Windows Subsystem Linux), je vous donnerai quelques tips pour rendre disponible l'application sur votre réseau local.

cd ~
VERSION="24.9.0"
git clone https://github.com/getsentry/self-hosted.git
cd self-hosted
git checkout ${VERSION}
sudo ./install.sh

Au cours de l'installation, vous serez invité à activer ou non la collecte de données destinée à améliorer le produit puis à créer le premier compte utilisateur destiné à la connexion.

Would you like to create a user account now? [Y/n]: Y
Email: mon.email@emailprovider.com
monMot2passeSécurisé&
monMot2passeSécurisé&

Added to organization: sentry
User created: mon.email@emailprovider.com

[...]

-----------------------------------------------------------------

You're all done! Run the following command to get Sentry running:

  docker compose up -d

-----------------------------------------------------------------

Exécuter la commande indiquée, via sudo si nécessaire, pour démarrer les containers.

Sentry est à présent installé !

Premier démarrage & Accès via réseau local

Note WSL

Pour autoriser l'accès à notre installation de Sentry sur un réseau local (projet mobile par exemple), voici les commandes destinées à paramétrer le pare-feu Windows et proxy :

netsh advfirewall firewall add rule name="Allowing LAN Sentry" dir=in action=allow protocol=TCP localport=9000
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=9000 connectaddress=localhost connectport=9000

Pour annuler les modifications : (nécessaire à chaque redémarrage du docker sinon inaccessible)

netsh advfirewall firewall delete rule name="Allowing LAN Sentry"
netsh interface portproxy delete v4tov4 listenaddress=0.0.0.0 listenport=9000

Rendez-vous à l'adresse http://127.0.0.1:9000/ pour accéder à l'interface web de Sentry. Connectez-vous avec le compte créé précédemment et nous voici redirigés vers la dernière étape de configuration que vous pouvez compléter à votre convenance. 

f0ad8c45-5682-4515-abb3-809cd75be5ca.png

Attention, pensez à désactiver votre adblock lors de l'utilisation de l'outil si vous utilisez une adresse IP à la place de 127.0.0.1 ou localhost, sans quoi les requêtes de reporting seront bloquées.

Note Root URL

Si vous passez d'un réseau local à un autre, il est possible que vous n'ayez pas accès à l'interface web Sentry pour modifier la Root URLUniform Ressource Locator qui correspond à l'adresse de l'API Sentry.

Pour cela vous pouvez définir l'adresse directement dans le système de fichier :

cd ~/self-hosted/sentry
nano config.yml
# Décommenter la ligne suivante
system.url-prefix: 'http://192.168.1.200:9000' # Spécifier l'adresse IP du poste de développement sur le réseau

Redémarrer le docker. (Si vous êtes sous WSL, retirez les modifs firewall et proxy puis remettez-les après le redémarrage des containers Sentry)

Note CSRF

Vous pouvez également rencontrer une erreur CSRF lors de la connexion à Sentry dans le cas ou l'adresse spécifiée en ROOT URL serait différente de 127.0.0.1:9000.

Pour cela vous pouvez ajouter l'IP à la whitelist depuis le système de fichier :

cd ~/self-hosted/sentry
nano sentry.conf.py
# Section CSRF Settings
# Décommenter CSRF_TRUSTED_ORIGINS et ajouter l'adresse IP du poste de développement sur le réseau
CSRF_TRUSTED_ORIGINS = ["http://192.168.1.200:9000","http://127.0.0.1:9000"]

Redémarrer le docker. (Si vous êtes sous WSL, retirez les modifs firewall et proxy puis remettez-les après le redémarrage des containers Sentry)

Création d'un projet et débogage

Cette partie et les suivantes s'adressent à tout type d'installation, SaaS comme self-hosted. 

23d08b3c-8151-4504-863a-a996fff8431e.png

Implémentation dans un projet Android

Dans un premier temps pour étudier le fonctionnement du système de débogage, nous pouvons créer un projet Android. À chaque création de projets, Sentry vous donne les étapes permettant son implémentation en fonction du langage sélectionné. 

890d0519-0b8b-4110-a4d8-d12676739c1b.png

Précision importante pour l'implémentation sur projet mobile comme AndroidAndroid est un système d'exploitation mobile basé sur Linux. ou iOSSystème d'exploitation des appareils Apple., vous devez avoir un accès par le réseau local à Sentry, une adresse en 127.0.0.1/localhost comme visible dans le DSN (Data Source Name) sur la capture ci-dessus ne fonctionnera pas même via un émulateur. Assurez-vous de configurer Sentry avec l'adresse IP privée de votre machine de développement ou un DNS (nom de domaine) personnalisé pour que votre application puisse communiquer avec le serveur Sentry.

Sentry peut également enregistrer des SessionReplay de notre application qui est une capture vidéo enrichie des actions effectuées par l'utilisateur avant le bug ou le crash. Pour activer cette fonctionnalité qui est encore en bêta sur certaines plateformes, nous pouvons ajouter les lignes suivantes dans AndroidManifest.xml :

<meta-data android:name="io.sentry.session-replay.error-sample-rate" android:value="1.0" />
<meta-data android:name="io.sentry.session-replay.session-sample-rate" android:value="1.0" />
<meta-data android:name="io.sentry.session-replay.redact-all-text" android:value="false" />
<meta-data android:name="io.sentry.session-replay.redact-all-images" android:value="false" />

Je vous invite à consulter la documentation très complète pour comprendre l'action des différents paramètres et notamment la partie confidentialité avec la biffure des textes ou images : https://docs.sentry.io/platforms/android/session-replay/

Pour l'exemple j'utilise une application de démonstration qui exécute ce code lors de l'appui sur le bouton enveloppe pour déclencher une exception :

val tab = intArrayOf(1,2)
Log.d("", "onCreate: "+ tab[4])

Vous pouvez également procéder de cette façon pour tester le bon fonctionnement :

Sentry.captureException(RuntimeException("This app uses Sentry! :)"))

Consultation du monitoring

La réception de l'erreur est instantanée sauf dans le cas d'une ANR (ApplicationC'est un programme conçu pour effectuer une ou plusieurs tâches. Réaliser des applications, c'est notre cœur de métier chez AXOPEN ! Not Responding) ou un redémarrage de l'application peut-être nécessaire pour effectuer l'envoi de la trace. 

6b964b79-03dd-48cc-8274-361c98607875.png

En visualisant les détails de la première erreur, nous pouvons voir la stack trace qui nous renseigne sur l'origine de l'erreur dans le code : 

86525b25-c0c1-4e23-bf59-0b970001b85a.png

Fonction très pratique, il est possible de lier Sentry à notre Git provider pour obtenir un lien direct de la trace avec notre source, pour cet exemple c'est peu pertinent, mais je vous invite à le faire dans vos projets plus complexes.

Nous avons ensuite la section Session Replay (si activée précédemment) avec le fil d'Ariane des actions de l'utilisateur :

L'application de démo comprend une Activité principale, un bouton NEXT pour passer d'un premier fragment à un second et un bouton enveloppe qui déclenche une exception. La vidéo des actions de l'utilisateur est synchronisée avec le fil d'Ariane, ce qui permet de connaitre les actions précédentes qui ont pu conduire à la levée de cette exception.

Il y a ensuite diverses informations très complètes sur l'appareil utilisé, la version des dépendances utilisées ainsi que diverses informations qui peuvent être plus ou moins pertinentes en fonction du bug que nous cherchons à identifier.

Analyse des performances API/Front

Dans cette section, nous allons nous attarder sur le volet insights que propose Sentry pour suivre le comportement de notre application.

J'ai choisi de monitorer un projet Angular/.NET en suivant les instructions fournies par Sentry pour l'intégration. 

6e7e119a-33cb-4084-986c-8e06854ac6e9.png

Implémentation dans un projet Angular

Ainsi pour le Front Angular 18 j'ai ajouté les packages suivants via NPM :

  • angular-http-server
  • @sentry/angular
  • @sentry/cli

Puis ajouté aux fichiers :

angular.json

{
  "projects": {
    "your-project": {
      "architect": {
        "build": {
          "options": {
            "sourceMap": true
          },
        },
      }
    }
  }
}

package.json

{
  "name": "...",
  "version": "2.5.3",
  "scripts": {
    "build_and_start_sentry": "ng build && npm run sentry:sourcemaps && cd .\dist\angular-front\browser && angular-http-server -p 4200",
    "sentry:sourcemaps": "sentry-cli sourcemaps inject --org sentry --project angular-front ./dist && sentry-cli --url http://192.168.1.200:9000/ sourcemaps upload --org sentry --project angular-front ./dist"
    ...
  },
  ...
}

Bonus & Explication sourcemaps

L'upload des fichiers sourcesmaps dans Sentry est recommandé si vous voulez déboguer votre projet.

Cela permet d'afficher directement le numéro de ligne et le code à l'origine du crash dans vos stackTraces :

 

00004757-dd57-4a92-9a9d-156c5a88e024.png

AngularAngular est un framework de développement JavaScript populaire basé sur TypeScript. ne génère pas de fichier sourcemap en mode développement, ce qui nécessite de compiler le projet, d'uploader les sourcesmaps dans sentry et de lancer la version compilée, dans l'exemple via angular-http-server. C'est ce que permet de faire le script build_and_start_sentry.

\ Le second intérêt d'utiliser des sources compilées est le test de performance de chargement de page similaire à Lighthouse intégré à Sentry, qui n'est pas utilisable (car ne reflète pas le fonctionnement de production) en mode développement avec la compilation Angular dynamique.

\ Les fichiers angular.json et package.json sont modifiés automatiquement si vous utilisez la cli interactive proposée par Sentry :

npx @sentry/wizard@latest -i sourcemaps

N'oubliez pas d'ajouter && angular-http-server -p votre_port à la fin du script de build.

Un fichier .sentryclirc est créé à la racine du projet avec le token d'authentification.

main.ts

import * as Sentry from "@sentry/angular";

Sentry.init({
  release: '2.5.3', // Vous pouvez spécifier la release du projet pour avoir un classement dans Sentry 
  dsn: "http://fa98649354db8751f3e4b3ff7f67c9da@192.168.1.200:9000/7",
  integrations: [
    Sentry.browserTracingIntegration(),
    Sentry.replayIntegration({
      maskAllText: false,
      blockAllMedia: false,
    }),
  ],
  // Tracing
  tracesSampleRate: 1.0, //  Capture 100% of the transactions
  // Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled
  tracePropagationTargets: ["localhost", /^https:\/\/yourserver\.io\/api/],
  // Session Replay
  replaysSessionSampleRate: 1.0, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production.
  replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.
});

app.module.ts

import * as Sentry from "@sentry/angular";

providers: [
  // -- Sentry : Bien spécifier les providers Sentry en premier
    {
      provide: ErrorHandler,
      useValue: Sentry.createErrorHandler({
        showDialog: true,
      }),
    },
    {
      provide: Sentry.TraceService,
      deps: [Router],
    },
    {
      provide: APP_INITIALIZER,
      useFactory: () => () => {},
      deps: [Sentry.TraceService],
      multi: true,
    },
  // -- Sentry : Suivi des providers de votre projet 
    {...},
    {provide: HTTP_INTERCEPTORS, ...},
    ...,
  ]

Attention, pensez à désactiver votre adblock lors de l'utilisation de l'outil si vous utilisez une adresse IP à la place de 127.0.0.1 ou localhost, sans quoi les requêtes de reporting seront bloquées.

Une astuce pour ne pas être confronté au blocage de l'outil par l'adblock de vos utilisateurs est d'intégrer un endpoint de relay/tunnel/proxy à votre API dédié aux appels Sentry. De cette façon les requêtes ne seront plus bloquées, car l'adresse appelée par l'application cliente sera tout naturellement celle de votre backend. Je vous conseille de consulter le git de Sentry pour plus d'information.

Implémentation dans un projet .Net

Pour l'API en .Net 7, j'ai ajouté les packages suivants via nuget :

  • Sentry
  • Sentry.AspNetCore
  • Sentry.Extensions.Logging
  • Sentry.Profiling

Puis ajouter au fichier Program.cs le code suivant :

using Sentry.Profiling;

public static void Main(string[] args)
{
    IHost host = CreateHostBuilder(args).Build();
    ...
    host.Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {  // -- Sentry
            webBuilder.UseSentry(options =>
                {
                    options.Dsn = "http://f086a7bcbc321eb035fd9f5a757fced5@192.168.1.200:9000/6";
                    options.Debug = true; // Pour voir plus de détails dans les logs de débogage
                    options.AutoSessionTracking = true;
                    // Set TracesSampleRate to 1.0 to capture 100%
                    // of transactions for tracing.
                    // We recommend adjusting this value in production.
                    options.TracesSampleRate = 1.0;

                    // Sample rate for profiling, applied on top of othe TracesSampleRate,
                    // e.g. 0.2 means we want to profile 20 % of the captured transactions.
                    // We recommend adjusting this value in production.
                    options.ProfilesSampleRate = 1.0;
                    // Requires NuGet package: Sentry.Profiling
                    // Note: By default, the profiler is initialized asynchronously. This can
                    // be tuned by passing a desired initialization timeout to the constructor.
                    options.AddIntegration(new ProfilingIntegration(
                        // During startup, wait up to 500ms to profile the app startup code.
                        // This could make launching the app a bit slower so comment it out if you
                        // prefer profiling to start asynchronously
                        TimeSpan.FromMilliseconds(500)
                    ));
                })
            // -- Sentry 
                .UseXXXX<Xxxx>();
        });

Analyse des insights

Après quelques utilisations de l'application pour générer de la donnée, nous pouvons étudier son comportement en fonction des actions utilisateur.

Routes

Dans l'onglet Requests, nous pouvons visualiser les routes du front Angular appelées avec leur temps de chargement et le pourcentage de code de retour HTTP 300, 400, 500 associé. 

02ad218f-9beb-47b0-ba67-74d121d79e1c.png

Voici ce que donne le détail de l'évènement d'une route : 

b70cefa9-cf8b-4458-8afd-30780960e4bb.png
L'une des forces de Sentry est de pouvoir lier automatiquement les appels Front et ses appels API aux requêtes SQL. En un coup d'œil dans cet exemple, l'outil met en évidence qu'une requête est plus lente que les autres et mérite potentiellement une optimisation pour accélérer le chargement de cette page.

Appels API

L'onglet Profiles permet la même remontée d'information de latence des appels API avec une précision aux 50, 75, 95 et 99 centilles : 

c36743c9-9446-462c-89e8-1e4a73ee7666.png

Requêtes SQL

La page requêtes permet la visualisation des performances moyennes d'exécution pour chacune des requêtes effectuées par le back. Les requêtes analysées peuvent avoir été écrites manuellement ou construites par EntityFramework dans le cas de .Net ou Hibernate dans le cadre du Java/Springboot

44075b82-1ac9-45cb-9e1e-330fab8c29d7.png

Expérience utilisateur

Pour mesurer l'expérience utilisateur (et performance SEO), Sentry propose deux options. La première destinée aux projets Web est une approche similaire à Lighthouse [LIEN VERS ARTICLE AXO] qui mesure l'impact du chargement des pages sur la navigation par le calcul d'un score de performance.

Il est important de noter que Lighthouse s'exécute sur des données dites de laboratoire à l'instant T où vous exécutez une analyse sur votre machine, là où Sentry fournit des données réelles de chargement chez les utilisateurs. 

c95ee5c0-6293-45b2-b394-92751c20137a.png

Le score est composé de 5 critères :

  1. Largest Contentful Paint (LCP) : Mesure la performance du chargement de la page.
  2. First Contentful Paint (FCP) : Mesure le temps passé avant que le premier contenu soit rendu (affiché)
  3. Interaction to Next Paint (INP) : Mesure le temps de réponse lors d'une interaction utilisateur. La latence entre le clic sur un bouton et l'apparition d'une information visuelle sur la page informant que le clic utilisateur a fonctionné.
  4. Cumulative Layout Shift (CLS) : Mesure la stabilité de la page (si des images décalent des éléments sur votre page lors de son chargement)
  5. Time To First Byte (TTFB) : Mesure le temps nécessaire au navigateur de l'utilisateur pour recevoir le premier octet du contenu de la page (il n'est pas question de rendu ici)

La seconde solution destinée aux projets mobiles mesure les temps d'affichages de chaque activité et fragment. 

6e198d62-5ae8-4968-9a31-ffd5d9678094.png

Conclusion

C'est ainsi que ce tour de découverte de Sentry s'achève. Vous savez à présent comment installer Sentry en auto hébergé, l'initialiser, instancier des projets mobiles, front web et API ainsi qu'analyser les données remontées par l'outil afin d'optimiser ou corriger votre application.

Voici un tableau comparatif non exhaustif des différentes fonctionnalités :

Fonctionnalité Présent dans Sentry Présent dans Firebase Crashlytics
Bugs et crashs
Reporting des erreurs en temps réel Oui Non (Au redémarrage uniquement)
Suivi des crashs Oui Oui
Intégration avec d'autres outils Oui (Git, Gitlab, Jira) Non
Traçabilité des événements (Breadcrumbs) Oui Non
Session Replay Oui Non
Performances
Monitoring des performances Oui Non
Profiling des performances (route, endpoints, SQL...) Oui Non
Alertes personnalisables Oui Non
Compatibilité Front (Client) Liste non exhaustive
Android natif Oui Oui
iOS natif Oui Oui
Capacitor Oui Non
Symfony Oui Non
Angular Oui Non
Compatibilité Back/API (Serveur) Liste non exhaustive
Java Springboot Oui Non
(ASP) .Net Core Oui Non