diff --git a/.gitignore b/.gitignore index 1a1f5ad..3d0ab97 100644 --- a/.gitignore +++ b/.gitignore @@ -290,3 +290,11 @@ __pycache__/ *.btm.cs *.odx.cs *.xsd.cs + +_site/* +index.md +toc.yml +.fsdocs/* +docs/* +# documentation +pentole/* diff --git a/Pentole/logginghelpers.fs b/Pentole/logginghelpers.fs new file mode 100644 index 0000000..8543593 --- /dev/null +++ b/Pentole/logginghelpers.fs @@ -0,0 +1,162 @@ +/// Provides convenience function to initialiaze and use Serilog loggers. +module Pentole.LoggingHelpers + +open System + +open Serilog +open Serilog.Events +open Serilog.Sinks.SystemConsole.Themes +open Serilog.Sinks.File + +/// +/// Choose the minimum log level for a namespace. +/// +/// +/// +/// let logger_config: LoggingHelpers.Configuration = { +/// files = [] +/// template = LoggingHelpers.Default.debug_template +/// theme = LoggingHelpers.Default.theme +/// overrides = [Warning "Microsoft.AspNetCore.MvC"; Info "Orleans.Runtime"] +/// } +/// +/// let logger = LoggingHelpers.from_config logger_config +/// +/// +type Override = + | Verbose of string + | Debug of string + | Information of string + | Warning of string + | Error of string + | Fatal of string + +/// +/// Indicates if flushing to the output file can be buffered or not. +/// +type Buffered = Yes | No +/// +/// Enable multi-process shared log files. +/// +type Shared = Yes | No + +/// +/// Roll when the file reaches fileSizeLimitBytes. +/// +/// +/// See also FileConfiguration.file_size_bytes_limit +/// +type RollOnSizeLimit = Yes | No + +/// +/// Configuration settings for file logging. +/// +/// +/// For FileLifecyceHooks and LoggingLevelSwitch see the relevant Serilog documentation. +/// +type FileConfiguration = { + path: string + level: LogEventLevel + template: string + format_provider: System.IFormatProvider + file_size_bytes_limit: uint64 + level_switch: Core.LoggingLevelSwitch option + buffered: Buffered + shared: Shared + flush_interval: TimeSpan option + rolling_interval: RollingInterval + roll_on_size_limit: RollOnSizeLimit + retained_files: uint + lifecycle_hooks: FileLifecycleHooks option +} + +type Configuration = { + theme: SystemConsoleTheme + overrides: Override list + template: string + files: FileConfiguration list +} +/// +/// Configures and creates a Serilog logger from the given configuration. +/// +/// The configuration object containing settings for logging. +/// A configured Serilog Logger instance. +/// +/// +/// let config = { theme = Default.theme; overrides = Default.overrides; template = Default.template; files = [] } +/// let logger = from_config config +/// +/// +let from_config (c: Configuration) = + + let override_ (lc: LoggerConfiguration) = function + | Verbose namespace_ -> + lc.MinimumLevel.Override (namespace_, LogEventLevel.Verbose) + | Debug namespace_ -> + lc.MinimumLevel.Override (namespace_, LogEventLevel.Debug) + | Information namespace_ -> + lc.MinimumLevel.Override (namespace_, LogEventLevel.Information) + | Warning namespace_ -> + lc.MinimumLevel.Override (namespace_, LogEventLevel.Warning) + | Error namespace_ -> + lc.MinimumLevel.Override (namespace_, LogEventLevel.Error) + | Fatal namespace_ -> + lc.MinimumLevel.Override (namespace_, LogEventLevel.Fatal) + + let lc = + c.overrides + |> List.fold (fun lc target -> override_ lc target) (LoggerConfiguration()) + + let null_or = function | Some a -> a | None -> null + let buffered = function | Buffered.Yes -> true | Buffered.No -> false + let shared = function | Shared.Yes -> true | Shared.No -> false + let roll = function | RollOnSizeLimit.Yes -> true | RollOnSizeLimit.No -> false + + let flush_interval = function Some ts -> Nullable ts | None -> Nullable () + + let lc = + c.files + |> List.fold (fun (lc: LoggerConfiguration) (fc: FileConfiguration) -> + lc.WriteTo.File( + path = fc.path, + restrictedToMinimumLevel = fc.level, + outputTemplate = fc.template, + formatProvider = fc.format_provider, + fileSizeLimitBytes = Nullable (int64 fc.file_size_bytes_limit), + levelSwitch = null_or fc.level_switch, + buffered = buffered fc.buffered, + shared = shared fc.shared, + flushToDiskInterval = flush_interval fc.flush_interval, + rollingInterval = fc.rolling_interval, + rollOnFileSizeLimit = roll fc.roll_on_size_limit, + retainedFileCountLimit = Nullable (int fc.retained_files), + encoding = System.Text.Encoding.UTF8, + hooks = null_or fc.lifecycle_hooks, + retainedFileTimeLimit = TimeSpan.Zero)) + lc + + lc + .WriteTo.Console(theme=c.theme, outputTemplate=c.template) + .CreateLogger() + +/// Holds some conventional defaults for the LoggingHelpers module +module Default = + let retained_files = 31 (* one month *) + let file_size_bytes = 1 * 1024 * 1024 * 1024 (* 1GB *) + let size_limit = 1 * 1024 * 1024 * 1024 (* 1GB *) + let template = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}"; + let debug_template = "[{Timestamp:HH:mm:ss} {Level:u3}] |{SourceContext}| {Message:lj}{NewLine}{Exception}" + let theme = Serilog.Sinks.SystemConsole.Themes.SystemConsoleTheme.Literate + + let overrides = [ + Warning "Orleans.Runtime" + Warning "Orleans.Hosting" + Warning "Microsoft" + // Warning "Microsoft.AspNetCore" + // Warning "Microsoft.AspNetCore.Hosting" + // Warning "Microsoft.AspNetCore.Mvc" + // Warning "Microsoft.AspNetCore.Routing" + // Warning "Orleans.Runtime.Silo" +// Warning "Orleans.Runtime.SiloOptionsLogger" + // Warning "Orleans.Runtime.SiloHostedService" + ]