# Seq pour ASP.NET Logging - Tracing avec SerilogTracing

<datetime class="hidden">2024-08-31T11:20</datetime>

<!--category-- ASP.NET, Seq, Serilog -->
# Introduction

Dans la partie précédente, je vous ai montré comment mettre en place [auto-hébergement pour Seq en utilisant ASP.NET Core ](/blog/selfhostingseq). Maintenant que nous l’avons installée, il est temps d’utiliser davantage de ses fonctionnalités ' pour permettre un suivi plus complet

[TOC]

# Traçage

Le traçage est comme la saisie d’un enregistrement.
Dans ce site, je l’utilise pour repérer rapidement les problèmes. Justement parce qu’il s’agit d’un site de loisirs, cela ne signifie pas que j’abandonne mes normes professionnelles.

## Établissement de Serilog

Il est très simple d'établir le suivi avec Serilog en utilisant [Traçage Serilog](https://github.com/serilog-tracing/serilog-tracing) package. Vous devez d’abord installer les paquets:

Nous ajoutons ici aussi le bassin Console et le bassins Seq.

```bash
dotnet add package SerilogTracing
dotnet add package SerilogTracing.Expressions
dotnet add package Serilog.Sinks.Console
dotnet add package Serilog.Sinks.Seq
```

La console est toujours utile pour le débugging et Seq est ce que nous 're ici pour. Seq comporte également un certain nombre de 'enrichersM SK3 qui peuvent ajouter des informations supplémentaires à vos logsMSC4

```bash
  "Serilog": {
    "Enrich": ["FromLogContext", "WithThreadId", "WithThreadName", "WithProcessId", "WithProcessName", "FromLogContext"],
    "MinimumLevel": "Warning",
    "WriteTo": [
        {
          "Name": "Seq",
          "Args":
          {
            "serverUrl": "http://seq:5341",
            "apiKey": ""
          }
        },
      {
        "Name": "Console"
      },
      {
        "Name": "File",
        "Args": {
          "path": "logs/applog-.txt",
          "rollingInterval": "Day"
        }
      }

    ],
    "Properties": {
      "ApplicationName": "mostlylucid"
    }
  }
```

Pour utiliser ces enrichisseurs, vous devez les ajouter à votre `Serilog` Configuration dans votre `appsettings.json` file. Vous devez aussi installer tous les enrichisseurs séparés à l'aide de Nuget

Il s’agit d’une des bonnes et mauvaises choses de Serilog, vous terminez par installer une BUNCH de paquets ; mais cela signifie que vous ajoutez seulement ce dont vous avez besoin, et non un seul paquet monolithique.
Voici la mine de '

![Enrichisseurs Serilog](serilogenrichers.png)

Avec toutes ces bombes, j’ai une très bonne sortie de log dans Seq.

![Erreur de Serilog Seq](serilogerror.png)

Vous voyez ici le message d’erreur, la trace du cheminement de l’écluse , l’ID du thread, l'ID du processus et le nom du processusM SK3 C’est tout une information utile lorsque vous MSC4essayez de repérer un problème

Il convient de noter que I' a établi `  "MinimumLevel": "Warning",` dans mon `appsettings.json` file. Cela signifie que seuls les avertissements et ceux ci-dessus seront enregistrés à Seq.

Cependant, dans Seq vous pouvez aussi spécifier cette valeur par clé Api; pour que vous puissiez avoir `Information` (ou si vous êtes vraiment enthousiaste `Debug`) réglage de l'enregistrement ici et limiter ce que Seq capte en réalité par la clé API.

![Key Seq Api](apikey.png)

