44 changed files with 88 additions and 683 deletions
@ -1,74 +0,0 @@ |
|||||||
using Serilog.Events; |
|
||||||
|
|
||||||
namespace Bit.Core.Settings; |
|
||||||
|
|
||||||
public interface ILogLevelSettings |
|
||||||
{ |
|
||||||
IBillingLogLevelSettings BillingSettings { get; set; } |
|
||||||
IApiLogLevelSettings ApiSettings { get; set; } |
|
||||||
IIdentityLogLevelSettings IdentitySettings { get; set; } |
|
||||||
IScimLogLevelSettings ScimSettings { get; set; } |
|
||||||
ISsoLogLevelSettings SsoSettings { get; set; } |
|
||||||
IAdminLogLevelSettings AdminSettings { get; set; } |
|
||||||
IEventsLogLevelSettings EventsSettings { get; set; } |
|
||||||
IEventsProcessorLogLevelSettings EventsProcessorSettings { get; set; } |
|
||||||
IIconsLogLevelSettings IconsSettings { get; set; } |
|
||||||
INotificationsLogLevelSettings NotificationsSettings { get; set; } |
|
||||||
} |
|
||||||
|
|
||||||
public interface IBillingLogLevelSettings |
|
||||||
{ |
|
||||||
LogEventLevel Default { get; set; } |
|
||||||
LogEventLevel Jobs { get; set; } |
|
||||||
} |
|
||||||
|
|
||||||
public interface IApiLogLevelSettings |
|
||||||
{ |
|
||||||
LogEventLevel Default { get; set; } |
|
||||||
LogEventLevel IdentityToken { get; set; } |
|
||||||
LogEventLevel IpRateLimit { get; set; } |
|
||||||
} |
|
||||||
|
|
||||||
public interface IIdentityLogLevelSettings |
|
||||||
{ |
|
||||||
LogEventLevel Default { get; set; } |
|
||||||
LogEventLevel IdentityToken { get; set; } |
|
||||||
LogEventLevel IpRateLimit { get; set; } |
|
||||||
} |
|
||||||
|
|
||||||
public interface IScimLogLevelSettings |
|
||||||
{ |
|
||||||
LogEventLevel Default { get; set; } |
|
||||||
} |
|
||||||
|
|
||||||
public interface ISsoLogLevelSettings |
|
||||||
{ |
|
||||||
LogEventLevel Default { get; set; } |
|
||||||
} |
|
||||||
|
|
||||||
public interface IAdminLogLevelSettings |
|
||||||
{ |
|
||||||
LogEventLevel Default { get; set; } |
|
||||||
} |
|
||||||
|
|
||||||
public interface IEventsLogLevelSettings |
|
||||||
{ |
|
||||||
LogEventLevel Default { get; set; } |
|
||||||
LogEventLevel IdentityToken { get; set; } |
|
||||||
} |
|
||||||
|
|
||||||
public interface IEventsProcessorLogLevelSettings |
|
||||||
{ |
|
||||||
LogEventLevel Default { get; set; } |
|
||||||
} |
|
||||||
|
|
||||||
public interface IIconsLogLevelSettings |
|
||||||
{ |
|
||||||
LogEventLevel Default { get; set; } |
|
||||||
} |
|
||||||
|
|
||||||
public interface INotificationsLogLevelSettings |
|
||||||
{ |
|
||||||
LogEventLevel Default { get; set; } |
|
||||||
LogEventLevel IdentityToken { get; set; } |
|
||||||
} |
|
||||||
@ -1,8 +0,0 @@ |
|||||||
using Serilog.Events; |
|
||||||
|
|
||||||
namespace Bit.Core.Settings.LoggingSettings; |
|
||||||
|
|
||||||
public class AdminLogLevelSettings : IAdminLogLevelSettings |
|
||||||
{ |
|
||||||
public LogEventLevel Default { get; set; } = LogEventLevel.Error; |
|
||||||
} |
|
||||||
@ -1,10 +0,0 @@ |
|||||||
using Serilog.Events; |
|
||||||
|
|
||||||
namespace Bit.Core.Settings.LoggingSettings; |
|
||||||
|
|
||||||
public class ApiLogLevelSettings : IApiLogLevelSettings |
|
||||||
{ |
|
||||||
public LogEventLevel Default { get; set; } = LogEventLevel.Error; |
|
||||||
public LogEventLevel IdentityToken { get; set; } = LogEventLevel.Fatal; |
|
||||||
public LogEventLevel IpRateLimit { get; set; } = LogEventLevel.Information; |
|
||||||
} |
|
||||||
@ -1,9 +0,0 @@ |
|||||||
using Serilog.Events; |
|
||||||
|
|
||||||
namespace Bit.Core.Settings.LoggingSettings; |
|
||||||
|
|
||||||
public class BillingLogLevelSettings : IBillingLogLevelSettings |
|
||||||
{ |
|
||||||
public LogEventLevel Default { get; set; } = LogEventLevel.Warning; |
|
||||||
public LogEventLevel Jobs { get; set; } = LogEventLevel.Information; |
|
||||||
} |
|
||||||
@ -1,9 +0,0 @@ |
|||||||
using Serilog.Events; |
|
||||||
|
|
||||||
namespace Bit.Core.Settings.LoggingSettings; |
|
||||||
|
|
||||||
public class EventsLogLevelSettings : IEventsLogLevelSettings |
|
||||||
{ |
|
||||||
public LogEventLevel Default { get; set; } = LogEventLevel.Error; |
|
||||||
public LogEventLevel IdentityToken { get; set; } = LogEventLevel.Fatal; |
|
||||||
} |
|
||||||
@ -1,8 +0,0 @@ |
|||||||
using Serilog.Events; |
|
||||||
|
|
||||||
namespace Bit.Core.Settings.LoggingSettings; |
|
||||||
|
|
||||||
public class EventsProcessorLogLevelSettings : IEventsProcessorLogLevelSettings |
|
||||||
{ |
|
||||||
public LogEventLevel Default { get; set; } = LogEventLevel.Warning; |
|
||||||
} |
|
||||||
@ -1,8 +0,0 @@ |
|||||||
using Serilog.Events; |
|
||||||
|
|
||||||
namespace Bit.Core.Settings.LoggingSettings; |
|
||||||
|
|
||||||
public class IconsLogLevelSettings : IIconsLogLevelSettings |
|
||||||
{ |
|
||||||
public LogEventLevel Default { get; set; } = LogEventLevel.Error; |
|
||||||
} |
|
||||||
@ -1,10 +0,0 @@ |
|||||||
using Serilog.Events; |
|
||||||
|
|
||||||
namespace Bit.Core.Settings.LoggingSettings; |
|
||||||
|
|
||||||
public class IdentityLogLevelSettings : IIdentityLogLevelSettings |
|
||||||
{ |
|
||||||
public LogEventLevel Default { get; set; } = LogEventLevel.Error; |
|
||||||
public LogEventLevel IdentityToken { get; set; } = LogEventLevel.Fatal; |
|
||||||
public LogEventLevel IpRateLimit { get; set; } = LogEventLevel.Information; |
|
||||||
} |
|
||||||
@ -1,16 +0,0 @@ |
|||||||
|
|
||||||
namespace Bit.Core.Settings.LoggingSettings; |
|
||||||
|
|
||||||
public class LogLevelSettings : ILogLevelSettings |
|
||||||
{ |
|
||||||
public IBillingLogLevelSettings BillingSettings { get; set; } = new BillingLogLevelSettings(); |
|
||||||
public IApiLogLevelSettings ApiSettings { get; set; } = new ApiLogLevelSettings(); |
|
||||||
public IIdentityLogLevelSettings IdentitySettings { get; set; } = new IdentityLogLevelSettings(); |
|
||||||
public IScimLogLevelSettings ScimSettings { get; set; } = new ScimLogLevelSettings(); |
|
||||||
public ISsoLogLevelSettings SsoSettings { get; set; } = new SsoLogLevelSettings(); |
|
||||||
public IAdminLogLevelSettings AdminSettings { get; set; } = new AdminLogLevelSettings(); |
|
||||||
public IEventsLogLevelSettings EventsSettings { get; set; } = new EventsLogLevelSettings(); |
|
||||||
public IEventsProcessorLogLevelSettings EventsProcessorSettings { get; set; } = new EventsProcessorLogLevelSettings(); |
|
||||||
public IIconsLogLevelSettings IconsSettings { get; set; } = new IconsLogLevelSettings(); |
|
||||||
public INotificationsLogLevelSettings NotificationsSettings { get; set; } = new NotificationsLogLevelSettings(); |
|
||||||
} |
|
||||||
@ -1,9 +0,0 @@ |
|||||||
using Serilog.Events; |
|
||||||
|
|
||||||
namespace Bit.Core.Settings.LoggingSettings; |
|
||||||
|
|
||||||
public class NotificationsLogLevelSettings : INotificationsLogLevelSettings |
|
||||||
{ |
|
||||||
public LogEventLevel Default { get; set; } = LogEventLevel.Warning; |
|
||||||
public LogEventLevel IdentityToken { get; set; } = LogEventLevel.Fatal; |
|
||||||
} |
|
||||||
@ -1,8 +0,0 @@ |
|||||||
using Serilog.Events; |
|
||||||
|
|
||||||
namespace Bit.Core.Settings.LoggingSettings; |
|
||||||
|
|
||||||
public class ScimLogLevelSettings : IScimLogLevelSettings |
|
||||||
{ |
|
||||||
public LogEventLevel Default { get; set; } = LogEventLevel.Warning; |
|
||||||
} |
|
||||||
@ -1,8 +0,0 @@ |
|||||||
using Serilog.Events; |
|
||||||
|
|
||||||
namespace Bit.Core.Settings.LoggingSettings; |
|
||||||
|
|
||||||
public class SsoLogLevelSettings : ISsoLogLevelSettings |
|
||||||
{ |
|
||||||
public LogEventLevel Default { get; set; } = LogEventLevel.Error; |
|
||||||
} |
|
||||||
@ -1,165 +1,78 @@ |
|||||||
using System.Security.Cryptography.X509Certificates; |
using Microsoft.AspNetCore.Hosting; |
||||||
using Bit.Core.Settings; |
|
||||||
using Microsoft.AspNetCore.Builder; |
|
||||||
using Microsoft.AspNetCore.Hosting; |
|
||||||
using Microsoft.Extensions.Configuration; |
using Microsoft.Extensions.Configuration; |
||||||
using Microsoft.Extensions.Hosting; |
using Microsoft.Extensions.Hosting; |
||||||
using Microsoft.Extensions.Logging; |
using Microsoft.Extensions.Logging; |
||||||
using Serilog; |
|
||||||
using Serilog.Events; |
|
||||||
using Serilog.Sinks.Syslog; |
|
||||||
|
|
||||||
namespace Bit.Core.Utilities; |
namespace Bit.Core.Utilities; |
||||||
|
|
||||||
public static class LoggerFactoryExtensions |
public static class LoggerFactoryExtensions |
||||||
{ |
{ |
||||||
public static void UseSerilog( |
/// <summary> |
||||||
this IApplicationBuilder appBuilder, |
/// |
||||||
IWebHostEnvironment env, |
/// </summary> |
||||||
IHostApplicationLifetime applicationLifetime, |
/// <param name="hostBuilder"></param> |
||||||
GlobalSettings globalSettings) |
/// <returns></returns> |
||||||
|
public static IHostBuilder AddSerilogFileLogging(this IHostBuilder hostBuilder) |
||||||
{ |
{ |
||||||
if (env.IsDevelopment() && !globalSettings.EnableDevLogging) |
return hostBuilder.ConfigureLogging((context, logging) => |
||||||
{ |
{ |
||||||
return; |
if (context.HostingEnvironment.IsDevelopment()) |
||||||
} |
|
||||||
|
|
||||||
applicationLifetime.ApplicationStopped.Register(Log.CloseAndFlush); |
|
||||||
} |
|
||||||
|
|
||||||
public static ILoggingBuilder AddSerilog( |
|
||||||
this ILoggingBuilder builder, |
|
||||||
WebHostBuilderContext context, |
|
||||||
Func<LogEvent, IGlobalSettings, bool>? filter = null) |
|
||||||
{ |
|
||||||
var globalSettings = new GlobalSettings(); |
|
||||||
ConfigurationBinder.Bind(context.Configuration.GetSection("GlobalSettings"), globalSettings); |
|
||||||
|
|
||||||
if (context.HostingEnvironment.IsDevelopment() && !globalSettings.EnableDevLogging) |
|
||||||
{ |
|
||||||
return builder; |
|
||||||
} |
|
||||||
|
|
||||||
bool inclusionPredicate(LogEvent e) |
|
||||||
{ |
|
||||||
if (filter == null) |
|
||||||
{ |
|
||||||
return true; |
|
||||||
} |
|
||||||
var eventId = e.Properties.TryGetValue("EventId", out var eventIdValue) ? eventIdValue.ToString() : null; |
|
||||||
if (eventId?.Contains(Constants.BypassFiltersEventId.ToString()) ?? false) |
|
||||||
{ |
{ |
||||||
return true; |
return; |
||||||
} |
} |
||||||
return filter(e, globalSettings); |
|
||||||
} |
|
||||||
|
|
||||||
var logSentryWarning = false; |
// If they have begun using the new settings location, use that |
||||||
var logSyslogWarning = false; |
if (!string.IsNullOrEmpty(context.Configuration["Logging:PathFormat"])) |
||||||
|
|
||||||
// Path format is the only required option for file logging, we will use that as |
|
||||||
// the keystone for if they have configured the new location. |
|
||||||
var newPathFormat = context.Configuration["Logging:PathFormat"]; |
|
||||||
|
|
||||||
var config = new LoggerConfiguration() |
|
||||||
.MinimumLevel.Verbose() |
|
||||||
.Enrich.FromLogContext() |
|
||||||
.Filter.ByIncludingOnly(inclusionPredicate); |
|
||||||
|
|
||||||
if (CoreHelpers.SettingHasValue(globalSettings.Sentry.Dsn)) |
|
||||||
{ |
|
||||||
config.WriteTo.Sentry(globalSettings.Sentry.Dsn) |
|
||||||
.Enrich.FromLogContext() |
|
||||||
.Enrich.WithProperty("Project", globalSettings.ProjectName); |
|
||||||
} |
|
||||||
else if (CoreHelpers.SettingHasValue(globalSettings.Syslog.Destination)) |
|
||||||
{ |
|
||||||
logSyslogWarning = true; |
|
||||||
// appending sitename to project name to allow easier identification in syslog. |
|
||||||
var appName = $"{globalSettings.SiteName}-{globalSettings.ProjectName}"; |
|
||||||
if (globalSettings.Syslog.Destination.Equals("local", StringComparison.OrdinalIgnoreCase)) |
|
||||||
{ |
{ |
||||||
config.WriteTo.LocalSyslog(appName); |
logging.AddFile(context.Configuration.GetSection("Logging")); |
||||||
} |
} |
||||||
else if (Uri.TryCreate(globalSettings.Syslog.Destination, UriKind.Absolute, out var syslogAddress)) |
else |
||||||
{ |
{ |
||||||
// Syslog's standard port is 514 (both UDP and TCP). TLS does not have a standard port, so assume 514. |
var globalSettingsSection = context.Configuration.GetSection("GlobalSettings"); |
||||||
int port = syslogAddress.Port >= 0 |
var loggingOptions = new LegacyFileLoggingOptions(); |
||||||
? syslogAddress.Port |
globalSettingsSection.Bind(loggingOptions); |
||||||
: 514; |
|
||||||
|
|
||||||
if (syslogAddress.Scheme.Equals("udp")) |
if (string.IsNullOrWhiteSpace(loggingOptions.LogDirectory)) |
||||||
{ |
|
||||||
config.WriteTo.UdpSyslog(syslogAddress.Host, port, appName); |
|
||||||
} |
|
||||||
else if (syslogAddress.Scheme.Equals("tcp")) |
|
||||||
{ |
|
||||||
config.WriteTo.TcpSyslog(syslogAddress.Host, port, appName); |
|
||||||
} |
|
||||||
else if (syslogAddress.Scheme.Equals("tls")) |
|
||||||
{ |
{ |
||||||
if (CoreHelpers.SettingHasValue(globalSettings.Syslog.CertificateThumbprint)) |
return; |
||||||
{ |
|
||||||
config.WriteTo.TcpSyslog(syslogAddress.Host, port, appName, |
|
||||||
useTls: true, |
|
||||||
certProvider: new CertificateStoreProvider(StoreName.My, StoreLocation.CurrentUser, |
|
||||||
globalSettings.Syslog.CertificateThumbprint)); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
config.WriteTo.TcpSyslog(syslogAddress.Host, port, appName, |
|
||||||
useTls: true, |
|
||||||
certProvider: new CertificateFileProvider(globalSettings.Syslog.CertificatePath, |
|
||||||
globalSettings.Syslog?.CertificatePassword ?? string.Empty)); |
|
||||||
} |
|
||||||
} |
} |
||||||
} |
|
||||||
} |
var projectName = loggingOptions.ProjectName |
||||||
else if (!string.IsNullOrEmpty(newPathFormat)) |
?? context.HostingEnvironment.ApplicationName; |
||||||
{ |
|
||||||
// Use new location |
if (loggingOptions.LogRollBySizeLimit.HasValue) |
||||||
builder.AddFile(context.Configuration.GetSection("Logging")); |
|
||||||
} |
|
||||||
else if (CoreHelpers.SettingHasValue(globalSettings.LogDirectory)) |
|
||||||
{ |
|
||||||
if (globalSettings.LogRollBySizeLimit.HasValue) |
|
||||||
{ |
|
||||||
var pathFormat = Path.Combine(globalSettings.LogDirectory, $"{globalSettings.ProjectName.ToLowerInvariant()}.log"); |
|
||||||
if (globalSettings.LogDirectoryByProject) |
|
||||||
{ |
{ |
||||||
pathFormat = Path.Combine(globalSettings.LogDirectory, globalSettings.ProjectName, "log.txt"); |
var pathFormat = loggingOptions.LogDirectoryByProject |
||||||
|
? Path.Combine(loggingOptions.LogDirectory, projectName, "log.txt") |
||||||
|
: Path.Combine(loggingOptions.LogDirectory, $"{projectName.ToLowerInvariant()}.log"); |
||||||
|
|
||||||
|
logging.AddFile( |
||||||
|
pathFormat: pathFormat, |
||||||
|
fileSizeLimitBytes: loggingOptions.LogRollBySizeLimit.Value |
||||||
|
); |
||||||
} |
} |
||||||
config.WriteTo.File(pathFormat, rollOnFileSizeLimit: true, |
else |
||||||
fileSizeLimitBytes: globalSettings.LogRollBySizeLimit); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
var pathFormat = Path.Combine(globalSettings.LogDirectory, $"{globalSettings.ProjectName.ToLowerInvariant()}_{{Date}}.log"); |
|
||||||
if (globalSettings.LogDirectoryByProject) |
|
||||||
{ |
{ |
||||||
pathFormat = Path.Combine(globalSettings.LogDirectory, globalSettings.ProjectName, "{Date}.txt"); |
var pathFormat = loggingOptions.LogDirectoryByProject |
||||||
|
? Path.Combine(loggingOptions.LogDirectory, projectName, "{Date}.txt") |
||||||
|
: Path.Combine(loggingOptions.LogDirectory, $"{projectName.ToLowerInvariant()}_{{Date}}.log"); |
||||||
|
|
||||||
|
logging.AddFile( |
||||||
|
pathFormat: pathFormat |
||||||
|
); |
||||||
} |
} |
||||||
config.WriteTo.RollingFile(pathFormat); |
|
||||||
} |
} |
||||||
config |
}); |
||||||
.Enrich.FromLogContext() |
} |
||||||
.Enrich.WithProperty("Project", globalSettings.ProjectName); |
|
||||||
} |
|
||||||
|
|
||||||
var serilog = config.CreateLogger(); |
|
||||||
|
|
||||||
if (logSentryWarning) |
|
||||||
{ |
|
||||||
serilog.Warning("Sentry for logging has been deprecated. Read more: https://btwrdn.com/log-deprecation"); |
|
||||||
} |
|
||||||
|
|
||||||
if (logSyslogWarning) |
|
||||||
{ |
|
||||||
serilog.Warning("Syslog for logging has been deprecated. Read more: https://btwrdn.com/log-deprecation"); |
|
||||||
} |
|
||||||
|
|
||||||
builder.AddSerilog(serilog); |
|
||||||
|
|
||||||
return builder; |
/// <summary> |
||||||
|
/// Our own proprietary options that we've always supported in `GlobalSettings` configuration section. |
||||||
|
/// </summary> |
||||||
|
private class LegacyFileLoggingOptions |
||||||
|
{ |
||||||
|
public string? ProjectName { get; set; } |
||||||
|
public string? LogDirectory { get; set; } = "/etc/bitwarden/logs"; |
||||||
|
public bool LogDirectoryByProject { get; set; } = true; |
||||||
|
public long? LogRollBySizeLimit { get; set; } |
||||||
} |
} |
||||||
} |
} |
||||||
|
|||||||
Loading…
Reference in new issue