Skip to content

Commit

Permalink
Monitoring configuration (#81)
Browse files Browse the repository at this point in the history
* Change IOptions to IOptionsMonitor for postgresDapper. Adding connection string builder for pg dapper

* Remove connection string when try to create connection string builder

* Adding listenig event about changing IOptionsMonitor

* Adding validation for duplicate key on library

* Open _dataBaseOptions for set value and don't change link

* Remove comments

* Change type of port from string to int

* Change field name and adding variable to save link

* Adding keep alive setting for building connection string

* Adding connection idle lifetime for pg connection string

* Clear connection pool when need to rotate connection

* Remove idle connection timeout for build connection string

* Return log factory

* Adding checking that UserName or Password was change before reset connection pull

* Adding extensions to builder for configurate logger

* Remove unuse varible. Change condition for validate credentials

* Change dictionary to concurrentDictionary

* remove logging

* refactoring

---------

Co-authored-by: Батура Иван <batura.i@MacBook-Pro-Komov.local>
Co-authored-by: Станислав Терещенков <tereschenkov.s@ati.su>
  • Loading branch information
3 people authored Jun 5, 2024
1 parent e341d8b commit cf83124
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 26 deletions.
17 changes: 17 additions & 0 deletions ATI.Services.Common/Logging/ConfigureLogBuildExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using ATI.Services.Common.Logging.Configuration;
using Microsoft.Extensions.Configuration;

namespace ATI.Services.Common.Logging;

public static class ConfigureLogBuildExtensions
{
public static IConfigurationBuilder AddLogger(this IConfigurationBuilder builder)
{
var configurationRoot = builder.Build();
var nLogOptions = configurationRoot.GetSection("NLogOptions").Get<NLogOptions>();
var nLogConfigurator = new NLogConfigurator(nLogOptions);
nLogConfigurator.ConfigureNLog();

return builder;
}
}
17 changes: 15 additions & 2 deletions ATI.Services.Common/Logging/LogHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,23 @@
using JetBrains.Annotations;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using NLog;
using NLog.Layouts;
using NLog.Web;
using ConfigurationManager = ATI.Services.Common.Behaviors.ConfigurationManager;
using ILogger = Microsoft.Extensions.Logging.ILogger;

namespace ATI.Services.Common.Logging
{
[UsedImplicitly(ImplicitUseTargetFlags.WithMembers)]
public class LogHelper
{
public static void ConfigureNLogFromAppSettings()
public static LogFactory ConfigureNLogFromAppSettings()
{
var nLogOptions = ConfigurationManager.ConfigurationRoot.GetSection("NLogOptions").Get<NLogOptions>();
var nLogConfigurator = new NLogConfigurator(nLogOptions);
nLogConfigurator.ConfigureNLog();
return nLogConfigurator.ConfigureNLog();
}

public static void ConfigureNlog(IWebHostEnvironment env)
Expand All @@ -42,5 +44,16 @@ public static void ConfigureMetricsLoggers()

NLogBuilder.ConfigureNLog(loggingConfiguration);
}

public static ILogger GetMicrosoftLogger(string categoryName)
{
var loggerFactory = LoggerFactory.Create(builder =>
{
var configuration = LogManager.Configuration;
builder.AddNLog(configuration);
});

return loggerFactory.CreateLogger(categoryName);
}
}
}
5 changes: 3 additions & 2 deletions ATI.Services.Common/Logging/NLogConfigurator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public NLogConfigurator(NLogOptions options)
$"${{aspnet-request:header={loggedHeader}}}")));
}

public void ConfigureNLog()
public LogFactory ConfigureNLog()
{
try
{
Expand All @@ -67,11 +67,12 @@ public void ConfigureNLog()

ApplyRules(configuration, _options.Rules);

NLogBuilder.ConfigureNLog(configuration);
return NLogBuilder.ConfigureNLog(configuration);
}
catch (Exception exception)
{
LogManager.GetCurrentClassLogger().Error(exception);
throw;
}
}

Expand Down
58 changes: 58 additions & 0 deletions ATI.Services.Common/Sql/ConnectionStringBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using Npgsql;

namespace ATI.Services.Common.Sql;

public static class ConnectionStringBuilder
{
public static string BuildPostgresConnectionString(DataBaseOptions options)
{
var builder = new NpgsqlConnectionStringBuilder();

if (options.ConnectionString != null)
{
builder.ConnectionString = options.ConnectionString;
return builder.ToString();
}

if (options.Port != null)
{
builder.Port = options.Port.Value;
}

if (options.Server != null)
{
builder.Host = options.Server;
}
if (options.Database != null)
{
builder.Database = options.Database;
}
if (options.UserName != null)
{
builder.Username = options.UserName;
}
if (options.Password != null)
{
builder.Password = options.Password;
}
if (options.MinPoolSize != null)
{
builder.MinPoolSize = options.MinPoolSize.Value;
}
if (options.MaxPoolSize != null)
{
builder.MaxPoolSize = options.MaxPoolSize.Value;
}
if (options.ConnectTimeout != null)
{
builder.ConnectionLifetime = options.ConnectTimeout.Value;
}
if (options.KeepAlive != null)
{
builder.KeepAlive = options.KeepAlive.Value;
}

builder.TrustServerCertificate = options.TrustServerCertificate ?? true;
return builder.ToString();
}
}
4 changes: 3 additions & 1 deletion ATI.Services.Common/Sql/DataBaseOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ public class DataBaseOptions
public TimeSpan Timeout { get; set; }
public IDictionary<string, int> TimeoutDictionary { get; set; } = new Dictionary<string, int>();
public TimeSpan? LongTimeRequest { get; set; }


