Мониторинг пула подключений и долгих
транзакций
В BPMSoft важно контролировать состояние пула подключений и отслеживать долгоживущие транзакции. Это позволяет своевременно выявлять проблемы и предотвращать ошибки, связанные с исчерпанием соединений.
Включение логирования пула подключений
Логирование состояния пула подключений позволяет контролировать количество занятых соединений и максимальный размер пула. Для активации этой функции во «внутреннем» web.config необходимо задать следующую настройку:
<add key="EnableDbConnectionPoolStatusLogging" value="true" />
Частота логирования задается параметром LongLivedDbOperationLoggingFrequencyMinutes:
<add key="LongLivedDbOperationLoggingFrequencyMinutes" value="3" />
Пример лога:
2024-11-26 11:52:06,684 [37] WARN dev$ DbConnection LogDbConnectionPoolStatus - DbConnectionPool info. Busy: 2 MaxPoolSize: 20
Логи по умолчанию записываются в Common, так как используется логгер DbConnection, не указанный в NLog.config.
Логирование долгоживущих транзакций и подключений
Долгоживущими считаются транзакции или подключения, существующие дольше установленного порога. Для их логирования во «внутреннем» web.config необходимо добавить следующие параметры:
<add key="LongLivedDbOperationAgeThresholdMinutes" value="3" /> <add key="EnableLongLivedDbTransactionsLogging" value="true" /> <add key="EnableLongLivedDbConnectionsLogging" value="true" />
Где:
- LongLivedDbOperationAgeThresholdMinutes — задает порог в минутах, по истечении которого транзакции и подключения считаются долгими;
- EnableLongLivedDbTransactionsLogging — включает логирование долгих транзакций;
- EnableLongLivedDbConnectionsLogging — включает логирование долгих подключений.
Логирование осуществляется с периодичностью, установленной в LongLivedDbOperationLoggingFrequencyMinutes.
Пример лога:
2024-11-26 11:53:06,687 [87] WARN dev$ DbConnection ForEach - DbConnection opened on: 11/26/2024 11:49:12 AM. CallStack: at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo) at System.Environment.get_StackTrace() at BPMSoft.Core.DB.DBExecutor.<get_DBConnection>b__23_0() at Polly.Policy.<>c__DisplayClass109_0.<Execute>b__0(Context ctx, CancellationToken ct) at Polly.Policy.<>c__DisplayClass103_0.<NoOp>b__1(Context ctx, CancellationToken ct) at Polly.NoOp.NoOpEngine.Implementation[TResult](Func`3 action, Context context, CancellationToken cancellationToken) at Polly.Policy.<>c.<NoOp>b__103_0(Action`2 action, Context context, CancellationToken cancellationToken) at Polly.Policy.Execute(Action`2 action, Context context, CancellationToken cancellationToken) at Polly.Policy.Execute(Action action) at BPMSoft.Core.DB.DBExecutor.get_DBConnection() at BPMSoft.Core.DB.DBExecutor.CreateCommand() at BPMSoft.Core.DB.DBExecutor.<ExecuteCommandAsync>d__111`1.MoveNext() at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.Start[TStateMachine](TStateMachine& stateMachine) at BPMSoft.Core.DB.DBExecutor.ExecuteCommandAsync[TResult](Func`2 commandExecutionCallback, Func`2 commandExecutionCallbackAsync, String sqlText, QueryParameterCollection queryParameters, CancellationToken cancellationToken, Boolean sync) at BPMSoft.Core.DB.DBExecutor.ExecuteCommand[TResult](Func`2 commandExecutionCallback, String sqlText, QueryParameterCollection queryParameters, CancellationToken cancellationToken) at BPMSoft.Core.DB.DBExecutor.InternalExecuteScalar[TResult](String sqlText, QueryParameterCollection queryParameters) at BPMSoft.DB.PostgreSql.PostgreSqlExecutor.<>c__DisplayClass43_0`1.<InternalExecuteScalar>b__0() at BPMSoft.DB.PostgreSql.PostgreSqlExecutor.ExecuteInLockIfInTransaction[TResult](Func`1 action) at BPMSoft.Core.DB.Select.<ExecuteScalarAsync>d__57`1.MoveNext() at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.Start[TStateMachine](TStateMachine& stateMachine) at BPMSoft.Core.DB.Select.ExecuteScalarAsync[TResult](Boolean sync) at BPMSoft.Core.DB.Select.ExecuteScalar[TResult]() at BPMSoft.Core.Configuration.SysAdminUnit.GetUserId(UserConnection userConnection, String userName) at BPMSoft.Web.Common.AuthModule.IsForbiddenPageForServiceUser(HttpContextBase httpContext) at BPMSoft.Web.Common.AuthModule.OnAuthenticateRequest(HttpContextBase context) at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step) at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) at System.Web.HttpApplication.PipelineStepManager.ResumeSteps(Exception error) at System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb) at System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags) at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags) at System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr pHandler, RequestNotificationStatus& notificationStatus) at System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr pHandler, RequestNotificationStatus& notificationStatus) at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags) at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
Использование
Данный механизм помогает анализировать проблемы, связанные с исчерпанием пула подключений, например, ошибки вида:
The connection pool has been exhausted, either raise MaxPoolSize (currently 1024) or Timeout (currently 500 seconds).
Логирование с указанием стектрейса упрощает поиск источников проблемных запросов.