Remarque: vous avez toujours une app à l’en-tête, vous pouvez aussi le rendre plus dynamique de sorte que vous puissiez régler le niveau en vol ). Voir la [Réservoir Seq ](https://github.com/datalust/serilog-sinks-seq)pour plus de détails.

```json
{
    "Serilog":
    {
        "LevelSwitches": { "$controlSwitch": "Information" },
        "MinimumLevel": { "ControlledBy": "$controlSwitch" },
        "WriteTo":
        [{
            "Name": "Seq",
            "Args":
            {
                "serverUrl": "http://localhost:5341",
                "apiKey": "yeEZyL3SMcxEKUijBjN",
                "controlLevelSwitch": "$controlSwitch"
            }
        }]
    }
}
```

## Traçage

Maintenant, nous ajoutons le Tracing, de nouveau en utilisant SerilogTracing it's pretty simple . Nous avons la même configuration que précédemment mais nous ajoutons un nouveau puits pour le traçageM SK3

```bash
dotnet add package SerilogTracing
dontet add package SerilogTracing.Expressions
dotnet add SerilogTracing.Instrumentation.AspNetCore
```

Nous ajoutons également un paquet supplémentaire pour enregistrer des informations plus détaillées sur le noyau de l’aspnet.

### Établissement dans `Program.cs`

Maintenant, nous pouvons commencer à utiliser réellement le traçage. Nous devons d’abord ajouter le tracé à notre `Program.cs` fichier.

```csharp
    using var listener = new ActivityListenerConfiguration()
        .Instrument.HttpClientRequests().Instrument
        .AspNetCoreRequests()
        .TraceToSharedLogger();
```

Le traçage utilise le concept de 'ActivitésM SK1 qui représentent une unité de travail . Vous pouvez lancer une activité, faire un certain travail puis l'arrêterMSC4 Ce concept est utile pour suivre une demande par divers servicesMNK5

Dans ce cas, nous ajoutons un traçage supplémentaire pour les demandes de HttpClient et celles d’AspNetCore. Nous avons également ajouté `TraceToSharedLogger` qui affichera l'activité au même loggeur que le reste de notre application.

## Utilisation du traçage dans un service

Maintenant que nous avons mis en place le traçage, nous pouvons commencer à l'utiliser dans notre application. C'est un exemple de service qui utilise le Traçage.

```csharp
    public async Task<PostListViewModel> GetPostsByCategory(string category, int page = 1, int pageSize = 10,
        string language = MarkdownBaseService.EnglishLanguage)
    {
        using var activity = Log.Logger.StartActivity("GetPostsByCategory {Category}, {Page}, {PageSize}, {Language}",
            new { category, page, pageSize, language });
        try
        {
            var count = await NoTrackingQuery()
                .Where(x => x.Categories.Any(c => c.Name == category) && x.LanguageEntity.Name == language)
                .CountAsync();
            var posts = await PostsQuery()
                .Where(x => x.Categories.Any(c => c.Name == category) && x.LanguageEntity.Name == language)
                .OrderByDescending(x => x.PublishedDate.DateTime)
                .Skip((page - 1) * pageSize)
                .Take(pageSize)
                .ToListAsync();

            var languages = await GetLanguagesForSlugs(posts.Select(x => x.Slug).ToList());
            var postListViewModel = new PostListViewModel
            {
                Page = page,
                PageSize = pageSize,
                TotalItems = count,
                Posts = posts.Select(x => x.ToListModel(
                    languages.FirstOrDefault(entry => entry.Key == x.Slug).Value.ToArray())).ToList()
            };
            activity.Complete();
            return postListViewModel;
        }
        catch (Exception e)
        {
            activity.Complete(LogEventLevel.Error, e);
        }

        return new PostListViewModel();
    }
```

Les lignes importantes sont les suivantes ::

```csharp
  using var activity = Log.Logger.StartActivity("GetPostsByCategory {Category}, {Page}, {PageSize}, {Language}",
            new { category, page, pageSize, language });
```

Cela démarre une nouvelle 'activité ' qui est une unité de travail. ElleM SK3 est utile pour suivre une demande par le biais de plusieurs servicesMSC4
Comme nous l’avons emballé dans une déclaration d’utilisation, cela complétera et éliminera à la fin de notre méthode mais c’est une bonne pratique de le terminer explicitement.

```csharp
            activity.Complete();
```

Dans le cadre de notre gestion des exceptions, nous complétons également l’activité mais avec un niveau d’erreur et l’exception. Ceci est utile pour repérer les problèmes dans votre application.

## Utilisation des traces

Maintenant que nous avons tout ce setup, nous pouvons commencer à l'utiliser. Voici'est un exemple d'une trace dans ma applicationM SK2

![Trace Http](httptrace.png)

Vous pouvez voir les étapes multiples d’un seul message ainsi que toutes les demandes et tous les temps des clients de Http.

Remarque J'utilise Postgres pour ma base de données, contrairement au serveur SQL, le pilote npgsql a un support natif pour la traçage afin que vous puissiez obtenir des données très utiles à partir de vos demandes de bases de données comme l'application SQL exécutée , horaires etcM SK2 Ces données sont enregistrées sous 'spansMSC4 dans Seq et voyez liek les suivants:

```json
  "@t": "2024-08-31T15:23:31.0872838Z",
"@mt": "mostlylucid",
"@m": "mostlylucid",
"@i": "3c386a9a",
"@tr": "8f9be07e41f7121cbf2866c6cd886a90",
"@sp": "8d716c5f01ad07a0",
"@st": "2024-08-31T15:23:31.0706848Z",
"@ps": "622f1c86a8b33304",
"@sk": "Client",
"ActionId": "91f5105d-93fa-4e7f-9708-b1692e046a8a",
"ActionName": "Mostlylucid.Controllers.HomeController.Index (Mostlylucid)",
"ApplicationName": "mostlylucid",
"ConnectionId": "0HN69PVEQ9S7C",
"ProcessId": 30496,
"ProcessName": "Mostlylucid",
"RequestId": "0HN69PVEQ9S7C:00000015",
"RequestPath": "/",
"SourceContext": "Npgsql",
"ThreadId": 47,
"ThreadName": ".NET TP Worker",
"db.connection_id": 1565,
"db.connection_string": "Host=localhost;Database=mostlylucid;Port=5432;Username=postgres;Application Name=mostlylucid",
"db.name": "mostlylucid",
"db.statement": "SELECT t.\"Id\", t.\"ContentHash\", t.\"HtmlContent\", t.\"LanguageId\", t.\"Markdown\", t.\"PlainTextContent\", t.\"PublishedDate\", t.\"SearchVector\", t.\"Slug\", t.\"Title\", t.\"UpdatedDate\", t.\"WordCount\", t.\"Id0\", t0.\"BlogPostId\", t0.\"CategoryId\", t0.\"Id\", t0.\"Name\", t.\"Name\"\r\nFROM (\r\n    SELECT b.\"Id\", b.\"ContentHash\", b.\"HtmlContent\", b.\"LanguageId\", b.\"Markdown\", b.\"PlainTextContent\", b.\"PublishedDate\", b.\"SearchVector\", b.\"Slug\", b.\"Title\", b.\"UpdatedDate\", b.\"WordCount\", l.\"Id\" AS \"Id0\", l.\"Name\", b.\"PublishedDate\" AT TIME ZONE 'UTC' AS c\r\n    FROM mostlylucid.\"BlogPosts\" AS b\r\n    INNER JOIN mostlylucid.\"Languages\" AS l ON b.\"LanguageId\" = l.\"Id\"\r\n    WHERE l.\"Name\" = @__language_0\r\n    ORDER BY b.\"PublishedDate\" AT TIME ZONE 'UTC' DESC\r\n    LIMIT @__p_2 OFFSET @__p_1\r\n) AS t\r\nLEFT JOIN (\r\n    SELECT b0.\"BlogPostId\", b0.\"CategoryId\", c.\"Id\", c.\"Name\"\r\n    FROM mostlylucid.blogpostcategory AS b0\r\n    INNER JOIN mostlylucid.\"Categories\" AS c ON b0.\"CategoryId\" = c.\"Id\"\r\n) AS t0 ON t.\"Id\" = t0.\"BlogPostId\"\r\nORDER BY t.c DESC, t.\"Id\", t.\"Id0\", t0.\"BlogPostId\", t0.\"CategoryId\"",
"db.system": "postgresql",
"db.user": "postgres",
"net.peer.ip": "::1",
"net.peer.name": "localhost",
"net.transport": "ip_tcp",
"otel.status_code": "OK"
```

Vous pouvez voir que cela inclut presque tout ce dont vous avez besoin pour connaître la demande, l’ SQL exécutée , la chaîne de connexion, etc.

# En conclusion

I'je n’ai scratché que la surface du Tracing ici,ilM SK2est une zone de bit avec des défenseurs passionnés . J’espère que j’ai montré combien il est simple d’aller de l’avant avec un simple traçage à l’aide de Seq MST5 Serilog pour ASPMSC6Applications de base NETMSP7 De cette façon, je peux tirer beaucoup des avantages d’outils plus puissants comme Application Insights sans le coût d’Azure MST8les choses peuvent devenir trop coûteuses lorsque les registres sont grandsMst9