Logboekregistratie toevoegen aan uw Service Fabric-toepassing
Uw toepassing moet voldoende informatie verstrekken om deze forensisch op te sporen wanneer er problemen optreden. Logboekregistratie is een van de belangrijkste dingen die u kunt toevoegen aan uw Service Fabric-toepassing. Wanneer er een fout optreedt, kan een goede logboekregistratie u een manier bieden om fouten te onderzoeken. Door logboekpatronen te analyseren, kunt u manieren vinden om de prestaties of het ontwerp van uw toepassing te verbeteren. In dit document ziet u een aantal verschillende opties voor logboekregistratie.
EventFlow
Met de EventFlow-bibliotheeksuite kunnen toepassingen definiëren welke diagnostische gegevens moeten worden verzameld en waar ze moeten worden uitgevoerd. Diagnostische gegevens kunnen van alles zijn, van prestatiemeteritems tot toepassingstraceringen. Deze wordt uitgevoerd in hetzelfde proces als de toepassing, dus de communicatieoverhead wordt geminimaliseerd. Zie Azure Service Fabric Event Aggregation met EventFlow voor meer informatie over EventFlow en Service Fabric.
Gestructureerde EventSource-gebeurtenissen gebruiken
Als u bericht gebeurtenissen per use-case definieert, kunt u gegevens over de gebeurtenis verpakken in de context van de gebeurtenis. U kunt gemakkelijker zoeken en filteren op basis van de namen of waarden van de opgegeven gebeurteniseigenschappen. Het structureren van de instrumentatie-uitvoer maakt het gemakkelijker te lezen, maar vereist meer gedachten en tijd om een gebeurtenis te definiëren voor elke use-case.
Sommige gebeurtenisdefinities kunnen worden gedeeld in de hele toepassing. Een methode voor het starten of stoppen van een methode zou bijvoorbeeld opnieuw worden gebruikt voor veel services in een toepassing. Een domeinspecifieke service, zoals een ordersysteem, kan een CreateOrder-gebeurtenis hebben, die een eigen unieke gebeurtenis heeft. Deze benadering kan veel gebeurtenissen genereren en mogelijk coördinatie van id's in projectteams vereisen.
[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);
}
...
EventSource algemeen gebruiken
Omdat het definiëren van specifieke gebeurtenissen lastig kan zijn, definiëren veel mensen een aantal gebeurtenissen met een gemeenschappelijke set parameters die hun informatie over het algemeen als een tekenreeks uitvoeren. Veel van het gestructureerde aspect gaat verloren en het is moeilijker om de resultaten te zoeken en te filteren. In deze benadering worden enkele gebeurtenissen gedefinieerd die meestal overeenkomen met de logboekregistratieniveaus. Het volgende codefragment definieert een foutopsporing en foutbericht:
[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);
}
...
Het gebruik van een hybride van gestructureerde en algemene instrumentatie kan ook goed werken. Gestructureerde instrumentatie wordt gebruikt voor het rapporteren van fouten en metrische gegevens. Algemene gebeurtenissen kunnen worden gebruikt voor de gedetailleerde logboekregistratie die door technici wordt gebruikt voor probleemoplossing.
Microsoft.Extensions.Logging
Het ASP.NET Core-logboekregistratie (Microsoft.Extensions.Logging NuGet-pakket) is een framework voor logboekregistratie dat een standaard-API voor logboekregistratie biedt voor uw toepassing. Ondersteuning voor andere back-ends voor logboekregistratie kan worden aangesloten op ASP.NET Core-logboekregistratie. Dit biedt u een breed scala aan ondersteuning voor het aanmelden in uw toepassing wordt verwerkt, zonder dat u veel code hoeft te wijzigen.
Voeg het NuGet-pakket Microsoft.Extensions.Logging toe aan het project dat u wilt instrumenteren. Voeg ook providerpakketten toe. Zie Logboekregistratie in ASP.NET Core voor meer informatie.
Voeg een using-instructie voor Microsoft.Extensions.Logging toe aan uw servicebestand.
Definieer een privévariabele binnen uw serviceklasse.
private ILogger _logger = null;
Voeg in de constructor van uw serviceklasse deze code toe:
_logger = new LoggerFactory().CreateLogger<Stateless>();
Begin met het instrumenteren van uw code in uw methoden. Hier volgen enkele voorbeelden:
_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);
Andere logboekproviders gebruiken
Sommige externe providers gebruiken de benadering die in de voorgaande sectie wordt beschreven, waaronder Serilog, NLog en Loggr. U kunt deze allemaal aansluiten op ASP.NET Core-logboekregistratie of u kunt ze afzonderlijk gebruiken. Serilog heeft een functie waarmee alle berichten die worden verzonden vanuit een logboekregistratie worden verrijkt. Deze functie kan handig zijn om de servicenaam, het type en de partitiegegevens uit te voeren. Voer de volgende stappen uit om deze mogelijkheid te gebruiken in de ASP.NET Core-infrastructuur:
Voeg de Pakketten Serilog, Serilog.Extensions.Logging, Serilog.Sinks.Literate en Serilog.Sinks.Observable NuGet toe aan het project.
Maak een
LoggerConfiguration
en het loggerexemplaren.Log.Logger = new LoggerConfiguration().WriteTo.LiterateConsole().CreateLogger();
Voeg een
Serilog.ILogger
argument toe aan de serviceconstructor en geef de zojuist gemaakte logboekregistratie door.ServiceRuntime.RegisterServiceAsync("StatelessType", context => new Stateless(context, Log.Logger)).GetAwaiter().GetResult();
In de serviceconstructor maakt u eigenschapverrijkers voor ServiceTypeName, ServiceName, PartitionId en InstanceId.
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>(); }
Instrumenteer de code hetzelfde als als als u ASP.NET Core zonder Serilog gebruikte.
Notitie
U wordt aangeraden de statische
Log.Logger
gegevens niet te gebruiken in het voorgaande voorbeeld. Service Fabric kan meerdere exemplaren van hetzelfde servicetype binnen één proces hosten. Als u de statischeLog.Logger
waarde gebruikt, geeft de laatste schrijver van de eigenschappenverrijkers waarden weer voor alle exemplaren die worden uitgevoerd. Dit is een van de redenen waarom de _logger variabele een privélidvariabele van de serviceklasse is. U moet ook de_logger
beschikbare voor algemene code maken, die in verschillende services kan worden gebruikt.
Volgende stappen
- Lees meer informatie over toepassingsbewaking in Service Fabric.
- Meer informatie over logboekregistratie met EventFlow en Windows Azure Diagnostics.