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"
+ ]