Megosztás a következőn keresztül:


Naplózás hozzáadása Service Fabric-alkalmazáshoz

Az alkalmazásnak elegendő információval kell rendelkeznie ahhoz, hogy hibakeresést hajtson létre, ha problémák merülnek fel. A naplózás az egyik legfontosabb dolog, amelyet hozzáadhat a Service Fabric-alkalmazáshoz. Ha hiba történik, a jó naplózás lehetővé teszi a hibák kivizsgálását. A naplóminták elemzésével módot találhat az alkalmazás teljesítményének vagy kialakításának javítására. Ez a dokumentum néhány különböző naplózási lehetőséget mutat be.

EventFlow

Az EventFlow-kódtárcsomag lehetővé teszi az alkalmazások számára, hogy meghatározzák, hogy milyen diagnosztikai adatokat gyűjtsenek, és hová kell kimenetelniük. A diagnosztikai adatok a teljesítményszámlálóktól az alkalmazáskövetésekig bármi lehetnek. A folyamat az alkalmazáshoz hasonlóan fut, így a kommunikációs többletterhelés minimálisra csökken. Az EventFlow-ról és a Service Fabricről további információt az Azure Service Fabric Event Aggregation with EventFlow szolgáltatásban talál.

Strukturált EventSource-események használata

Az üzenetesemények használati eset alapján történő definiálásával adatokat csomagolhat az eseményről az esemény kontextusában. Egyszerűbben kereshet és szűrhet a megadott eseménytulajdonságok neve vagy értékei alapján. A rendszerállapot kimenetének strukturálása megkönnyíti az olvasást, de több gondolkodást és időt igényel az egyes használati esetek eseményeinek definiálásához.

Egyes eseménydefiníciók a teljes alkalmazásban megoszthatóak. Egy metódus indítási vagy leállítási eseménye például egy alkalmazás számos szolgáltatásában újra felhasználható. Egy tartományspecifikus szolgáltatás, például egy rendelési rendszer, rendelkezhet egy CreateOrder-eseménysel , amelynek saját egyedi eseménye van. Ez a megközelítés számos eseményt generálhat, és szükség lehet az azonosítók projektcsapatok közötti összehangolására.

[EventSource(Name = "MyCompany-VotingState-VotingStateService")]
internal sealed class ServiceEventSource : EventSource
{
    public static readonly ServiceEventSource Current = new ServiceEventSource();

    // The instance constructor is private to enforce singleton semantics.
    private ServiceEventSource() : base() { }

    ...

    // The ServiceTypeRegistered event contains a unique identifier, an event attribute that defined the event, and the code implementation of the event.
    private const int ServiceTypeRegisteredEventId = 3;
    [Event(ServiceTypeRegisteredEventId, Level = EventLevel.Informational, Message = "Service host process {0} registered service type {1}", Keywords = Keywords.ServiceInitialization)]
    public void ServiceTypeRegistered(int hostProcessId, string serviceType)
    {
        WriteEvent(ServiceTypeRegisteredEventId, hostProcessId, serviceType);
    }

    // The ServiceHostInitializationFailed event contains a unique identifier, an event attribute that defined the event, and the code implementation of the event.
    private const int ServiceHostInitializationFailedEventId = 4;
    [Event(ServiceHostInitializationFailedEventId, Level = EventLevel.Error, Message = "Service host initialization failed", Keywords = Keywords.ServiceInitialization)]
    public void ServiceHostInitializationFailed(string exception)
    {
        WriteEvent(ServiceHostInitializationFailedEventId, exception);
    }

    ...

Az EventSource általános használata

Mivel adott események definiálása nehéz lehet, sokan meghatároznak néhány eseményt olyan közös paraméterkészlettel, amely általában sztringként adja ki az információkat. A strukturált szempontok nagy része elveszik, és nehezebb keresni és szűrni az eredményeket. Ebben a megközelítésben néhány olyan esemény van meghatározva, amelyek általában a naplózási szinteknek felelnek meg. Az alábbi kódrészlet hibakeresést és hibaüzenetet határoz meg:

[EventSource(Name = "MyCompany-VotingState-VotingStateService")]
internal sealed class ServiceEventSource : EventSource
{
    public static readonly ServiceEventSource Current = new ServiceEventSource();

    // The Instance constructor is private, to enforce singleton semantics.
    private ServiceEventSource() : base() { }

    ...

    private const int DebugEventId = 10;
    [Event(DebugEventId, Level = EventLevel.Verbose, Message = "{0}")]
    public void Debug(string msg)
    {
        WriteEvent(DebugEventId, msg);
    }

    private const int ErrorEventId = 11;
    [Event(ErrorEventId, Level = EventLevel.Error, Message = "Error: {0} - {1}")]
    public void Error(string error, string msg)
    {
        WriteEvent(ErrorEventId, error, msg);
    }