public int? KeepAlive { get; set; }
public int? Port { get; set; }
public string Server { get; set; }
public string Database { get; set; }
public string UserName { get; set; }
Expand Down
33 changes: 17 additions & 16 deletions ATI.Services.Common/Sql/PostgresDapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ namespace ATI.Services.Common.Sql;
[PublicAPI]
public class PostgresDapper
{
private readonly DataBaseOptions _options;
public DataBaseOptions Options { get; set; }

private readonly MetricsInstance _metrics;
private readonly ILogger _logger = LogManager.GetCurrentClassLogger();
private const string ReadMetricTypeLabel = "read";
Expand All @@ -28,10 +29,10 @@ public class PostgresDapper
private const string FunctionQuery = "SELECT * FROM";
private const string ProcedureQuery = "CALL";

public PostgresDapper(DataBaseOptions options, MetricsFactory metricsFactory)
public PostgresDapper(DataBaseOptions options, MetricsFactory metricsFactory)
{
_options = options;
_metrics = metricsFactory.CreateSqlMetricsFactory(nameof(PostgresDapper), _options.LongTimeRequest, "type");
Options = options;
_metrics = metricsFactory.CreateSqlMetricsFactory(nameof(PostgresDapper), Options.LongTimeRequest, "type");
}

public async Task<OperationResult> ExecuteFunctionAsync(
Expand Down Expand Up @@ -88,7 +89,7 @@ private async Task<OperationResult> ExecuteAsync(
longTimeRequest,
FullMetricTypeLabel);

await using var connection = new NpgsqlConnection(_options.ConnectionString);
await using var connection = new NpgsqlConnection(ConnectionStringBuilder.BuildPostgresConnectionString(Options));

if (receiveNotice)
connection.Notice += LoggOnNotice;
Expand Down Expand Up @@ -132,7 +133,7 @@ public async Task<OperationResult<T>> ExecuteFunctionObjectAsync<T>(
FullMetricTypeLabel);

var timeout = timeoutInSeconds ?? GetTimeOut(functionName);
await using var connection = new NpgsqlConnection(_options.ConnectionString);
await using var connection = new NpgsqlConnection(ConnectionStringBuilder.BuildPostgresConnectionString(Options));

if (receiveNotice)
connection.Notice += LoggOnNotice;
Expand Down Expand Up @@ -177,7 +178,7 @@ public async Task<OperationResult<T>> ExecuteFunctionObjectAsync<T>(

var timeout = timeoutInSeconds ?? GetTimeOut(functionName);

await using var connection = new NpgsqlConnection(_options.ConnectionString);
await using var connection = new NpgsqlConnection(ConnectionStringBuilder.BuildPostgresConnectionString(Options));

if (receiveNotice)
connection.Notice += LoggOnNotice;
Expand Down Expand Up @@ -230,7 +231,7 @@ public async Task<OperationResult<T>> ExecuteFunctionObjectAsync<T>(
FullMetricTypeLabel);

var timeout = timeoutInSeconds ?? GetTimeOut(functionName);
await using var connection = new NpgsqlConnection(_options.ConnectionString);
await using var connection = new NpgsqlConnection(ConnectionStringBuilder.BuildPostgresConnectionString(Options));

if (receiveNotice)
connection.Notice += LoggOnNotice;
Expand Down Expand Up @@ -289,7 +290,7 @@ public async Task<OperationResult<List<T>>> ExecuteFunctionListAsync<T>(
FullMetricTypeLabel);

var timeout = timeoutInSeconds ?? GetTimeOut(functionName);
await using var connection = new NpgsqlConnection(_options.ConnectionString);
await using var connection = new NpgsqlConnection(ConnectionStringBuilder.BuildPostgresConnectionString(Options));

if (receiveNotice)
connection.Notice += LoggOnNotice;
Expand Down Expand Up @@ -334,7 +335,7 @@ public async Task<OperationResult<List<T>>> ExecuteFunctionListAsync<T>(
FullMetricTypeLabel);

var timeout = timeoutInSeconds ?? GetTimeOut(functionName);
await using var connection = new NpgsqlConnection(_options.ConnectionString);
await using var connection = new NpgsqlConnection(ConnectionStringBuilder.BuildPostgresConnectionString(Options));

if (receiveNotice)
connection.Notice += LoggOnNotice;
Expand Down Expand Up @@ -386,7 +387,7 @@ public async Task<OperationResult<List<T>>> ExecuteFunctionListAsync<T>(
FullMetricTypeLabel);

var timeout = timeoutInSeconds ?? GetTimeOut(functionName);
await using var connection = new NpgsqlConnection(_options.ConnectionString);
await using var connection = new NpgsqlConnection(ConnectionStringBuilder.BuildPostgresConnectionString(Options));

if (receiveNotice)
connection.Notice += LoggOnNotice;
Expand Down Expand Up @@ -447,7 +448,7 @@ public async Task<OperationResult<Dictionary<TKey, TValue>>> ExecuteScalarDictio
FullMetricTypeLabel);

var timeout = timeoutInSeconds ?? GetTimeOut(functionName);
await using var connection = new NpgsqlConnection(_options.ConnectionString);
await using var connection = new NpgsqlConnection(ConnectionStringBuilder.BuildPostgresConnectionString(Options));

if (receiveNotice)
connection.Notice += LoggOnNotice;
Expand Down Expand Up @@ -492,8 +493,8 @@ public async Task<OperationResult<List<T>>> ExecuteRawSqlAsync<T>(
longTimeRequest,
FullMetricTypeLabel);

var timeout = timeoutInSeconds ?? _options.Timeout.Seconds;
await using var connection = new NpgsqlConnection(_options.ConnectionString);
var timeout = timeoutInSeconds ?? Options.Timeout.Seconds;
await using var connection = new NpgsqlConnection(ConnectionStringBuilder.BuildPostgresConnectionString(Options));

if (receiveNotice)
connection.Notice += LoggOnNotice;
Expand Down Expand Up @@ -538,9 +539,9 @@ private string GetQuery(DynamicParameters @params, string functionName, string q

private int GetTimeOut(string procedureName)
{
return _options.TimeoutDictionary.TryGetValue(procedureName, out var tempTimeout)
return Options.TimeoutDictionary.TryGetValue(procedureName, out var tempTimeout)
? tempTimeout
: _options.Timeout.Seconds;
: Options.Timeout.Seconds;
}

private void LogWithParameters(Exception e, string procedureName, string metricEntity, DynamicParameters parameters)
Expand Down
35 changes: 30 additions & 5 deletions ATI.Services.Common/Sql/PostgresDapperProvider.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using ATI.Services.Common.Metrics;
using JetBrains.Annotations;
using Microsoft.Extensions.Options;
using NLog;
using Npgsql;

namespace ATI.Services.Common.Sql;

[PublicAPI]
public class PostgresDapperProvider
{
private readonly Logger _logger = LogManager.GetCurrentClassLogger();
private readonly Dictionary<string, PostgresDapper> _configuredDataBases = new();
private readonly ConcurrentDictionary<string, PostgresDapper> _configuredDataBases = new();

public PostgresDapperProvider(IOptions<DbManagerOptions> dbManagerOptions, MetricsFactory metricsFactory)
public PostgresDapperProvider(IOptionsMonitor<DbManagerOptions> dbManagerOptions, MetricsFactory metricsFactory)
{
foreach (var kvDataBaseOptions in dbManagerOptions.Value.DataBaseOptions)
foreach (var kvDataBaseOptions in dbManagerOptions.CurrentValue.DataBaseOptions)
{
_configuredDataBases.Add(kvDataBaseOptions.Key, new PostgresDapper(kvDataBaseOptions.Value, metricsFactory));
_configuredDataBases.TryAdd(kvDataBaseOptions.Key, new PostgresDapper(kvDataBaseOptions.Value, metricsFactory));
}

dbManagerOptions.OnChange(o => ReloadDatabases(o.DataBaseOptions, metricsFactory));
}

public PostgresDapper GetDb(string dbName)
{
var isDbConfigured = _configuredDataBases.TryGetValue(dbName, out var db);
Expand All @@ -29,4 +33,25 @@ public PostgresDapper GetDb(string dbName)
_logger.Error($"No {dbName} database was configured");
return null;
}

private void ReloadDatabases(Dictionary<string, DataBaseOptions> newDataBaseOptions, MetricsFactory metricsFactory)
{
foreach (var (dbName, newDbOptions) in newDataBaseOptions)
{
if (_configuredDataBases.TryGetValue(dbName, out var oldDbOptions))
{
//Если кто-то сменил change token IOptionsMonitor, и не сменил креды от бд, не нужно сбрасывать коннекшен пул
if (oldDbOptions.Options.UserName == newDbOptions.UserName
&& oldDbOptions.Options.Password == newDbOptions.Password)
continue;

// Удаляем старые коннекты при смене коннекшн стринга, так как у постгрес имеется лимит на количество открытых соединений
NpgsqlConnection.ClearPool(new NpgsqlConnection(ConnectionStringBuilder.BuildPostgresConnectionString(oldDbOptions.Options)));
oldDbOptions.Options = newDbOptions;

}
else
_configuredDataBases.TryAdd(dbName, new PostgresDapper(newDbOptions, metricsFactory));
}
}
}

0 comments on commit cf83124

Please sign in to comment.