From ac083d51d8e246317f7f3d76fc122f4ba22730ca Mon Sep 17 00:00:00 2001 From: Ruben Bartelink Date: Mon, 22 Jun 2020 17:23:02 +0100 Subject: [PATCH 01/12] module Logging->type --- README.md | 8 ++-- equinox-shipping/Watchdog/Infrastructure.fs | 38 +++++++++++++++ equinox-shipping/Watchdog/Program.fs | 25 +--------- equinox-shipping/Watchdog/Watchdog.fsproj | 1 + propulsion-consumer/Infrastructure.fs | 17 ++++++- propulsion-consumer/Program.fs | 18 +------- propulsion-projector/Infrastructure.fs | 46 +++++++++++++++++++ propulsion-projector/Program.fs | 34 ++------------ propulsion-projector/Projector.fsproj | 1 + propulsion-reactor/Infrastructure.fs | 45 +++++++++++++++++- propulsion-reactor/Program.fs | 35 ++------------ propulsion-summary-consumer/Infrastructure.fs | 17 ++++++- propulsion-summary-consumer/Program.fs | 20 ++------ propulsion-sync/Program.fs | 1 - .../Infrastructure.fs | 17 ++++++- propulsion-tracking-consumer/Program.fs | 19 +------- 16 files changed, 197 insertions(+), 145 deletions(-) create mode 100644 equinox-shipping/Watchdog/Infrastructure.fs create mode 100644 propulsion-projector/Infrastructure.fs diff --git a/README.md b/README.md index 6996b39b4..0d8daa47e 100644 --- a/README.md +++ b/README.md @@ -249,7 +249,7 @@ _Responsible for: mapping Environment Variables and the Command Line `argv` to a NOTE: there's a [medium term plan to submit a PR to Argu](https://github.com/fsprojects/Argu/issues/143) extending it to be able to fall back to environment variables where a value is not supplied, by means of declarative attributes on the Argument specification in the DU, _including having the `--help` message automatically include a reference to the name of the environment variable that one can supply the value through_ -### `module Logging` +### `type Logging` _Responsible for applying logging config and setting up loggers for the application_ @@ -258,10 +258,10 @@ _Responsible for applying logging config and setting up loggers for the applicat #### example ``` -module Logging = +type Logging() = - let initialize verbose = - Log.Logger <- LoggerConfiguration(….) + static member Initialize(?minimumLevel) = + Log.Logger <- LoggerConfiguration(….) ``` ### `start` function diff --git a/equinox-shipping/Watchdog/Infrastructure.fs b/equinox-shipping/Watchdog/Infrastructure.fs new file mode 100644 index 000000000..2d14b4938 --- /dev/null +++ b/equinox-shipping/Watchdog/Infrastructure.fs @@ -0,0 +1,38 @@ +[] +module Shipping.Watchdog.Infrastructure + +open Serilog +open System.Runtime.CompilerServices + +[] +type LoggerConfigurationExtensions() = + + [] + static member inline ExcludeChangeFeedProcessorV2InternalDiagnostics(c : LoggerConfiguration) = + let isCfp429a = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.LeaseManagement.DocumentServiceLeaseUpdater").Invoke + let isCfp429b = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.PartitionManagement.LeaseRenewer").Invoke + let isCfp429c = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.PartitionManagement.PartitionLoadBalancer").Invoke + let isCfp429d = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.FeedProcessing.PartitionProcessor").Invoke + let isCfp x = isCfp429a x || isCfp429b x || isCfp429c x || isCfp429d x + c.Filter.ByExcluding(fun x -> isCfp x) + + [] + static member inline ConfigureChangeFeedProcessorLogging(c : LoggerConfiguration, verbose : bool) = + // LibLog writes to the global logger, so we need to control the emission + let cfpl = if verbose then Serilog.Events.LogEventLevel.Debug else Serilog.Events.LogEventLevel.Warning + c.MinimumLevel.Override("Microsoft.Azure.Documents.ChangeFeedProcessor", cfpl) + |> fun c -> if verbose then c.ExcludeChangeFeedProcessorV2InternalDiagnostics() else c + +// Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline +type Logging() = + + static member Initialize(?minimumLevel, ?changeFeedProcessorVerbose) = + Log.Logger <- + LoggerConfiguration() + .Destructure.FSharpTypes() + .Enrich.FromLogContext() + |> fun c -> match minimumLevel with Some m -> c.MinimumLevel.Is m | None -> c + |> fun c -> c.ConfigureChangeFeedProcessorLogging((changeFeedProcessorVerbose = Some true)) + |> fun c -> let t = "[{Timestamp:HH:mm:ss} {Level:u3}] {partitionKeyRangeId,2} {Message:lj} {NewLine}{Exception}" + c.WriteTo.Console(theme=Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code, outputTemplate=t) + |> fun c -> c.CreateLogger() diff --git a/equinox-shipping/Watchdog/Program.fs b/equinox-shipping/Watchdog/Program.fs index d0cc88fb7..c53697d88 100644 --- a/equinox-shipping/Watchdog/Program.fs +++ b/equinox-shipping/Watchdog/Program.fs @@ -53,7 +53,7 @@ module Args = | Cosmos _ -> "specify CosmosDB input parameters." and Arguments(a : ParseResults) = member __.ConsumerGroupName = a.GetResult ConsumerGroupName - member __.Verbose = a.Contains Verbose + member __.MinimumLevel = if a.Contains Verbose then Some Events.LogEventLevel.Debug else None member __.CfpVerbose = a.Contains CfpVerbose member __.MaxReadAhead = a.GetResult(MaxReadAhead, 16) member __.MaxConcurrentStreams = a.GetResult(MaxWriters, 8) @@ -175,27 +175,6 @@ module Args = let parser = ArgumentParser.Create(programName=programName) parser.ParseCommandLine argv |> Arguments -module Logging = - - let initialize verbose changeFeedProcessorVerbose = - Log.Logger <- - LoggerConfiguration() - .Destructure.FSharpTypes() - .Enrich.FromLogContext() - |> fun c -> if verbose then c.MinimumLevel.Debug() else c - // LibLog writes to the global logger, so we need to control the emission - |> fun c -> let cfpl = if changeFeedProcessorVerbose then Serilog.Events.LogEventLevel.Debug else Serilog.Events.LogEventLevel.Warning - c.MinimumLevel.Override("Microsoft.Azure.Documents.ChangeFeedProcessor", cfpl) - |> fun c -> let isCfp429a = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.LeaseManagement.DocumentServiceLeaseUpdater").Invoke - let isCfp429b = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.PartitionManagement.LeaseRenewer").Invoke - let isCfp429c = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.PartitionManagement.PartitionLoadBalancer").Invoke - let isCfp429d = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.FeedProcessing.PartitionProcessor").Invoke - let isCfp x = isCfp429a x || isCfp429b x || isCfp429c x || isCfp429d x - if changeFeedProcessorVerbose then c else c.Filter.ByExcluding(fun x -> isCfp x) - |> fun c -> let t = "[{Timestamp:HH:mm:ss} {Level:u3}] {partitionKeyRangeId,2} {Message:lj} {NewLine}{Exception}" - c.WriteTo.Console(theme=Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code, outputTemplate=t) - |> fun c -> c.CreateLogger() - let [] AppName = "Watchdog" let startWatchdog log (processingTimeout, stats : Handler.Stats) (maxReadAhead, maxConcurrentStreams) driveTransaction @@ -242,7 +221,7 @@ let run args = [] let main argv = try let args = Args.parse argv - try Logging.initialize args.Verbose args.CfpVerbose + try Logging.Initialize(?minimumLevel=args.MinimumLevel, changeFeedProcessorVerbose=args.CfpVerbose) try Configuration.initialize () if run args then 0 else 3 with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 diff --git a/equinox-shipping/Watchdog/Watchdog.fsproj b/equinox-shipping/Watchdog/Watchdog.fsproj index b574c2ccb..a771969ee 100644 --- a/equinox-shipping/Watchdog/Watchdog.fsproj +++ b/equinox-shipping/Watchdog/Watchdog.fsproj @@ -8,6 +8,7 @@ + diff --git a/propulsion-consumer/Infrastructure.fs b/propulsion-consumer/Infrastructure.fs index 62dfd8564..7b6b05328 100644 --- a/propulsion-consumer/Infrastructure.fs +++ b/propulsion-consumer/Infrastructure.fs @@ -47,4 +47,19 @@ type System.Threading.SemaphoreSlim with do! semaphore.Await() try return! workflow finally semaphore.Release() |> ignore - } \ No newline at end of file + } + +open Serilog + +// Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline +type Logging() = + + static member Initialize(?minimumLevel) = + Log.Logger <- + LoggerConfiguration() + .Destructure.FSharpTypes() + .Enrich.FromLogContext() + |> fun c -> match minimumLevel with Some m -> c.MinimumLevel.Is m | None -> c + |> fun c -> let theme = Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code + c.WriteTo.Console(theme=theme, outputTemplate="[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties}{NewLine}{Exception}") + |> fun c -> c.CreateLogger() diff --git a/propulsion-consumer/Program.fs b/propulsion-consumer/Program.fs index b7b35b472..d4081ccfc 100644 --- a/propulsion-consumer/Program.fs +++ b/propulsion-consumer/Program.fs @@ -69,7 +69,7 @@ module Args = member __.LagFrequency = a.TryGetResult LagFreqM |> Option.map TimeSpan.FromMinutes member __.MaxDop = a.GetResult(MaxDop, 8) - member __.Verbose = a.Contains Verbose + member __.MinimumLevel = if a.Contains Verbose then Some Events.LogEventLevel.Debug else None /// Parse the commandline; can throw exceptions in response to missing arguments and/or `-h`/`--help` args let parse argv = @@ -77,20 +77,6 @@ module Args = let parser = ArgumentParser.Create(programName = programName) parser.ParseCommandLine argv |> Arguments -// TODO remove this entire comment after reading https://github.com/jet/dotnet-templates#module-logging -// Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline -module Logging = - - let initialize verbose = - Log.Logger <- - LoggerConfiguration() - .Destructure.FSharpTypes() - .Enrich.FromLogContext() - |> fun c -> if verbose then c.MinimumLevel.Debug() else c - |> fun c -> let theme = Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code - c.WriteTo.Console(theme=theme, outputTemplate="[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties}{NewLine}{Exception}") - |> fun c -> c.CreateLogger() - let [] AppName = "ConsumerTemplate" let start (args : Args.Arguments) = @@ -112,7 +98,7 @@ let run args = [] let main argv = try let args = Args.parse argv - try Logging.initialize args.Verbose + try Logging.Initialize(?minimumLevel=args.MinimumLevel) try Configuration.initialize () if run args then 0 else 3 with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 diff --git a/propulsion-projector/Infrastructure.fs b/propulsion-projector/Infrastructure.fs new file mode 100644 index 000000000..c7fedeaff --- /dev/null +++ b/propulsion-projector/Infrastructure.fs @@ -0,0 +1,46 @@ +[] +module ProjectorTemplate.Infrastructure + +open Serilog +open System.Runtime.CompilerServices + +#if cosmos +[] +type LoggerConfigurationExtensions() = + + [] + static member inline ExcludeChangeFeedProcessorV2InternalDiagnostics(c : LoggerConfiguration) = + let isCfp429a = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.LeaseManagement.DocumentServiceLeaseUpdater").Invoke + let isCfp429b = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.PartitionManagement.LeaseRenewer").Invoke + let isCfp429c = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.PartitionManagement.PartitionLoadBalancer").Invoke + let isCfp429d = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.FeedProcessing.PartitionProcessor").Invoke + let isCfp x = isCfp429a x || isCfp429b x || isCfp429c x || isCfp429d x + c.Filter.ByExcluding(fun x -> isCfp x) + + [] + static member inline ConfigureChangeFeedProcessorLogging(c : LoggerConfiguration, verbose : bool) = + // LibLog writes to the global logger, so we need to control the emission + let cfpl = if verbose then Serilog.Events.LogEventLevel.Debug else Serilog.Events.LogEventLevel.Warning + c.MinimumLevel.Override("Microsoft.Azure.Documents.ChangeFeedProcessor", cfpl) + |> fun c -> if verbose then c.ExcludeChangeFeedProcessorV2InternalDiagnostics() else c + +#endif +// Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline +type Logging() = + +#if cosmos + static member Initialize(?minimumLevel, ?changeFeedProcessorVerbose) = +#else + static member Initialize(?minimumLevel) = +#endif + Log.Logger <- + LoggerConfiguration() + .Destructure.FSharpTypes() + .Enrich.FromLogContext() + |> fun c -> match minimumLevel with Some m -> c.MinimumLevel.Is m | None -> c +#if cosmos + |> fun c -> c.ConfigureChangeFeedProcessorLogging((changeFeedProcessorVerbose = Some true)) +#endif + |> fun c -> let t = "[{Timestamp:HH:mm:ss} {Level:u3}] {partitionKeyRangeId,2} {Message:lj} {NewLine}{Exception}" + c.WriteTo.Console(theme=Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code, outputTemplate=t) + |> fun c -> c.CreateLogger() diff --git a/propulsion-projector/Program.fs b/propulsion-projector/Program.fs index 9bb7b8169..693cdb2e1 100644 --- a/propulsion-projector/Program.fs +++ b/propulsion-projector/Program.fs @@ -315,7 +315,7 @@ module Args = | SqlMs _ -> "specify SqlStreamStore input parameters." //#endif and Arguments(a : ParseResults) = - member __.Verbose = a.Contains Verbose + member __.MinimumLevel = if a.Contains Verbose then Some Events.LogEventLevel.Debug else None member __.ConsumerGroupName = a.GetResult ConsumerGroupName member __.MaxReadAhead = a.GetResult(MaxReadAhead, 64) member __.MaxConcurrentProcessors = a.GetResult(MaxWriters, 1024) @@ -374,34 +374,6 @@ module Args = let parser = ArgumentParser.Create(programName=programName) parser.ParseCommandLine argv |> Arguments -// TODO remove this entire comment after reading https://github.com/jet/dotnet-templates#module-logging -// Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline -module Logging = - -#if cosmos - let initialize verbose changeFeedProcessorVerbose = -#else - let initialize verbose = -#endif - Log.Logger <- - LoggerConfiguration() - .Destructure.FSharpTypes() - .Enrich.FromLogContext() - |> fun c -> if verbose then c.MinimumLevel.Debug() else c -#if cosmos - // LibLog writes to the global logger, so we need to control the emission - |> fun c -> let cfpl = if changeFeedProcessorVerbose then Serilog.Events.LogEventLevel.Debug else Serilog.Events.LogEventLevel.Warning - c.MinimumLevel.Override("Microsoft.Azure.Documents.ChangeFeedProcessor", cfpl) - |> fun c -> let isCfp429a = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.LeaseManagement.DocumentServiceLeaseUpdater").Invoke - let isCfp429b = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.PartitionManagement.LeaseRenewer").Invoke - let isCfp429c = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.PartitionManagement.PartitionLoadBalancer").Invoke - let isCfp429d = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.FeedProcessing.PartitionProcessor").Invoke - let isCfp x = isCfp429a x || isCfp429b x || isCfp429c x || isCfp429d x - if changeFeedProcessorVerbose then c else c.Filter.ByExcluding(fun x -> isCfp x) -#endif - |> fun c -> let t = "[{Timestamp:HH:mm:ss} {Level:u3}] {partitionKeyRangeId,2} {Message:lj} {NewLine}{Exception}" - c.WriteTo.Console(theme=Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code, outputTemplate=t) - |> fun c -> c.CreateLogger() //#if esdb module Checkpoints = @@ -510,9 +482,9 @@ let run args = let main argv = try let args = Args.parse argv #if cosmos - try Logging.initialize args.Verbose args.Cosmos.CfpVerbose + try Logging.Initialize(?minimumLevel=args.MinimumLevel, changeFeedProcessorVerbose=args.Cosmos.CfpVerbose) #else - try Logging.initialize args.Verbose + try Logging.Initialize(?minimumLevel=args.MinimumLevel) #endif try Configuration.initialize () if run args then 0 else 3 diff --git a/propulsion-projector/Projector.fsproj b/propulsion-projector/Projector.fsproj index 403c5118c..9829c0922 100644 --- a/propulsion-projector/Projector.fsproj +++ b/propulsion-projector/Projector.fsproj @@ -8,6 +8,7 @@ + diff --git a/propulsion-reactor/Infrastructure.fs b/propulsion-reactor/Infrastructure.fs index 8f947e1f0..84427232d 100644 --- a/propulsion-reactor/Infrastructure.fs +++ b/propulsion-reactor/Infrastructure.fs @@ -1,6 +1,8 @@ namespace ReactorTemplate +open System.Runtime.CompilerServices open FSharp.UMX // see https://github.com/fsprojects/FSharp.UMX - % operator and ability to apply units of measure to Guids+strings +open Serilog open System module EventCodec = @@ -25,4 +27,45 @@ and [] clientId module ClientId = let toString (value : ClientId) : string = Guid.toStringN %value let parse (value : string) : ClientId = let raw = Guid.Parse value in % raw - let (|Parse|) = parse \ No newline at end of file + let (|Parse|) = parse + +#if (!kafkaEventSpans) +[] +type LoggerConfigurationExtensions() = + + [] + static member inline ExcludeChangeFeedProcessorV2InternalDiagnostics(c : LoggerConfiguration) = + let isCfp429a = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.LeaseManagement.DocumentServiceLeaseUpdater").Invoke + let isCfp429b = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.PartitionManagement.LeaseRenewer").Invoke + let isCfp429c = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.PartitionManagement.PartitionLoadBalancer").Invoke + let isCfp429d = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.FeedProcessing.PartitionProcessor").Invoke + let isCfp x = isCfp429a x || isCfp429b x || isCfp429c x || isCfp429d x + c.Filter.ByExcluding(fun x -> isCfp x) + + [] + static member inline ConfigureChangeFeedProcessorLogging(c : LoggerConfiguration, verbose : bool) = + // LibLog writes to the global logger, so we need to control the emission + let cfpl = if verbose then Serilog.Events.LogEventLevel.Debug else Serilog.Events.LogEventLevel.Warning + c.MinimumLevel.Override("Microsoft.Azure.Documents.ChangeFeedProcessor", cfpl) + |> fun c -> if verbose then c.ExcludeChangeFeedProcessorV2InternalDiagnostics() else c + +#endif +// Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful Args.parse +type Logging() = + +#if (!kafkaEventSpans) + static member Initialize(?minimumLevel, ?changeFeedProcessorVerbose) = +#else + static member Initialize(?minimumLevel) = +#endif + Log.Logger <- + LoggerConfiguration() + .Destructure.FSharpTypes() + .Enrich.FromLogContext() + |> fun c -> match minimumLevel with Some m -> c.MinimumLevel.Is m | None -> c +#if (!kafkaEventSpans) + |> fun c -> c.ConfigureChangeFeedProcessorLogging((changeFeedProcessorVerbose = Some true)) +#endif + |> fun c -> let t = "[{Timestamp:HH:mm:ss} {Level:u3}] {partitionKeyRangeId,2} {Message:lj} {NewLine}{Exception}" + c.WriteTo.Console(theme=Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code, outputTemplate=t) + |> fun c -> c.CreateLogger() diff --git a/propulsion-reactor/Program.fs b/propulsion-reactor/Program.fs index 6ee00b73c..eda3e30fa 100644 --- a/propulsion-reactor/Program.fs +++ b/propulsion-reactor/Program.fs @@ -101,12 +101,12 @@ module Args = #endif and Arguments(a : ParseResults) = member __.ConsumerGroupName = a.GetResult ConsumerGroupName - member __.Verbose = a.Contains Parameters.Verbose //#if (!kafkaEventSpans) member __.CfpVerbose = a.Contains CfpVerbose //#endif member __.MaxReadAhead = a.GetResult(MaxReadAhead, 16) member __.MaxConcurrentStreams = a.GetResult(MaxWriters, 8) + member __.MinimumLevel = if a.Contains Parameters.Verbose then Some Events.LogEventLevel.Debug else None member __.StatsInterval = TimeSpan.FromMinutes 1. member __.StateInterval = TimeSpan.FromMinutes 5. //#if filter @@ -488,35 +488,6 @@ module Args = let parser = ArgumentParser.Create(programName=programName) parser.ParseCommandLine argv |> Arguments -// TODO remove this entire comment after reading https://github.com/jet/dotnet-templates#module-logging -// Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful Args.parse -module Logging = - -#if (!kafkaEventSpans) - let initialize verbose changeFeedProcessorVerbose = -#else - let initialize verbose = -#endif - Log.Logger <- - LoggerConfiguration() - .Destructure.FSharpTypes() - .Enrich.FromLogContext() - |> fun c -> if verbose then c.MinimumLevel.Debug() else c -#if (!kafkaEventSpans) - // LibLog writes to the global logger, so we need to control the emission - |> fun c -> let cfpl = if changeFeedProcessorVerbose then Serilog.Events.LogEventLevel.Debug else Serilog.Events.LogEventLevel.Warning - c.MinimumLevel.Override("Microsoft.Azure.Documents.ChangeFeedProcessor", cfpl) - |> fun c -> let isCfp429a = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.LeaseManagement.DocumentServiceLeaseUpdater").Invoke - let isCfp429b = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.PartitionManagement.LeaseRenewer").Invoke - let isCfp429c = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.PartitionManagement.PartitionLoadBalancer").Invoke - let isCfp429d = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.FeedProcessing.PartitionProcessor").Invoke - let isCfp x = isCfp429a x || isCfp429b x || isCfp429c x || isCfp429d x - if changeFeedProcessorVerbose then c else c.Filter.ByExcluding(fun x -> isCfp x) -#endif - |> fun c -> let t = "[{Timestamp:HH:mm:ss} {Level:u3}] {partitionKeyRangeId,2} {Message:lj} {NewLine}{Exception}" - c.WriteTo.Console(theme=Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code, outputTemplate=t) - |> fun c -> c.CreateLogger() - let [] AppName = "ReactorTemplate" //#if multiSource @@ -715,9 +686,9 @@ let run args = let main argv = try let args = Args.parse argv #if (!kafkaEventSpans) - try Logging.initialize args.Verbose args.CfpVerbose + try Logging.Initialize(?minimumLevel=args.MinimumLevel, changeFeedProcessorVerbose=args.CfpVerbose) #else - try Logging.initialize args.Verbose + try Logging.Initialize(?minimumLevel=args.MinimumLevel) #endif try Configuration.initialize () if run args then 0 else 3 diff --git a/propulsion-summary-consumer/Infrastructure.fs b/propulsion-summary-consumer/Infrastructure.fs index 174ff901f..6c9290327 100644 --- a/propulsion-summary-consumer/Infrastructure.fs +++ b/propulsion-summary-consumer/Infrastructure.fs @@ -24,4 +24,19 @@ and [] clientId module ClientId = let toString (value : ClientId) : string = Guid.toStringN %value let parse (value : string) : ClientId = let raw = Guid.Parse value in % raw - let (|Parse|) = parse \ No newline at end of file + let (|Parse|) = parse + +open Serilog + +// Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline +type Logging() = + + static member Initialize(?minimumLevel) = + Log.Logger <- + LoggerConfiguration() + .Destructure.FSharpTypes() + .Enrich.FromLogContext() + |> fun c -> match minimumLevel with Some m -> c.MinimumLevel.Is m | None -> c + |> fun c -> let theme = Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code + c.WriteTo.Console(theme=theme, outputTemplate="[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties}{NewLine}{Exception}") + |> fun c -> c.CreateLogger() diff --git a/propulsion-summary-consumer/Program.fs b/propulsion-summary-consumer/Program.fs index 86fc21209..9d2a8240b 100644 --- a/propulsion-summary-consumer/Program.fs +++ b/propulsion-summary-consumer/Program.fs @@ -111,7 +111,8 @@ module Args = member __.LagFrequency = a.TryGetResult LagFreqM |> Option.map TimeSpan.FromMinutes member __.MaxConcurrentStreams = a.GetResult(MaxWriters, 8) - member __.Verbose = a.Contains Verbose + + member __.MinimumLevel = if a.Contains Verbose then Some Events.LogEventLevel.Debug else None member __.StatsInterval = TimeSpan.FromMinutes 1. member __.StateInterval = TimeSpan.FromMinutes 5. @@ -121,21 +122,6 @@ module Args = let parser = ArgumentParser.Create(programName=programName) parser.ParseCommandLine argv |> Arguments -// TODO remove this entire comment after reading https://github.com/jet/dotnet-templates#module-logging -// Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline -module Logging = - - let initialize verbose = - Log.Logger <- - LoggerConfiguration() - .Destructure.FSharpTypes() - .Enrich.FromLogContext() - |> fun c -> if verbose then c.MinimumLevel.Debug() else c - |> fun c -> let theme = Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code - if not verbose then c.WriteTo.Console(theme=theme) - else c.WriteTo.Console(theme=theme, outputTemplate="[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties}{NewLine}{Exception}") - |> fun c -> c.CreateLogger() - let [] AppName = "ConsumerTemplate" let start (args : Args.Arguments) = @@ -161,7 +147,7 @@ let run args = [] let main argv = try let args = Args.parse argv - try Logging.initialize args.Verbose + try Logging.Initialize(?minimumLevel=args.MinimumLevel) try Configuration.initialize () if run args then 0 else 3 with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 diff --git a/propulsion-sync/Program.fs b/propulsion-sync/Program.fs index 9b9180c70..6bf8afad9 100644 --- a/propulsion-sync/Program.fs +++ b/propulsion-sync/Program.fs @@ -440,7 +440,6 @@ module Args = let parser = ArgumentParser.Create(programName=programName) parser.ParseCommandLine argv |> Arguments -// TODO remove this entire comment after reading https://github.com/jet/dotnet-templates#module-logging // Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline module Logging = diff --git a/propulsion-tracking-consumer/Infrastructure.fs b/propulsion-tracking-consumer/Infrastructure.fs index b10b721b8..046e67ff1 100644 --- a/propulsion-tracking-consumer/Infrastructure.fs +++ b/propulsion-tracking-consumer/Infrastructure.fs @@ -20,4 +20,19 @@ and [] skuId module SkuId = let toString (value : SkuId) : string = % value let parse (value : string) : SkuId = let raw = value in % raw - let (|Parse|) = parse \ No newline at end of file + let (|Parse|) = parse + +open Serilog + +// Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline +type Logging() = + + static member Initialize(?minimumLevel) = + Log.Logger <- + LoggerConfiguration() + .Destructure.FSharpTypes() + .Enrich.FromLogContext() + |> fun c -> match minimumLevel with Some m -> c.MinimumLevel.Is m | None -> c + |> fun c -> let theme = Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code + c.WriteTo.Console(theme=theme, outputTemplate="[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties}{NewLine}{Exception}") + |> fun c -> c.CreateLogger() diff --git a/propulsion-tracking-consumer/Program.fs b/propulsion-tracking-consumer/Program.fs index dfd9fb1b6..20ef55b62 100644 --- a/propulsion-tracking-consumer/Program.fs +++ b/propulsion-tracking-consumer/Program.fs @@ -111,8 +111,8 @@ module Args = member __.LagFrequency = a.TryGetResult LagFreqM |> Option.map TimeSpan.FromMinutes member __.MaxConcurrentStreams = a.GetResult(MaxWriters, 8) - member __.Verbose = a.Contains Verbose + member __.MinimumLevel = if a.Contains Verbose then Some Events.LogEventLevel.Debug else None member __.StatsInterval = TimeSpan.FromMinutes 1. member __.StateInterval = TimeSpan.FromMinutes 5. @@ -122,21 +122,6 @@ module Args = let parser = ArgumentParser.Create(programName=programName) parser.ParseCommandLine argv |> Arguments -// TODO remove this entire comment after reading https://github.com/jet/dotnet-templates#module-logging -// Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline -module Logging = - - let initialize verbose = - Log.Logger <- - LoggerConfiguration() - .Destructure.FSharpTypes() - .Enrich.FromLogContext() - |> fun c -> if verbose then c.MinimumLevel.Debug() else c - |> fun c -> let theme = Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code - if not verbose then c.WriteTo.Console(theme=theme) - else c.WriteTo.Console(theme=theme, outputTemplate="[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties}{NewLine}{Exception}") - |> fun c -> c.CreateLogger() - let [] AppName = "ConsumerTemplate" let start (args : Args.Arguments) = @@ -166,7 +151,7 @@ let run args = [] let main argv = try let args = Args.parse argv - try Logging.initialize args.Verbose + try Logging.Initialize(?minimumLevel=args.MinimumLevel) try Configuration.initialize () run args with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 From 6015731fd4e4b8b052f2fab4c8fa514be2522f58 Mon Sep 17 00:00:00 2001 From: Ruben Bartelink Date: Mon, 22 Jun 2020 17:40:52 +0100 Subject: [PATCH 02/12] Tidy --- propulsion-consumer/Infrastructure.fs | 3 +-- propulsion-reactor/.template.config/template.json | 1 - propulsion-reactor/Infrastructure.fs | 6 +++++- propulsion-reactor/Reactor.fsproj | 2 -- propulsion-summary-consumer/Infrastructure.fs | 3 +-- propulsion-tracking-consumer/Infrastructure.fs | 3 +-- 6 files changed, 8 insertions(+), 10 deletions(-) diff --git a/propulsion-consumer/Infrastructure.fs b/propulsion-consumer/Infrastructure.fs index 7b6b05328..ebecc0e85 100644 --- a/propulsion-consumer/Infrastructure.fs +++ b/propulsion-consumer/Infrastructure.fs @@ -1,6 +1,7 @@ [] module private ConsumerTemplate.Infrastructure +open Serilog open System open System.Threading.Tasks @@ -49,8 +50,6 @@ type System.Threading.SemaphoreSlim with finally semaphore.Release() |> ignore } -open Serilog - // Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline type Logging() = diff --git a/propulsion-reactor/.template.config/template.json b/propulsion-reactor/.template.config/template.json index e030d354c..cdaef17bc 100644 --- a/propulsion-reactor/.template.config/template.json +++ b/propulsion-reactor/.template.config/template.json @@ -81,7 +81,6 @@ { "condition": "blank && !kafka", "exclude": [ - "Infrastructure.fs", "Todo.fs", "Contract.fs" ] diff --git a/propulsion-reactor/Infrastructure.fs b/propulsion-reactor/Infrastructure.fs index 84427232d..2e4815ba4 100644 --- a/propulsion-reactor/Infrastructure.fs +++ b/propulsion-reactor/Infrastructure.fs @@ -1,10 +1,13 @@ namespace ReactorTemplate -open System.Runtime.CompilerServices +#if (kafka || !blank) open FSharp.UMX // see https://github.com/fsprojects/FSharp.UMX - % operator and ability to apply units of measure to Guids+strings +#endif open Serilog open System +open System.Runtime.CompilerServices +#if (kafka || !blank) module EventCodec = /// Uses the supplied codec to decode the supplied event record `x` (iff at LogEventLevel.Debug, detail fails to `log` citing the `stream` and content) @@ -29,6 +32,7 @@ module ClientId = let parse (value : string) : ClientId = let raw = Guid.Parse value in % raw let (|Parse|) = parse +#endif #if (!kafkaEventSpans) [] type LoggerConfigurationExtensions() = diff --git a/propulsion-reactor/Reactor.fsproj b/propulsion-reactor/Reactor.fsproj index aea976f20..e6adc3f31 100644 --- a/propulsion-reactor/Reactor.fsproj +++ b/propulsion-reactor/Reactor.fsproj @@ -10,9 +10,7 @@ - - diff --git a/propulsion-summary-consumer/Infrastructure.fs b/propulsion-summary-consumer/Infrastructure.fs index 6c9290327..2eaf3de1b 100644 --- a/propulsion-summary-consumer/Infrastructure.fs +++ b/propulsion-summary-consumer/Infrastructure.fs @@ -1,6 +1,7 @@ namespace ConsumerTemplate open FSharp.UMX // see https://github.com/fsprojects/FSharp.UMX - % operator and ability to apply units of measure to Guids+strings +open Serilog open System module EventCodec = @@ -26,8 +27,6 @@ module ClientId = let parse (value : string) : ClientId = let raw = Guid.Parse value in % raw let (|Parse|) = parse -open Serilog - // Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline type Logging() = diff --git a/propulsion-tracking-consumer/Infrastructure.fs b/propulsion-tracking-consumer/Infrastructure.fs index 046e67ff1..69bfbfbb9 100644 --- a/propulsion-tracking-consumer/Infrastructure.fs +++ b/propulsion-tracking-consumer/Infrastructure.fs @@ -1,6 +1,7 @@ namespace ConsumerTemplate open FSharp.UMX // see https://github.com/fsprojects/FSharp.UMX - % operator and ability to apply units of measure to Guids+strings +open Serilog module EventCodec = @@ -22,8 +23,6 @@ module SkuId = let parse (value : string) : SkuId = let raw = value in % raw let (|Parse|) = parse -open Serilog - // Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline type Logging() = From bb5a4a668ed6a07ee75751a5569dda402901817c Mon Sep 17 00:00:00 2001 From: Ruben Bartelink Date: Mon, 22 Jun 2020 19:18:54 +0100 Subject: [PATCH 03/12] Remove minimumLevel --- README.md | 4 ++-- equinox-shipping/Watchdog/Infrastructure.fs | 4 ++-- equinox-shipping/Watchdog/Program.fs | 4 ++-- propulsion-consumer/Infrastructure.fs | 4 ++-- propulsion-consumer/Program.fs | 4 ++-- propulsion-projector/Infrastructure.fs | 4 ++-- propulsion-projector/Program.fs | 6 +++--- propulsion-reactor/Infrastructure.fs | 4 ++-- propulsion-reactor/Program.fs | 6 +++--- propulsion-summary-consumer/Infrastructure.fs | 4 ++-- propulsion-summary-consumer/Program.fs | 4 ++-- propulsion-tracking-consumer/Infrastructure.fs | 4 ++-- propulsion-tracking-consumer/Program.fs | 4 ++-- 13 files changed, 28 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 0d8daa47e..034eca797 100644 --- a/README.md +++ b/README.md @@ -260,7 +260,7 @@ _Responsible for applying logging config and setting up loggers for the applicat ``` type Logging() = - static member Initialize(?minimumLevel) = + static member Initialize(?verbose) = Log.Logger <- LoggerConfiguration(….) ``` @@ -298,7 +298,7 @@ let run args = [] let main argv = try let args = Args.parse argv - try Logging.initialize args.Verbose + try Logging.Initialize(verbose=args.Verbose) try Configuration.initialize () if run args then 0 else 3 with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 diff --git a/equinox-shipping/Watchdog/Infrastructure.fs b/equinox-shipping/Watchdog/Infrastructure.fs index 2d14b4938..bc420aaee 100644 --- a/equinox-shipping/Watchdog/Infrastructure.fs +++ b/equinox-shipping/Watchdog/Infrastructure.fs @@ -26,12 +26,12 @@ type LoggerConfigurationExtensions() = // Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline type Logging() = - static member Initialize(?minimumLevel, ?changeFeedProcessorVerbose) = + static member Initialize(?verbose, ?changeFeedProcessorVerbose) = Log.Logger <- LoggerConfiguration() .Destructure.FSharpTypes() .Enrich.FromLogContext() - |> fun c -> match minimumLevel with Some m -> c.MinimumLevel.Is m | None -> c + |> fun c -> if verbose = Some true then c.MinimumLevel.Debug() else c |> fun c -> c.ConfigureChangeFeedProcessorLogging((changeFeedProcessorVerbose = Some true)) |> fun c -> let t = "[{Timestamp:HH:mm:ss} {Level:u3}] {partitionKeyRangeId,2} {Message:lj} {NewLine}{Exception}" c.WriteTo.Console(theme=Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code, outputTemplate=t) diff --git a/equinox-shipping/Watchdog/Program.fs b/equinox-shipping/Watchdog/Program.fs index c53697d88..d390ebed1 100644 --- a/equinox-shipping/Watchdog/Program.fs +++ b/equinox-shipping/Watchdog/Program.fs @@ -53,7 +53,7 @@ module Args = | Cosmos _ -> "specify CosmosDB input parameters." and Arguments(a : ParseResults) = member __.ConsumerGroupName = a.GetResult ConsumerGroupName - member __.MinimumLevel = if a.Contains Verbose then Some Events.LogEventLevel.Debug else None + member __.Verbose = a.Contains Verbose member __.CfpVerbose = a.Contains CfpVerbose member __.MaxReadAhead = a.GetResult(MaxReadAhead, 16) member __.MaxConcurrentStreams = a.GetResult(MaxWriters, 8) @@ -221,7 +221,7 @@ let run args = [] let main argv = try let args = Args.parse argv - try Logging.Initialize(?minimumLevel=args.MinimumLevel, changeFeedProcessorVerbose=args.CfpVerbose) + try Logging.Initialize(verbose=args.Verbose, changeFeedProcessorVerbose=args.CfpVerbose) try Configuration.initialize () if run args then 0 else 3 with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 diff --git a/propulsion-consumer/Infrastructure.fs b/propulsion-consumer/Infrastructure.fs index ebecc0e85..908039f42 100644 --- a/propulsion-consumer/Infrastructure.fs +++ b/propulsion-consumer/Infrastructure.fs @@ -53,12 +53,12 @@ type System.Threading.SemaphoreSlim with // Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline type Logging() = - static member Initialize(?minimumLevel) = + static member Initialize(?verbose) = Log.Logger <- LoggerConfiguration() .Destructure.FSharpTypes() .Enrich.FromLogContext() - |> fun c -> match minimumLevel with Some m -> c.MinimumLevel.Is m | None -> c + |> fun c -> if verbose = Some true then c.MinimumLevel.Debug() else c |> fun c -> let theme = Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code c.WriteTo.Console(theme=theme, outputTemplate="[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties}{NewLine}{Exception}") |> fun c -> c.CreateLogger() diff --git a/propulsion-consumer/Program.fs b/propulsion-consumer/Program.fs index d4081ccfc..ba40113be 100644 --- a/propulsion-consumer/Program.fs +++ b/propulsion-consumer/Program.fs @@ -69,7 +69,7 @@ module Args = member __.LagFrequency = a.TryGetResult LagFreqM |> Option.map TimeSpan.FromMinutes member __.MaxDop = a.GetResult(MaxDop, 8) - member __.MinimumLevel = if a.Contains Verbose then Some Events.LogEventLevel.Debug else None + member __.Verbose = a.Contains Verbose /// Parse the commandline; can throw exceptions in response to missing arguments and/or `-h`/`--help` args let parse argv = @@ -98,7 +98,7 @@ let run args = [] let main argv = try let args = Args.parse argv - try Logging.Initialize(?minimumLevel=args.MinimumLevel) + try Logging.Initialize(verbose=args.Verbose) try Configuration.initialize () if run args then 0 else 3 with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 diff --git a/propulsion-projector/Infrastructure.fs b/propulsion-projector/Infrastructure.fs index c7fedeaff..391a41fbf 100644 --- a/propulsion-projector/Infrastructure.fs +++ b/propulsion-projector/Infrastructure.fs @@ -31,13 +31,13 @@ type Logging() = #if cosmos static member Initialize(?minimumLevel, ?changeFeedProcessorVerbose) = #else - static member Initialize(?minimumLevel) = + static member Initialize(?verbose) = #endif Log.Logger <- LoggerConfiguration() .Destructure.FSharpTypes() .Enrich.FromLogContext() - |> fun c -> match minimumLevel with Some m -> c.MinimumLevel.Is m | None -> c + |> fun c -> if verbose = Some true then c.MinimumLevel.Debug() else c #if cosmos |> fun c -> c.ConfigureChangeFeedProcessorLogging((changeFeedProcessorVerbose = Some true)) #endif diff --git a/propulsion-projector/Program.fs b/propulsion-projector/Program.fs index 693cdb2e1..a506f838c 100644 --- a/propulsion-projector/Program.fs +++ b/propulsion-projector/Program.fs @@ -315,7 +315,7 @@ module Args = | SqlMs _ -> "specify SqlStreamStore input parameters." //#endif and Arguments(a : ParseResults) = - member __.MinimumLevel = if a.Contains Verbose then Some Events.LogEventLevel.Debug else None + member __.Verbose = a.Contains Verbose member __.ConsumerGroupName = a.GetResult ConsumerGroupName member __.MaxReadAhead = a.GetResult(MaxReadAhead, 64) member __.MaxConcurrentProcessors = a.GetResult(MaxWriters, 1024) @@ -482,9 +482,9 @@ let run args = let main argv = try let args = Args.parse argv #if cosmos - try Logging.Initialize(?minimumLevel=args.MinimumLevel, changeFeedProcessorVerbose=args.Cosmos.CfpVerbose) + try Logging.Initialize(verbose=args.Verbose, changeFeedProcessorVerbose=args.Cosmos.CfpVerbose) #else - try Logging.Initialize(?minimumLevel=args.MinimumLevel) + try Logging.Initialize(verbose=args.Verbose) #endif try Configuration.initialize () if run args then 0 else 3 diff --git a/propulsion-reactor/Infrastructure.fs b/propulsion-reactor/Infrastructure.fs index 2e4815ba4..3c3a84ea3 100644 --- a/propulsion-reactor/Infrastructure.fs +++ b/propulsion-reactor/Infrastructure.fs @@ -58,7 +58,7 @@ type LoggerConfigurationExtensions() = type Logging() = #if (!kafkaEventSpans) - static member Initialize(?minimumLevel, ?changeFeedProcessorVerbose) = + static member Initialize(?verbose, ?changeFeedProcessorVerbose) = #else static member Initialize(?minimumLevel) = #endif @@ -66,7 +66,7 @@ type Logging() = LoggerConfiguration() .Destructure.FSharpTypes() .Enrich.FromLogContext() - |> fun c -> match minimumLevel with Some m -> c.MinimumLevel.Is m | None -> c + |> fun c -> if verbose = Some true then c.MinimumLevel.Debug() else c #if (!kafkaEventSpans) |> fun c -> c.ConfigureChangeFeedProcessorLogging((changeFeedProcessorVerbose = Some true)) #endif diff --git a/propulsion-reactor/Program.fs b/propulsion-reactor/Program.fs index eda3e30fa..b7301c023 100644 --- a/propulsion-reactor/Program.fs +++ b/propulsion-reactor/Program.fs @@ -106,7 +106,7 @@ module Args = //#endif member __.MaxReadAhead = a.GetResult(MaxReadAhead, 16) member __.MaxConcurrentStreams = a.GetResult(MaxWriters, 8) - member __.MinimumLevel = if a.Contains Parameters.Verbose then Some Events.LogEventLevel.Debug else None + member __.Verbose = a.Contains Parameters.Verbose member __.StatsInterval = TimeSpan.FromMinutes 1. member __.StateInterval = TimeSpan.FromMinutes 5. //#if filter @@ -686,9 +686,9 @@ let run args = let main argv = try let args = Args.parse argv #if (!kafkaEventSpans) - try Logging.Initialize(?minimumLevel=args.MinimumLevel, changeFeedProcessorVerbose=args.CfpVerbose) + try Logging.Initialize(verbose=args.Verbose, changeFeedProcessorVerbose=args.CfpVerbose) #else - try Logging.Initialize(?minimumLevel=args.MinimumLevel) + try Logging.Initialize(verbose=args.Verbose) #endif try Configuration.initialize () if run args then 0 else 3 diff --git a/propulsion-summary-consumer/Infrastructure.fs b/propulsion-summary-consumer/Infrastructure.fs index 2eaf3de1b..1b4832d9d 100644 --- a/propulsion-summary-consumer/Infrastructure.fs +++ b/propulsion-summary-consumer/Infrastructure.fs @@ -30,12 +30,12 @@ module ClientId = // Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline type Logging() = - static member Initialize(?minimumLevel) = + static member Initialize(?verbose) = Log.Logger <- LoggerConfiguration() .Destructure.FSharpTypes() .Enrich.FromLogContext() - |> fun c -> match minimumLevel with Some m -> c.MinimumLevel.Is m | None -> c + |> fun c -> if verbose = Some true then c.MinimumLevel.Debug() else c |> fun c -> let theme = Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code c.WriteTo.Console(theme=theme, outputTemplate="[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties}{NewLine}{Exception}") |> fun c -> c.CreateLogger() diff --git a/propulsion-summary-consumer/Program.fs b/propulsion-summary-consumer/Program.fs index 9d2a8240b..54ee6abe1 100644 --- a/propulsion-summary-consumer/Program.fs +++ b/propulsion-summary-consumer/Program.fs @@ -112,7 +112,7 @@ module Args = member __.MaxConcurrentStreams = a.GetResult(MaxWriters, 8) - member __.MinimumLevel = if a.Contains Verbose then Some Events.LogEventLevel.Debug else None + member __.Verbose = a.Contains Verbose member __.StatsInterval = TimeSpan.FromMinutes 1. member __.StateInterval = TimeSpan.FromMinutes 5. @@ -147,7 +147,7 @@ let run args = [] let main argv = try let args = Args.parse argv - try Logging.Initialize(?minimumLevel=args.MinimumLevel) + try Logging.Initialize(verbose=args.Verbose) try Configuration.initialize () if run args then 0 else 3 with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 diff --git a/propulsion-tracking-consumer/Infrastructure.fs b/propulsion-tracking-consumer/Infrastructure.fs index 69bfbfbb9..60e972745 100644 --- a/propulsion-tracking-consumer/Infrastructure.fs +++ b/propulsion-tracking-consumer/Infrastructure.fs @@ -26,12 +26,12 @@ module SkuId = // Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline type Logging() = - static member Initialize(?minimumLevel) = + static member Initialize(?verbose) = Log.Logger <- LoggerConfiguration() .Destructure.FSharpTypes() .Enrich.FromLogContext() - |> fun c -> match minimumLevel with Some m -> c.MinimumLevel.Is m | None -> c + |> fun c -> if verbose = Some true then c.MinimumLevel.Debug() else c |> fun c -> let theme = Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code c.WriteTo.Console(theme=theme, outputTemplate="[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties}{NewLine}{Exception}") |> fun c -> c.CreateLogger() diff --git a/propulsion-tracking-consumer/Program.fs b/propulsion-tracking-consumer/Program.fs index 20ef55b62..e92851d1e 100644 --- a/propulsion-tracking-consumer/Program.fs +++ b/propulsion-tracking-consumer/Program.fs @@ -112,7 +112,7 @@ module Args = member __.MaxConcurrentStreams = a.GetResult(MaxWriters, 8) - member __.MinimumLevel = if a.Contains Verbose then Some Events.LogEventLevel.Debug else None + member __.Verbose = a.Contains Verbose member __.StatsInterval = TimeSpan.FromMinutes 1. member __.StateInterval = TimeSpan.FromMinutes 5. @@ -151,7 +151,7 @@ let run args = [] let main argv = try let args = Args.parse argv - try Logging.Initialize(?minimumLevel=args.MinimumLevel) + try Logging.Initialize(verbose=args.Verbose) try Configuration.initialize () run args with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 From 628d9087e0fc9fa7e46f6d2065d5f982de3d12d3 Mon Sep 17 00:00:00 2001 From: Ruben Bartelink Date: Tue, 27 Oct 2020 17:23:27 +0000 Subject: [PATCH 04/12] Rejig to fit ServiceMain --- propulsion-projector/Infrastructure.fs | 6 ++-- propulsion-projector/Program.fs | 50 ++++++++++++++++++-------- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/propulsion-projector/Infrastructure.fs b/propulsion-projector/Infrastructure.fs index 391a41fbf..52419e818 100644 --- a/propulsion-projector/Infrastructure.fs +++ b/propulsion-projector/Infrastructure.fs @@ -31,10 +31,9 @@ type Logging() = #if cosmos static member Initialize(?minimumLevel, ?changeFeedProcessorVerbose) = #else - static member Initialize(?verbose) = + static member Configure(configuration : LoggerConfiguration, ?verbose) = #endif - Log.Logger <- - LoggerConfiguration() + configuration .Destructure.FSharpTypes() .Enrich.FromLogContext() |> fun c -> if verbose = Some true then c.MinimumLevel.Debug() else c @@ -43,4 +42,3 @@ type Logging() = #endif |> fun c -> let t = "[{Timestamp:HH:mm:ss} {Level:u3}] {partitionKeyRangeId,2} {Message:lj} {NewLine}{Exception}" c.WriteTo.Console(theme=Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code, outputTemplate=t) - |> fun c -> c.CreateLogger() diff --git a/propulsion-projector/Program.fs b/propulsion-projector/Program.fs index a506f838c..f821e78d4 100644 --- a/propulsion-projector/Program.fs +++ b/propulsion-projector/Program.fs @@ -369,11 +369,16 @@ module Args = //#endif /// Parse the commandline; can throw exceptions in response to missing arguments and/or `-h`/`--help` args - let parse argv = + let private parse argv = let programName = System.Reflection.Assembly.GetEntryAssembly().GetName().Name let parser = ArgumentParser.Create(programName=programName) parser.ParseCommandLine argv |> Arguments + let tryParse (argv : string[]) = + try parse argv |> Ok + with:? Argu.ArguParseException as e -> Error e.Message + | MissingArg msg -> Error msg + //#if esdb module Checkpoints = @@ -472,24 +477,41 @@ let build (args : Args.Arguments) = //#endif // sss sink, pipeline -let run args = +type ServiceResult = + | FailedToStart of message : string + | Unhealthy + | Completed + +let run args : Async = async { let sink, pipeline = build args pipeline |> Async.Start - sink.AwaitCompletion() |> Async.RunSynchronously - sink.RanToCompletion + do! sink.AwaitCompletion() + return if sink.RanToCompletion then Completed else Unhealthy +} + +type ServiceMain() = + static member Run(argv, parseArgs, configureLog, initConfig, run) = + try match parseArgs argv with + | Error msg -> eprintfn "%s" msg; 1 + | Ok args -> + try let loggerConfiguration : LoggerConfiguration = LoggerConfiguration() |> configureLog args + Log.Logger <- loggerConfiguration.CreateLogger() + try match initConfig args with + | Error msg -> eprintfn "%s" msg; 1 + | Ok () -> + match run args |> Async.RunSynchronously with + | FailedToStart msg -> eprintfn "%s" msg; 1 + | Completed -> 0 + | Unhealthy -> 3 + with e -> Log.Fatal(e, "Exiting"); 2 + finally Log.CloseAndFlush() + with e -> eprintfn "%O" e; 1 [] let main argv = - try let args = Args.parse argv #if cosmos - try Logging.Initialize(verbose=args.Verbose, changeFeedProcessorVerbose=args.Cosmos.CfpVerbose) + let initLog (args : Args.Arguments) c = Logging.Initialize(c, verbose=args.Verbose, changeFeedProcessorVerbose=args.Cosmos.CfpVerbose) #else - try Logging.Initialize(verbose=args.Verbose) + let initLog (args : Args.Arguments) c = Logging.Configure(c, verbose=args.Verbose) #endif - try Configuration.initialize () - if run args then 0 else 3 - with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 - finally Log.CloseAndFlush() - with Args.MissingArg msg -> eprintfn "%s" msg; 1 - | :? Argu.ArguParseException as e -> eprintfn "%s" e.Message; 1 - | e -> eprintf "Exception %s" e.Message; 1 + ServiceMain.Run(argv, Args.tryParse, initLog, ignore >> Configuration.initialize, run) From e25c5d9af6f4765dac16da2c3d8c813ad8271448 Mon Sep 17 00:00:00 2001 From: Ruben Bartelink Date: Wed, 28 Oct 2020 15:17:38 +0000 Subject: [PATCH 05/12] Apply format discussed with @enricosada --- README.md | 27 ++++-- equinox-shipping/Watchdog/Infrastructure.fs | 24 ++--- equinox-shipping/Watchdog/Program.fs | 15 +-- propulsion-consumer/Infrastructure.fs | 20 ++-- propulsion-consumer/Program.fs | 15 +-- propulsion-projector/Infrastructure.fs | 8 +- propulsion-projector/Program.fs | 69 ++++++++------ propulsion-reactor/Infrastructure.fs | 28 +++--- propulsion-reactor/Program.fs | 17 ++-- propulsion-summary-consumer/Infrastructure.fs | 20 ++-- propulsion-summary-consumer/Program.fs | 15 +-- propulsion-sync/Infrastructure.fs | 23 +++++ propulsion-sync/Program.fs | 93 +++++++++---------- propulsion-sync/Sync.fsproj | 1 + .../Infrastructure.fs | 20 ++-- propulsion-tracking-consumer/Program.fs | 15 +-- 16 files changed, 237 insertions(+), 173 deletions(-) create mode 100644 propulsion-sync/Infrastructure.fs diff --git a/README.md b/README.md index 034eca797..b187d81a0 100644 --- a/README.md +++ b/README.md @@ -221,7 +221,7 @@ _Responsible for: Loading secrets and custom configuration, supplying defaults w Wiring up retrieval of configuration values is the most environment-dependent aspect of the wiring up of an application's interaction with its environment and/or data storage mechanisms. This is particularly relevant where there is variance between local (development time), testing and production deployments. For this reason, the retrieval of values from configuration stores or key vaults is not managed directly within the [`module Args` section](#module-args) -The `Settings` module is responsible for the following: +The `Configuration` module is responsible for the following: 1. Feeding defaults into process-local Environment Variables, _where those are not already supplied_ 2. Encapsulating all bindings to Configuration or Secret stores (Vaults) in order that this does not have to be complected with the argument parsing or defaulting in `module Args` @@ -260,8 +260,16 @@ _Responsible for applying logging config and setting up loggers for the applicat ``` type Logging() = - static member Initialize(?verbose) = - Log.Logger <- LoggerConfiguration(….) + static member Initialize(configure) = + let loggerConfiguration : LoggerConfiguration = LoggerConfiguration() |> configure + Log.Logger <- loggerConfiguration.CreateLogger() + + static member Configure(configuration : LoggingConfiguration, ?verbose) = + configuration + .Destructure.FSharpTypes() + .Enrich.FromLogContext() + |> fun c -> if verbose = Some true then c.MinimumLevel.Debug() else c + // etc. ``` ### `start` function @@ -290,17 +298,18 @@ The `run` function formalizes the overall pattern. It is responsible for: #### example ``` -let run args = +let run args = async { use consumer = start args - consumer.AwaitCompletion() |> Async.RunSynchronously - consumer.RanToCompletion + return! consumer.AwaitCompletion() +} [] let main argv = try let args = Args.parse argv - try Logging.Initialize(verbose=args.Verbose) - try Configuration.initialize () - if run args then 0 else 3 + try Logging.Initialize(fun c -> Logging.Configure c, verbose=args.Verbose)) + try Configuration.load () + run args |> Async.RunSynchronously + 0 with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 finally Log.CloseAndFlush() with Args.MissingArg msg -> eprintfn "%s" msg; 1 diff --git a/equinox-shipping/Watchdog/Infrastructure.fs b/equinox-shipping/Watchdog/Infrastructure.fs index bc420aaee..69e1268e1 100644 --- a/equinox-shipping/Watchdog/Infrastructure.fs +++ b/equinox-shipping/Watchdog/Infrastructure.fs @@ -21,18 +21,20 @@ type LoggerConfigurationExtensions() = // LibLog writes to the global logger, so we need to control the emission let cfpl = if verbose then Serilog.Events.LogEventLevel.Debug else Serilog.Events.LogEventLevel.Warning c.MinimumLevel.Override("Microsoft.Azure.Documents.ChangeFeedProcessor", cfpl) - |> fun c -> if verbose then c.ExcludeChangeFeedProcessorV2InternalDiagnostics() else c + |> fun c -> if verbose then c else c.ExcludeChangeFeedProcessorV2InternalDiagnostics() // Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline type Logging() = - static member Initialize(?verbose, ?changeFeedProcessorVerbose) = - Log.Logger <- - LoggerConfiguration() - .Destructure.FSharpTypes() - .Enrich.FromLogContext() - |> fun c -> if verbose = Some true then c.MinimumLevel.Debug() else c - |> fun c -> c.ConfigureChangeFeedProcessorLogging((changeFeedProcessorVerbose = Some true)) - |> fun c -> let t = "[{Timestamp:HH:mm:ss} {Level:u3}] {partitionKeyRangeId,2} {Message:lj} {NewLine}{Exception}" - c.WriteTo.Console(theme=Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code, outputTemplate=t) - |> fun c -> c.CreateLogger() + static member Initialize(configure) = + let loggerConfiguration : LoggerConfiguration = LoggerConfiguration() |> configure + Log.Logger <- loggerConfiguration.CreateLogger() + + static member Configure(configuration : LoggerConfiguration, ?verbose, ?changeFeedProcessorVerbose) = + configuration + .Destructure.FSharpTypes() + .Enrich.FromLogContext() + |> fun c -> if verbose = Some true then c.MinimumLevel.Debug() else c + |> fun c -> c.ConfigureChangeFeedProcessorLogging((changeFeedProcessorVerbose = Some true)) + |> fun c -> let t = "[{Timestamp:HH:mm:ss} {Level:u3}] {partitionKeyRangeId,2} {Message:lj} {NewLine}{Exception}" + c.WriteTo.Console(theme=Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code, outputTemplate=t) diff --git a/equinox-shipping/Watchdog/Program.fs b/equinox-shipping/Watchdog/Program.fs index d390ebed1..9b966d353 100644 --- a/equinox-shipping/Watchdog/Program.fs +++ b/equinox-shipping/Watchdog/Program.fs @@ -16,7 +16,7 @@ module Configuration = printfn "Setting %s from %A" var key EnvVar.set var (loadF key) - let initialize () = + let load () = // e.g. initEnvVar "EQUINOX_COSMOS_CONTAINER" "CONSUL KEY" readFromConsul () // TODO add any custom logic preprocessing commandline arguments and/or gathering custom defaults from external sources, etc @@ -212,18 +212,19 @@ let build (args : Args.Arguments) = ?maxDocuments=maxDocuments, ?lagReportFreq=lagFrequency) sink, pipeline -let run args = +let run args = async { let sink, pipeline = build args pipeline |> Async.Start - sink.AwaitCompletion() |> Async.RunSynchronously - sink.RanToCompletion + return! sink.AwaitCompletion() +} [] let main argv = try let args = Args.parse argv - try Logging.Initialize(verbose=args.Verbose, changeFeedProcessorVerbose=args.CfpVerbose) - try Configuration.initialize () - if run args then 0 else 3 + try Logging.Initialize(fun c -> Logging.Configure(c, verbose=args.Verbose, changeFeedProcessorVerbose=args.CfpVerbose)) + try Configuration.load () + run args |> Async.RunSynchronously + 0 with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 finally Log.CloseAndFlush() with Args.MissingArg msg -> eprintfn "%s" msg; 1 diff --git a/propulsion-consumer/Infrastructure.fs b/propulsion-consumer/Infrastructure.fs index 908039f42..d72fb62e2 100644 --- a/propulsion-consumer/Infrastructure.fs +++ b/propulsion-consumer/Infrastructure.fs @@ -53,12 +53,14 @@ type System.Threading.SemaphoreSlim with // Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline type Logging() = - static member Initialize(?verbose) = - Log.Logger <- - LoggerConfiguration() - .Destructure.FSharpTypes() - .Enrich.FromLogContext() - |> fun c -> if verbose = Some true then c.MinimumLevel.Debug() else c - |> fun c -> let theme = Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code - c.WriteTo.Console(theme=theme, outputTemplate="[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties}{NewLine}{Exception}") - |> fun c -> c.CreateLogger() + static member Initialize(configure) = + let loggerConfiguration : LoggerConfiguration = LoggerConfiguration() |> configure + Log.Logger <- loggerConfiguration.CreateLogger() + + static member Configure(configuration : LoggerConfiguration, ?verbose) = + configuration + .Destructure.FSharpTypes() + .Enrich.FromLogContext() + |> fun c -> if verbose = Some true then c.MinimumLevel.Debug() else c + |> fun c -> let theme = Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code + c.WriteTo.Console(theme=theme, outputTemplate="[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties}{NewLine}{Exception}") diff --git a/propulsion-consumer/Program.fs b/propulsion-consumer/Program.fs index ba40113be..0cb0733b0 100644 --- a/propulsion-consumer/Program.fs +++ b/propulsion-consumer/Program.fs @@ -18,7 +18,7 @@ module Configuration = printfn "Setting %s from %A" var key EnvVar.set var (loadF key) - let initialize () = + let load () = // e.g. initEnvVar "EQUINOX_COSMOS_CONTAINER" "CONSUL KEY" readFromConsul () // TODO add any custom logic preprocessing commandline arguments and/or gathering custom defaults from external sources, etc @@ -90,17 +90,18 @@ let start (args : Args.Arguments) = //NultiMessages.Parallel.Start(c, args.MaxDop) MultiStreams.start(c, args.MaxDop) -let run args = +let run args = async { use consumer = start args - consumer.AwaitCompletion() |> Async.RunSynchronously - consumer.RanToCompletion + return! consumer.AwaitCompletion() +} [] let main argv = try let args = Args.parse argv - try Logging.Initialize(verbose=args.Verbose) - try Configuration.initialize () - if run args then 0 else 3 + try Logging.Initialize(fun c-> Logging.Configure(c, verbose=args.Verbose)) + try Configuration.load () + run args |> Async.RunSynchronously + 0 with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 finally Log.CloseAndFlush() with Args.MissingArg msg -> eprintfn "%s" msg; 1 diff --git a/propulsion-projector/Infrastructure.fs b/propulsion-projector/Infrastructure.fs index 52419e818..406a8533c 100644 --- a/propulsion-projector/Infrastructure.fs +++ b/propulsion-projector/Infrastructure.fs @@ -22,14 +22,18 @@ type LoggerConfigurationExtensions() = // LibLog writes to the global logger, so we need to control the emission let cfpl = if verbose then Serilog.Events.LogEventLevel.Debug else Serilog.Events.LogEventLevel.Warning c.MinimumLevel.Override("Microsoft.Azure.Documents.ChangeFeedProcessor", cfpl) - |> fun c -> if verbose then c.ExcludeChangeFeedProcessorV2InternalDiagnostics() else c + |> fun c -> if verbose then c else c.ExcludeChangeFeedProcessorV2InternalDiagnostics() #endif // Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline type Logging() = + static member Initialize(configure) = + let loggerConfiguration : LoggerConfiguration = LoggerConfiguration() |> configure + Log.Logger <- loggerConfiguration.CreateLogger() + #if cosmos - static member Initialize(?minimumLevel, ?changeFeedProcessorVerbose) = + static member Configure(configuration : LoggerConfiguration, ?minimumLevel, ?changeFeedProcessorVerbose) = #else static member Configure(configuration : LoggerConfiguration, ?verbose) = #endif diff --git a/propulsion-projector/Program.fs b/propulsion-projector/Program.fs index f821e78d4..ff9c9e430 100644 --- a/propulsion-projector/Program.fs +++ b/propulsion-projector/Program.fs @@ -21,7 +21,7 @@ module Configuration = printfn "Setting %s from %A" var key EnvVar.set var (loadF key) - let initialize () = + let load () = // e.g. initEnvVar "EQUINOX_COSMOS_CONTAINER" "CONSUL KEY" readFromConsul () // TODO add any custom logic preprocessing commandline arguments and/or gathering custom defaults from external sources, etc @@ -355,9 +355,9 @@ module Args = member __.BuildSqlStreamStoreParams() = let src = __.SqlStreamStore let spec : Propulsion.SqlStreamStore.ReaderSpec = - { consumerGroup = __.ConsumerGroupName - maxBatchSize = src.MaxBatchSize - tailSleepInterval = src.TailInterval } + { consumerGroup = __.ConsumerGroupName + maxBatchSize = src.MaxBatchSize + tailSleepInterval = src.TailInterval } src, spec //#endif //#if kafka @@ -369,16 +369,11 @@ module Args = //#endif /// Parse the commandline; can throw exceptions in response to missing arguments and/or `-h`/`--help` args - let private parse argv = + let parse argv = let programName = System.Reflection.Assembly.GetEntryAssembly().GetName().Name let parser = ArgumentParser.Create(programName=programName) parser.ParseCommandLine argv |> Arguments - let tryParse (argv : string[]) = - try parse argv |> Ok - with:? Argu.ArguParseException as e -> Error e.Message - | MissingArg msg -> Error msg - //#if esdb module Checkpoints = @@ -477,41 +472,59 @@ let build (args : Args.Arguments) = //#endif // sss sink, pipeline -type ServiceResult = - | FailedToStart of message : string - | Unhealthy - | Completed - -let run args : Async = async { +let run args = async { let sink, pipeline = build args pipeline |> Async.Start do! sink.AwaitCompletion() - return if sink.RanToCompletion then Completed else Unhealthy } +module ExitExceptions = + + let (|MessageException|_|) : exn -> Option = function + | (:? Argu.ArguParseException) as e -> Some e.Message + | Args.MissingArg msg -> Some msg + | _ -> None + + let mapExitExceptionsAsync f x = async { + try let! res = f x + return Ok res + with MessageException message -> return Error message + } + + let mapExitExceptions f x = + try Ok (f x) + with MessageException message -> Error message + type ServiceMain() = - static member Run(argv, parseArgs, configureLog, initConfig, run) = - try match parseArgs argv with + + static member Run(argv, parseArguments, configureLog, loadConfiguration, run) = + try match parseArguments argv with | Error msg -> eprintfn "%s" msg; 1 | Ok args -> - try let loggerConfiguration : LoggerConfiguration = LoggerConfiguration() |> configureLog args - Log.Logger <- loggerConfiguration.CreateLogger() - try match initConfig args with + try Logging.Initialize(configureLog args) + try match loadConfiguration args with | Error msg -> eprintfn "%s" msg; 1 | Ok () -> match run args |> Async.RunSynchronously with - | FailedToStart msg -> eprintfn "%s" msg; 1 - | Completed -> 0 - | Unhealthy -> 3 + | Error msg -> eprintfn "%s" msg; 1 + | Ok () -> 0 with e -> Log.Fatal(e, "Exiting"); 2 finally Log.CloseAndFlush() with e -> eprintfn "%O" e; 1 + static member Run(argv : string[], parseArguments, configureLog, loadConfiguration : unit -> unit, run) = + ServiceMain.Run + ( argv, + parseArguments |> ExitExceptions.mapExitExceptions, + configureLog, + (ignore >> loadConfiguration) |> ExitExceptions.mapExitExceptions, + run |> ExitExceptions.mapExitExceptionsAsync) + [] let main argv = #if cosmos - let initLog (args : Args.Arguments) c = Logging.Initialize(c, verbose=args.Verbose, changeFeedProcessorVerbose=args.Cosmos.CfpVerbose) + let configLog (args : Args.Arguments) c = Logging.Configure(c, verbose=args.Verbose, changeFeedProcessorVerbose=args.Cosmos.CfpVerbose) #else - let initLog (args : Args.Arguments) c = Logging.Configure(c, verbose=args.Verbose) + let configLog (args : Args.Arguments) c = Logging.Configure(c, verbose=args.Verbose) #endif - ServiceMain.Run(argv, Args.tryParse, initLog, ignore >> Configuration.initialize, run) + ServiceMain.Run(argv, Args.parse, configLog, Configuration.load, run) diff --git a/propulsion-reactor/Infrastructure.fs b/propulsion-reactor/Infrastructure.fs index 3c3a84ea3..32b362c12 100644 --- a/propulsion-reactor/Infrastructure.fs +++ b/propulsion-reactor/Infrastructure.fs @@ -51,25 +51,27 @@ type LoggerConfigurationExtensions() = // LibLog writes to the global logger, so we need to control the emission let cfpl = if verbose then Serilog.Events.LogEventLevel.Debug else Serilog.Events.LogEventLevel.Warning c.MinimumLevel.Override("Microsoft.Azure.Documents.ChangeFeedProcessor", cfpl) - |> fun c -> if verbose then c.ExcludeChangeFeedProcessorV2InternalDiagnostics() else c + |> fun c -> if verbose then c else c.ExcludeChangeFeedProcessorV2InternalDiagnostics() #endif -// Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful Args.parse +// Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline type Logging() = + static member Initialize(configure) = + let loggerConfiguration : LoggerConfiguration = LoggerConfiguration() |> configure + Log.Logger <- loggerConfiguration.CreateLogger() + #if (!kafkaEventSpans) - static member Initialize(?verbose, ?changeFeedProcessorVerbose) = + static member Configure(configuration : LoggerConfiguration, ?verbose, ?changeFeedProcessorVerbose) = #else - static member Initialize(?minimumLevel) = + static member Configure(configuration : LoggerConfiguration, ?minimumLevel) = #endif - Log.Logger <- - LoggerConfiguration() - .Destructure.FSharpTypes() - .Enrich.FromLogContext() - |> fun c -> if verbose = Some true then c.MinimumLevel.Debug() else c + configuration + .Destructure.FSharpTypes() + .Enrich.FromLogContext() + |> fun c -> if verbose = Some true then c.MinimumLevel.Debug() else c #if (!kafkaEventSpans) - |> fun c -> c.ConfigureChangeFeedProcessorLogging((changeFeedProcessorVerbose = Some true)) + |> fun c -> c.ConfigureChangeFeedProcessorLogging((changeFeedProcessorVerbose = Some true)) #endif - |> fun c -> let t = "[{Timestamp:HH:mm:ss} {Level:u3}] {partitionKeyRangeId,2} {Message:lj} {NewLine}{Exception}" - c.WriteTo.Console(theme=Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code, outputTemplate=t) - |> fun c -> c.CreateLogger() + |> fun c -> let t = "[{Timestamp:HH:mm:ss} {Level:u3}] {partitionKeyRangeId,2} {Message:lj} {NewLine}{Exception}" + c.WriteTo.Console(theme=Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code, outputTemplate=t) diff --git a/propulsion-reactor/Program.fs b/propulsion-reactor/Program.fs index b7301c023..7f7a33912 100644 --- a/propulsion-reactor/Program.fs +++ b/propulsion-reactor/Program.fs @@ -27,7 +27,7 @@ module Configuration = printfn "Setting %s from %A" var key EnvVar.set var (loadF key) - let initialize () = + let load () = // e.g. initEnvVar "EQUINOX_COSMOS_CONTAINER" "CONSUL KEY" readFromConsul () // TODO add any custom logic preprocessing commandline arguments and/or gathering custom defaults from external sources, etc @@ -672,26 +672,27 @@ let build (args : Args.Arguments) = sink, pipeline #endif // !kafkaEventSpans -let run args = +let run args = async { #if (!kafkaEventSpans) let sink, pipeline = build args pipeline |> Async.Start #else let sink = build args #endif - sink.AwaitCompletion() |> Async.RunSynchronously - sink.RanToCompletion + return! sink.AwaitCompletion() +} [] let main argv = try let args = Args.parse argv #if (!kafkaEventSpans) - try Logging.Initialize(verbose=args.Verbose, changeFeedProcessorVerbose=args.CfpVerbose) + try Logging.Initialize(fun c -> Logging.Configure(c, verbose=args.Verbose, changeFeedProcessorVerbose=args.CfpVerbose)) #else - try Logging.Initialize(verbose=args.Verbose) + try Logging.Initialize(fun c -> Logging.Configure(c, verbose=args.Verbose)) #endif - try Configuration.initialize () - if run args then 0 else 3 + try Configuration.load () + run args |> Async.RunSynchronously + 0 with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 finally Log.CloseAndFlush() with Args.MissingArg msg -> eprintfn "%s" msg; 1 diff --git a/propulsion-summary-consumer/Infrastructure.fs b/propulsion-summary-consumer/Infrastructure.fs index 1b4832d9d..1c5aebd2e 100644 --- a/propulsion-summary-consumer/Infrastructure.fs +++ b/propulsion-summary-consumer/Infrastructure.fs @@ -30,12 +30,14 @@ module ClientId = // Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline type Logging() = - static member Initialize(?verbose) = - Log.Logger <- - LoggerConfiguration() - .Destructure.FSharpTypes() - .Enrich.FromLogContext() - |> fun c -> if verbose = Some true then c.MinimumLevel.Debug() else c - |> fun c -> let theme = Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code - c.WriteTo.Console(theme=theme, outputTemplate="[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties}{NewLine}{Exception}") - |> fun c -> c.CreateLogger() + static member Initialize(configure) = + let loggerConfiguration : LoggerConfiguration = LoggerConfiguration() |> configure + Log.Logger <- loggerConfiguration.CreateLogger() + + static member Configure(configuration : LoggerConfiguration, ?verbose) = + configuration + .Destructure.FSharpTypes() + .Enrich.FromLogContext() + |> fun c -> if verbose = Some true then c.MinimumLevel.Debug() else c + |> fun c -> let theme = Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code + c.WriteTo.Console(theme=theme, outputTemplate="[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties}{NewLine}{Exception}") diff --git a/propulsion-summary-consumer/Program.fs b/propulsion-summary-consumer/Program.fs index 54ee6abe1..056b27237 100644 --- a/propulsion-summary-consumer/Program.fs +++ b/propulsion-summary-consumer/Program.fs @@ -18,7 +18,7 @@ module Configuration = printfn "Setting %s from %A" var key EnvVar.set var (loadF key) - let initialize () = + let load () = // e.g. initEnvVar "EQUINOX_COSMOS_CONTAINER" "CONSUL KEY" readFromConsul () // TODO add any custom logic preprocessing commandline arguments and/or gathering custom defaults from external sources, etc @@ -139,17 +139,18 @@ let start (args : Args.Arguments) = ( Log.Logger, config, parseStreamSummaries, Ingester.ingest service, args.MaxConcurrentStreams, stats, args.StateInterval) -let run args = +let run args = async { use consumer = start args - consumer.AwaitCompletion() |> Async.RunSynchronously - consumer.RanToCompletion + return! consumer.AwaitCompletion() +} [] let main argv = try let args = Args.parse argv - try Logging.Initialize(verbose=args.Verbose) - try Configuration.initialize () - if run args then 0 else 3 + try Logging.Initialize(fun c -> Logging.Configure(c, verbose=args.Verbose)) + try Configuration.load () + run args |> Async.RunSynchronously + 0 with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 finally Log.CloseAndFlush() with Args.MissingArg msg -> eprintfn "%s" msg; 1 diff --git a/propulsion-sync/Infrastructure.fs b/propulsion-sync/Infrastructure.fs new file mode 100644 index 000000000..adb3d5464 --- /dev/null +++ b/propulsion-sync/Infrastructure.fs @@ -0,0 +1,23 @@ +namespace SyncTemplate + +open Serilog +open System.Runtime.CompilerServices + +[] +type LoggerConfigurationExtensions() = + + [] + static member inline ExcludeChangeFeedProcessorV2InternalDiagnostics(c : LoggerConfiguration) = + let isCfp429a = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.LeaseManagement.DocumentServiceLeaseUpdater").Invoke + let isCfp429b = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.PartitionManagement.LeaseRenewer").Invoke + let isCfp429c = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.PartitionManagement.PartitionLoadBalancer").Invoke + let isCfp429d = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.FeedProcessing.PartitionProcessor").Invoke + let isCfp x = isCfp429a x || isCfp429b x || isCfp429c x || isCfp429d x + c.Filter.ByExcluding(fun x -> isCfp x) + + [] + static member inline ConfigureChangeFeedProcessorLogging(c : LoggerConfiguration, verbose : bool) = + // LibLog writes to the global logger, so we need to control the emission + let cfpl = if verbose then Serilog.Events.LogEventLevel.Debug else Serilog.Events.LogEventLevel.Warning + c.MinimumLevel.Override("Microsoft.Azure.Documents.ChangeFeedProcessor", cfpl) + |> fun c -> if verbose then c else c.ExcludeChangeFeedProcessorV2InternalDiagnostics() diff --git a/propulsion-sync/Program.fs b/propulsion-sync/Program.fs index 6bf8afad9..594e77757 100644 --- a/propulsion-sync/Program.fs +++ b/propulsion-sync/Program.fs @@ -25,7 +25,7 @@ module Configuration = printfn "Setting %s from %A" var key EnvVar.set var (loadF key) - let initialize () = + let load () = // e.g. initEnvVar "EQUINOX_COSMOS_CONTAINER" "CONSUL KEY" readFromConsul () // TODO add any custom logic preprocessing commandline arguments and/or gathering custom defaults from external sources, etc @@ -440,47 +440,44 @@ module Args = let parser = ArgumentParser.Create(programName=programName) parser.ParseCommandLine argv |> Arguments +open Serilog.Events + // Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline -module Logging = - - open Serilog.Events - let initialize verbose changeFeedProcessorVerbose maybeSeqEndpoint = - Log.Logger <- - LoggerConfiguration() - .Destructure.FSharpTypes() - .Enrich.FromLogContext() - |> fun c -> // LibLog writes to the global logger, so we need to control the emission if we don't want to pass loggers everywhere - let cfpLevel = if changeFeedProcessorVerbose then LogEventLevel.Debug else LogEventLevel.Warning - c.MinimumLevel.Override("Microsoft.Azure.Documents.ChangeFeedProcessor", cfpLevel) - |> fun c -> let ingesterLevel = if changeFeedProcessorVerbose then LogEventLevel.Debug else LogEventLevel.Information - c.MinimumLevel.Override(typeof.FullName, ingesterLevel) - |> fun c -> if verbose then c.MinimumLevel.Debug() else c - |> fun c -> let generalLevel = if verbose then LogEventLevel.Information else LogEventLevel.Warning - c.MinimumLevel.Override(typeof.FullName, generalLevel) - .MinimumLevel.Override(typeof.FullName, generalLevel) - .MinimumLevel.Override(typeof.FullName, LogEventLevel.Information) - |> fun c -> let t = "[{Timestamp:HH:mm:ss} {Level:u3}] {partitionKeyRangeId} {Tranche} {Message:lj} {NewLine}{Exception}" - let configure (a : Configuration.LoggerSinkConfiguration) : unit = - a.Logger(fun l -> - l.WriteTo.Sink(Equinox.EventStore.Log.InternalMetrics.Stats.LogSink()) - .WriteTo.Sink(Equinox.Cosmos.Store.Log.InternalMetrics.Stats.LogSink()) |> ignore) |> ignore - a.Logger(fun l -> - let isEqx = Filters.Matching.FromSource().Invoke - let isWriterA = Filters.Matching.FromSource().Invoke - let isWriterB = Filters.Matching.FromSource().Invoke - let isCp = Filters.Matching.FromSource().Invoke - let isCfp429a = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.LeaseManagement.DocumentServiceLeaseUpdater").Invoke - let isCfp429b = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.PartitionManagement.LeaseRenewer").Invoke - let isCfp429c = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.PartitionManagement.PartitionLoadBalancer").Invoke - let isCfp429d = Filters.Matching.FromSource("Microsoft.Azure.Documents.ChangeFeedProcessor.FeedProcessing.PartitionProcessor").Invoke - let isCfp x = isCfp429a x || isCfp429b x || isCfp429c x || isCfp429d x - (if changeFeedProcessorVerbose then l else l.Filter.ByExcluding(fun x -> isEqx x || isWriterA x || isWriterB x || isCp x || isCfp x)) - .WriteTo.Console(theme=Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code, outputTemplate=t) - |> ignore) |> ignore - c.WriteTo.Async(bufferSize=65536, blockWhenFull=true, configure=Action<_> configure) - |> fun c -> match maybeSeqEndpoint with None -> c | Some endpoint -> c.WriteTo.Seq(endpoint) - |> fun c -> c.CreateLogger() - Log.ForContext(), Log.ForContext() +type Logging() = + + static member Initialize(configure) = + let loggerConfiguration : LoggerConfiguration = LoggerConfiguration() |> configure + Log.Logger <- loggerConfiguration.CreateLogger() + + static member Configure(configuration : LoggerConfiguration, verbose, changeFeedProcessorVerbose, ?maybeSeqEndpoint) = + configuration + .Destructure.FSharpTypes() + .Enrich.FromLogContext() + |> fun c -> c.ConfigureChangeFeedProcessorLogging(changeFeedProcessorVerbose) + |> fun c -> let ingesterLevel = if changeFeedProcessorVerbose then LogEventLevel.Debug else LogEventLevel.Information + c.MinimumLevel.Override(typeof.FullName, ingesterLevel) + |> fun c -> if verbose then c.MinimumLevel.Debug() else c + |> fun c -> let generalLevel = if verbose then LogEventLevel.Information else LogEventLevel.Warning + c.MinimumLevel.Override(typeof.FullName, generalLevel) + .MinimumLevel.Override(typeof.FullName, generalLevel) + .MinimumLevel.Override(typeof.FullName, LogEventLevel.Information) + |> fun c -> let t = "[{Timestamp:HH:mm:ss} {Level:u3}] {partitionKeyRangeId} {Tranche} {Message:lj} {NewLine}{Exception}" + let configure (a : Configuration.LoggerSinkConfiguration) : unit = + a.Logger(fun l -> + l.WriteTo.Sink(Equinox.EventStore.Log.InternalMetrics.Stats.LogSink()) + .WriteTo.Sink(Equinox.Cosmos.Store.Log.InternalMetrics.Stats.LogSink()) |> ignore) |> ignore + a.Logger(fun l -> + let isEqx = Filters.Matching.FromSource().Invoke + let isWriterA = Filters.Matching.FromSource().Invoke + let isWriterB = Filters.Matching.FromSource().Invoke + let isCp = Filters.Matching.FromSource().Invoke + let l = + if changeFeedProcessorVerbose then l + else l.Filter.ByExcluding(fun x -> isEqx x || isWriterA x || isWriterB x || isCp x) + l.WriteTo.Console(theme=Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code, outputTemplate=t) + |> ignore) |> ignore + c.WriteTo.Async(bufferSize=65536, blockWhenFull=true, configure=System.Action<_> configure) + |> fun c -> match maybeSeqEndpoint with None -> c | Some endpoint -> c.WriteTo.Seq(endpoint) //#if marveleqx [] @@ -646,18 +643,20 @@ let build (args : Args.Arguments, log, storeLog : ILogger) = args.MaxReadAhead, args.StatsInterval) sink, runPipeline -let run (args, log, storeLog) = +let run args = async { + let log, storeLog = Log.ForContext(), Log.ForContext() let sink, pipeline = build (args, log, storeLog) pipeline |> Async.Start - sink.AwaitCompletion() |> Async.RunSynchronously - sink.RanToCompletion + return! sink.AwaitCompletion() +} [] let main argv = try let args = Args.parse argv - try let log, storeLog = Logging.initialize args.Verbose args.CfpVerbose args.MaybeSeqEndpoint - try Configuration.initialize () - if run (args, log, storeLog) then 0 else 3 + try Logging.Initialize(fun c -> Logging.Configure(c, args.Verbose, args.CfpVerbose, ?maybeSeqEndpoint = args.MaybeSeqEndpoint)) + try Configuration.load () + run args |> Async.RunSynchronously + 0 with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 finally Log.CloseAndFlush() with Args.MissingArg msg -> eprintfn "%s" msg; 1 diff --git a/propulsion-sync/Sync.fsproj b/propulsion-sync/Sync.fsproj index e96fffec5..8bc550bf7 100644 --- a/propulsion-sync/Sync.fsproj +++ b/propulsion-sync/Sync.fsproj @@ -7,6 +7,7 @@ + diff --git a/propulsion-tracking-consumer/Infrastructure.fs b/propulsion-tracking-consumer/Infrastructure.fs index 60e972745..9698a4c0a 100644 --- a/propulsion-tracking-consumer/Infrastructure.fs +++ b/propulsion-tracking-consumer/Infrastructure.fs @@ -26,12 +26,14 @@ module SkuId = // Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline type Logging() = - static member Initialize(?verbose) = - Log.Logger <- - LoggerConfiguration() - .Destructure.FSharpTypes() - .Enrich.FromLogContext() - |> fun c -> if verbose = Some true then c.MinimumLevel.Debug() else c - |> fun c -> let theme = Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code - c.WriteTo.Console(theme=theme, outputTemplate="[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties}{NewLine}{Exception}") - |> fun c -> c.CreateLogger() + static member Initialize(configure) = + let loggerConfiguration : LoggerConfiguration = LoggerConfiguration() |> configure + Log.Logger <- loggerConfiguration.CreateLogger() + + static member Configure(configuration : LoggerConfiguration, ?verbose) = + configuration + .Destructure.FSharpTypes() + .Enrich.FromLogContext() + |> fun c -> if verbose = Some true then c.MinimumLevel.Debug() else c + |> fun c -> let theme = Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code + c.WriteTo.Console(theme=theme, outputTemplate="[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties}{NewLine}{Exception}") diff --git a/propulsion-tracking-consumer/Program.fs b/propulsion-tracking-consumer/Program.fs index e92851d1e..957a71c81 100644 --- a/propulsion-tracking-consumer/Program.fs +++ b/propulsion-tracking-consumer/Program.fs @@ -18,7 +18,7 @@ module Configuration = printfn "Setting %s from %A" var key EnvVar.set var (loadF key) - let initialize () = + let load () = // e.g. initEnvVar "EQUINOX_COSMOS_CONTAINER" "CONSUL KEY" readFromConsul () // TODO add any custom logic preprocessing commandline arguments and/or gathering custom defaults from external sources, etc @@ -143,17 +143,18 @@ let start (args : Args.Arguments) = ( Log.Logger, config, sequencer.ConsumeResultToStreamEvent(), Ingester.ingest service, args.MaxConcurrentStreams, stats, args.StateInterval) -let run args = +let run args = async { use consumer = start args - consumer.AwaitCompletion() |> Async.RunSynchronously - if consumer.RanToCompletion then 0 else 3 + return! consumer.AwaitCompletion() +} [] let main argv = try let args = Args.parse argv - try Logging.Initialize(verbose=args.Verbose) - try Configuration.initialize () - run args + try Logging.Initialize(fun c -> Logging.Configure(c, verbose=args.Verbose)) + try Configuration.load () + run args |> Async.RunSynchronously + 0 with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 finally Log.CloseAndFlush() with Args.MissingArg msg -> eprintfn "%s" msg; 1 From 2162d3b4c52ad02788c4736dcf636a76909f5f70 Mon Sep 17 00:00:00 2001 From: Ruben Bartelink Date: Wed, 28 Oct 2020 15:26:19 +0000 Subject: [PATCH 06/12] Rename Configuration load back to initialize --- equinox-shipping/Watchdog/Program.fs | 2 +- propulsion-consumer/Program.fs | 4 ++-- propulsion-projector/Program.fs | 12 ++++++------ propulsion-reactor/Program.fs | 2 +- propulsion-summary-consumer/Program.fs | 2 +- propulsion-sync/Program.fs | 2 +- propulsion-tracking-consumer/Program.fs | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/equinox-shipping/Watchdog/Program.fs b/equinox-shipping/Watchdog/Program.fs index 9b966d353..ed1aa7ccf 100644 --- a/equinox-shipping/Watchdog/Program.fs +++ b/equinox-shipping/Watchdog/Program.fs @@ -16,7 +16,7 @@ module Configuration = printfn "Setting %s from %A" var key EnvVar.set var (loadF key) - let load () = + let initialize () = // e.g. initEnvVar "EQUINOX_COSMOS_CONTAINER" "CONSUL KEY" readFromConsul () // TODO add any custom logic preprocessing commandline arguments and/or gathering custom defaults from external sources, etc diff --git a/propulsion-consumer/Program.fs b/propulsion-consumer/Program.fs index 0cb0733b0..c608ab569 100644 --- a/propulsion-consumer/Program.fs +++ b/propulsion-consumer/Program.fs @@ -18,7 +18,7 @@ module Configuration = printfn "Setting %s from %A" var key EnvVar.set var (loadF key) - let load () = + let initialize () = // e.g. initEnvVar "EQUINOX_COSMOS_CONTAINER" "CONSUL KEY" readFromConsul () // TODO add any custom logic preprocessing commandline arguments and/or gathering custom defaults from external sources, etc @@ -98,7 +98,7 @@ let run args = async { [] let main argv = try let args = Args.parse argv - try Logging.Initialize(fun c-> Logging.Configure(c, verbose=args.Verbose)) + try Logging.Initialize(fun c -> Logging.Configure(c, verbose=args.Verbose)) try Configuration.load () run args |> Async.RunSynchronously 0 diff --git a/propulsion-projector/Program.fs b/propulsion-projector/Program.fs index ff9c9e430..a461e426b 100644 --- a/propulsion-projector/Program.fs +++ b/propulsion-projector/Program.fs @@ -21,7 +21,7 @@ module Configuration = printfn "Setting %s from %A" var key EnvVar.set var (loadF key) - let load () = + let initialize () = // e.g. initEnvVar "EQUINOX_COSMOS_CONTAINER" "CONSUL KEY" readFromConsul () // TODO add any custom logic preprocessing commandline arguments and/or gathering custom defaults from external sources, etc @@ -497,12 +497,12 @@ module ExitExceptions = type ServiceMain() = - static member Run(argv, parseArguments, configureLog, loadConfiguration, run) = + static member Run(argv, parseArguments, configureLog, initializeConfiguration, run) = try match parseArguments argv with | Error msg -> eprintfn "%s" msg; 1 | Ok args -> try Logging.Initialize(configureLog args) - try match loadConfiguration args with + try match initializeConfiguration args with | Error msg -> eprintfn "%s" msg; 1 | Ok () -> match run args |> Async.RunSynchronously with @@ -512,12 +512,12 @@ type ServiceMain() = finally Log.CloseAndFlush() with e -> eprintfn "%O" e; 1 - static member Run(argv : string[], parseArguments, configureLog, loadConfiguration : unit -> unit, run) = + static member Run(argv : string[], parseArguments, configureLog, initializeConfiguration : unit -> unit, run) = ServiceMain.Run ( argv, parseArguments |> ExitExceptions.mapExitExceptions, configureLog, - (ignore >> loadConfiguration) |> ExitExceptions.mapExitExceptions, + (ignore >> initializeConfiguration) |> ExitExceptions.mapExitExceptions, run |> ExitExceptions.mapExitExceptionsAsync) [] @@ -527,4 +527,4 @@ let main argv = #else let configLog (args : Args.Arguments) c = Logging.Configure(c, verbose=args.Verbose) #endif - ServiceMain.Run(argv, Args.parse, configLog, Configuration.load, run) + ServiceMain.Run(argv, Args.parse, configLog, Configuration.initialize, run) diff --git a/propulsion-reactor/Program.fs b/propulsion-reactor/Program.fs index 7f7a33912..549e26be3 100644 --- a/propulsion-reactor/Program.fs +++ b/propulsion-reactor/Program.fs @@ -27,7 +27,7 @@ module Configuration = printfn "Setting %s from %A" var key EnvVar.set var (loadF key) - let load () = + let initialize () = // e.g. initEnvVar "EQUINOX_COSMOS_CONTAINER" "CONSUL KEY" readFromConsul () // TODO add any custom logic preprocessing commandline arguments and/or gathering custom defaults from external sources, etc diff --git a/propulsion-summary-consumer/Program.fs b/propulsion-summary-consumer/Program.fs index 056b27237..6d7a31d84 100644 --- a/propulsion-summary-consumer/Program.fs +++ b/propulsion-summary-consumer/Program.fs @@ -18,7 +18,7 @@ module Configuration = printfn "Setting %s from %A" var key EnvVar.set var (loadF key) - let load () = + let initialize () = // e.g. initEnvVar "EQUINOX_COSMOS_CONTAINER" "CONSUL KEY" readFromConsul () // TODO add any custom logic preprocessing commandline arguments and/or gathering custom defaults from external sources, etc diff --git a/propulsion-sync/Program.fs b/propulsion-sync/Program.fs index 594e77757..d8bd785ac 100644 --- a/propulsion-sync/Program.fs +++ b/propulsion-sync/Program.fs @@ -25,7 +25,7 @@ module Configuration = printfn "Setting %s from %A" var key EnvVar.set var (loadF key) - let load () = + let initialize () = // e.g. initEnvVar "EQUINOX_COSMOS_CONTAINER" "CONSUL KEY" readFromConsul () // TODO add any custom logic preprocessing commandline arguments and/or gathering custom defaults from external sources, etc diff --git a/propulsion-tracking-consumer/Program.fs b/propulsion-tracking-consumer/Program.fs index 957a71c81..8720cf6c5 100644 --- a/propulsion-tracking-consumer/Program.fs +++ b/propulsion-tracking-consumer/Program.fs @@ -18,7 +18,7 @@ module Configuration = printfn "Setting %s from %A" var key EnvVar.set var (loadF key) - let load () = + let initialize () = // e.g. initEnvVar "EQUINOX_COSMOS_CONTAINER" "CONSUL KEY" readFromConsul () // TODO add any custom logic preprocessing commandline arguments and/or gathering custom defaults from external sources, etc From cbef98f35e5a4c3b25f05d9e8f7799d18ceeb79e Mon Sep 17 00:00:00 2001 From: Ruben Bartelink Date: Wed, 28 Oct 2020 15:27:20 +0000 Subject: [PATCH 07/12] expand name of configureLog --- propulsion-projector/Program.fs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/propulsion-projector/Program.fs b/propulsion-projector/Program.fs index a461e426b..bba277af7 100644 --- a/propulsion-projector/Program.fs +++ b/propulsion-projector/Program.fs @@ -523,8 +523,8 @@ type ServiceMain() = [] let main argv = #if cosmos - let configLog (args : Args.Arguments) c = Logging.Configure(c, verbose=args.Verbose, changeFeedProcessorVerbose=args.Cosmos.CfpVerbose) + let configureLog (args : Args.Arguments) c = Logging.Configure(c, verbose=args.Verbose, changeFeedProcessorVerbose=args.Cosmos.CfpVerbose) #else - let configLog (args : Args.Arguments) c = Logging.Configure(c, verbose=args.Verbose) + let configureLog (args : Args.Arguments) c = Logging.Configure(c, verbose=args.Verbose) #endif - ServiceMain.Run(argv, Args.parse, configLog, Configuration.initialize, run) + ServiceMain.Run(argv, Args.parse, configureLog, Configuration.initialize, run) From 18f627aa01a23d9462b1a9086f601dd97051143f Mon Sep 17 00:00:00 2001 From: Ruben Bartelink Date: Wed, 28 Oct 2020 15:42:24 +0000 Subject: [PATCH 08/12] ifdef ServiceMain --- propulsion-projector/Program.fs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/propulsion-projector/Program.fs b/propulsion-projector/Program.fs index bba277af7..ef6f39a2a 100644 --- a/propulsion-projector/Program.fs +++ b/propulsion-projector/Program.fs @@ -478,6 +478,24 @@ let run args = async { do! sink.AwaitCompletion() } +#if !PROPOSAL +[] +let main argv = + try let args = Args.parse argv +#if cosmos + try Logging.Initialize(fun c -> Logging.Configure(c, args.Verbose args.Cosmos.CfpVerbose) +#else + try Logging.Initialize(fun c -> Logging.Configure(c, verbose=args.Verbose)) +#endif + try Configuration.initialize () + run args |> Async.RunSynchronously + 0 + with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 + finally Log.CloseAndFlush() + with Args.MissingArg msg -> eprintfn "%s" msg; 1 + | :? Argu.ArguParseException as e -> eprintfn "%s" e.Message; 1 + | e -> eprintf "Exception %s" e.Message; 1 +#else module ExitExceptions = let (|MessageException|_|) : exn -> Option = function @@ -519,7 +537,6 @@ type ServiceMain() = configureLog, (ignore >> initializeConfiguration) |> ExitExceptions.mapExitExceptions, run |> ExitExceptions.mapExitExceptionsAsync) - [] let main argv = #if cosmos @@ -528,3 +545,4 @@ let main argv = let configureLog (args : Args.Arguments) c = Logging.Configure(c, verbose=args.Verbose) #endif ServiceMain.Run(argv, Args.parse, configureLog, Configuration.initialize, run) +#endif \ No newline at end of file From e1e3c254f2b0730ef39a3187ecd83994e7f10fc0 Mon Sep 17 00:00:00 2001 From: Ruben Bartelink Date: Thu, 29 Oct 2020 07:48:05 +0000 Subject: [PATCH 09/12] Cleanup Logger Configure --- README.md | 9 +++------ equinox-shipping/Watchdog/Infrastructure.fs | 7 ++----- equinox-shipping/Watchdog/Program.fs | 4 ++-- propulsion-consumer/Infrastructure.fs | 7 ++----- propulsion-consumer/Program.fs | 4 ++-- propulsion-projector/Infrastructure.fs | 7 ++----- propulsion-projector/Program.fs | 4 ++-- propulsion-reactor/Infrastructure.fs | 7 ++----- propulsion-reactor/Program.fs | 6 +++--- propulsion-summary-consumer/Infrastructure.fs | 7 ++----- propulsion-summary-consumer/Program.fs | 4 ++-- propulsion-sync/Program.fs | 11 ++++------- propulsion-tracking-consumer/Infrastructure.fs | 8 +++----- propulsion-tracking-consumer/Program.fs | 4 ++-- 14 files changed, 33 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index b187d81a0..114f55420 100644 --- a/README.md +++ b/README.md @@ -260,10 +260,7 @@ _Responsible for applying logging config and setting up loggers for the applicat ``` type Logging() = - static member Initialize(configure) = - let loggerConfiguration : LoggerConfiguration = LoggerConfiguration() |> configure - Log.Logger <- loggerConfiguration.CreateLogger() - + [] static member Configure(configuration : LoggingConfiguration, ?verbose) = configuration .Destructure.FSharpTypes() @@ -306,8 +303,8 @@ let run args = async { [] let main argv = try let args = Args.parse argv - try Logging.Initialize(fun c -> Logging.Configure c, verbose=args.Verbose)) - try Configuration.load () + try Log.Logger <- LoggerConfiguration().Configure(verbose=args.Verbose).CreateLogger() + try Configuration.initialize () run args |> Async.RunSynchronously 0 with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 diff --git a/equinox-shipping/Watchdog/Infrastructure.fs b/equinox-shipping/Watchdog/Infrastructure.fs index 69e1268e1..a44240059 100644 --- a/equinox-shipping/Watchdog/Infrastructure.fs +++ b/equinox-shipping/Watchdog/Infrastructure.fs @@ -23,13 +23,10 @@ type LoggerConfigurationExtensions() = c.MinimumLevel.Override("Microsoft.Azure.Documents.ChangeFeedProcessor", cfpl) |> fun c -> if verbose then c else c.ExcludeChangeFeedProcessorV2InternalDiagnostics() -// Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline +[] type Logging() = - static member Initialize(configure) = - let loggerConfiguration : LoggerConfiguration = LoggerConfiguration() |> configure - Log.Logger <- loggerConfiguration.CreateLogger() - + [] static member Configure(configuration : LoggerConfiguration, ?verbose, ?changeFeedProcessorVerbose) = configuration .Destructure.FSharpTypes() diff --git a/equinox-shipping/Watchdog/Program.fs b/equinox-shipping/Watchdog/Program.fs index ed1aa7ccf..dfe7d2b07 100644 --- a/equinox-shipping/Watchdog/Program.fs +++ b/equinox-shipping/Watchdog/Program.fs @@ -221,8 +221,8 @@ let run args = async { [] let main argv = try let args = Args.parse argv - try Logging.Initialize(fun c -> Logging.Configure(c, verbose=args.Verbose, changeFeedProcessorVerbose=args.CfpVerbose)) - try Configuration.load () + try Log.Logger <- LoggerConfiguration().Configure(verbose=args.Verbose, changeFeedProcessorVerbose=args.CfpVerbose).CreateLogger() + try Configuration.initialize () run args |> Async.RunSynchronously 0 with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 diff --git a/propulsion-consumer/Infrastructure.fs b/propulsion-consumer/Infrastructure.fs index d72fb62e2..953487b70 100644 --- a/propulsion-consumer/Infrastructure.fs +++ b/propulsion-consumer/Infrastructure.fs @@ -50,13 +50,10 @@ type System.Threading.SemaphoreSlim with finally semaphore.Release() |> ignore } -// Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline +[] type Logging() = - static member Initialize(configure) = - let loggerConfiguration : LoggerConfiguration = LoggerConfiguration() |> configure - Log.Logger <- loggerConfiguration.CreateLogger() - + [] static member Configure(configuration : LoggerConfiguration, ?verbose) = configuration .Destructure.FSharpTypes() diff --git a/propulsion-consumer/Program.fs b/propulsion-consumer/Program.fs index c608ab569..cb309ab08 100644 --- a/propulsion-consumer/Program.fs +++ b/propulsion-consumer/Program.fs @@ -98,8 +98,8 @@ let run args = async { [] let main argv = try let args = Args.parse argv - try Logging.Initialize(fun c -> Logging.Configure(c, verbose=args.Verbose)) - try Configuration.load () + try Log.Logger <- LoggerConfiguration().Configure(verbose=args.Verbose).CreateLogger() + try Configuration.initialize () run args |> Async.RunSynchronously 0 with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 diff --git a/propulsion-projector/Infrastructure.fs b/propulsion-projector/Infrastructure.fs index 406a8533c..2af16d3ce 100644 --- a/propulsion-projector/Infrastructure.fs +++ b/propulsion-projector/Infrastructure.fs @@ -25,13 +25,10 @@ type LoggerConfigurationExtensions() = |> fun c -> if verbose then c else c.ExcludeChangeFeedProcessorV2InternalDiagnostics() #endif -// Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline +[] type Logging() = - static member Initialize(configure) = - let loggerConfiguration : LoggerConfiguration = LoggerConfiguration() |> configure - Log.Logger <- loggerConfiguration.CreateLogger() - + [] #if cosmos static member Configure(configuration : LoggerConfiguration, ?minimumLevel, ?changeFeedProcessorVerbose) = #else diff --git a/propulsion-projector/Program.fs b/propulsion-projector/Program.fs index ef6f39a2a..07c14c68e 100644 --- a/propulsion-projector/Program.fs +++ b/propulsion-projector/Program.fs @@ -483,9 +483,9 @@ let run args = async { let main argv = try let args = Args.parse argv #if cosmos - try Logging.Initialize(fun c -> Logging.Configure(c, args.Verbose args.Cosmos.CfpVerbose) + try Log.Logger <- LoggerConfiguration().Configure(verbose=args.Verbose, changeFeedProcessorVerbose=args.CfpVerbose).CreateLogger() #else - try Logging.Initialize(fun c -> Logging.Configure(c, verbose=args.Verbose)) + try Log.Logger <- LoggerConfiguration().Configure(verbose=args.Verbose).CreateLogger() #endif try Configuration.initialize () run args |> Async.RunSynchronously diff --git a/propulsion-reactor/Infrastructure.fs b/propulsion-reactor/Infrastructure.fs index 32b362c12..a05360d95 100644 --- a/propulsion-reactor/Infrastructure.fs +++ b/propulsion-reactor/Infrastructure.fs @@ -54,13 +54,10 @@ type LoggerConfigurationExtensions() = |> fun c -> if verbose then c else c.ExcludeChangeFeedProcessorV2InternalDiagnostics() #endif -// Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline +[] type Logging() = - static member Initialize(configure) = - let loggerConfiguration : LoggerConfiguration = LoggerConfiguration() |> configure - Log.Logger <- loggerConfiguration.CreateLogger() - + [] #if (!kafkaEventSpans) static member Configure(configuration : LoggerConfiguration, ?verbose, ?changeFeedProcessorVerbose) = #else diff --git a/propulsion-reactor/Program.fs b/propulsion-reactor/Program.fs index 549e26be3..f86314cd3 100644 --- a/propulsion-reactor/Program.fs +++ b/propulsion-reactor/Program.fs @@ -686,11 +686,11 @@ let run args = async { let main argv = try let args = Args.parse argv #if (!kafkaEventSpans) - try Logging.Initialize(fun c -> Logging.Configure(c, verbose=args.Verbose, changeFeedProcessorVerbose=args.CfpVerbose)) + try Log.Logger <- LoggerConfiguration().Configure(verbose=args.Verbose, changeFeedProcessorVerbose=args.CfpVerbose).CreateLogger() #else - try Logging.Initialize(fun c -> Logging.Configure(c, verbose=args.Verbose)) + try Log.Logger <- LoggerConfiguration().Configure(verbose=args.Verbose).CreateLogger() #endif - try Configuration.load () + try Configuration.initialize () run args |> Async.RunSynchronously 0 with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 diff --git a/propulsion-summary-consumer/Infrastructure.fs b/propulsion-summary-consumer/Infrastructure.fs index 1c5aebd2e..e42ec43c8 100644 --- a/propulsion-summary-consumer/Infrastructure.fs +++ b/propulsion-summary-consumer/Infrastructure.fs @@ -27,13 +27,10 @@ module ClientId = let parse (value : string) : ClientId = let raw = Guid.Parse value in % raw let (|Parse|) = parse -// Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline +[] type Logging() = - static member Initialize(configure) = - let loggerConfiguration : LoggerConfiguration = LoggerConfiguration() |> configure - Log.Logger <- loggerConfiguration.CreateLogger() - + [] static member Configure(configuration : LoggerConfiguration, ?verbose) = configuration .Destructure.FSharpTypes() diff --git a/propulsion-summary-consumer/Program.fs b/propulsion-summary-consumer/Program.fs index 6d7a31d84..41ec52444 100644 --- a/propulsion-summary-consumer/Program.fs +++ b/propulsion-summary-consumer/Program.fs @@ -147,8 +147,8 @@ let run args = async { [] let main argv = try let args = Args.parse argv - try Logging.Initialize(fun c -> Logging.Configure(c, verbose=args.Verbose)) - try Configuration.load () + try Log.Logger <- LoggerConfiguration().Configure(verbose=args.Verbose).CreateLogger() + try Configuration.initialize () run args |> Async.RunSynchronously 0 with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 diff --git a/propulsion-sync/Program.fs b/propulsion-sync/Program.fs index d8bd785ac..04bbfbe47 100644 --- a/propulsion-sync/Program.fs +++ b/propulsion-sync/Program.fs @@ -442,13 +442,10 @@ module Args = open Serilog.Events -// Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline +[] type Logging() = - static member Initialize(configure) = - let loggerConfiguration : LoggerConfiguration = LoggerConfiguration() |> configure - Log.Logger <- loggerConfiguration.CreateLogger() - + [] static member Configure(configuration : LoggerConfiguration, verbose, changeFeedProcessorVerbose, ?maybeSeqEndpoint) = configuration .Destructure.FSharpTypes() @@ -653,8 +650,8 @@ let run args = async { [] let main argv = try let args = Args.parse argv - try Logging.Initialize(fun c -> Logging.Configure(c, args.Verbose, args.CfpVerbose, ?maybeSeqEndpoint = args.MaybeSeqEndpoint)) - try Configuration.load () + try Log.Logger <- LoggerConfiguration().Configure(args.Verbose, args.CfpVerbose, ?maybeSeqEndpoint = args.MaybeSeqEndpoint).CreateLogger() + try Configuration.initialize () run args |> Async.RunSynchronously 0 with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 diff --git a/propulsion-tracking-consumer/Infrastructure.fs b/propulsion-tracking-consumer/Infrastructure.fs index 9698a4c0a..17fb4b0e1 100644 --- a/propulsion-tracking-consumer/Infrastructure.fs +++ b/propulsion-tracking-consumer/Infrastructure.fs @@ -2,6 +2,7 @@ open FSharp.UMX // see https://github.com/fsprojects/FSharp.UMX - % operator and ability to apply units of measure to Guids+strings open Serilog +open System.Runtime.CompilerServices module EventCodec = @@ -23,13 +24,10 @@ module SkuId = let parse (value : string) : SkuId = let raw = value in % raw let (|Parse|) = parse -// Application logic assumes the global `Serilog.Log` is initialized _immediately_ after a successful ArgumentParser.ParseCommandline +[] type Logging() = - static member Initialize(configure) = - let loggerConfiguration : LoggerConfiguration = LoggerConfiguration() |> configure - Log.Logger <- loggerConfiguration.CreateLogger() - + [] static member Configure(configuration : LoggerConfiguration, ?verbose) = configuration .Destructure.FSharpTypes() diff --git a/propulsion-tracking-consumer/Program.fs b/propulsion-tracking-consumer/Program.fs index 8720cf6c5..d81899091 100644 --- a/propulsion-tracking-consumer/Program.fs +++ b/propulsion-tracking-consumer/Program.fs @@ -151,8 +151,8 @@ let run args = async { [] let main argv = try let args = Args.parse argv - try Logging.Initialize(fun c -> Logging.Configure(c, verbose=args.Verbose)) - try Configuration.load () + try Log.Logger <- LoggerConfiguration().Configure(verbose=args.Verbose).CreateLogger() + try Configuration.initialize () run args |> Async.RunSynchronously 0 with e when not (e :? Args.MissingArg) -> Log.Fatal(e, "Exiting"); 2 From f65e264f267a657891dbdaa99bae3b0b66735b81 Mon Sep 17 00:00:00 2001 From: Ruben Bartelink Date: Thu, 29 Oct 2020 07:51:17 +0000 Subject: [PATCH 10/12] Further cleanup --- propulsion-projector/Program.fs | 52 ------------------------------- propulsion-sync/Infrastructure.fs | 35 +++++++++++++++++++++ propulsion-sync/Program.fs | 36 --------------------- 3 files changed, 35 insertions(+), 88 deletions(-) diff --git a/propulsion-projector/Program.fs b/propulsion-projector/Program.fs index 07c14c68e..371f412a4 100644 --- a/propulsion-projector/Program.fs +++ b/propulsion-projector/Program.fs @@ -478,7 +478,6 @@ let run args = async { do! sink.AwaitCompletion() } -#if !PROPOSAL [] let main argv = try let args = Args.parse argv @@ -495,54 +494,3 @@ let main argv = with Args.MissingArg msg -> eprintfn "%s" msg; 1 | :? Argu.ArguParseException as e -> eprintfn "%s" e.Message; 1 | e -> eprintf "Exception %s" e.Message; 1 -#else -module ExitExceptions = - - let (|MessageException|_|) : exn -> Option = function - | (:? Argu.ArguParseException) as e -> Some e.Message - | Args.MissingArg msg -> Some msg - | _ -> None - - let mapExitExceptionsAsync f x = async { - try let! res = f x - return Ok res - with MessageException message -> return Error message - } - - let mapExitExceptions f x = - try Ok (f x) - with MessageException message -> Error message - -type ServiceMain() = - - static member Run(argv, parseArguments, configureLog, initializeConfiguration, run) = - try match parseArguments argv with - | Error msg -> eprintfn "%s" msg; 1 - | Ok args -> - try Logging.Initialize(configureLog args) - try match initializeConfiguration args with - | Error msg -> eprintfn "%s" msg; 1 - | Ok () -> - match run args |> Async.RunSynchronously with - | Error msg -> eprintfn "%s" msg; 1 - | Ok () -> 0 - with e -> Log.Fatal(e, "Exiting"); 2 - finally Log.CloseAndFlush() - with e -> eprintfn "%O" e; 1 - - static member Run(argv : string[], parseArguments, configureLog, initializeConfiguration : unit -> unit, run) = - ServiceMain.Run - ( argv, - parseArguments |> ExitExceptions.mapExitExceptions, - configureLog, - (ignore >> initializeConfiguration) |> ExitExceptions.mapExitExceptions, - run |> ExitExceptions.mapExitExceptionsAsync) -[] -let main argv = -#if cosmos - let configureLog (args : Args.Arguments) c = Logging.Configure(c, verbose=args.Verbose, changeFeedProcessorVerbose=args.Cosmos.CfpVerbose) -#else - let configureLog (args : Args.Arguments) c = Logging.Configure(c, verbose=args.Verbose) -#endif - ServiceMain.Run(argv, Args.parse, configureLog, Configuration.initialize, run) -#endif \ No newline at end of file diff --git a/propulsion-sync/Infrastructure.fs b/propulsion-sync/Infrastructure.fs index adb3d5464..d82aeef73 100644 --- a/propulsion-sync/Infrastructure.fs +++ b/propulsion-sync/Infrastructure.fs @@ -1,6 +1,7 @@ namespace SyncTemplate open Serilog +open Serilog.Events open System.Runtime.CompilerServices [] @@ -21,3 +22,37 @@ type LoggerConfigurationExtensions() = let cfpl = if verbose then Serilog.Events.LogEventLevel.Debug else Serilog.Events.LogEventLevel.Warning c.MinimumLevel.Override("Microsoft.Azure.Documents.ChangeFeedProcessor", cfpl) |> fun c -> if verbose then c else c.ExcludeChangeFeedProcessorV2InternalDiagnostics() + +[] +type Logging() = + + [] + static member Configure(configuration : LoggerConfiguration, verbose, changeFeedProcessorVerbose, ?maybeSeqEndpoint) = + configuration + .Destructure.FSharpTypes() + .Enrich.FromLogContext() + |> fun c -> c.ConfigureChangeFeedProcessorLogging(changeFeedProcessorVerbose) + |> fun c -> let ingesterLevel = if changeFeedProcessorVerbose then LogEventLevel.Debug else LogEventLevel.Information + c.MinimumLevel.Override(typeof.FullName, ingesterLevel) + |> fun c -> if verbose then c.MinimumLevel.Debug() else c + |> fun c -> let generalLevel = if verbose then LogEventLevel.Information else LogEventLevel.Warning + c.MinimumLevel.Override(typeof.FullName, generalLevel) + .MinimumLevel.Override(typeof.FullName, generalLevel) + .MinimumLevel.Override(typeof.FullName, LogEventLevel.Information) + |> fun c -> let t = "[{Timestamp:HH:mm:ss} {Level:u3}] {partitionKeyRangeId} {Tranche} {Message:lj} {NewLine}{Exception}" + let configure (a : Configuration.LoggerSinkConfiguration) : unit = + a.Logger(fun l -> + l.WriteTo.Sink(Equinox.EventStore.Log.InternalMetrics.Stats.LogSink()) + .WriteTo.Sink(Equinox.Cosmos.Store.Log.InternalMetrics.Stats.LogSink()) |> ignore) |> ignore + a.Logger(fun l -> + let isEqx = Filters.Matching.FromSource().Invoke + let isWriterA = Filters.Matching.FromSource().Invoke + let isWriterB = Filters.Matching.FromSource().Invoke + let isCp = Filters.Matching.FromSource().Invoke + let l = + if changeFeedProcessorVerbose then l + else l.Filter.ByExcluding(fun x -> isEqx x || isWriterA x || isWriterB x || isCp x) + l.WriteTo.Console(theme=Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code, outputTemplate=t) + |> ignore) |> ignore + c.WriteTo.Async(bufferSize=65536, blockWhenFull=true, configure=System.Action<_> configure) + |> fun c -> match maybeSeqEndpoint with None -> c | Some endpoint -> c.WriteTo.Seq(endpoint) diff --git a/propulsion-sync/Program.fs b/propulsion-sync/Program.fs index 04bbfbe47..effac5b73 100644 --- a/propulsion-sync/Program.fs +++ b/propulsion-sync/Program.fs @@ -440,42 +440,6 @@ module Args = let parser = ArgumentParser.Create(programName=programName) parser.ParseCommandLine argv |> Arguments -open Serilog.Events - -[] -type Logging() = - - [] - static member Configure(configuration : LoggerConfiguration, verbose, changeFeedProcessorVerbose, ?maybeSeqEndpoint) = - configuration - .Destructure.FSharpTypes() - .Enrich.FromLogContext() - |> fun c -> c.ConfigureChangeFeedProcessorLogging(changeFeedProcessorVerbose) - |> fun c -> let ingesterLevel = if changeFeedProcessorVerbose then LogEventLevel.Debug else LogEventLevel.Information - c.MinimumLevel.Override(typeof.FullName, ingesterLevel) - |> fun c -> if verbose then c.MinimumLevel.Debug() else c - |> fun c -> let generalLevel = if verbose then LogEventLevel.Information else LogEventLevel.Warning - c.MinimumLevel.Override(typeof.FullName, generalLevel) - .MinimumLevel.Override(typeof.FullName, generalLevel) - .MinimumLevel.Override(typeof.FullName, LogEventLevel.Information) - |> fun c -> let t = "[{Timestamp:HH:mm:ss} {Level:u3}] {partitionKeyRangeId} {Tranche} {Message:lj} {NewLine}{Exception}" - let configure (a : Configuration.LoggerSinkConfiguration) : unit = - a.Logger(fun l -> - l.WriteTo.Sink(Equinox.EventStore.Log.InternalMetrics.Stats.LogSink()) - .WriteTo.Sink(Equinox.Cosmos.Store.Log.InternalMetrics.Stats.LogSink()) |> ignore) |> ignore - a.Logger(fun l -> - let isEqx = Filters.Matching.FromSource().Invoke - let isWriterA = Filters.Matching.FromSource().Invoke - let isWriterB = Filters.Matching.FromSource().Invoke - let isCp = Filters.Matching.FromSource().Invoke - let l = - if changeFeedProcessorVerbose then l - else l.Filter.ByExcluding(fun x -> isEqx x || isWriterA x || isWriterB x || isCp x) - l.WriteTo.Console(theme=Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code, outputTemplate=t) - |> ignore) |> ignore - c.WriteTo.Async(bufferSize=65536, blockWhenFull=true, configure=System.Action<_> configure) - |> fun c -> match maybeSeqEndpoint with None -> c | Some endpoint -> c.WriteTo.Seq(endpoint) - //#if marveleqx [] module EventV0Parser = From 1d77471e7ee0537f923a201abd34be4f0a0286b5 Mon Sep 17 00:00:00 2001 From: Ruben Bartelink Date: Thu, 29 Oct 2020 08:05:56 +0000 Subject: [PATCH 11/12] Fix compilation --- propulsion-projector/Infrastructure.fs | 2 +- propulsion-reactor/Infrastructure.fs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/propulsion-projector/Infrastructure.fs b/propulsion-projector/Infrastructure.fs index 2af16d3ce..9765761b3 100644 --- a/propulsion-projector/Infrastructure.fs +++ b/propulsion-projector/Infrastructure.fs @@ -30,7 +30,7 @@ type Logging() = [] #if cosmos - static member Configure(configuration : LoggerConfiguration, ?minimumLevel, ?changeFeedProcessorVerbose) = + static member Configure(configuration : LoggerConfiguration, ?verbose, ?changeFeedProcessorVerbose) = #else static member Configure(configuration : LoggerConfiguration, ?verbose) = #endif diff --git a/propulsion-reactor/Infrastructure.fs b/propulsion-reactor/Infrastructure.fs index a05360d95..92e2c712e 100644 --- a/propulsion-reactor/Infrastructure.fs +++ b/propulsion-reactor/Infrastructure.fs @@ -61,7 +61,7 @@ type Logging() = #if (!kafkaEventSpans) static member Configure(configuration : LoggerConfiguration, ?verbose, ?changeFeedProcessorVerbose) = #else - static member Configure(configuration : LoggerConfiguration, ?minimumLevel) = + static member Configure(configuration : LoggerConfiguration, ?verbose) = #endif configuration .Destructure.FSharpTypes() From ee2f3c5cfd1e2c2b27b971ac70e7fa559a6cb466 Mon Sep 17 00:00:00 2001 From: Ruben Bartelink Date: Thu, 29 Oct 2020 08:25:06 +0000 Subject: [PATCH 12/12] Tidy --- CHANGELOG.md | 1 + equinox-testbed/Program.fs | 3 ++- equinox-web-csharp/Web/Program.cs | 18 +++++++++++------- equinox-web/Web/Program.fs | 12 +++++++----- propulsion-projector/Infrastructure.fs | 14 +++++++------- propulsion-projector/Program.fs | 2 +- propulsion-sync/Infrastructure.fs | 2 +- 7 files changed, 30 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c7660924d..8c22a408b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ The `Unreleased` section name is replaced by the expected version of next releas ### Added ### Changed +- Cleaned and moved `Logging` logic out to `Infrastructure.fs` [#76](https://github.com/jet/dotnet-templates/pull/76) - Polished `SemaphoreSlim` extensions [#79](https://github.com/jet/dotnet-templates/pull/79) ### Removed diff --git a/equinox-testbed/Program.fs b/equinox-testbed/Program.fs index c7ef0c938..7c672bd71 100644 --- a/equinox-testbed/Program.fs +++ b/equinox-testbed/Program.fs @@ -109,7 +109,8 @@ module Args = #endif let createStoreLog verbose verboseConsole maybeSeqEndpoint = - let c = LoggerConfiguration().Destructure.FSharpTypes() + let c = LoggerConfiguration() + .Destructure.FSharpTypes() let c = if verbose then c.MinimumLevel.Debug() else c //#if eventStore let c = c.WriteTo.Sink(Equinox.EventStore.Log.InternalMetrics.Stats.LogSink()) diff --git a/equinox-web-csharp/Web/Program.cs b/equinox-web-csharp/Web/Program.cs index 7548f3ffa..4784eebc3 100755 --- a/equinox-web-csharp/Web/Program.cs +++ b/equinox-web-csharp/Web/Program.cs @@ -8,19 +8,23 @@ namespace TodoBackendTemplate.Web { + static class Logging + { + public static LoggerConfiguration Configure(this LoggerConfiguration c) => + c + .MinimumLevel.Debug() + .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning) + // .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + .Enrich.FromLogContext() + .WriteTo.Console(); + } static class Program { public static async Task Main(string[] argv) { try { - Log.Logger = new LoggerConfiguration() - .MinimumLevel.Debug() - .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning) - // .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) - .Enrich.FromLogContext() - .WriteTo.Console() - .CreateLogger(); + Log.Logger = new LoggerConfiguration().Configure().CreateLogger(); var host = WebHost .CreateDefaultBuilder(argv) .UseSerilog() diff --git a/equinox-web/Web/Program.fs b/equinox-web/Web/Program.fs index 75fc1fe09..8d46295c6 100644 --- a/equinox-web/Web/Program.fs +++ b/equinox-web/Web/Program.fs @@ -4,14 +4,16 @@ open Microsoft.AspNetCore open Microsoft.AspNetCore.Hosting open Serilog -let initLogging () = - Log.Logger <- - LoggerConfiguration() +[] +type Logging() = + + [] + static member Configure(c : LoggerConfiguration) = + c .MinimumLevel.Debug() .MinimumLevel.Override("Microsoft.AspNetCore", Serilog.Events.LogEventLevel.Warning) .Enrich.FromLogContext() .WriteTo.Console() - .CreateLogger() let createWebHostBuilder args : IWebHostBuilder = WebHost @@ -21,7 +23,7 @@ let createWebHostBuilder args : IWebHostBuilder = [] let main argv = - try initLogging () + try Log.Logger <- LoggerConfiguration().Configure().CreateLogger() createWebHostBuilder(argv).Build().Run() 0 with e -> diff --git a/propulsion-projector/Infrastructure.fs b/propulsion-projector/Infrastructure.fs index 9765761b3..885cba9f2 100644 --- a/propulsion-projector/Infrastructure.fs +++ b/propulsion-projector/Infrastructure.fs @@ -34,12 +34,12 @@ type Logging() = #else static member Configure(configuration : LoggerConfiguration, ?verbose) = #endif - configuration - .Destructure.FSharpTypes() - .Enrich.FromLogContext() - |> fun c -> if verbose = Some true then c.MinimumLevel.Debug() else c + configuration + .Destructure.FSharpTypes() + .Enrich.FromLogContext() + |> fun c -> if verbose = Some true then c.MinimumLevel.Debug() else c #if cosmos - |> fun c -> c.ConfigureChangeFeedProcessorLogging((changeFeedProcessorVerbose = Some true)) + |> fun c -> c.ConfigureChangeFeedProcessorLogging((changeFeedProcessorVerbose = Some true)) #endif - |> fun c -> let t = "[{Timestamp:HH:mm:ss} {Level:u3}] {partitionKeyRangeId,2} {Message:lj} {NewLine}{Exception}" - c.WriteTo.Console(theme=Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code, outputTemplate=t) + |> fun c -> let t = "[{Timestamp:HH:mm:ss} {Level:u3}] {partitionKeyRangeId,2} {Message:lj} {NewLine}{Exception}" + c.WriteTo.Console(theme=Sinks.SystemConsole.Themes.AnsiConsoleTheme.Code, outputTemplate=t) diff --git a/propulsion-projector/Program.fs b/propulsion-projector/Program.fs index 371f412a4..df4f37f6a 100644 --- a/propulsion-projector/Program.fs +++ b/propulsion-projector/Program.fs @@ -482,7 +482,7 @@ let run args = async { let main argv = try let args = Args.parse argv #if cosmos - try Log.Logger <- LoggerConfiguration().Configure(verbose=args.Verbose, changeFeedProcessorVerbose=args.CfpVerbose).CreateLogger() + try Log.Logger <- LoggerConfiguration().Configure(verbose=args.Verbose, changeFeedProcessorVerbose=args.Cosmos.CfpVerbose).CreateLogger() #else try Log.Logger <- LoggerConfiguration().Configure(verbose=args.Verbose).CreateLogger() #endif diff --git a/propulsion-sync/Infrastructure.fs b/propulsion-sync/Infrastructure.fs index d82aeef73..aa0051fcb 100644 --- a/propulsion-sync/Infrastructure.fs +++ b/propulsion-sync/Infrastructure.fs @@ -31,10 +31,10 @@ type Logging() = configuration .Destructure.FSharpTypes() .Enrich.FromLogContext() + |> fun c -> if verbose then c.MinimumLevel.Debug() else c |> fun c -> c.ConfigureChangeFeedProcessorLogging(changeFeedProcessorVerbose) |> fun c -> let ingesterLevel = if changeFeedProcessorVerbose then LogEventLevel.Debug else LogEventLevel.Information c.MinimumLevel.Override(typeof.FullName, ingesterLevel) - |> fun c -> if verbose then c.MinimumLevel.Debug() else c |> fun c -> let generalLevel = if verbose then LogEventLevel.Information else LogEventLevel.Warning c.MinimumLevel.Override(typeof.FullName, generalLevel) .MinimumLevel.Override(typeof.FullName, generalLevel)