    ...

A strukturált és általános rendszerállapot hibrid használata is jól működik. A strukturált rendszerállapot a hibák és metrikák jelentésére szolgál. Az általános események a mérnökök által a hibaelhárításhoz felhasznált részletes naplózáshoz használhatók.

Microsoft.Extensions.Logging

A ASP.NET Core-naplózás (Microsoft.Extensions.Logging NuGet-csomag) egy naplózási keretrendszer, amely egy szabványos naplózási API-t biztosít az alkalmazás számára. A többi naplózási háttérrendszer támogatása csatlakoztatható ASP.NET Core-naplózáshoz. Ez széles körű támogatást nyújt az alkalmazásba való naplózáshoz anélkül, hogy sok kódot kellene módosítania.

  1. Adja hozzá a Microsoft.Extensions.Logging NuGet-csomagot a használni kívánt projekthez. Emellett vegye fel a szolgáltatói csomagokat is. További információ: Naplózás a ASP.NET Core-ban.

  2. Adjon hozzá egy felhasználói irányelvet a Microsoft.Extensions.Logging szolgáltatásfájlhoz.

  3. Definiáljon egy privát változót a szolgáltatásosztályon belül.

    private ILogger _logger = null;
    
  4. A szolgáltatásosztály konstruktorában adja hozzá a következő kódot:

    _logger = new LoggerFactory().CreateLogger<Stateless>();
    
  5. Kezdje el a kód rendszerezését a metódusokban. Íme néhány példa:

    _logger.LogDebug("Debug-level event from Microsoft.Logging");
    _logger.LogInformation("Informational-level event from Microsoft.Logging");
    
    // In this variant, we're adding structured properties RequestName and Duration, which have values MyRequest and the duration of the request.
    // Later in the article, we discuss why this step is useful.
    _logger.LogInformation("{RequestName} {Duration}", "MyRequest", requestDuration);
    

Más naplózási szolgáltatók használata

Egyes külső szolgáltatók az előző szakaszban ismertetett megközelítést használják, beleértve a Serilogot, az NLogot és a Loggrot. Ezeket csatlakoztathatja ASP.NET Core-naplózáshoz, vagy külön is használhatja őket. A Serilog egy olyan funkcióval rendelkezik, amely kibővíti a naplózóktól küldött összes üzenetet. Ez a funkció hasznos lehet a szolgáltatásnév, a típus és a partíció adatainak kimenetéhez. Ha ezt a képességet a ASP.NET Core-infrastruktúrában szeretné használni, hajtsa végre az alábbi lépéseket:

  1. Adja hozzá a Serilog,Serilog.Extensions.Logging, Serilog.Sinks.Literate és Serilog.Sinks.Observable NuGet csomagokat a projekthez.

  2. Hozzon létre egy LoggerConfiguration és a naplózó példányt.

    Log.Logger = new LoggerConfiguration().WriteTo.LiterateConsole().CreateLogger();
    
  3. Adjon hozzá egy argumentumot Serilog.ILogger a szolgáltatáskonstruktorhoz, és adja át az újonnan létrehozott naplózót.

    ServiceRuntime.RegisterServiceAsync("StatelessType", context => new Stateless(context, Log.Logger)).GetAwaiter().GetResult();
    
  4. A szolgáltatáskonstruktorban hozza létre a ServiceTypeName, a ServiceName, a PartitionId és az InstanceId tulajdonságnövelőit.

    public Stateless(StatelessServiceContext context, Serilog.ILogger serilog)
        : base(context)
    {
        PropertyEnricher[] properties = new PropertyEnricher[]
        {
            new PropertyEnricher("ServiceTypeName", context.ServiceTypeName),
            new PropertyEnricher("ServiceName", context.ServiceName),
            new PropertyEnricher("PartitionId", context.PartitionId),
            new PropertyEnricher("InstanceId", context.ReplicaOrInstanceId),
        };
    
        serilog.ForContext(properties);
    
        _logger = new LoggerFactory().AddSerilog(serilog.ForContext(properties)).CreateLogger<Stateless>();
    }
    
  5. A kódot ugyanúgy kell beállítani, mintha a Serilog nélküli ASP.NET Core-t használták volna.

    Feljegyzés

    Javasoljuk, hogy ne használja a statikust Log.Logger az előző példában. A Service Fabric egyetlen folyamaton belül több azonos szolgáltatástípusú példányt is üzemeltethet. Ha a statikust Log.Loggerhasználja, a tulajdonságnövelők utolsó írója az összes futó példány értékeit jeleníti meg. Ez az egyik oka annak, hogy a _logger változó a szolgáltatásosztály privát tag változója. Emellett elérhetővé kell tennie a _logger gyakori kódot is, amely a szolgáltatások között használható.

Következő lépések

  • További információ az alkalmazásfigyelésről a Service Fabricben.
  • További információ az EventFlow és a Windows Azure Diagnostics naplózásáról.