åã®èšäºã§ ãDiagnosticSourceã¡ã«ããºã ã«ã€ããŠèª¬æããããã䜿çšããŠSqlConnection
ã¯ã©ã¹ãšSqlCommand
ã¯ã©ã¹ãä»ããŠããŒã¿ããŒã¹ãžã®èŠæ±ãã€ã³ã¿ãŒã»ããããå®è¡æéã枬å®ããæ¹æ³ãç°¡åãªäŸã§ç€ºããŸããã
çŸåšãDiagnosticSourceã¯æ¢ã«AspNetCoreãEntityFrameworkCoreãHttpClientãããã³SqlClientã§äœ¿çšãããŠããŸã-ãããããç¬èªã®ã€ãã³ããéä¿¡ãããããã¯ã€ã³ã¿ãŒã»ããããã³åŠçã§ããŸãã
ãã®èšäºã§ã¯ãå®éã«ASP.NET Coreã¢ããªã±ãŒã·ã§ã³ã§DiagnosticSourceã䜿çšããæ¹æ³ã®ããã€ãã®äŸãæ€èšããŸãã
- ãµãŒãã¹éã®CorrelationIDããã³è»¢éããããŒ
- ã¡ããªãã¯ãšãã¬ãŒã¹ã®ã³ã¬ã¯ã·ã§ã³
- ãã®ã³ã°
ããã«ããã®èšäºã§ã¯ãåŠçã«äœ¿çšã§ããã¢ããªã±ãŒã·ã§ã³ã§äœ¿çšã§ããã€ãã³ãã®ãªã¹ããåéããããšã«ããŸããããŸãããããžã§ã¯ãã§DiagnosticSourceã¡ã«ããºã ã䜿çšããå Žåã«çºçããå¯èœæ§ã®ããèœãšãç©Žã«ã€ããŠã説æããŸãã
æ¢åã®ã€ãã³ã
äŸã®æ€èšã«ç§»ãåã«ãDiagnosticSourceãä»ããŠã€ãã³ããéä¿¡ããã³ã³ããŒãã³ããããã³ãããã®ã€ãã³ãã®ååãç解ããå¿
èŠããããŸãã æ®å¿µãªãããã€ãã³ãã®å®å
šãªãªã¹ãã¯ããã¥ã¡ã³ãã®ã©ãã«ãèšèŒãããŠããããGitHubã®ãœãŒã¹ã³ãŒãã§ã®ã¿èŠã€ããããšãã§ããŸãã
ãããã£ãŠãååšããã€ãã³ããç解ããæãç°¡åãªæ¹æ³ã¯ã IObserver<DiagnosticListener>
ããã³IObserver<KeyValuePair<string, object>>
ã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ããã¯ã©ã¹ãäœæãããã®äžã®DiagnosticListener
ã€ã³ã¹ã¿ã³ã¹ããµãã¹ã¯ã©ã€ãããã¢ããªã±ãŒã·ã§ã³ã§ãã£ãããããã€ãã³ãã確èªããããšã§ãã åæ§ã«ãåã€ãã³ãã§éä¿¡ããããã©ã¡ãŒã¿ãŒãå€å¥ã§ããŸãã
ã¿ã¹ã¯ãç°¡çŽ åããããã«ã4ã€ã®ã³ã³ããŒãã³ãã®æãæçšãªã€ãã³ãïŒããã¯å®å
šãªãªã¹ãã§ã¯ãããŸããïŒã®ããã€ããæ¢ã«åéããŠããŸãã
Microsoft.AspNetCoreMicrosoft.AspNetCore
ã³ã³ããŒãã³ãã®ã€ãã³ãã䜿çšãããšãASP.NET Coreã§ã®httpèŠæ±åŠçã®ã©ã€ãã€ãã³ããã€ã³ã¿ãŒã»ããã§ããŸãã
- Microsoft.AspNetCore.Hosting.HttpRequestIn.Start
- Microsoft.AspNetCore.Hosting.HttpRequestIn.Stop
ãããã®ã€ãã³ãã¯ãhttpèŠæ±ã®åŠçã®æåãšæåŸã«çºçããŸãã
- Microsoft.AspNetCore.Diagnostics.UnhandledException
æªåŠçã®äŸå€ã§çºçããŸãã ããã¯ããã®ã³ã³ããŒãã³ãã®äŸå€ãåŠçã§ããå¯äžã®å Žæã§ãã
- Microsoft.AspNetCore.Mvc.BeforeAction
- Microsoft.AspNetCore.Mvc.AfterAction
UseMvc
ã䜿çšãããšãã«è¿œå ãããããã«ãŠã§ã¢ã§httpèŠæ±ãåŠçããååŸã«çºçãUseMvc
ã å®è³ªçã«ã次ã®ã€ãã³ãã¯ãã¹ãŠ2ã€ã®éã§çºçããŸãã
- Microsoft.AspNetCore.Mvc.BeforeOnAuthorization
- Microsoft.AspNetCore.Mvc.AfterOnAuthorization
èš±å¯ã®ååŸã«çºçããŸãã
- Microsoft.AspNetCore.Mvc.BeforeActionMethod
- Microsoft.AspNetCore.Mvc.AfterActionMethod
ã³ã³ãããŒã©ãŒã¡ãœããã®å®è¡ã®ååŸã«çºçããŸãã
- Microsoft.AspNetCore.Mvc.BeforeActionResult
- Microsoft.AspNetCore.Mvc.AfterActionResult
ã³ã³ãããŒã©ãŒã¡ãœããããè¿ãããExecuteResultAsync
ã€ã³ã¹ã¿ã³ã¹ã§ExecuteResultAsync
ãåŒã³åºãååŸã«çºçããŸãã ããã«ã¯ãããšãã°ãjsonã§çµæãã·ãªã¢ã«åããããšãå«ãŸããŸãã
- Microsoft.AspNetCore.Mvc.BeforeHandlerMethod
- Microsoft.AspNetCore.Mvc.AfterHandlerMethod
ASP.NETããŒãžã§äœ¿çšãããŸãã ããŒãžã¢ãã«ã¡ãœããã®å®è¡ååŸã«çºçããŸãã
- Microsoft.AspNetCore.Mvc.BeforeView
- Microsoft.AspNetCore.Mvc.AfterView
ãã¥ãŒã®ã¬ã³ããªã³ã°ã®ååŸã«çºçããŸãã
Microsoft.EntityFrameworkCoreMicrosoft.EntityFrameworkCore
ã³ã³ããŒãã³ãã®ã€ãã³ãã䜿çšãããšãEntityFrameworkCoreãä»ããŠããŒã¿ããŒã¹ã¢ã¯ã»ã¹ã€ãã³ããã€ã³ã¿ãŒã»ããã§ããŸãã
- Microsoft.EntityFrameworkCore.Infrastructure.ContextInitialized
- Microsoft.EntityFrameworkCore.Infrastructure.ContextDisposed
DbContext
ã€ã³ã¹ã¿ã³ã¹ã䜿çšããååŸã«çºçããŸã
- Microsoft.EntityFrameworkCore.Database.Connection.ConnectionOpening
- Microsoft.EntityFrameworkCore.Database.Connection.ConnectionOpened
- Microsoft.EntityFrameworkCore.Database.Connection.ConnectionError
ããŒã¿ããŒã¹æ¥ç¶ãéãååŸã«çºçããŸãã æ¥ç¶ãæ£åžžã«éãããå Žåã ConnectionOpened
ã€ãã³ããçºçããŸãã æ¥ç¶ãéããšãã«ãšã©ãŒãçºçãããšã ConnectionError
ã€ãã³ããçºçããŸãã
- Microsoft.EntityFrameworkCore.Database.Connection.ConnectionClosing
- Microsoft.EntityFrameworkCore.Database.Connection.ConnectionClosed
- Microsoft.EntityFrameworkCore.Database.Connection.ConnectionError
åæ§ã«ãããŒã¿ããŒã¹æ¥ç¶ãéããååŸã«çºçããŸãã
- Microsoft.EntityFrameworkCore.Database.Command.CommandExecuting
- Microsoft.EntityFrameworkCore.Database.Command.CommandExecuted
- Microsoft.EntityFrameworkCore.Database.Command.CommandError
åæ§ã«ãããŒã¿ããŒã¹ãžã®ã¯ãšãªã®ååŸã«çºçããŸãã
- Microsoft.EntityFrameworkCore.Database.Command.DataReaderDisposing
DbDataReader
ã€ã³ã¹ã¿ã³ã¹ããèªã¿åã£ãåŸã«çºçããŸãã
SqlClientDiagnosticListenerSqlClientDiagnosticListener
ã³ã³ããŒãã³ãã®ã€ãã³ãã䜿çšãããšã察å¿ããADO.NETãããã€ããŒãä»ããŠSQL ServerããŒã¿ããŒã¹ã«ã¢ã¯ã»ã¹ããã€ãã³ããã€ã³ã¿ãŒã»ããã§ããŸãã
- System.Data.SqlClient.WriteConnectionOpenBefore
- System.Data.SqlClient.WriteConnectionOpenAfter
- System.Data.SqlClient.WriteConnectionOpenError
ããŒã¿ããŒã¹æ¥ç¶ãéãååŸã«çºçããŸãã æ¥ç¶ãæ£åžžã«éãããå Žåã WriteConnectionOpenAfter
ã€ãã³ãWriteConnectionOpenAfter
ã æ¥ç¶ãéããšãã«ãšã©ãŒãçºçãããšã WriteConnectionOpenError
ã€ãã³ãWriteConnectionOpenError
ã
- System.Data.SqlClient.WriteConnectionCloseBefore
- System.Data.SqlClient.WriteConnectionCloseAfter
- System.Data.SqlClient.WriteConnectionCloseError
åæ§ã«ãããŒã¿ããŒã¹æ¥ç¶ãéããååŸã«çºçããŸãã
- System.Data.SqlClient.WriteCommandBefore
- System.Data.SqlClient.WriteCommandAfter
- System.Data.SqlClient.WriteCommandError
åæ§ã«ãããŒã¿ããŒã¹ãžã®ã¯ãšãªã®ååŸã«çºçããŸãã
HttpHandlerDiagnosticListenerHttpHandlerDiagnosticListener
ã³ã³ããŒãã³ãã®ã€ãã³ããHttpHandlerDiagnosticListener
ãããšãããšãã°HttpClient
ã¯ã©ã¹ã䜿çšããå Žåã«ãçºä¿¡HTTPèŠæ±ãã€ã³ã¿ãŒã»ããHttpHandlerDiagnosticListener
ãŸãã
- System.Net.Http.HttpRequestOut.Start
- System.Net.Http.HttpRequestOut.Stop
çºä¿¡HTTPèŠæ±ã®ååŸã«çºçããŸãã
- System.Net.Http.Exception
çºä¿¡HTTPèŠæ±äžã«ãšã©ãŒãçºçããå Žåã«çºçããŸãã
ã¡ãªã¿ã«ã DiagnosticSourceã®ã€ãã³ãã®åœåã«é¢ããæšå¥šäºé
ãšèŠåã«ã€ããŠèª¬æããŠããDiagnosticSource User's GuideããããŸã ã
ç°¡åã«æšæž¬ã§ããããã«ãMicrosoftã¯ãããã®æšå¥šäºé
ã«åŸãããå察ã®ããšãè¡ããŸã=ïŒïŒããããŸãããèªåŒµããŸããDiagnosticSourceãŠãŒã¶ãŒã¬ã€ããç»å Žããåã«ãDiagnosticSourceã.NET Coreã³ã³ããŒãã³ãã§äœ¿çšããå§ããŸããïŒ
å
±éã³ãŒã
以äžã§æ€èšãããã¹ãŠã®äŸã¯ãASP.NET Coreã¢ããªã±ãŒã·ã§ã³ã§äœ¿çšããããã®ãšæ³å®ããïŒããã¯å¿
é ã§ã¯ãããŸããïŒãåºæ¬ã¯ã©ã¹DiagnosticObserverBase
ã䜿çšããŠDiagnosticObserverBase
ããã€ãã³ãããµãã¹ã¯ã©ã€ãããŠåŠçããŸãã
ãã®ã¯ã©ã¹ã¯ã ååã®èšäºã® ExampleDiagnosticObserver
ã¯ã©ã¹ã«åºã¥ããŠããããã®æäœã®èª¬æãåç
§ã§ããŸãã ã€ãã³ãããµãã¹ã¯ã©ã€ãããŠåŠçããããã«ããã®ã¯ã©ã¹ã¯Microsoft.Extensions.DiagnosticAdapterã® NuGetããã±ãŒãžã®SubscribeWithAdapter
ã¡ãœããã䜿çšããŸã ã
public abstract class DiagnosticObserverBase : IObserver<DiagnosticListener> { private readonly List<IDisposable> _subscriptions = new List<IDisposable>(); protected abstract bool IsMatch(string name); void IObserver<DiagnosticListener>.OnNext(DiagnosticListener diagnosticListener) { if (IsMatch(diagnosticListener.Name)) { var subscription = diagnosticListener.SubscribeWithAdapter(this); _subscriptions.Add(subscription); } } void IObserver<DiagnosticListener>.OnError(Exception error) { } void IObserver<DiagnosticListener>.OnCompleted() { _subscriptions.ForEach(x => x.Dispose()); _subscriptions.Clear(); } }
ç¹å®ã®ã³ã³ããŒãã³ãããã€ãã³ãããµãã¹ã¯ã©ã€ãããã«ã¯ãæ°ããã¯ã©ã¹ãäœæãã DiagnosticObserverBase
ããç¶æ¿ãããµãã¹ã¯ã©ã€ãããã³ã³ããŒãã³ãã«å¯ŸããŠtrue
ãè¿ãIsMatch
ã¡ãœãããåå®çŸ©ããã€ãã³ããåŠçããã¡ãœãããè¿œå ããååãæå®ããDiagnosticNameAttribute
å±æ§ã§ããŒã¯ããå¿
èŠããããŸãåŠçãããã€ãã³ãã äŸïŒ
public sealed class SomeDiagnosticObserver : DiagnosticObserverBase { protected override bool IsMatch(string name) { return name == "SomeComponent"; } [DiagnosticName("SomeEvent")] public void OnSomeEvent() {
DIã³ã³ãããŒã®DiagnosticObserverBase
ã¯ã©ã¹ã«åºã¥ããŠãã³ãã©ãŒãç»é²ããã«ã¯ã AddDiagnosticObserver
æ¡åŒµAddDiagnosticObserver
䜿çšããŸããããã¯ãStartup.csãã¡ã€ã«ã®ConfigureServices
ã¡ãœããã§äœ¿çšãããŸãã
public static class DiagnosticServiceCollectionExtensions { public static void AddDiagnosticObserver<TDiagnosticObserver>( this IServiceCollection services) where TDiagnosticObserver : DiagnosticObserverBase { services.TryAddEnumerable(ServiceDescriptor .Transient<DiagnosticObserverBase, TDiagnosticObserver>()); } }
ãŸããDiagnosticSourceããã€ãã³ãããµãã¹ã¯ã©ã€ãããã«ã¯ã Configure
ã¡ãœããã«æ¬¡ã®è¡ãè¿œå ããŸãã
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { var diagnosticObservers = app .ApplicationServices.GetServices<DiagnosticObserverBase>(); foreach (var diagnosticObserver in diagnosticObservers) { DiagnosticListener.AllListeners.Subscribe(diagnosticObserver); }
ããããããã¯ç»é²ããã®ã«æé©ãªæ¹æ³ã§ã¯ãªããå®éã«ã¯éåžžãã®ãããªç®çã§IHostedService
ã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšããŸãããäŸã§ååã§ãã
ããã€ãã®èœãšãç©Ž
ãããžã§ã¯ãã§DiagnosticSourceã䜿çšããããšã«æ±ºããå Žåã¯ãç§ã詳ãã説æãããéèªæãªç¹ã«åºããããããããŸããã
ååšããªãã€ãã³ãã®ãããŒãã³ãã©ãå¿
èŠã«ãªãå ŽåããããŸãã
éåžžãäžéšã®ã³ã³ããŒãã³ãããã®äœæ¥ã«é¢ããã€ãã³ããéä¿¡ããå Žåãã€ãã³ããéä¿¡ããã³ãŒãã¯æ¬¡ã®ãšããã§ãã
if (_diagnosticSource.IsEnabled("SomeEvent")) _diagnosticSource.Write("SomeEvent", new { });
ããã«ããã誰ãã€ãã³ããåŠçããäºå®ããªãå Žåã«ãã©ã¡ãŒã¿ãæã€ãªããžã§ã¯ããäœæãããã¬ããŒãžã³ã¬ã¯ã·ã§ã³ãå°ãç¯çŽã§ããŸãã
ãã ããå Žåã«ãã£ãŠã¯ããµãã£ãã¯ã¹ã.Start
ãš.Stop
ã€ãã³ãããã¢ã«ãªããäž¡æ¹ãšãæ©èœãããã©ããã.Stop
ãŸãã ãã®ãããªã€ãã³ããéä¿¡ããã³ãŒãã¯æ¬¡ã®ããã«ãªããŸãã
ãããã£ãŠã SomeEvent.Stop
ã€ãã³ããšSomeEvent.Stop
ã€ãã³ãããµãã¹ã¯ã©ã€ãããã«ã¯ã SomeEvent
ã€ãã³ãã®ãããŒãã³ãã©ãŒãè¿œå ããå¿
èŠããããŸããããã¯åŒã³åºãããŸãããããã®ååšã¯ãã§ãã¯ãããŸãã
ããã€ãã®ã€ãã³ãã¯ãã¢ã«ãªããããã€ãã®ããªãã«ã¯
System.Net.Http.HttpRequestOut.Start
ãSystem.Net.Http.HttpRequestOut.Stop
ãªã©ãäžéšã®ã€ãã³ãã¯ãã¢ã«ãªã£ãŠããŸãã ã€ãŸããæ¥å°ŸèŸã.Start
ã€ãã³ãã¯äœããã®æäœã®éå§åã«åŒã³åºãããæ¥å°ŸèŸã.Stop
ã€ãã³ãã¯æåŸã«åŒã³åºãããŸãã ãã®å Žåãæäœããšã©ãŒã§çµäºãããã©ããã«é¢ä¿ãªããæåŸã®ã€ãã³ããããªã¬ãŒãããããšãä¿èšŒãããŸãïŒé©åãªãã³ãã©ãŒãããå ŽåïŒã
ãã ããäžéšã®ã€ãã³ãã¯ããªãã«ã§ããããšãã°ã System.Data.SqlClient.WriteCommandBefore
ã System.Data.SqlClient.WriteCommandAfter
ãããã³System.Data.SqlClient.WriteCommandError
ã§ãæåŸã®ã€ãã³ãã¯æäœã®çµæã«äŸåããŸãã ãã®å Žåãæäœãæ£åžžã«å®äºããå Žåã¯System.Data.SqlClient.WriteCommandAfter
ã€ãã³ãã®ã¿ãçºçããæäœäžã«ãšã©ãŒãçºçããå Žåã¯System.Data.SqlClient.WriteCommandError
ã€ãã³ãã®ã¿ãSystem.Data.SqlClient.WriteCommandError
ãŸãã
ããšãã°ãã€ãã³ãã䜿çšããŠæäœã®æéã枬å®ããå Žåããããèæ
®ããå¿
èŠããããŸãã ããšãã°ãæäœã®éå§æã«ã¹ããããŠã©ãããéå§ããå ŽåãããŒã¿ã倱ããªãããã«2ã€ã®å Žæã§ã¹ããããŠã©ãããåæ¢ããå¿
èŠããããŸãã
DiagnosticSourceã®äŸ
ããã§ãDiagnosticSourceã¡ã«ããºã ãå®éã®ã¢ããªã±ãŒã·ã§ã³ã§ã©ã®ããã«å®è¡ã§ããããæ€èšããæºåããã¹ãŠæŽããŸããã
ãµãŒãã¹éã®CorrelationIDããã³è»¢éããããŒ
ãã€ã¯ããµãŒãã¹ã®äžçã§ã¯ãCorrelationIDãšããçšèªãããèŠãããŸãã ããã¯ããµãŒãã¹ã«ã¢ã¯ã»ã¹ãããã³ã«çæãããèå¥åã§ãããhttpããããŒãä»ããŠãµãŒãã¹éã§ããã«éä¿¡ãããŸãã éåžžããã®èå¥åã¯ãã°ã«æžã蟌ãŸãããããåäžã®ãã©ã³ã¶ã¯ã·ã§ã³ã®äžéšãšããŠåä¿¡ããè€æ°ã®ãµãŒãã¹ããã®ã¡ãã»ãŒãžããªã³ã¯ã§ããŸãã
ASP.NET Coreã«ã¯CorrelationId NuGetããã±ãŒãžããããŸãããéçºè
ã¯ãã¹ãŠã®çºä¿¡èŠæ±ã«é©åãªããããŒãæåã§è¿œå ããå¿
èŠãããããã䜿çšããã®ã¯ããŸã䟿å©ã§ã¯ãããŸããã
DiagnosticSourceã䜿çšããŠCorrelationIdãå®è£
ããŸãã ãŸããèå¥åã®ä¿åãæ
åœããCorrelationId
ã¯ã©ã¹ãè¿œå ããŸãã
public static class CorrelationId { private static readonly AsyncLocal<Guid?> _current = new AsyncLocal<Guid?>(); public static Guid Current { get { var value = _current.Value; if (value == null) throw new InvalidOperationException("CorrelationId isn't assigned."); return value.Value; } set { _current.Value = value; } } }
ãã®ã¯ã©ã¹ã¯ãã¿ã€ãAsyncLocal <T>ã®ã€ã³ã¹ã¿ã³ã¹ã䜿çšããŠãçŸåšã®CorrelationIdå€ãæ ŒçŽããŸããããã¯ãåãªã¯ãšã¹ãã«å¯ŸããŠäžæã§ãããéåæã³ãŒããæäœãããšãã«ThreadPoolããå¥ã®ã¹ã¬ããã«æ£ãã転éãããŸã
次ã®ã¹ãããã¯ãDiagnosticSourceããã€ãã³ããã³ãã©ãŒãè¿œå ããããšã§ããããã«ãããçä¿¡ããã³çºä¿¡HTTPèŠæ±ãã€ã³ã¿ãŒã»ãããããŸãã åä¿¡ãªã¯ãšã¹ãã§ã¯ã X-Correlation-ID
ããããŒã®ååšã確èªããååšããªãå Žåã¯ã Guid.NewGuid()
ä»ããŠæ°ããèå¥åãçæããŸãã çºä¿¡ãªã¯ãšã¹ãã§ã¯ã CorrelationId.Current
ã䜿çšããŠããããŒãè¿œå ããã ãã§ãã
public sealed class CorrelationIdHandler : DiagnosticObserverBase { protected override bool IsMatch(string name) { return name == "Microsoft.AspNetCore" || name == "HttpHandlerDiagnosticListener"; }
ãã®ã¯ã©ã¹ã§ã¯ã IsMatch
ã¡ãœããIsMatch
ã Microsoft.AspNetCore
ã³ã³ããŒãã³ãïŒçä¿¡HTTPèŠæ±ã«å¯Ÿå¿ïŒããã³HttpHandlerDiagnosticListener
ïŒçºä¿¡HTTPèŠæ±ã«è²¬ä»»ïŒããã®ã€ãã³ããåŠçããããšãå ±åããŸãã ããããŒã®çŽæ¥åŠçã¯ã OnHttpRequestInStart
ããã³OnHttpRequestOutStart
çºçãOnHttpRequestOutStart
ã
ããã«ã2ã€ã®ãããŒã¡ãœããOnHttpRequestIn
ãšOnHttpRequestOut
ãè¿œå ããOnHttpRequestIn
ããOnHttpRequestOut
ã åŠçäžã¯åŒã³åºãããŸãããã Start
ãã³ãã©ãšStop
ãã³ãã©ã®ãã¢ãåŒã³åºããã©ããã決å®ããããã«äœ¿çšãããŸãã ãããããªããã°ããããã®ã€ãã³ãã¯ããªã¬ãŒãããŸããã
Startup.csãã¡ã€ã«ã«ãã³ãã©ãŒãç»é²ããã ãã§ãã
services.AddDiagnosticObserver<CorrelationIdHandler>();
å®éã«ã¯ã1ã€ã§ã¯ãªãç¹å®ã®ãã¬ãã£ãã¯ã¹ïŒããšãã°ããX-Api-ãïŒãæã€è€æ°ã®ããããŒã転éããããšãæçšã§ããããã«ãããããããã³ã³ããã¹ãäŒæãå®è£
ãããŸãã ãã®ã¡ã«ããºã ã䜿çšãããšããªã¯ãšã¹ãæ¬äœãä»ããŠãã®å€ãæ瀺çã«æž¡ãããšãªãããããµãŒãã¹ã®ç¹å®ã®ããŒã«å€ãèšå®ããå¥ã®ãµãŒãã¹ã«èªã¿èŸŒãããšãã§ããŸãã äžèšã®CorrelationIdHandler
ã¯ã©ã¹ã«åºã¥ããŠãåæ§ã®ã¡ã«ããºã ãç°¡åã«å®è£
ã§ããŸãã
ã¡ããªãã¯ãšãã¬ãŒã¹ã®ã³ã¬ã¯ã·ã§ã³
ã¡ããªãã¯ãšãã¬ãŒã¹ã¯ãã¢ããªã±ãŒã·ã§ã³ã®éèŠãªéšåã§ãã ã¡ããªãã¯ã䜿çšãããšãã¢ããªã±ãŒã·ã§ã³ã®ç£èŠãšããã·ã¥ããŒããããã³ãã¬ãŒã¹ãæ§æããŠããããã®ããã«ããã¯ãèŠã€ããããšãã§ããŸãã
OZON.ruã§ã¯ã Prometheusã䜿çšããŠã¡ããªãã¯ãåéããASP.NET CoreãµãŒãã¹ã®å Žåã¯NuGetããã±ãŒãžPrometheus.Client.AspNetCoreã䜿çšããŸãã
ãã¬ãŒã¹ãåéããã«ã¯ã OpenTracingãšJaegerã䜿çšããŸãã ïŒãåžæã®å Žåã¯ãDotNetMsk MeetutïŒ30ã§ã®ç§ã®è¬æŒ ã.NETã§ã®OpenTracingã®äœ¿çšããã芧ãã ããïŒ
ãã ããå€ãã®éçºè
ã¯ãã¢ããªã±ãŒã·ã§ã³ãã¡ããªãã¯ãšãã¬ãŒã¹ã§ã«ããŒããããšã«ããŸãç±å¿ã§ã¯ãããŸãããããã¯ãå€ãã®å Žåãè¿œå ã®çµ±äžã³ãŒããèšè¿°ããå¿
èŠãããããããžãã¹ã¿ã¹ã¯ããšããŸãæŽåæ§ããªãããã§ãã
幞ããªããšã«ãDiagnosticSourceãéããŠã€ãã³ãããã£ã¹ãããããã»ãšãã©ã®ã³ã³ããŒãã³ãã¯ãã¢ã®ã€ãã³ããéä¿¡ããŸããæåã®ã€ãã³ãã¯ç¹å®ã®æäœã®éå§ã瀺ãã2çªç®ã¯ç¹å®ã®æäœã®å®äºã瀺ããŸãã ããã«ãããããšãã°ãæåã«ã¹ããããŠã©ãããéå§ãã次ã«åæ¢ããŠç¹å®ã®ã¡ããªãã¯ãäžããããšãã§ããŸãã
ããšãã°ããã¹ãŠã®ã³ã³ãããŒã©ãŒã¢ã¯ã·ã§ã³ã®å®è¡æéã®ã¡ããªãã¯ãåéããå Žåã次ã®ã¯ã©ã¹ã䜿çšã§ããŸãã
public sealed class AspNetCoreMetricsHandler : DiagnosticObserverBase { private readonly Histogram requestDurationSeconds; public MetricsHandler(MetricFactory metricFactory) {
ããã§ãã³ã³ã¹ãã©ã¯ã¿ãŒã§Prometheus.Clientã® NuGetããã±ãŒãžãããã¹ãã°ã©ã ã¡ããªãã¯ã宣èšããŸãã ãã®ã¡ããªãã¯ã«ã©ãã«ãaction_nameããè¿œå ããŸããããã«ãããã³ã³ãããŒã©ãŒã®ããŸããŸãªã¢ã¯ã·ã§ã³ã§åéãããã¡ããªãã¯ãåºå¥ã§ããŸãã
ã€ãã³ãåŠçã®éå§æã«ïŒ OnHttpRequestInStart
ã¡ãœããïŒãã¹ããããŠã©ãããéå§ããŠã¯ãšãªã®å®è¡æéã枬å®ããŸãã ãŸããåŠçãããŠããã¢ã¯ã·ã§ã³ã®ååïŒ OnBeforeAction
ã¡ãœããïŒãèŠããŠããŸãã ãããŠæåŸã«ããªã¯ãšã¹ãïŒ OnHttpRequestInStop
ã¡ãœããïŒãåŠçããåŸã httpContext.Items
ã³ã¬ã¯ã·ã§ã³ãããã¹ãŠã®ããŒã¿ãå床ååŸããã¡ããªãã¯ã«æžã蟌ã¿ãŸãã
MetricFactory
ãã¡ã€ã«ã«ãã³ãã©ãŒãšMetricFactory
ã€ã³ã¹ã¿ã³ã¹ãç»é²ããã ãã§ãã
services.AddSingleton(Prometheus.Client.Metrics.DefaultFactory); services.AddDiagnosticObserver<AspNetCoreMetricsHandler>();
åæ§ã®ææ³ã䜿çšããŠãNuGet OpenTracingããã±ãŒãžã䜿çšããŠãã¬ãŒã¹ãåéã§ããŸãã
ãã®ã³ã°
DiagnosticSourceã®ãã1ã€ã®éåžžã«äŸ¿å©ãªã¢ããªã±ãŒã·ã§ã³ã¯ãäŸå€ãã°ã§ãã ããããããªããããå¿
èŠãªã®ãããšããçåãçãããããããŸããã çµå±ã®ãšãããã³ãŒããtry-catchãããã¯ã«ã©ããããããæªåŠçã®ãã¹ãŠã®äŸå€ã«å¯ŸããŠ1ã€ã®ã°ããŒãã«ãã³ãã©ãŒãæ§æããããšãã§ããŸãã
äºå®ãDiagnosticSourceã€ãã³ãã«ããäŸå€åŠçã¯ãäŸå€ã®çç±ãç解ããã®ã«åœ¹ç«ã€ããŸããŸãªãªããžã§ã¯ãããŸã å©çšå¯èœãªéåžžã«æ©ã段éã§çºçãããšããããšã§ãã ïŒDiagnosticSourceã§ã¯äŸå€ã®åŠçã®ã¿ãèš±å¯ãããŸããããã以äžã®äŒæã¯åŠšããããªãããšã«æ³šæããŠãã ããïŒ
ã¯ãšãªããã¹ããšãã®ãã©ã¡ãŒã¿ãŒããã°ã«èšé²ããªãããããŒã¿ããŒã¹ã«ã¢ã¯ã»ã¹ãããšãã«ãã¹ãŠã®äŸå€ãéäžçã«åŠçãããšããŸãã DiagnosticSourceã䜿çšããŠã次ã®ããã«ãããè¡ãããšãã§ããŸãã
public sealed class SqlClientLoggingHandler : DiagnosticObserverBase { private readonly ILogger<SqlClientLoggingHandler> _logger; public SqlClientLoggingHandler(ILogger<SqlClientLoggingHandler> logger) { _logger = logger; } protected override bool IsMatch(string name) { return name == "SqlClientDiagnosticListener"; } [DiagnosticName("System.Data.SqlClient.WriteCommandError")] public void OnCommandError(DbCommand command, Exception exception) { var sb = new StringBuilder(); sb.AppendLine("Command: " + command.CommandText); if (command.Parameters.Count > 0) { sb.AppendLine("Parameters: "); foreach (DbParameter parameter in command.Parameters) { sb.AppendLine($"\t{parameter.ParameterName}: {parameter.Value}"); } } _logger.LogError(exception, sb.ToString()); } }
IsMatch
, SqlClientDiagnosticListener
, OnCommandError
.
Startup.cs :
services.AddDiagnosticObserver<SqlClientLoggingHandler>();
ãããã«
DiagnosticSource. , , , DiagnosticSource, ASP.NET Core.
OZON.ru . , NuGet , , .
, , DiagnosticSource .