diff --git a/examples/Libryy/LoggingV4.fs b/examples/Libryy/LoggingV4.fs index 96209d9e0..85fee920e 100644 --- a/examples/Libryy/LoggingV4.fs +++ b/examples/Libryy/LoggingV4.fs @@ -299,29 +299,14 @@ module Alt = >>-. x) Job.start markNack >>-. altCommit) -/// Why was the message/metric/event not logged? -[] -type LogError = - /// The buffer of the target was full, so the message was not logged. - | BufferFull of target:string - /// The target, or the processing step before the targets, rejected the message. - | Rejected - -type internal LogResult = Alt, LogError>> +type internal LogResult = Alt, string>> module internal Promise = let unit: Promise = Promise (()) -[] -module internal LogError = - let rejected: LogError = Rejected - let bufferFull target: LogError = BufferFull target - [] module internal LogResult = - let success: Alt, LogError>> = Alt.always (Result.Ok Promise.unit) - let bufferFull target: Alt, LogError>> = Alt.always (Result.Error (BufferFull target)) - let rejected: Alt, LogError>> = Alt.always (Result.Error Rejected) + let success: LogResult = Alt.always (Result.Ok Promise.unit) module internal H = /// Finds all exceptions @@ -360,6 +345,12 @@ type Message = |> Seq.map (fun (KeyValue (k, v)) -> k.Substring(Literals.FieldsPrefix.Length), v) |> Map.ofSeq + member x.getContext(): Map = + x.context + |> Map.filter (fun k _ -> + not (k.StartsWith Literals.FieldsPrefix) + && not (k.StartsWith Literals.LogaryPrefix)) + /// If you're looking for how to transform the Message's fields, then use the /// module methods rather than instance methods, since you'll be creating new /// values rather than changing an existing value. @@ -378,9 +369,7 @@ module Logger = logger.logWithAck (false, logLevel) messageFactory ^-> function | Ok _ -> true - | Result.Error Rejected -> - true - | Result.Error (BufferFull _) -> + | Result.Error error -> false let private printDotOnOverflow accepted = @@ -396,10 +385,7 @@ module Logger = logger.logWithAck (true, logLevel) messageFactory ^=> function | Ok _ -> Job.result () - | Result.Error Rejected -> - Job.result () - | Result.Error (BufferFull target) -> - //Job.raises (exn (sprintf "logWithAck (true, _) should have waited for the RingBuffer(s) to accept the Message. Target(%s)" target)) + | Result.Error error -> Job.result () /// Special case: e.g. Fatal messages. @@ -409,19 +395,20 @@ module Logger = logger.logWithAck (true, level) messageFactory ^=> function | Ok promise -> Job.start (promise ^=> IVar.fill ack) - | Result.Error Rejected -> - IVar.fill ack () - | Result.Error (BufferFull target) -> - //let e = exn (sprintf "logWithAck (true, _) should have waited for the RingBuffer(s) to accept the Message. Target(%s)" target) - //IVar.fillFailure ack e + | Result.Error error -> IVar.fill ack () start inner ack :> Promise<_> + let private ensureName name = + fun (m: Message) -> + if m.name.Length = 0 then { m with name = name } else m + let apply (transform: Message -> Message) (logger: Logger): Logger = + let ensureName = ensureName logger.name { new Logger with member x.logWithAck (waitForBuffers, logLevel) messageFactory = - logger.logWithAck (waitForBuffers, logLevel) (messageFactory >> transform) + logger.logWithAck (waitForBuffers, logLevel) (messageFactory >> ensureName >> transform) member x.name = logger.name } @@ -675,12 +662,12 @@ module internal LiterateTokenisation = | _ -> OtherSymbol - let tokeniseValue (options: LiterateOptions) (fields: Map) (template: string) = + let tokeniseValue (options: LiterateOptions) (fields: Map) (context: Map) (template: string) = let themedParts = ResizeArray() let matchedFields = ResizeArray() let foundText (text: string) = themedParts.Add (text, Text) let foundProp (prop: FsMtParser.Property) = - match Map.tryFind prop.name fields with + match fields |> Map.tryFind prop.name |> Option.orElseWith (fun () -> context |> Map.tryFind prop.name) with | Some propValue -> // render using string.Format, so the formatting is applied let stringFormatTemplate = prop.AppendPropertyString(StringBuilder(), "0").ToString() @@ -736,8 +723,8 @@ module internal LiterateTokenisation = .ToString("HH:mm:ss", options.formatProvider), Subtext - let fields = message.getFields() - let _, themedMessageParts = message.value |> tokeniseValue options fields + let fields, context = message.getFields(), message.getContext() + let _, themedMessageParts = message.value |> tokeniseValue options fields context let themedExceptionParts = tokeniseExns options message [ yield "[", Punctuation @@ -758,9 +745,9 @@ module internal Formatting = open Literate open System.Text - let formatValue (fields: Map) value = + let formatValue (fields: Map) (context: Map) value = let matchedFields, themedParts = - LiterateTokenisation.tokeniseValue (LiterateOptions.createInvariant()) fields value + LiterateTokenisation.tokeniseValue (LiterateOptions.createInvariant()) fields context value matchedFields, System.String.Concat(themedParts |> Seq.map fst) let formatLevel (level: LogLevel) = @@ -793,8 +780,8 @@ module internal Formatting = /// let the ISO8601 love flow let defaultFormatter (message: Message) = - let fields = message.getFields() - let matchedFields, valueString = formatValue fields message.value + let fields, context = message.getFields(), message.getContext() + let matchedFields, valueString = formatValue fields context message.value // [I] 2014-04-05T12:34:56Z: Hello World! [my.sample.app] formatLevel message.level + @@ -891,23 +878,23 @@ module internal LiterateFormatting = let tokeniserForOutputTemplate template: LiterateTokeniser = let tokens = parseTemplate template fun options message -> - let fields = message.getFields() + let fields, context = message.getFields(), message.getContext() // render the message template first so we have the template-matched fields available let matchedFields, messageParts = - tokeniseValue options fields message.value + tokeniseValue options fields context message.value let tokeniseOutputTemplateField fieldName format = seq { match fieldName with - | "timestamp" -> yield! tokeniseTimestamp format options message - | "timestampUtc" -> yield! tokeniseTimestampUtc format options message - | "level" -> yield! tokeniseLogLevel options message - | "source" -> yield! tokeniseSource options message - | "newline" -> yield! tokeniseNewline options message - | "tab" -> yield! tokeniseTab options message - | "message" -> yield! messageParts - | "properties" -> yield! tokeniseExtraFields options message matchedFields - | "exceptions" -> yield! tokeniseExns options message - | _ -> yield! tokeniseMissingField fieldName format + | "timestamp" -> yield! tokeniseTimestamp format options message + | "timestampUtc" -> yield! tokeniseTimestampUtc format options message + | "level" -> yield! tokeniseLogLevel options message + | "source" -> yield! tokeniseSource options message + | "newline" -> yield! tokeniseNewline options message + | "tab" -> yield! tokeniseTab options message + | "message" -> yield! messageParts + | "properties" -> yield! tokeniseExtraFields options message matchedFields + | "exceptions" -> yield! tokeniseExns options message + | _ -> yield! tokeniseMissingField fieldName format } seq { @@ -1122,6 +1109,9 @@ module Message = let setField name value (message: Message): Message = { message with context = message.context |> Map.add (Literals.FieldsPrefix + name) (box value) } + let setFields (fields: Map) (message: Message): Message = + fields |> Seq.fold (fun m (KeyValue (k, vO)) -> m |> setField k vO) message + let tryGetField name (message: Message): 'a option = tryGetContext (Literals.FieldsPrefix + name) message diff --git a/examples/Logary.ConsoleApp/Program.fs b/examples/Logary.ConsoleApp/Program.fs index 7de24974f..f26813f48 100644 --- a/examples/Logary.ConsoleApp/Program.fs +++ b/examples/Logary.ConsoleApp/Program.fs @@ -16,6 +16,7 @@ open Logary.Configuration open Logary.Targets open Logary.Configuration open Logary.Configuration.Transformers +open NodaTime module RandomWalk = @@ -115,20 +116,20 @@ let main argv = let randomWalkPipe = Events.events - |> Pipe.tickTimer (randomness) (TimeSpan.FromMilliseconds 500.) + |> Pipe.tickTimer (randomness) (Duration.FromMilliseconds 500.) let processing = Events.compose [ Events.events |> Events.minLevel LogLevel.Fatal |> Events.sink ["fatal"] //Events.events - //|> Pipe.tickTimer (WinPerfCounters.appMetrics (PointName.ofSingle "app")) (TimeSpan.FromMilliseconds 5000.) + //|> Pipe.tickTimer (WinPerfCounters.appMetrics (PointName.ofSingle "app")) (Duration.FromMilliseconds 5000.) //|> Pipe.map Array.toSeq //|> Events.flattenToProcessing //|> Events.sink ["console"; "influxdb"] //Events.events - //|> Pipe.tickTimer (WinPerfCounters.systemMetrics (PointName.ofSingle "system")) (TimeSpan.FromMilliseconds 5000.) + //|> Pipe.tickTimer (WinPerfCounters.systemMetrics (PointName.ofSingle "system")) (Duration.FromMilliseconds 5000.) //|> Pipe.map Array.toSeq //|> Events.flattenToProcessing //|> Events.sink ["console"; "influxdb"] @@ -138,7 +139,7 @@ let main argv = randomWalkPipe |> Pipe.choose (Message.tryGetGauge "Logary.ConsoleApp.randomWalk") - |> Pipe.tickTimer timing (TimeSpan.FromSeconds 10.) + |> Pipe.tickTimer timing (Duration.FromSeconds 10.) |> Pipe.map Array.toSeq |> Events.flattenSeq |> Events.sink ["console"] diff --git a/examples/Logary.ConsoleApp/paket.references b/examples/Logary.ConsoleApp/paket.references index daaca70d7..a8ddcc980 100644 --- a/examples/Logary.ConsoleApp/paket.references +++ b/examples/Logary.ConsoleApp/paket.references @@ -2,3 +2,4 @@ group Examples RabbitMQ.Client FSharp.Core Argu +NodaTime \ No newline at end of file diff --git a/examples/Logary.MetricsWriter/Program.fs b/examples/Logary.MetricsWriter/Program.fs index 6cc62d2d3..f394129d1 100644 --- a/examples/Logary.MetricsWriter/Program.fs +++ b/examples/Logary.MetricsWriter/Program.fs @@ -43,8 +43,8 @@ let main argv = let clock = SystemClock.Instance let tenSecondsEWMATicker = EWMATicker (Duration.FromSeconds 1L, Duration.FromSeconds 10L, clock) let randomWalk = Sample.randomWalk "randomWalk" - let walkPipe = Events.events |> Pipe.tickTimer randomWalk (TimeSpan.FromMilliseconds 500.) - let systemMetrics = Events.events |> Pipe.tickTimer (systemMetrics (PointName.parse "sys")) (TimeSpan.FromSeconds 10.) + let walkPipe = Events.events |> Pipe.tickTimer randomWalk (Duration.FromMilliseconds 500.) + let systemMetrics = Events.events |> Pipe.tickTimer (systemMetrics (PointName.parse "sys")) (Duration.FromSeconds 10.) let processing = Events.compose [ walkPipe @@ -52,14 +52,14 @@ let main argv = walkPipe |> Pipe.choose (Message.tryGetGauge "randomWalk") - |> Pipe.counter (fun _ -> 1L) (TimeSpan.FromSeconds 2.) + |> Pipe.counter (fun _ -> 1L) (Duration.FromSeconds 2.) |> Pipe.map (fun counted -> Message.eventFormat (Info, "There are {totalNumbers} randomWalk within 2s", [|counted|])) |> Events.sink ["Console";] walkPipe |> Pipe.choose (Message.tryGetGauge "randomWalk") |> Pipe.map (fun _ -> 1L) // think of randomWalk as an event, mapping to 1 - |> Pipe.tickTimer tenSecondsEWMATicker (TimeSpan.FromSeconds 5.) + |> Pipe.tickTimer tenSecondsEWMATicker (Duration.FromSeconds 5.) |> Pipe.map (fun rate -> Message.eventFormat (Info, "tenSecondsEWMA of randomWalk's rate is {rateInSec}", [|rate|])) |> Events.sink ["Console";] diff --git a/paket.dependencies b/paket.dependencies index 7628d0b97..00ba077df 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -52,7 +52,7 @@ nuget protobuf-net github eiriktsarpalis/TypeShape src/TypeShape/TypeShape.fs github eiriktsarpalis/TypeShape src/TypeShape/Utils.fs github haf/YoLo:bd91bbe94a183aa9dc9c13e885c73b20516b01e7 YoLo.fs -github logary/RingBuffer:014138cdfc9dff76e74dc154e68c929655bcbd86 RingBuffer.fs +github logary/RingBuffer RingBuffer.fs github logary/logary src/Logary.CSharp.Facade/Facade.cs github logary/logary src/Logary.Facade/Facade.fs github messagetemplates/messagetemplates-fsharp src/FsMtParser/FsMtParserFull.fs @@ -88,4 +88,5 @@ group Benchmarks nuget Hopac nuget NodaTime nuget Expecto - nuget Expecto.BenchmarkDotNet + nuget Expecto.BenchmarkDotNet == 8.6.5 + nuget BenchmarkDotNet == 0.10.14 diff --git a/paket.lock b/paket.lock index a8cba738d..bacfd1940 100644 --- a/paket.lock +++ b/paket.lock @@ -1086,7 +1086,7 @@ GITHUB remote: haf/YoLo YoLo.fs (bd91bbe94a183aa9dc9c13e885c73b20516b01e7) remote: logary/RingBuffer - RingBuffer.fs (014138cdfc9dff76e74dc154e68c929655bcbd86) + RingBuffer.fs (4ae23a7481076091fff153961196df302683d756) Expecto Expecto.BenchmarkDotNet Expecto.FsCheck @@ -1128,29 +1128,27 @@ NUGET BenchmarkDotNet.Core (>= 0.10.14) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net46)) Microsoft.CodeAnalysis.CSharp (>= 2.6.1) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net46)) System.Threading.Tasks (>= 4.3) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net46)) - Expecto (8.0) + Expecto (8.6.5) Argu (>= 5.1) Mono.Cecil (>= 0.10) System.Diagnostics.FileVersionInfo (>= 4.3) - restriction: || (&& (== net471) (< net461)) (== netcoreapp2.0) - Expecto.BenchmarkDotNet (8.0) - BenchmarkDotNet (>= 0.10.13) + Expecto.BenchmarkDotNet (8.6.5) + BenchmarkDotNet (>= 0.10.14) FSharp.Core (>= 4.3.4) - System.ValueTuple (>= 4.4) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net461)) FParsec (1.0.3) FSharp.Core (>= 4.0.0.1) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net40)) FSharp.Core (>= 4.2.3) - restriction: || (&& (== net471) (< net40)) (== netcoreapp2.0) NETStandard.Library (>= 1.6.1) - restriction: || (&& (== net471) (< net40)) (== netcoreapp2.0) - FSharp.Core (4.3.4) - Hopac (0.3.23) - FSharp.Core (>= 4.0.1.7-alpha) - NETStandard.Library (>= 1.6) - Microsoft.CodeAnalysis.Analyzers (2.6) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net46)) - Microsoft.CodeAnalysis.Common (2.8.2) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net46)) - Microsoft.CodeAnalysis.Analyzers (>= 1.1) + FSharp.Core (4.5.4) + Hopac (0.4.1) + FSharp.Core (>= 4.5 < 5.0) + Microsoft.CodeAnalysis.Analyzers (2.6.2) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net46)) + Microsoft.CodeAnalysis.Common (2.10) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net46)) + Microsoft.CodeAnalysis.Analyzers (>= 2.6.1) System.AppContext (>= 4.3) System.Collections (>= 4.3) System.Collections.Concurrent (>= 4.3) - System.Collections.Immutable (>= 1.3.1) + System.Collections.Immutable (>= 1.5) System.Console (>= 4.3) System.Diagnostics.Debug (>= 4.3) System.Diagnostics.FileVersionInfo (>= 4.3) @@ -1164,7 +1162,7 @@ NUGET System.Linq (>= 4.3) System.Linq.Expressions (>= 4.3) System.Reflection (>= 4.3) - System.Reflection.Metadata (>= 1.4.2) + System.Reflection.Metadata (>= 1.6) System.Resources.ResourceManager (>= 4.3) System.Runtime (>= 4.3) System.Runtime.Extensions (>= 4.3) @@ -1178,6 +1176,7 @@ NUGET System.Text.Encoding.Extensions (>= 4.3) System.Threading (>= 4.3) System.Threading.Tasks (>= 4.3) + System.Threading.Tasks.Extensions (>= 4.3) System.Threading.Tasks.Parallel (>= 4.3) System.Threading.Thread (>= 4.3) System.ValueTuple (>= 4.3) @@ -1185,8 +1184,8 @@ NUGET System.Xml.XDocument (>= 4.3) System.Xml.XmlDocument (>= 4.3) System.Xml.XPath.XDocument (>= 4.3) - Microsoft.CodeAnalysis.CSharp (2.8.2) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net46)) - Microsoft.CodeAnalysis.Common (2.8.2) + Microsoft.CodeAnalysis.CSharp (2.10) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net46)) + Microsoft.CodeAnalysis.Common (2.10) Microsoft.DotNet.InternalAbstractions (1.0) System.AppContext (>= 4.1) - restriction: || (&& (== net471) (< net451)) (== netcoreapp2.0) System.Collections (>= 4.0.11) - restriction: || (&& (== net471) (< net451)) (== netcoreapp2.0) @@ -1196,7 +1195,7 @@ NUGET System.Runtime.Extensions (>= 4.1) - restriction: || (&& (== net471) (< net451)) (== netcoreapp2.0) System.Runtime.InteropServices (>= 4.1) - restriction: || (&& (== net471) (< net451)) (== netcoreapp2.0) System.Runtime.InteropServices.RuntimeInformation (>= 4.0) - restriction: || (&& (== net471) (< net451)) (== netcoreapp2.0) - Microsoft.DotNet.PlatformAbstractions (2.0.4) + Microsoft.DotNet.PlatformAbstractions (2.1) System.AppContext (>= 4.1) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) System.Collections (>= 4.0.11) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) System.IO (>= 4.1) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) @@ -1204,14 +1203,14 @@ NUGET System.Reflection.TypeExtensions (>= 4.1) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) System.Runtime.Extensions (>= 4.1) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) System.Runtime.InteropServices (>= 4.1) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Runtime.InteropServices.RuntimeInformation (>= 4.0) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) - Microsoft.NETCore.Platforms (2.0.2) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (&& (== net471) (>= netcoreapp2.0)) (== netcoreapp2.0) - Microsoft.NETCore.Targets (2.0) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - Microsoft.Win32.Registry (4.4) - Microsoft.NETCore.Platforms (>= 2.0) - restriction: || (&& (== net471) (>= netcoreapp2.0)) (== netcoreapp2.0) - System.Security.AccessControl (>= 4.4) - System.Security.Principal.Windows (>= 4.4) - Mono.Cecil (0.10) + System.Runtime.InteropServices.RuntimeInformation (>= 4.0) + Microsoft.NETCore.Platforms (2.2) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (&& (== net471) (>= netcoreapp2.0)) (== netcoreapp2.0) + Microsoft.NETCore.Targets (2.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) + Microsoft.Win32.Registry (4.5) + System.Memory (>= 4.5) - restriction: || (&& (== net471) (< net46)) (&& (== net471) (>= netcoreapp2.0)) (&& (== net471) (>= uap10.1)) (== netcoreapp2.0) + System.Security.AccessControl (>= 4.5) + System.Security.Principal.Windows (>= 4.5) + Mono.Cecil (0.10.1) System.Collections (>= 4.0.11) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) System.IO.FileSystem (>= 4.0.1) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) System.IO.FileSystem.Primitives (>= 4.0.1) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) @@ -1220,38 +1219,46 @@ NUGET System.Security.Cryptography.Algorithms (>= 4.2) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) System.Security.Cryptography.Csp (>= 4.0) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) System.Threading (>= 4.0.11) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) - NETStandard.Library (2.0.3) - Microsoft.NETCore.Platforms (>= 1.1) - NodaTime (2.3) - NETStandard.Library (>= 1.6.1) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Runtime.Serialization.Xml (>= 4.1.1) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) - runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.2) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) - runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.2) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) - runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.2) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) - runtime.native.System (4.3) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) + NETStandard.Library (2.0.3) - restriction: || (&& (== net471) (< net40)) (== netcoreapp2.0) Microsoft.NETCore.Platforms (>= 1.1) - Microsoft.NETCore.Targets (>= 1.1) + NodaTime (2.4.2) + runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) + runtime.debian.9-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) + runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) + runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) + runtime.fedora.27-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) + runtime.fedora.28-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) + runtime.native.System (4.3.1) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) + Microsoft.NETCore.Platforms (>= 1.1.1) + Microsoft.NETCore.Targets (>= 1.1.3) runtime.native.System.Security.Cryptography.Apple (4.3.1) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple (>= 4.3.1) - runtime.native.System.Security.Cryptography.OpenSsl (4.3.2) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) - runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.2) - runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.2) - runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.2) - runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.2) - runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.2) - runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.2) - runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.2) - runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.2) - runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.2) - runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.2) - runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.2) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) - runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.2) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) + runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) + runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) + runtime.debian.9-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) + runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) + runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) + runtime.fedora.27-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) + runtime.fedora.28-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) + runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) + runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) + runtime.opensuse.42.3-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) + runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) + runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) + runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) + runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) + runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) + runtime.ubuntu.18.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3) + runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) + runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) + runtime.opensuse.42.3-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple (4.3.1) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) - runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.2) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) - runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.2) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) - runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.2) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) - runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.2) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) - runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.2) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) + runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) + runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) + runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) + runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) + runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) + runtime.ubuntu.18.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3) - restriction: || (&& (== net471) (< net35)) (== netcoreapp2.0) System.AppContext (4.3) System.Runtime (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) System.Collections (4.3) @@ -1259,24 +1266,12 @@ NUGET Microsoft.NETCore.Targets (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) System.Runtime (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) System.Collections.Concurrent (4.3) - System.Collections (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Diagnostics.Debug (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Diagnostics.Tracing (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Globalization (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Reflection (>= 4.3) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Resources.ResourceManager (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Runtime (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Runtime.Extensions (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Threading (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Threading.Tasks (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Collections.Immutable (1.4) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net46)) - System.Configuration.ConfigurationManager (4.4.1) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Security.Cryptography.ProtectedData (>= 4.4) - restriction: || (&& (== net471) (< net461)) (&& (== net471) (>= netcoreapp2.0)) (== netcoreapp2.0) + System.Collections.Immutable (1.5) + System.Configuration.ConfigurationManager (4.5) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) + System.Security.Cryptography.ProtectedData (>= 4.5) - restriction: || (&& (== net471) (< net461)) (== netcoreapp2.0) + System.Security.Permissions (>= 4.5) System.Console (4.3.1) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net46)) System.Diagnostics.Debug (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - Microsoft.NETCore.Targets (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Runtime (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) System.Diagnostics.FileVersionInfo (4.3) Microsoft.NETCore.Platforms (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) System.Globalization (>= 4.3) - restriction: || (&& (== net471) (< net46)) (== netcoreapp2.0) @@ -1288,14 +1283,7 @@ NUGET System.Runtime.Extensions (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) System.Runtime.InteropServices (>= 4.3) - restriction: || (&& (== net471) (< net46)) (== netcoreapp2.0) System.Diagnostics.StackTrace (4.3) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net46)) - System.Diagnostics.Tools (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - Microsoft.NETCore.Targets (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Runtime (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Diagnostics.Tracing (4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - Microsoft.NETCore.Platforms (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - Microsoft.NETCore.Targets (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Runtime (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) + System.Diagnostics.Tools (4.3) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net46)) System.Dynamic.Runtime (4.3) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net46)) System.Globalization (4.3) Microsoft.NETCore.Platforms (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) @@ -1326,32 +1314,8 @@ NUGET System.Runtime (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) System.Runtime.Extensions (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) System.Linq.Expressions (4.3) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net46)) - System.Private.DataContractSerialization (4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Collections (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) - System.Collections.Concurrent (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) - System.Diagnostics.Debug (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) - System.Globalization (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) - System.IO (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) - System.Linq (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) - System.Reflection (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) - System.Reflection.Emit.ILGeneration (>= 4.3) - restriction: || (&& (== net471) (< net46)) (== netcoreapp2.0) - System.Reflection.Emit.Lightweight (>= 4.3) - restriction: || (&& (== net471) (< net46)) (== netcoreapp2.0) - System.Reflection.Extensions (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) - System.Reflection.Primitives (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) - System.Reflection.TypeExtensions (>= 4.3) - System.Resources.ResourceManager (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) - System.Runtime (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) - System.Runtime.Extensions (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) - System.Runtime.Serialization.Primitives (>= 4.3) - System.Text.Encoding (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) - System.Text.Encoding.Extensions (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) - System.Text.RegularExpressions (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) - System.Threading (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) - System.Threading.Tasks (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) - System.Xml.ReaderWriter (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) - System.Xml.XDocument (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) - System.Xml.XmlDocument (>= 4.3) - System.Xml.XmlSerializer (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) + System.Memory (4.5.1) - restriction: || (&& (== net471) (< net46)) (&& (== net471) (>= netcoreapp2.0)) (&& (== net471) (>= uap10.1)) (== netcoreapp2.0) + System.Runtime.CompilerServices.Unsafe (>= 4.5) System.Reflection (4.3) Microsoft.NETCore.Platforms (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) Microsoft.NETCore.Targets (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) @@ -1364,11 +1328,11 @@ NUGET System.Reflection.Emit.ILGeneration (>= 4.3) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) System.Reflection.Primitives (>= 4.3) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) System.Runtime (>= 4.3) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Reflection.Emit.ILGeneration (4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) + System.Reflection.Emit.ILGeneration (4.3) - restriction: || (&& (== net471) (>= netcoreapp1.1)) (== netcoreapp2.0) System.Reflection (>= 4.3) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) System.Reflection.Primitives (>= 4.3) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) System.Runtime (>= 4.3) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Reflection.Emit.Lightweight (4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) + System.Reflection.Emit.Lightweight (4.3) - restriction: || (&& (== net471) (>= netcoreapp1.1)) (== netcoreapp2.0) System.Reflection (>= 4.3) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) System.Reflection.Emit.ILGeneration (>= 4.3) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) System.Reflection.Primitives (>= 4.3) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) @@ -1378,12 +1342,13 @@ NUGET Microsoft.NETCore.Targets (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) System.Reflection (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) System.Runtime (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Reflection.Metadata (1.5) - System.Reflection.Primitives (4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (&& (== net471) (>= netcoreapp1.1)) (== netcoreapp2.0) + System.Reflection.Metadata (1.6) + System.Collections.Immutable (>= 1.5) + System.Reflection.Primitives (4.3) - restriction: || (&& (== net471) (>= netcoreapp1.1)) (== netcoreapp2.0) Microsoft.NETCore.Platforms (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) Microsoft.NETCore.Targets (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) System.Runtime (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Reflection.TypeExtensions (4.4) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) + System.Reflection.TypeExtensions (4.5.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) System.Resources.ResourceManager (4.3) Microsoft.NETCore.Platforms (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) Microsoft.NETCore.Targets (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) @@ -1393,6 +1358,7 @@ NUGET System.Runtime (4.3) Microsoft.NETCore.Platforms (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) Microsoft.NETCore.Targets (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) + System.Runtime.CompilerServices.Unsafe (4.5.2) System.Runtime.Extensions (4.3) Microsoft.NETCore.Platforms (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) Microsoft.NETCore.Targets (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) @@ -1408,7 +1374,7 @@ NUGET System.Reflection.Primitives (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (&& (== net471) (>= netcoreapp1.1)) (== netcoreapp2.0) System.Runtime (>= 4.3) System.Runtime.Handles (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (&& (== net471) (>= netcoreapp1.1)) (== netcoreapp2.0) - System.Runtime.InteropServices.RuntimeInformation (4.3) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) + System.Runtime.InteropServices.RuntimeInformation (4.3) runtime.native.System (>= 4.3) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) System.Reflection (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) System.Reflection.Extensions (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) @@ -1421,19 +1387,12 @@ NUGET System.Resources.ResourceManager (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) System.Runtime (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) System.Runtime.Extensions (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Runtime.Serialization.Primitives (4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) + System.Runtime.Serialization.Primitives (4.3) - restriction: || (&& (== net471) (>= netcoreapp1.1)) (== netcoreapp2.0) System.Resources.ResourceManager (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) System.Runtime (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Runtime.Serialization.Xml (4.3) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) - System.IO (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Private.DataContractSerialization (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Runtime (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Runtime.Serialization.Primitives (>= 4.3) - System.Text.Encoding (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Xml.ReaderWriter (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Security.AccessControl (4.4.1) + System.Security.AccessControl (4.5) Microsoft.NETCore.Platforms (>= 2.0) - restriction: || (&& (== net471) (>= netcoreapp2.0)) (== netcoreapp2.0) - System.Security.Principal.Windows (>= 4.4) + System.Security.Principal.Windows (>= 4.5) System.Security.Cryptography.Algorithms (4.3.1) Microsoft.NETCore.Platforms (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net46)) (== netcoreapp2.0) runtime.native.System.Security.Cryptography.Apple (>= 4.3.1) - restriction: || (&& (== net471) (< net46)) (== netcoreapp2.0) @@ -1484,32 +1443,33 @@ NUGET System.Runtime (>= 4.3) - restriction: || (&& (== net471) (< net46)) (== netcoreapp2.0) System.Threading (>= 4.3) - restriction: || (&& (== net471) (< net46)) (== netcoreapp2.0) System.Threading.Tasks (>= 4.3) - restriction: || (&& (== net471) (< net46)) (== netcoreapp2.0) - System.Security.Cryptography.ProtectedData (4.4) - restriction: || (&& (== net471) (< net45)) (&& (== net471) (>= netcoreapp2.0)) (== netcoreapp2.0) + System.Security.Cryptography.ProtectedData (4.5) - restriction: || (&& (== net471) (< net45)) (== netcoreapp2.0) + System.Memory (>= 4.5) - restriction: || (&& (== net471) (< net46)) (== netcoreapp2.0) System.Security.Cryptography.X509Certificates (4.3.2) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net46)) System.Security.Cryptography.Algorithms (>= 4.3) System.Security.Cryptography.Encoding (>= 4.3) - System.Security.Principal.Windows (4.4.1) + System.Security.Permissions (4.5) - restriction: || (&& (== net471) (>= monoandroid)) (&& (== net471) (>= monotouch)) (&& (== net471) (< net45)) (&& (== net471) (>= xamarinmac)) (&& (== net471) (>= xamarintvos)) (&& (== net471) (>= xamarinwatchos)) (== netcoreapp2.0) + System.Security.AccessControl (>= 4.5) + System.Security.Principal.Windows (4.5.1) Microsoft.NETCore.Platforms (>= 2.0) - restriction: || (&& (== net471) (>= netcoreapp2.0)) (== netcoreapp2.0) System.Text.Encoding (4.3) Microsoft.NETCore.Platforms (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) Microsoft.NETCore.Targets (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) System.Runtime (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Text.Encoding.CodePages (4.4) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net46)) + System.Text.Encoding.CodePages (4.5) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net46)) + System.Runtime.CompilerServices.Unsafe (>= 4.5) System.Text.Encoding.Extensions (4.3) - Microsoft.NETCore.Platforms (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - Microsoft.NETCore.Targets (>= 1.1) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Runtime (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Text.Encoding (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) System.Text.RegularExpressions (4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) System.Runtime (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (&& (== net471) (>= netcoreapp1.1)) (== netcoreapp2.0) System.Threading (4.3) System.Runtime (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) System.Threading.Tasks (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) System.Threading.Tasks (4.3) - System.Threading.Tasks.Extensions (4.4) + System.Threading.Tasks.Extensions (4.5.1) + System.Runtime.CompilerServices.Unsafe (>= 4.5) System.Threading.Tasks.Parallel (4.3) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net46)) System.Threading.Thread (4.3) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net46)) - System.ValueTuple (4.4) + System.ValueTuple (4.5) System.Xml.ReaderWriter (4.3.1) System.Collections (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) System.Diagnostics.Debug (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) @@ -1526,19 +1486,7 @@ NUGET System.Text.RegularExpressions (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) System.Threading.Tasks (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) System.Threading.Tasks.Extensions (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Xml.XDocument (4.3) - System.Collections (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Diagnostics.Debug (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Diagnostics.Tools (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Globalization (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.IO (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Reflection (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Resources.ResourceManager (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Runtime (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Runtime.Extensions (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Text.Encoding (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Threading (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) - System.Xml.ReaderWriter (>= 4.3) - restriction: || (&& (== net471) (>= dnxcore50)) (&& (== net471) (< net45)) (== netcoreapp2.0) + System.Xml.XDocument (4.3) - restriction: || (== net471) (&& (== netcoreapp2.0) (>= net46)) System.Xml.XmlDocument (4.3) System.Collections (>= 4.3) - restriction: || (&& (== net471) (< net46)) (== netcoreapp2.0) System.Diagnostics.Debug (>= 4.3) - restriction: || (&& (== net471) (< net46)) (== netcoreapp2.0) diff --git a/src/Logary.Facade/Facade.fs b/src/Logary.Facade/Facade.fs index adf13f947..80a1feea1 100644 --- a/src/Logary.Facade/Facade.fs +++ b/src/Logary.Facade/Facade.fs @@ -296,29 +296,14 @@ module Alt = >>-. x) Job.start markNack >>-. altCommit) -/// Why was the message/metric/event not logged? -[] -type LogError = - /// The buffer of the target was full, so the message was not logged. - | BufferFull of target:string - /// The target, or the processing step before the targets, rejected the message. - | Rejected - -type internal LogResult = Alt, LogError>> +type internal LogResult = Alt, string>> module internal Promise = let unit: Promise = Promise (()) -[] -module internal LogError = - let rejected: LogError = Rejected - let bufferFull target: LogError = BufferFull target - [] module internal LogResult = - let success: Alt, LogError>> = Alt.always (Result.Ok Promise.unit) - let bufferFull target: Alt, LogError>> = Alt.always (Result.Error (BufferFull target)) - let rejected: Alt, LogError>> = Alt.always (Result.Error Rejected) + let success: LogResult = Alt.always (Result.Ok Promise.unit) module internal H = /// Finds all exceptions @@ -359,11 +344,9 @@ type Message = member x.getContext(): Map = x.context - |> Map.toSeq - |> Seq.filter (fun (k, _) -> + |> Map.filter (fun k _ -> not (k.StartsWith Literals.FieldsPrefix) && not (k.StartsWith Literals.LogaryPrefix)) - |> Map.ofSeq /// If you're looking for how to transform the Message's fields, then use the /// module methods rather than instance methods, since you'll be creating new @@ -383,9 +366,7 @@ module Logger = logger.logWithAck (false, logLevel) messageFactory ^-> function | Ok _ -> true - | Result.Error Rejected -> - true - | Result.Error (BufferFull _) -> + | Result.Error error -> false let private printDotOnOverflow accepted = @@ -401,10 +382,7 @@ module Logger = logger.logWithAck (true, logLevel) messageFactory ^=> function | Ok _ -> Job.result () - | Result.Error Rejected -> - Job.result () - | Result.Error (BufferFull target) -> - //Job.raises (exn (sprintf "logWithAck (true, _) should have waited for the RingBuffer(s) to accept the Message. Target(%s)" target)) + | Result.Error error -> Job.result () /// Special case: e.g. Fatal messages. @@ -414,11 +392,7 @@ module Logger = logger.logWithAck (true, level) messageFactory ^=> function | Ok promise -> Job.start (promise ^=> IVar.fill ack) - | Result.Error Rejected -> - IVar.fill ack () - | Result.Error (BufferFull target) -> - //let e = exn (sprintf "logWithAck (true, _) should have waited for the RingBuffer(s) to accept the Message. Target(%s)" target) - //IVar.fillFailure ack e + | Result.Error error -> IVar.fill ack () start inner ack :> Promise<_> diff --git a/src/Logary.PerfTests/Program.fs b/src/Logary.PerfTests/Program.fs index 9114694ad..0c178c756 100644 --- a/src/Logary.PerfTests/Program.fs +++ b/src/Logary.PerfTests/Program.fs @@ -3,20 +3,13 @@ namespace Logary.PerfTests open System open System.Threading open Expecto -open Expecto.Flip open Logary open Logary.Configuration open Logary.Message -open BenchmarkDotNet -open BenchmarkDotNet.Horology open BenchmarkDotNet.Code open BenchmarkDotNet.Jobs -open BenchmarkDotNet.Reports open BenchmarkDotNet.Attributes -open BenchmarkDotNet.Attributes.Jobs -open BenchmarkDotNet.Attributes.Exporters -open BenchmarkDotNet.Attributes.Columns -open BenchmarkDotNet.Attributes.Jobs +open NodaTime module TestData = let helloWorld = @@ -36,13 +29,13 @@ module TestData = module Values = let run = Hopac.Hopac.run + let targets = Map [ - "noop", Targets.Noop.create Targets.Noop.empty "sink" - "single_nodelay", Targets.BadBoy.create Targets.BadBoy.empty "sink" - "single_delay", Targets.BadBoy.create Targets.BadBoy.empty "sink" - "batch_nodelay", Targets.BadBoy.create Targets.BadBoy.empty "sink" - "batch_delay", Targets.BadBoy.create Targets.BadBoy.empty "sink" + "single_nodelay", Targets.BadBoy.create {Targets.BadBoy.empty with delay = Duration.Zero; batch = false } "sink" + "single_delay", Targets.BadBoy.create {Targets.BadBoy.empty with batch = false } "sink" + "batch_nodelay", Targets.BadBoy.create {Targets.BadBoy.empty with delay = Duration.Zero; batch = true } "sink" + "batch_delay", Targets.BadBoy.create {Targets.BadBoy.empty with batch = true } "sink" ] let baseJob = @@ -54,6 +47,16 @@ module Values = .WithGcServer(true) .WithGcConcurrent(true) + + let smallInvocationJob = + Job.Default + .WithInvocationCount(16) + .WithWarmupCount(4) + .WithLaunchCount(1) + //.WithIterationTime(TimeInterval.Millisecond * 200) + .WithGcServer(true) + .WithGcConcurrent(true) + [] type LogaryValue = val logger: Logger @@ -62,9 +65,6 @@ type LogaryValue = let logary = Config.create "Logary.ConsoleApp" "localhost" |> Config.target (targets |> Map.find target) - |> Config.ilogger (ILogger.LiterateConsole Warn) - |> Config.processing (Events.events |> Events.sink [ "sink" ]) - |> Config.loggerMinLevel ".*" Debug |> Config.buildAndRun { logger = logary.getLogger (PointName [| "PerfTestLogger" |]) target = target } @@ -82,7 +82,7 @@ type BP() = val mutable logary: LogaryValue member x.Configs() = - [ "single_nodelay"; "batch_delay" ] + [ "single_nodelay";"batch_delay" ] |> Seq.map (LogaryValue >> LogaryParam >> toParam) [] @@ -100,7 +100,7 @@ type ACK() = val mutable logary: LogaryValue member x.LogaryConfigs() = - [ "single_nodelay"; "batch_delay" ] + [ "single_nodelay";"batch_delay" ] |> Seq.map (LogaryValue >> LogaryParam >> toParam) [] @@ -114,13 +114,14 @@ type Simple() = val mutable logary: LogaryValue member x.LogaryConfigs() = - [ "single_nodelay"; "batch_delay" ] + [ "single_nodelay";"batch_delay" ] |> Seq.map (LogaryValue >> LogaryParam >> toParam) [] member x.simp() = x.logary.logger.logSimple (TestData.multiGaugeMessage Warn) + module Tests = open BenchmarkDotNet.Diagnosers open BenchmarkDotNet.Exporters.Csv @@ -134,9 +135,9 @@ module Tests = let config xJ = { benchmarkConfig with exporters = - [ new CsvExporter(CsvSeparator.Comma) - new Exporters.HtmlExporter() - new Exporters.RPlotExporter() + [ new BenchmarkDotNet.Exporters.Csv.CsvExporter(CsvSeparator.Comma) + new BenchmarkDotNet.Exporters.HtmlExporter() + new BenchmarkDotNet.Exporters.RPlotExporter() ] diagnosers = [ new MemoryDiagnoser() ] @@ -146,20 +147,17 @@ module Tests = testList "benchmarks" [ test "backpressure" { let cfg = config (Job(Job.Core, baseJob)) - let summary: Summary = benchmark cfg (id >> box) |> unbox - () + benchmark cfg box |> ignore } test "simple" { let cfg = config (Job(Job.Core, baseJob)) - let summary: Summary = benchmark cfg (id >> box) |> unbox - () + benchmark cfg box |> ignore } test "ack" { - let cfg = config (Job(Job.Core, baseJob)) - let summary: Summary = benchmark cfg (id >> box) |> unbox - () + let cfg = config (Job(Job.Core, smallInvocationJob)) + benchmark cfg box |> ignore } ] diff --git a/src/Logary.Tests/Engine.fs b/src/Logary.Tests/Engine.fs index 93e6b3c8d..85d575b77 100644 --- a/src/Logary.Tests/Engine.fs +++ b/src/Logary.Tests/Engine.fs @@ -78,6 +78,31 @@ let run pipe (targets:ResizeArray) = let tests = [ testList "processing builder" [ + testCaseJob "pipe compose" (job { + let processing = + Events.compose [ + Events.events + |> Events.minLevel Fatal + |> Events.sink ["1"] + + Events.events + |> Events.minLevel Warn + |> Events.sink ["2"] + ] + + let! targets = [mockTarget "1"; mockTarget "2"; ] |> Job.seqCollect + let! sendMsg, ctss = run processing targets + let msgToSend = Message.event Error "error message" + do! sendMsg msgToSend + + let! msgsFromEachTarget = targets |> Seq.Con.mapJob (fun t -> t.getMsgs ()) + let (msgs1,msgs2) = (msgsFromEachTarget.[0],msgsFromEachTarget.[1]) + + Expect.equal (List.length msgs1) 0 "should have 0 message in target 1" + Expect.equal (List.length msgs2) 1 "should have 1 message in target 2" + }) + + ptestCaseJob "message routing" (job { // context @@ -85,7 +110,7 @@ let tests = Events.compose [ Events.events |> Events.service "svc1" - |> Pipe.counter (fun _ -> 1L) (TimeSpan.FromMilliseconds 100.) + |> Pipe.counter (fun _ -> 1L) (Duration.FromMilliseconds 100.) |> Pipe.map (fun counted -> Message.event Info (sprintf "counter result is %i within 100 ms" counted)) |> Events.sink ["1"] @@ -97,7 +122,7 @@ let tests = Events.events |> Events.minLevel Warn |> Events.sink ["3"] Events.events - |> Pipe.bufferTime (TimeSpan.FromMilliseconds 200.) + |> Pipe.bufferTime (Duration.FromMilliseconds 200.) |> Pipe.map (fun msgs -> Message.event Info (sprintf "there are %i msgs on every 200 milliseconds" (Seq.length msgs))) |> Events.sink ["4"] @@ -196,12 +221,12 @@ let tests = let processing = Events.compose [ Events.events - |> Pipe.tickTimer pingOk (TimeSpan.FromSeconds 1.) // check health every 1 seconds + |> Pipe.tickTimer pingOk (Duration.FromSeconds 1.) // check health every 1 seconds |> Pipe.filter (fun msg -> msg.level >= Warn) |> Events.sink ["TargetForUnhealthySvc"] // report unhealthy info into some target Events.events - |> Pipe.withTickJob (pingFailed.TickEvery (TimeSpan.FromSeconds 1.)) + |> Pipe.withTickJob (pingFailed.TickEvery (Duration.FromSeconds 1.)) |> Pipe.tick pingFailed |> Pipe.filter (fun msg -> msg.level >= Warn) |> Events.sink ["TargetForUnhealthySvc"] diff --git a/src/Logary.Tests/Formatting.fs b/src/Logary.Tests/Formatting.fs index 170ed96a9..c7e938fd8 100644 --- a/src/Logary.Tests/Formatting.fs +++ b/src/Logary.Tests/Formatting.fs @@ -423,22 +423,23 @@ let textPrinters = ProjectionTestExcept { user => User { - name => "whatever" - id => 999 created => DateTime { - Year => 2017 - TimeOfDay => 00:00:00 - Ticks => 636459552000000000 - Second => 0 - Month => 11 - Minute => 0 - Millisecond => 0 - Kind => "Unspecified" - Hour => 0 - DayOfYear => 315 + Day => 11 DayOfWeek => "Saturday" - Day => 11}}}""" + DayOfYear => 315 + Hour => 0 + Kind => "Unspecified" + Millisecond => 0 + Minute => 0 + Month => 11 + Second => 0 + Ticks => 636459552000000000 + TimeOfDay => 00:00:00 + Year => 2017} + id => 999 + name => "whatever"}} +""" let except = <@@ Destructure.except(fun t -> [|t.user.created.Date|]) @@> let invalid = <@@ 1 + 1 @@> Logary.Configuration.Config.projection except diff --git a/src/Logary.Tests/FsMessageTemplates.fs b/src/Logary.Tests/FsMessageTemplates.fs index cc6bcf4d3..4cf7e6231 100644 --- a/src/Logary.Tests/FsMessageTemplates.fs +++ b/src/Logary.Tests/FsMessageTemplates.fs @@ -78,23 +78,23 @@ let messageTemplates = testCase "a class instance is rendered in simple notation" <| fun () -> MtAssert.RenderedAs( "I sat at {@Chair}", [|Chair()|], - """I sat at Chair { Legs: [1, 2, 3, 4], Back: "straight" }""") + """I sat at Chair { Back: "straight", Legs: [1, 2, 3, 4] }""") testCase "a class instance is rendered in simple notation using format provider" <| fun () -> MtAssert.RenderedAs( "I received {@Receipt}", [|Receipt()|], - "I received Receipt { When: 20/05/2013 16:39:00, Sum: 12,345 }", + "I received Receipt { Sum: 12,345, When: 20/05/2013 16:39:00 }", provider=CultureInfo("fr-FR")) testCase "a F# record object is rendered in simple notation with type" <| fun () -> MtAssert.RenderedAs( "I sat at {@Chair}", [|{ Back="straight"; Legs=[|1;2;3;4|] }|], - """I sat at ChairRecord { Legs: [1, 2, 3, 4], Back: "straight" }""") + """I sat at ChairRecord { Back: "straight", Legs: [1, 2, 3, 4] }""") testCase "a F# record object is rendered in simple notation with type using format provider" <| fun () -> MtAssert.RenderedAs( "I received {@Receipt}", [| { Sum=12.345; When=DateTime(2013, 5, 20, 16, 39, 0) } |], - "I received ReceiptRecord { When: 20/05/2013 16:39:00, Sum: 12,345 }", + "I received ReceiptRecord { Sum: 12,345, When: 20/05/2013 16:39:00 }", provider=(CultureInfo("fr-FR"))) testCase "an object with default destructuring is rendered as a string literal" <| fun () -> @@ -174,22 +174,9 @@ let messageTemplates = let values: obj[] = [| Cust() |] yield [| "C#"; values; "cus #{$cust:0,0}, pleasure to see you"; "cus #\"1234\", pleasure to see you" |] yield [| "F#"; values; "cus #{$cust:0,0}, pleasure to see you"; "cus #\"1234\", pleasure to see you" |] - } + yield [| "C#"; values; "cus #{@cust,80:0,0}, pleasure to see you"; """cus # Cust { Number: 1234, Seat: Chair { Back: "straight", Legs: [1, 2, 3, 4] } }, pleasure to see you""" |] + yield [| "F#"; values; "cus #{@cust,80:0,0}, pleasure to see you"; """cus # Cust { Number: 1234, Seat: Chair { Back: "straight", Legs: [1, 2, 3, 4] } }, pleasure to see you""" |] - for i, objs in ``get alignment structure values`` () |> Seq.mapi (fun i x -> i, x) do - yield testCase (sprintf "%i: %s" i (objs.[2] :?> string)) <| fun () -> - MtAssert.RenderedAs(downcast objs.[2], downcast objs.[1], downcast objs.[3]) - ] - - ptestList "alignment skipped" [ - // move these into the non-skipped tests when https://github.com/logary/logary/issues/294 is fixed. - let ``get alignment structure values`` (): obj[] seq = - seq { - let values: obj[] = [| Cust() |] - // formats/alignments don't propagate through to the 'destructured' inside values - // They only apply to the outer (fully rendered) property text - yield [| "C#"; values; "cus #{@cust,80:0,0}, pleasure to see you"; "cus # Cust { Seat: Chair { Back: \"straight\", Legs: [1, 2, 3, 4] }, Number: 1234 }, pleasure to see you" |] - yield [| "F#"; values; "cus #{@cust,80:0,0}, pleasure to see you"; "cus # Cust { Seat: Chair { Back: \"straight\", Legs: [1, 2, 3, 4] }, Number: 1234 }, pleasure to see you" |] } for i, objs in ``get alignment structure values`` () |> Seq.mapi (fun i x -> i, x) do @@ -207,7 +194,7 @@ let messageTemplates = let template = "I like {@item1} and {@item2}" let values: obj[] = [| ChairItem({ Back="straight"; Legs=[|1;2;3;4|] }) ReceiptItem({ Sum=12.345; When=DateTime(2013, 5, 20, 16, 39, 0) }) |] - let expected = """I like ("ChairItem": ChairRecord { Legs: [1, 2, 3, 4], Back: "straight" }) and ("ReceiptItem": ReceiptRecord { When: 20/05/2013 16:39:00, Sum: 12,345 })""" + let expected = """I like ("ChairItem": ChairRecord { Back: "straight", Legs: [1, 2, 3, 4] }) and ("ReceiptItem": ReceiptRecord { Sum: 12,345, When: 20/05/2013 16:39:00 })""" MtAssert.RenderedAs( template, values, expected, provider) @@ -231,7 +218,7 @@ let messageTemplates = // Render fields deeper than level 2 with 'null' values // In this case, only The Trunk.Item3 (Tree list) is after level 2 - let expected = """I like ("Leaf": 12,345) and ("Leaf": 12,345) and ("Trunk": [12,345, 20/05/2013 16:39:00 +09:30, [("Leaf": 12,345), ("Leaf": 12,345)]]) and ("ChairItem": ChairRecord { Legs: [1, 2, 3, 4, 5], Back: "slanted" })""" + let expected = """I like ("Leaf": 12,345) and ("Leaf": 12,345) and ("Trunk": [12,345, 20/05/2013 16:39:00 +09:30, [("Leaf": 12,345), ("Leaf": 12,345)]]) and ("ChairItem": ChairRecord { Back: "slanted", Legs: [1, 2, 3, 4, 5] })""" MtAssert.RenderedAs( template, values, expected, provider, maxDepth=2) diff --git a/src/Logary.Tests/Registry.fs b/src/Logary.Tests/Registry.fs index 4c8061a09..c99069989 100644 --- a/src/Logary.Tests/Registry.fs +++ b/src/Logary.Tests/Registry.fs @@ -95,7 +95,7 @@ let tests = [ } testCaseJob "log with span" (job { - let! logm, out, _ = Utils.buildLogManagerWith (fun conf -> conf |> Config.middleware (Middleware.ambientSpanId ())) + let! logm, out, _ = Utils.buildLogManagerWith (fun conf -> conf |> Config.middleware Middleware.ambientSpanId) let checkSpanId spanId = job { do! logm.flushPending () diff --git a/src/Logary.Tests/Utils.fs b/src/Logary.Tests/Utils.fs index 52701c85c..3b581d744 100644 --- a/src/Logary.Tests/Utils.fs +++ b/src/Logary.Tests/Utils.fs @@ -169,7 +169,7 @@ let logMsgWaitAndShutdown (targetApi: Target.T) (logCallBack: (Message -> Job do! logger.infoWithBP (Logging.Message.eventX (sprintf "Waiting for Target(%s) to ACK message" targetApi.name)) @@ -233,7 +233,7 @@ module Expect = while cont do linea <- trim (sra.ReadLine()) linee <- trim (sre.ReadLine()) - linea |> Expect.equal "Should equal the expected line" linee + linea |> Expect.equal message linee cont <- not (isNull linea || isNull linee) open System.Text diff --git a/src/Logary/CSharp.fs b/src/Logary/CSharp.fs index ead6b17a9..eb9772fdd 100644 --- a/src/Logary/CSharp.fs +++ b/src/Logary/CSharp.fs @@ -603,7 +603,7 @@ type LoggerEx = : Task = let ct = CancellationToken.None // if isNull ct then CancellationToken.None else ct let msgFac = fun _ -> Message.eventFormat (level, formatTemplate, args) - let call = Logger.log logger level msgFac + let call = logger.logWithBP level msgFac upcast Alt.toTask ct call [] @@ -622,7 +622,7 @@ type LoggerEx = gaugeWithUnit logger.name measurement (Gauge (Float value, units)) |> setFieldsFromObject fields - Alt.toTask ct (Logger.log logger Debug (fun _ -> message)) + Alt.toTask ct (logger.log Debug (fun _ -> message)) // corresponds to: logSimple diff --git a/src/Logary/Configuration/Config.fs b/src/Logary/Configuration/Config.fs index 11fba15df..81dc35799 100644 --- a/src/Logary/Configuration/Config.fs +++ b/src/Logary/Configuration/Config.fs @@ -11,6 +11,7 @@ open Logary.Targets open Logary.Configuration open Logary.MessageTemplates.Destructure open Logary.Formatting +open NodaTime /// Specifies the internal logger targets for Logary. [] @@ -31,7 +32,9 @@ module Config = middleware: Middleware list processing: Processing setGlobals: bool - loggerLevels : (string * LogLevel) list + loggerLevels: (string * LogLevel) list + logResultHandler: ProcessResult -> unit + defaultWaitForBuffersTimeout: Duration } let create service host = @@ -45,6 +48,8 @@ module Config = setGlobals = true processing = Events.events loggerLevels = [(".*", LogLevel.Info)] + logResultHandler = function | Result.Error error -> System.Console.Error.Write (MessageWriter.singleLineNoContext.format error) | _ -> () + defaultWaitForBuffersTimeout = Duration.FromSeconds 3L } let target tconf lconf = @@ -84,6 +89,9 @@ module Config = let loggerMinLevel path minLevel lconf = { lconf with loggerLevels = (path, minLevel) :: lconf.loggerLevels } + let logResultHandler handler lconf = + { lconf with logResultHandler = handler } + let disableGlobals lconf = { lconf with setGlobals = false } @@ -136,6 +144,8 @@ module Config = member x.middleware = middleware member x.processing = lconf.processing member x.loggerLevels = lconf.loggerLevels + member x.logResultHandler = lconf.logResultHandler + member x.defaultWaitForBuffersTimeout = lconf.defaultWaitForBuffersTimeout } Registry.create conf >>- fun registry -> @@ -148,9 +158,11 @@ module Config = // TO CONSIDER: config below around registry, instead of as globals + /// use this to choose which properties you want or not to show on message formatting let projection projectionExpr = Logary.Internals.Global.Destructure.configProjection projectionExpr + /// use this to customise how to destructure type let destructurer<'t> (factory: CustomDestructureFactory<'t>) = Logary.Internals.Global.Destructure.configDestructure<'t> factory diff --git a/src/Logary/Configuration/Events.fs b/src/Logary/Configuration/Events.fs index efab2d27b..7255c2f45 100644 --- a/src/Logary/Configuration/Events.fs +++ b/src/Logary/Configuration/Events.fs @@ -21,7 +21,7 @@ module Events = let minLevel level pipe = pipe |> Pipe.filter (fun msg -> msg.level >= level) - /// if msg with no specific sinks, will send to all targets + /// if msg with no specific sinks, it will send to all targets let sink (names: string list) pipe = pipe |> Pipe.map (Message.addSinks names) @@ -31,23 +31,33 @@ module Events = fun (msgs: #seq<_>) -> HasResult << Alt.prepareJob <| fun () -> + let putAllPromises = IVar () + msgs - |> Seq.Con.mapJob (fun msg -> next msg |> PipeResult.orDefault LogResult.rejected) - |> Job.map (fun results -> Result.sequence (results.ToArray())) - |> Job.map (function - | Ok _ -> - LogResult.success - | Result.Error [] -> - failwithf "No results for %A" (List.ofSeq msgs) - | Result.Error (e :: _) -> - Alt.always (Result.Error e)) - ) + |> Seq.Con.mapJob (fun msg -> next msg |> PipeResult.orDefault LogResult.success) + >>= IVar.fill putAllPromises + |> Job.start + >>-. putAllPromises ^-> ProcessResult.reduce + ) + /// compose here means dispatch each event/message to all pipes, not chains them. let compose pipes = - let build cont = - let composed = - pipes |> List.fold (fun k pipe -> pipe.build k) cont - - fun sourceItem -> composed sourceItem - - { build = build; tickTimerJobs = List.collect (fun pipe -> pipe.tickTimerJobs) pipes } \ No newline at end of file + let allTickTimerJobs = List.collect (fun pipe -> pipe.tickTimerJobs) pipes + + let build = + fun cont -> + let allBuildedSource = pipes |> List.map (fun pipe -> pipe.build cont) + fun sourceItem -> + HasResult << Alt.prepareJob <| fun () -> + let alllogedAcks = IVar () + + allBuildedSource + |> Hopac.Extensions.Seq.Con.mapJob (fun logWithAck -> + logWithAck sourceItem |> PipeResult.orDefault (LogResult.success)) + >>= IVar.fill alllogedAcks + |> Job.start + >>-. alllogedAcks ^-> ProcessResult.reduce + + { build = build + tickTimerJobs = allTickTimerJobs + } \ No newline at end of file diff --git a/src/Logary/Configuration/LogManager.fs b/src/Logary/Configuration/LogManager.fs index 5a325039c..f63540197 100644 --- a/src/Logary/Configuration/LogManager.fs +++ b/src/Logary/Configuration/LogManager.fs @@ -34,6 +34,7 @@ type LogManager = /// the name of the class. Also have a look at Logging.GetCurrentLogger(). abstract getLogger: PointName -> Logger + /// middleware for individual loggers (compose at call-site) abstract getLoggerWithMiddleware: PointName -> Middleware -> Logger /// Awaits that all targets finish responding to a flush message diff --git a/src/Logary/Configuration/Pipe.fs b/src/Logary/Configuration/Pipe.fs index dab811738..9f94e4c03 100644 --- a/src/Logary/Configuration/Pipe.fs +++ b/src/Logary/Configuration/Pipe.fs @@ -4,6 +4,7 @@ open System open Hopac open Hopac.Infixes open Logary.Configuration.Transformers +open NodaTime [] type PipeResult<'a> = @@ -35,9 +36,9 @@ module PipeResult = let iter f x = match x with | HasResult x -> f x | _ -> () -/// 'contInput means continuation function input -/// 'contRes means continuation function output -/// 'sourceItem means pipe source element +/// 'contInput means continuation function input. +/// 'contRes means continuation function output. +/// 'sourceItem means pipe source element. /// when we have a pipe, we can pass a continuation to it, /// and then we can pipe source item to its builded processing [] @@ -112,7 +113,7 @@ module Pipe = with | e -> // todo: handle exception - eprintfn "%A" e + eprintfn "%O" e upcast (loop state) updateMb ^=> (ticker.Folder state >> loop) @@ -131,9 +132,9 @@ module Pipe = Mailbox.Now.send updateMb prev NoResult) - let tickTimer (ticker: Ticker<_,_,_>) (timespan: TimeSpan) pipe = + let tickTimer (ticker: Ticker<_,_,_>) (duration: Duration) pipe = pipe - |> withTickJob (ticker.TickEvery timespan) + |> withTickJob (ticker.TickEvery duration) |> tick ticker let buffer n pipe = @@ -149,9 +150,9 @@ module Pipe = else NoResult) - let bufferTime timespan pipe = + let bufferTime duration pipe = let ticker = BufferTicker () - pipe |> tickTimer ticker timespan + pipe |> tickTimer ticker duration /// maybe use ArraySegment instead let slidingWindow size pipe = @@ -178,10 +179,10 @@ module Pipe = // window.[slidingLen] <- prev // cont window) - let counter (mapping: _ -> int64) timespan pipe = + let counter (mapping: _ -> int64) duration pipe = pipe |> map mapping - |> bufferTime timespan + |> bufferTime duration |> map (Seq.sum) let percentile (mapping: _ -> int64 array) quantile pipe = diff --git a/src/Logary/Configuration/Ticker.fs b/src/Logary/Configuration/Ticker.fs index d7dc1f05c..23efebf97 100644 --- a/src/Logary/Configuration/Ticker.fs +++ b/src/Logary/Configuration/Ticker.fs @@ -3,6 +3,8 @@ namespace Logary.Configuration open Hopac open Hopac.Infixes open Logary.Configuration.Transformers +open NodaTime +open Logary type Cancellation = internal { cancelled: IVar } @@ -28,11 +30,11 @@ type Ticker<'state,'t,'r> (initialState:'state) = member this.Ticked = tickCh :> Alt<_> member this.Tick () = tickCh *<- () - member this.TickEvery timespan = + member this.TickEvery (duration: Duration) = let cancellation = Cancellation.create () let rec loop () = Alt.choose [ - timeOut timespan ^=> fun _ -> + timeOut (duration.toTimeSpanSafe()) ^=> fun _ -> this.Tick () ^=> fun _ -> loop () diff --git a/src/Logary/Configuration/Uri.fs b/src/Logary/Configuration/Uri.fs index 3528f15ee..c46e6669b 100644 --- a/src/Logary/Configuration/Uri.fs +++ b/src/Logary/Configuration/Uri.fs @@ -177,7 +177,7 @@ module TargetConfig = failwithf "Module '%s' did not have 'create' \"(name: string) -> (conf: 'conf) -> TargetConf\" function. This should be fixed in the target's code (with [] on itself)." x.moduleName -// printfn "Invoking create on '%O'" createMethod + //printfn "Invoking create on '%O'" createMethod createMethod.Invoke(null, [| conf; name |]) :?> TargetConf diff --git a/src/Logary/Constants.fs b/src/Logary/Constants.fs index 069a2290d..d3bee0d7f 100644 --- a/src/Logary/Constants.fs +++ b/src/Logary/Constants.fs @@ -42,6 +42,9 @@ module KnownLiterals = [] let WaitForBuffers = LogaryPrefix + "waitForBuffers" + [] + let WaitForBuffersTimeout = LogaryPrefix + "waitForBuffersTimeout" + [] let SpanIdContextName = LogaryPrefix + "spanId" diff --git a/src/Logary/DataModel.fs b/src/Logary/DataModel.fs index 4114fb7b5..1f484d744 100644 --- a/src/Logary/DataModel.fs +++ b/src/Logary/DataModel.fs @@ -275,25 +275,19 @@ and SpanInfo = static member formatId (id: Guid) = id.ToString("n") -/// Why was the message/metric/event not logged? +/// describe the time scope info about a span, will be sent as a message's context data [] -type LogError = - /// The buffer of the target was full, so the message was not logged. - | BufferFull of target:string - /// The target, or the processing step before the targets, rejected the message. - | Rejected - - static member wasRejected (e: LogError) = - match e with - | Rejected -> true - | _ -> false - - static member bufferWasFull (e: LogError) = - match e with - | BufferFull _ -> true - | _ -> false - -type internal LogResult = Alt, LogError>> +type SpanLog = + { traceId: string + spanId: string + parentSpanId: string + beginAt: int64 // number of ticks since the Unix epoch. Negative values represent instants before the Unix epoch. (from NodaTime) + endAt: int64 // number of ticks since the Unix epoch. Negative values represent instants before the Unix epoch. (from NodaTime) + duration: int64 // total number of ticks in the duration as a 64-bit integer. (from NodaTime) + } + +type internal ProcessResult = Result, Message> +type internal LogResult = Alt /// See the docs on the funtions for descriptions on how Ack works in conjunction /// with the promise. @@ -302,12 +296,14 @@ type Logger = /// `Messages` produced from this instance. abstract name: PointName - /// - `waitForBuffers`: This causes the logger/caller to block on the RingBuffer being - /// available to take the message. Giving a true here may cause the + /// Returns an Alt that commits on ALL N Targets' buffers accepting the message. + /// Even if the Alt was not committed to, one or more targets (fewer than N) may have accepted the message. + /// And this can not be canceled. + /// + /// - `waitForBuffers`: `true` means waiting for each target buffer to be available to take the message. + /// `false` means it will try to detect whether the buffer is full and return immediately. abstract logWithAck: waitForBuffers:bool * level:LogLevel -> messageFactory:(LogLevel -> Message) -> LogResult - //abstract log: Message -> Alt, unit>> - /// Gets the currently set log level (minimal,inclusive), /// aka. the granularity with which things are being logged. abstract level: LogLevel @@ -320,6 +316,7 @@ type internal LoggerWrapper(logger: Logger) = default x.level = logger.level default x.logWithAck (waitForBuffers, logLevel) messageFactory = logger.logWithAck (waitForBuffers, logLevel) messageFactory + interface Logger with member x.name = x.name member x.level = x.level diff --git a/src/Logary/Extensions/NodaTime.Duration.fs b/src/Logary/Extensions/NodaTime.Duration.fs index 9ed5cd140..cb97f647a 100644 --- a/src/Logary/Extensions/NodaTime.Duration.fs +++ b/src/Logary/Extensions/NodaTime.Duration.fs @@ -3,12 +3,19 @@ namespace Logary open NodaTime open System open System.Runtime.CompilerServices -open Logary [] module DurationEx = + let timeSpanMaxDuration = Duration.FromTimeSpan(TimeSpan.MaxValue) + let timeSpanMinDuration = Duration.FromTimeSpan(TimeSpan.MinValue) type Duration with [] member dur.toGauge () = Gauge (BigInt (dur.ToBigIntegerNanoseconds()), Scaled (Seconds, float Constants.NanosPerSecond)) + + [] + member dur.toTimeSpanSafe() = + if dur < timeSpanMinDuration then TimeSpan.MinValue + elif dur > timeSpanMaxDuration then TimeSpan.MaxValue + else dur.ToTimeSpan() diff --git a/src/Logary/Formatting/Literate.fs b/src/Logary/Formatting/Literate.fs index ceed8f545..061967106 100644 --- a/src/Logary/Formatting/Literate.fs +++ b/src/Logary/Formatting/Literate.fs @@ -34,31 +34,33 @@ module Literate = /// the lines (outer list), each consisting of a string and a literate token specifying how that string is to be /// formatted. let rec private tokeniseException (e: exn): seq<(string * LiterateToken) list> = - // each inner list represents a written/outputted text line - seq { - yield printLine (ExnType (e.GetType().FullName, e.Message)) - yield! DotNetStacktrace.parse e.StackTrace |> Seq.map printLine - match e with - | :? AggregateException as ae when not (isNull ae.InnerExceptions) && ae.InnerExceptions.Count > 1 -> - let mutable i = 0 - for e in ae.InnerExceptions do - i <- i + 1 - let firstLine, remainder = tokeniseException e |> Seq.headTail + if isNull e then Seq.empty + else + // each inner list represents a written/outputted text line + seq { + yield printLine (ExnType (e.GetType().FullName, e.Message)) + yield! DotNetStacktrace.parse e.StackTrace |> Seq.map printLine + match e with + | :? AggregateException as ae when not (isNull ae.InnerExceptions) && ae.InnerExceptions.Count > 1 -> + let mutable i = 0 + for e in ae.InnerExceptions do + i <- i + 1 + let firstLine, remainder = tokeniseException e |> Seq.headTail + yield printLine StacktraceDelim + yield [ + yield sprintf "Inner exn#", Subtext + yield string i, NumericSymbol + yield sprintf " ", Punctuation + yield! firstLine + ] + yield! remainder + + | _ when not (isNull e.InnerException) -> yield printLine StacktraceDelim - yield [ - yield sprintf "Inner exn#", Subtext - yield string i, NumericSymbol - yield sprintf " ", Punctuation - yield! firstLine - ] - yield! remainder - - | _ when not (isNull e.InnerException) -> - yield printLine StacktraceDelim - yield! tokeniseException e.InnerException - | _ -> - () - } + yield! tokeniseException e.InnerException + | _ -> + () + } let tokeniseExceptions (pvd: IFormatProvider) (nl: string) (m: Message) = let exceptions = diff --git a/src/Logary/Formatting/MessageTemplates.fs b/src/Logary/Formatting/MessageTemplates.fs index 2c4487e19..bddaca7b1 100644 --- a/src/Logary/Formatting/MessageTemplates.fs +++ b/src/Logary/Formatting/MessageTemplates.fs @@ -396,7 +396,7 @@ module MessageTemplates = let nvs = ty.GetProperties(lookupPropFlags) |> Array.filter (fun p -> not <| isNull p && (isInclude p.Name)) - |> Array.sortBy (fun p -> p.Name) + |> Array.sortByDescending (fun p -> p.Name) |> Array.fold (fun nvs p -> let name = p.Name match tryGetValueWithProp p instance with @@ -662,20 +662,30 @@ module MessageTemplates = } let tokeniseProperty (writeState: WriteState) (pt: Property) (pv: TemplatePropertyValue) = - match pv with - | ScalarValue sv -> - let tokenised = tokeniseScalarValue writeState.provider sv pt.format - - if pt.align.isEmpty then tokenised |> Seq.singleton - else - let (formated, token) = tokenised - let padded = + let tokenised = + match pv with + | ScalarValue sv -> tokeniseScalarValue writeState.provider sv pt.format |> Seq.singleton + | _ -> tokenisePropValueCompact writeState pv null + + if pt.align.isEmpty then tokenised + else + let sb = System.Text.StringBuilder () + tokenised |> Seq.map fst |> Seq.iter (sb.Append >> ignore) + let allFormatedTextWithoutAlign = sb.ToString () + if pt.align.width > allFormatedTextWithoutAlign.Length then + let pads = pt.align.width - allFormatedTextWithoutAlign.Length + seq { match pt.align.direction with - | AlignDirection.Right -> formated.PadLeft(pt.align.width, ' ') - | AlignDirection.Left -> formated.PadRight(pt.align.width, ' ') - | _ -> formated - (padded, token) |> Seq.singleton - | _ -> tokenisePropValueCompact writeState pv null + | AlignDirection.Right -> + yield! (" ", Subtext) |> Seq.replicate pads + yield! tokenised + | AlignDirection.Left -> + yield! tokenised + yield! (" ", Subtext) |> Seq.replicate pads + | _ -> yield! tokenised + } + else tokenised + let tokeniseTemplate (pvd: IFormatProvider) (t: Template) tryGetPropertyValue = t.tokens diff --git a/src/Logary/Global.fs b/src/Logary/Global.fs index a63116ffa..aebcf59b2 100644 --- a/src/Logary/Global.fs +++ b/src/Logary/Global.fs @@ -73,8 +73,8 @@ module internal Global = member x.level = withLogger (fun logger -> logger.level) - member x.logWithAck (waitForBuffers, level) msgFactory = - withLogger (fun logger -> logger.logWithAck (waitForBuffers, level) (msgFactory >> ensureName)) + member x.logWithAck (putBufferTimeOut, level) msgFactory = + withLogger (fun logger -> logger.logWithAck (putBufferTimeOut, level) (msgFactory >> ensureName)) /// Call to initialise Logary with a new Logary instance. let initialise cfg = @@ -210,6 +210,29 @@ module internal Global = StructureValue (refId, typeTag, nvs)) + configDestructure(fun resolver req -> ScalarValue req.Value) + + configDestructure(fun resolver req -> + let spanLog = req.Value + let refCount = req.IdManager + match refCount.TryShowAsRefId req with + | _, Some pv -> pv + | refId, None -> + let typeTag = typeof.Name + let nvs = [ + if not <| isNull spanLog.traceId then + yield { Name = "TraceId"; Value = ScalarValue spanLog.traceId } + if not <| isNull spanLog.parentSpanId then + yield { Name = "ParentSpanId"; Value = ScalarValue spanLog.parentSpanId } + if not <| isNull spanLog.spanId then + yield { Name = "SpanId"; Value = ScalarValue spanLog.spanId } + yield { Name = "BeginAt"; Value = ScalarValue (Instant.FromUnixTimeTicks(spanLog.beginAt)) } + yield { Name = "EndAt"; Value = ScalarValue (Instant.FromUnixTimeTicks(spanLog.endAt)) } + yield { Name = "Duration"; Value = ScalarValue (Duration.FromTicks(spanLog.duration)) } + ] + + StructureValue (refId, typeTag, nvs)) + { new ICustomDestructureRegistry with member __.TryGetRegistration (runtimeType: Type) = diff --git a/src/Logary/Internals/InternalLogger.fs b/src/Logary/Internals/InternalLogger.fs index 85aa9458f..58fc0eaa1 100644 --- a/src/Logary/Internals/InternalLogger.fs +++ b/src/Logary/Internals/InternalLogger.fs @@ -16,7 +16,7 @@ module internal InternalLogger = private { addCh: Ch shutdownCh: Ch - messageCh: Ch * Ch, LogError>>> + messageCh: Ch * Ch> } with member x.name = PointName [| "Logary" |] @@ -29,6 +29,7 @@ module internal InternalLogger = match messageFactory logLevel with | msg when msg.name.isEmpty -> { msg with name = x.name } | msg -> msg + |> Message.setContext KnownLiterals.WaitForBuffers waitForBuffers message, nack, replCh @@ -55,10 +56,12 @@ module internal InternalLogger = messageCh ^=> fun (message, nack, replCh) -> let forwardToTarget = - if message.context |> HashMap.containsKey KnownLiterals.WaitForBuffers then - Target.logAllReduce targets message ^=> Ch.give replCh - else - Target.tryLogAllReduce targets message ^=> Ch.give replCh + let putBufferTimeOut = message |> Message.tryGetContext KnownLiterals.WaitForBuffersTimeout |> Option.defaultValue NodaTime.Duration.Zero + let putBufferTimeOut = + message |> Message.tryGetContext KnownLiterals.WaitForBuffers + |> Option.defaultValue false // non blocking waiting default + |> function | true -> putBufferTimeOut | false -> NodaTime.Duration.Zero + Target.logAllReduce putBufferTimeOut targets message ^=> Ch.give replCh (forwardToTarget <|> nack) ^=> fun () -> iserver targets diff --git a/src/Logary/Internals/Misc.fs b/src/Logary/Internals/Misc.fs index 6287fc7ac..4f90fe3e4 100644 --- a/src/Logary/Internals/Misc.fs +++ b/src/Logary/Internals/Misc.fs @@ -35,13 +35,6 @@ module internal Result = (rs, Ok []) ||> Array.foldBack folder -[] -module internal LogResult = - open Hopac - let success: Alt, LogError>> = Alt.always (Result.Ok Promise.unit) - let bufferFull target: Alt, LogError>> = Alt.always (Result.Error (BufferFull target)) - let rejected: Alt, LogError>> = Alt.always (Result.Error Rejected) - module internal Seq = /// Get the head and the tail of the sequence, throwing if the sequence contains no elements. let headTail (xs: #seq<_>): 't * seq<'t> = diff --git a/src/Logary/Internals/NullLogger.fs b/src/Logary/Internals/NullLogger.fs index 03af4e33f..adad07b9f 100644 --- a/src/Logary/Internals/NullLogger.fs +++ b/src/Logary/Internals/NullLogger.fs @@ -7,8 +7,10 @@ open Logary /// that is actually *the* internal logger target, to avoid recursive calls to /// itself. type private NullLogger() = + static let success = Alt.always (Result.Ok Promise.unit) + interface Logger with - member x.logWithAck (_, _) _ = LogResult.success + member x.logWithAck (_, _) _ = success member x.level = LogLevel.Fatal member x.name = PointName.ofList [ "Logary"; "NullLogger" ] diff --git a/src/Logary/Internals/Reflection.fs b/src/Logary/Internals/Reflection.fs index c0b978cbc..bd4308d04 100644 --- a/src/Logary/Internals/Reflection.fs +++ b/src/Logary/Internals/Reflection.fs @@ -2,9 +2,7 @@ namespace Logary.Internals module Reflection = open System - open System.Collections.Concurrent open Logary.Internals.TypeShape.Core - open Logary.Internals.TypeShape.Core.Utils /// Used internally to format the exception message to put in place of properties /// that could not be accessed without exceptions being thrown. @@ -35,9 +33,9 @@ module Reflection = | _ -> fun _ -> Seq.empty - let private propsResolvers = ConcurrentDictionary seq>() + let private prosFromFactoryWithMemorize = Logary.Internals.Cache.memoize propsFromFactory let propsFrom (value: obj): seq = - let valueType = value.GetType() - let resolver = propsResolvers.GetOrAdd(valueType, Func<_, _>(propsFromFactory)) - resolver value + match value with + | null -> Seq.empty + | _ -> prosFromFactoryWithMemorize (value.GetType()) value \ No newline at end of file diff --git a/src/Logary/LogResultModule.fs b/src/Logary/LogResultModule.fs new file mode 100644 index 000000000..483f4b013 --- /dev/null +++ b/src/Logary/LogResultModule.fs @@ -0,0 +1,38 @@ +namespace Logary + +[] +module internal LogResult = + open Hopac + + let success: LogResult = Alt.always (Result.Ok Promise.unit) + let error message : LogResult = Alt.always (Result.Error message) + + let notAcceptedByTarget (targetName: string) = error (Message.eventFormat("not accept by {target}", targetName)) + +module internal LogError = + let targetBufferFull (targetName: string): ProcessResult = Result.Error (Message.eventFormat("{target} 's log buffer is full", targetName)) + + let timeOutToPutBuffer (targetName: string) (waitSeconds: double): ProcessResult = Result.Error (Message.eventFormat("time out: waiting {duration} seconds to putting message on to {target} 's log buffer", waitSeconds, targetName)) + + let clientAbortLogging: ProcessResult = Result.Error (Message.eventFormat("client abort logging")) + + let registryClosed: ProcessResult = Result.Error (Message.eventFormat("registry has been shutdown")) + +[] +module internal ProcessResult = + open Hopac + + let success: ProcessResult = Ok (Promise.unit) + + let reduce (processResults: #seq): ProcessResult = + let errorMsg (errors: Message list) = Message.eventFormat ("some targets processing failed: {errors}", errors) + (([], []), processResults) + ||> Seq.fold (fun (oks, errors) result -> + match result with + | Ok promise -> promise :: oks, errors + | Result.Error error -> oks, error :: errors + ) + |> function + | [], [] -> success + | promises, [] -> promises |> Job.conIgnore |> memo |> Ok + | _, errors -> Result.Error (errorMsg errors) diff --git a/src/Logary/Logary.fsproj b/src/Logary/Logary.fsproj index 91609812c..a2236af80 100644 --- a/src/Logary/Logary.fsproj +++ b/src/Logary/Logary.fsproj @@ -48,8 +48,8 @@ - + @@ -66,6 +66,7 @@ + diff --git a/src/Logary/LoggerModule.fs b/src/Logary/LoggerModule.fs index 60f1b056a..6ef229cc9 100644 --- a/src/Logary/LoggerModule.fs +++ b/src/Logary/LoggerModule.fs @@ -2,61 +2,40 @@ open Hopac open Hopac.Infixes -open System open System.Runtime.CompilerServices -open System.Threading.Tasks open System.Diagnostics open Logary open NodaTime [] module Logger = - /// Log a message, but don't await all targets to flush. Equivalent to logWithBP. - /// Returns whether the message was successfully placed in the buffers. - /// SAFE. - let log (logger: Logger) logLevel messageFactory: Alt = - logger.logWithAck (false, logLevel) messageFactory ^-> function - | Ok _ -> - true - | Result.Error Rejected -> - true - | Result.Error (BufferFull _) -> - false - - let private printDotOnOverflow success = - if not success then System.Console.Error.Write '.' else () - - let logSimple (logger: Logger) msg: unit = - start (log logger msg.level (fun _ -> msg) ^-> printDotOnOverflow) + let defaultBackPressurePutBufferTimeOut = Duration.FromMinutes 1L + /// log message without blocking, and ignore its result. + /// if the buffer is full, drop this message let logWith (logger: Logger) level messageFactory: unit = - start (log logger level messageFactory ^-> printDotOnOverflow) - - let logWithBP (logger: Logger) logLevel messageFactory: Alt = - logger.logWithAck (true, logLevel) messageFactory ^=> function - | Ok _ -> - Job.result () - | Result.Error Rejected -> - Job.result () - | Result.Error (BufferFull target) -> - //Job.raises (exn (sprintf "logWithAck (true, _) should have waited for the RingBuffer(s) to accept the Message. Target(%s)" target)) - Job.result () - - /// Special case: e.g. Fatal messages. + queueIgnore (logger.logWithAck (false, level) messageFactory) + + /// log message without blocking, and ignore its result. + /// if the buffer is full, drop this message + let logSimple (logger: Logger) msg: unit = + logWith logger msg.level (fun _ -> msg) + + /// log message, but don't await all targets to flush. And backpressure the buffers. + /// + /// default `waitForBuffersTimeout` is 1 minutes to back pressure the buffers (not the backend process after target buffer) + let logWithBP (logger: Logger) logLevel messageFactory : Alt = + logger.logWithAck (true, logLevel) (messageFactory >> Message.waitForBuffersTimeout defaultBackPressurePutBufferTimeOut) ^-> ignore + + /// log message, leave the error result handle in registry error handler. + /// when read the return pomise, it will waiting for buffer's backend process flush logs + /// + /// default `waitForBuffersTimeout` is 1 minutes to back pressure the buffers (not the backend process after target buffer) let logAck (logger: Logger) level messageFactory: Promise = - let ack = IVar () - let inner = - logger.logWithAck (true, level) messageFactory ^=> function - | Ok promise -> - Job.start (promise ^=> IVar.fill ack) - | Result.Error Rejected -> - IVar.fill ack () - | Result.Error (BufferFull target) -> - //let e = exn (sprintf "logWithAck (true, _) should have waited for the RingBuffer(s) to accept the Message. Target(%s)" target) - //IVar.fillFailure ack e - IVar.fill ack () - start inner - ack :> Promise<_> + logger.logWithAck (true, level) (messageFactory >> Message.waitForBuffersTimeout defaultBackPressurePutBufferTimeOut) + >>=* function + | Ok promise -> promise + | _ -> Promise.unit let private ensureName name = fun (m: Message) -> @@ -73,8 +52,15 @@ module Logger = [] module LoggerEx = type Logger with + + /// Log a message, but don't await all targets to flush. + /// Returns whether the message was successfully placed in the buffers. + /// + /// if the buffer is full, drop this message, return false member x.log logLevel (messageFactory: LogLevel -> Message): Alt = - Logger.log x logLevel messageFactory + x.logWithAck (false, logLevel) messageFactory ^-> function + | Ok _ -> true + | _ -> false member x.logSimple message: unit = Logger.logSimple x message diff --git a/src/Logary/MessageModule.fs b/src/Logary/MessageModule.fs index aed5525d8..40f594729 100644 --- a/src/Logary/MessageModule.fs +++ b/src/Logary/MessageModule.fs @@ -191,6 +191,11 @@ module Message = let setSpanId (spanId: Guid) (message: Message) = message |> setContext KnownLiterals.SpanIdContextName (SpanInfo.formatId spanId) + /// For users who want to controll timeout in each message when logging `WaitForBuffers = true` + [] + let waitForBuffersTimeout (duration: Duration) (message: Message) = + message |> setContext KnownLiterals.WaitForBuffersTimeout duration + ///////////////// CTORS //////////////////// /// Create a new Message with the passed parameters. Consider using `event` and @@ -488,13 +493,15 @@ module Message = /// Adds a new exception to the "_logary.errors" internal field in the message. [] let addExn (e: exn) msg = - let errors = - match tryGetContext KnownLiterals.ErrorsContextName msg with - | Some errors -> - e :: errors - | _ -> - e :: [] - setContext KnownLiterals.ErrorsContextName errors msg + if isNull e then msg + else + let errors = + match tryGetContext KnownLiterals.ErrorsContextName msg with + | Some errors -> + e :: errors + | _ -> + e :: [] + setContext KnownLiterals.ErrorsContextName errors msg /// Adds new exceptions to the "_logary.errors" internal field in the message. [] diff --git a/src/Logary/MiddlewareModule.fs b/src/Logary/MiddlewareModule.fs index 3607bb77e..d7ef61171 100644 --- a/src/Logary/MiddlewareModule.fs +++ b/src/Logary/MiddlewareModule.fs @@ -57,7 +57,7 @@ module Middleware = |> next [] - let ambientSpanId (): Middleware = + let ambientSpanId: Middleware = fun next msg -> let ambientSpanId = Span.getActiveSpanId () match ambientSpanId with diff --git a/src/Logary/Registry.fs b/src/Logary/Registry.fs index b5ed4bd63..e59f339a7 100644 --- a/src/Logary/Registry.fs +++ b/src/Logary/Registry.fs @@ -9,7 +9,6 @@ open Logary.Message open Logary.Internals open Logary.Configuration open NodaTime -open System open System.Text.RegularExpressions open System.Collections.Concurrent @@ -20,12 +19,16 @@ type LogaryConf = abstract targets: HashMap /// Service metadata - what name etc. abstract runtimeInfo: RuntimeInfo - /// Extra middleware added to every resolved logger. + /// Extra middleware added to every resolved logger. (compose at call-site) abstract middleware: Middleware[] /// Optional stream transformer. abstract processing: Processing /// each logger's min level - abstract loggerLevels : (string * LogLevel) list + abstract loggerLevels: (string * LogLevel) list + /// handler for process log error + abstract logResultHandler: (ProcessResult -> unit) + /// time out duration waiting for each target buffer to be available to take the message, if users choose logging message and waitForBuffers + abstract defaultWaitForBuffersTimeout: Duration /// This is the main state container in Logary. module Registry = @@ -105,12 +108,8 @@ module Registry = let ensureName name (m: Message) = if m.name.isEmpty then { m with name = name } else m - let boxedUnit = box () - let ensureWaitFor waitForBuffers (m: Message) = - if waitForBuffers then - { m with context = m.context |> HashMap.add KnownLiterals.WaitForBuffers boxedUnit } - else - m + let ensureWaitFor timeOut (m: Message) = + m |> Message.setContext KnownLiterals.WaitForBuffers timeOut let inline getLogger (t: T) name mid = let nameStr = name.ToString () @@ -133,7 +132,7 @@ module Registry = member x.logWithAck (waitForBuffers, level) messageFactory = if level >= x.level then // When the registry is shut down, reject the log message. - let rejection = t.isClosed ^->. Result.Error Rejected + let rejection = t.isClosed ^->. LogError.registryClosed let logMessage = Alt.prepareFun <| fun () -> messageFactory level @@ -170,7 +169,7 @@ module Registry = match timeout with | None -> processAlt ^->. (name,true) | Some duration -> - timeOut (duration.ToTimeSpan ()) ^->. (name,false) + timeOut (duration.toTimeSpanSafe()) ^->. (name,false) <|> processAlt ^->. (name,true) @@ -207,11 +206,10 @@ module Registry = && not ("true" = Env.varDefault "LOGARY_I_PROMISE_I_HAVE_PURCHASED_LICENSE" (fun () -> "false")) then failwith "You must purchase a license for Logary to run it on or with IIS or Kestrel." - // Middleware at: - // - LogaryConf (goes on all loggers) (through engine,and compose at call-site) - // - TargetConf (goes on specific target) (composes in engine when sending msg to target) - // - individual loggers (through engine,and compose at call-site) - + // Middlewares at: + // - LogaryConf (goes on all loggers) (compose at call-site) + // - TargetConf (goes on specific target) (composes when creating target,not compose at call-site when sending message) + // - individual loggers (compose at call-site) let create (conf: LogaryConf): Job = Impl.lc () @@ -222,11 +220,13 @@ module Registry = let rlogger = ri.logger |> Logger.apply (setName rname) + // PipeResult.NoResult usually means do some fire-and-forget operation,e.g. push msg on to some buffer/sinks, wating for some condition to trigger next action. + // so we should treat it as the msg has been logged/processed. use `LogResult.success` may be more reasonable. let wrapper sendMsg mid msg = msg |> Middleware.compose (mid |> Option.fold (fun s t -> t :: s) rmid) |> sendMsg - |> PipeResult.orDefault LogResult.rejected + |> PipeResult.orDefault LogResult.success let flushCh, shutdownCh, isClosed = Ch (), Ch (), IVar () @@ -267,7 +267,22 @@ module Registry = if Array.isEmpty targets then NoResult else - msg |> Target.tryLogAllReduce targets |> HasResult) + let putBufferTimeOut = msg |> Message.tryGetContext KnownLiterals.WaitForBuffersTimeout |> Option.defaultValue conf.defaultWaitForBuffersTimeout + let putBufferTimeOut = + msg |> Message.tryGetContext KnownLiterals.WaitForBuffers + |> Option.defaultValue false // non blocking waiting default + |> function | true -> putBufferTimeOut | false -> Duration.Zero + + msg + |> Target.logAllReduce putBufferTimeOut targets + |> Alt.afterFun (fun result -> + try + conf.logResultHandler result + with + | e -> + eprintfn "%O" e + result) + |> HasResult) runningPipe >>= fun (sendMsg, ctss) -> let state = diff --git a/src/Logary/SpanModule.fs b/src/Logary/SpanModule.fs index 09b819e23..350e66838 100644 --- a/src/Logary/SpanModule.fs +++ b/src/Logary/SpanModule.fs @@ -8,18 +8,6 @@ open NodaTime [] module Span = - - /// describe the time scope info about a span, will be sent as a message's context data - [] - type internal SpanLog = - { traceId: string - spanId: string - parentSpanId: string - beginAt: int64 // number of ticks since the Unix epoch. Negative values represent instants before the Unix epoch. (from NodaTime) - endAt: int64 // number of ticks since the Unix epoch. Negative values represent instants before the Unix epoch. (from NodaTime) - duration: int64 // total number of ticks in the duration as a 64-bit integer. (from NodaTime) - } - type private T = { traceId: Guid spanId: Guid @@ -98,7 +86,6 @@ module Span = (t.messageFac >> transform) level |> setContext KnownLiterals.SpanInfoContextName spanLog - |> setSpanId spanInfo.spanId if not hasFired then do hasFired <- true diff --git a/src/Logary/TargetConf.fs b/src/Logary/TargetConf.fs index 250d5c084..2b4036517 100644 --- a/src/Logary/TargetConf.fs +++ b/src/Logary/TargetConf.fs @@ -19,6 +19,7 @@ type TargetConf = /// Supervision policy. Use `Logary.Internals.Policy` to choose. By default, /// uses exponential backup with a maximum delay, retrying forever. policy: Policy + /// (goes on specific target) (composes when creating target, not compose at call-site when sending message) middleware: Middleware list server: TargetAPI -> Job } diff --git a/src/Logary/TargetModule.fs b/src/Logary/TargetModule.fs index e36ac0124..c0b1fbe98 100644 --- a/src/Logary/TargetModule.fs +++ b/src/Logary/TargetModule.fs @@ -1,4 +1,5 @@ namespace Logary +open NodaTime module Target = open System @@ -7,6 +8,7 @@ module Target = open Hopac.Extensions open Logary.Message open Logary.Internals + open NodaTime /// A target instance is a target loop job that can be re-executed on failure, /// and a normal path of communication; the `requests` `RingBuffer` as well as @@ -26,95 +28,47 @@ module Target = member x.accepts message = Rule.accepts message x.rules - /// WARNING: this may cause you headaches; are you sure you don't want to use tryLog? - /// - /// Returns an Alt that commits on the Targets' buffer accepting the message. - let log (x: T) (msg: Message): LogResult = - let msg = x.transform msg - if not (x.accepts msg) then LogResult.rejected - else - let ack = IVar () - let targetMsg = Log (msg, ack) - RingBuffer.put x.api.requests targetMsg ^->. - Ok (upcast ack) - /// If the alternative is committed to, the RingBuffer WILL enqueue the message. The tryLog operation is done as - /// `Ch.give x.tryPut m`. + /// Returns an Alt that commits on the Targets' buffer accepting the message. /// - /// Returns an Alt that commits on the Targets' buffer accepting the message OR the RingBuffer telling the caller that - /// it was full, and returning an Error(BufferFull [targetName]) LogResult. - let tryLog (x: T) (msg: Message): LogResult = + /// - `putBufferTimeOut` means it will try to wait this duration for putting the message onto buffer,otherwise return timeout error, and cancel putting message. + /// if `putBufferTimeOut <= Duration.Zero` , it will try to detect whether the buffer is full and return immediately + let log (putBufferTimeOut: Duration) (x: T) (msg: Message): LogResult = let msg = x.transform msg - if not (x.accepts msg) then LogResult.rejected + if not (x.accepts msg) then LogResult.notAcceptedByTarget x.name else let ack = IVar () let targetMsg = Log (msg, ack) - // This returns immediately if the buffer is full; and the RingBuffer's server is - // always available to notify the caller that the buffer is full. - RingBuffer.tryPut x.api.requests targetMsg ^-> function + if putBufferTimeOut <= Duration.Zero then + RingBuffer.tryPut x.api.requests targetMsg ^-> function | true -> Result.Ok (upcast ack) | false -> - Result.Error (BufferFull x.name) + LogError.targetBufferFull x.name + else + RingBuffer.put x.api.requests targetMsg ^->. Result.Ok (upcast ack) + <|> + timeOut (putBufferTimeOut.toTimeSpanSafe()) ^-> fun _ -> LogError.timeOutToPutBuffer x.name putBufferTimeOut.TotalSeconds - /// returns: an Alt committed on: - /// buffer took message <- dangerousBlockOnBuffer - /// buffer maybe took message <- not dangerousBlockOnBuffer - let private logAll_ dangerousBlockOnBuffer targets msg = + let tryLog (x: T) (msg: Message): LogResult = log Duration.Zero x msg + + let private logAll_ putBufferTimeOut targets msg = Alt.withNackJob <| fun nack -> //printfn "tryLogAll: creating alt with nack for %i targets" targets.Length let putAllPromises = IVar () - let abortPut = nack ^->. Result.Error Rejected + let abortPut = nack ^->. LogError.clientAbortLogging let createPutJob t = - if dangerousBlockOnBuffer then - log t msg <|> abortPut - else - tryLog t msg <|> abortPut + log putBufferTimeOut t msg <|> abortPut let tryPutAll = Seq.Con.mapJob createPutJob targets - >>- fun results -> - //printfn "tryLogAll: array-ing %i results" results.Count - results.ToArray() >>= IVar.fill putAllPromises Job.start tryPutAll >>-. putAllPromises - /// WARNING: this may cause you headaches; are you sure you don't want to use tryLogAll? - /// - /// Returns an Alt that commits on ALL N Targets' buffers accepting the message. Even if the Alt was not committed to, - /// one or more targets (fewer than N) may have accepted the message. - let logAll (targets: T[]) (msg: Message): Alt, LogError>[]> = - logAll_ (* DO BLOCK — WARNING *) true targets msg - - /// Tries to log the `Message` to all the targets. - let tryLogAll (targets: T[]) (msg: Message): Alt, LogError>[]> = - logAll_ (* do not block *) false targets msg - - let private logAllReduceHandler (results: Result, LogError>[]) = - match results with - | [||] -> - //printfn "tryLogAllReduce: Success from empty targets array" - LogResult.success :> Job<_> - | ps -> - match Result.sequence ps with - | Ok promises -> - let latch = Latch promises.Length - let dec = Latch.decrement latch - Job.start (promises |> Seq.Con.iterJob (fun p -> p ^=>. dec)) - >>-. Ok (memo (Latch.await latch)) - | Result.Error [] -> - // should not happen, error list always non empty: - //printfn "tryLogAllReduce: Failure from empty error array" - Job.result (Result.Error Rejected) - | Result.Error (e :: _) -> - //printfn "tryLogAllReduce: Failure from NON-empty error array %A" e - Job.result (Result.Error e) - - - let tryLogAllReduce targets msg: LogResult = - tryLogAll targets msg ^=> logAllReduceHandler - let logAllReduce targets msg: LogResult = - logAll targets msg ^=> logAllReduceHandler + /// Returns an Alt that commits on ALL N Targets' buffers accepting the message. + /// Even if the Alt was not committed to, one or more targets (fewer than N) may have accepted the message. + let logAllReduce putBufferTimeOut targets msg: LogResult = + logAll_ putBufferTimeOut targets msg ^-> ProcessResult.reduce /// Send a flush RPC to the target and return the async with the ACKs. This will /// create an Alt that is composed of a job that blocks on placing the Message diff --git a/src/Logary/Targets/BadBoy.fs b/src/Logary/Targets/BadBoy.fs index a018c6402..bfa9d7e22 100644 --- a/src/Logary/Targets/BadBoy.fs +++ b/src/Logary/Targets/BadBoy.fs @@ -27,11 +27,11 @@ module internal Impl = let take = RingBuffer.take api.requests ^=> function | Log (message, ack) -> - ilogger.timeAlt (timeOut (conf.delay.ToTimeSpan()), "single loop delay") + ilogger.timeAlt (timeOut (conf.delay.toTimeSpanSafe()), "single loop delay") >>=. ack *<= () >>= singleLoopDelay | Flush (ack, nack) -> - let simulateWrite = timeOut (conf.delay.ToTimeSpan()) ^=>. IVar.fill ack () + let simulateWrite = timeOut (conf.delay.toTimeSpanSafe()) ^=>. IVar.fill ack () (simulateWrite <|> nack) >>= singleLoopDelay let shutdown = @@ -66,7 +66,7 @@ module internal Impl = ackCh *<= () :: flushes) ([], [], []) - ilogger.timeAlt (timeOut (conf.delay.ToTimeSpan()), "batch loop delay, delaying", logBefore=true) ^=> fun () -> + ilogger.timeAlt (timeOut (conf.delay.toTimeSpanSafe()), "batch loop delay, delaying", logBefore=true) ^=> fun () -> Job.conIgnore acks >>=. Job.conIgnore flushes >>= batchLoopDelay let shutdown = diff --git a/src/adapters/Logary.Adapters.Facade/Logary.Adapters.Facade.fs b/src/adapters/Logary.Adapters.Facade/Logary.Adapters.Facade.fs index 390e4d0ef..00c38b8a9 100644 --- a/src/adapters/Logary.Adapters.Facade/Logary.Adapters.Facade.fs +++ b/src/adapters/Logary.Adapters.Facade/Logary.Adapters.Facade.fs @@ -390,14 +390,8 @@ module LoggerAdapter = module LogResult = /// Homomorphism on the LogResult value. - let mapErr<'err> (onFull: string -> 'err) (onRejected: 'err) (xA: LogResult) = - xA ^-> function - | Ok ack -> - Ok ack - | Result.Error (BufferFull target) -> - Result.Error (onFull target) - | Result.Error Rejected -> - Result.Error onRejected + let mapErr<'err> (onError: Message -> 'err) (xA: LogResult) = + xA ^-> Result.mapError onError let createMapErr = let mapErrMethodModule = Type.GetType "Logary.Adapters.Facade.LoggerAdapter+LogResult, Logary.Adapters.Facade" @@ -408,22 +402,23 @@ module LoggerAdapter = let ofLogResult (loggerType: Type): LogResult -> obj = // HOT PATH - let logErrorType = findModule (loggerType, "LogError") - let logErrorModule = findModule (loggerType, "LogErrorModule") - - let bufferFullMethod = findStaticMethod (logErrorModule, "bufferFull") - let bufferFullFSharpFunction = typedefof>.MakeGenericType([| typeof; logErrorType |]) - let bufferFull = - FSharpValue.MakeFunction( - bufferFullFSharpFunction, - fun (target: obj) -> bufferFullMethod.Invoke(null, [| target |])) - - let rejectedValue = findStaticProperty(logErrorModule, "rejected").GetValue(null, null) - let mapErr = LogResult.createMapErr loggerType - fun (result: LogResult) -> - let args = [| bufferFull; rejectedValue; box result |] - // do rawPrintM mapErr args - mapErr.Invoke(null, args) + // let logErrorType = findModule (loggerType, "LogError") + // let logErrorModule = findModule (loggerType, "LogErrorModule") + + // let bufferFullMethod = findStaticMethod (logErrorModule, "bufferFull") + // let bufferFullFSharpFunction = typedefof>.MakeGenericType([| typeof; logErrorType |]) + // let bufferFull = + // FSharpValue.MakeFunction( + // bufferFullFSharpFunction, + // fun (target: obj) -> bufferFullMethod.Invoke(null, [| target |])) + + // let rejectedValue = findStaticProperty(logErrorModule, "rejected").GetValue(null, null) + + let onError message = MessageWriter.verbatim.format message + + // let mapErr = LogResult.createMapErr loggerType + + LogResult.mapErr onError >> box let internal (|LogWithAck|LogWithAckV3|Log|LogSimple|) (invocation: IInvocation, defaultName: string[], v: ApiVersion, loggerType: Type) diff --git a/src/ingestion/Logary.Ingestion.HTTP/AssemblyInfo.fs b/src/ingestion/Logary.Ingestion.HTTP/AssemblyInfo.fs index 772b569db..8c3653d87 100644 --- a/src/ingestion/Logary.Ingestion.HTTP/AssemblyInfo.fs +++ b/src/ingestion/Logary.Ingestion.HTTP/AssemblyInfo.fs @@ -2,8 +2,8 @@ namespace System open System.Reflection -[] -[] +[] +[] [] [] [] @@ -11,8 +11,8 @@ open System.Reflection do () module internal AssemblyVersionInformation = - let [] AssemblyTitle = "Logary.Ingestion.HTTP" - let [] AssemblyProduct = "Logary.Ingestion.HTTP" + let [] AssemblyTitle = "Logary.Ingestion.Http" + let [] AssemblyProduct = "Logary.Ingestion.Http" let [] AssemblyCopyright = "Copyright © 2018 Henrik Feldt" let [] AssemblyDescription = "Logary is a high performance, multi-target logging, metric and health-check library for mono and .Net." let [] AssemblyVersion = "5.0.0" diff --git a/src/legacy/Logary.Services.SQLServerHealth/Program.fs b/src/legacy/Logary.Services.SQLServerHealth/Program.fs index 3b3795116..52e337451 100644 --- a/src/legacy/Logary.Services.SQLServerHealth/Program.fs +++ b/src/legacy/Logary.Services.SQLServerHealth/Program.fs @@ -81,7 +81,7 @@ let execute interval sqlConf riemann argv (exiting: ManualResetEventSlim) = let processing = Events.compose [ Events.events - |> Pipe.tickTimer sqlServerHealthTicker (TimeSpan.FromTicks(Duration.ticks interval |> int64)) + |> Pipe.tickTimer sqlServerHealthTicker interval |> Events.sink [cons; rm;] ] diff --git a/src/legacy/Logary.Targets.DB.Tests/DBTarget.fs b/src/legacy/Logary.Targets.DB.Tests/DBTarget.fs index be031bb13..382cfcb65 100644 --- a/src/legacy/Logary.Targets.DB.Tests/DBTarget.fs +++ b/src/legacy/Logary.Targets.DB.Tests/DBTarget.fs @@ -143,7 +143,7 @@ let targetTests = let! target = start (fun () -> db) let logToTarget = - Target.log target + Target.log (Duration.FromSeconds 1L) target >> Alt.afterFun (Expect.isOk "Should log successfully") // when @@ -186,7 +186,7 @@ let targetTests = let! target = start (fun () -> SQLiteDB.openConn SQLiteDB.InMemConnStrEmpheral) let logToTarget = - Target.log target + Target.log (Duration.FromSeconds 1L) target >> Alt.afterFun (Expect.isOk "Should log successfully") do! Job.tryFinallyJob @@ -211,7 +211,7 @@ let targetTests = let! target = start (fun () -> db) let logToTarget = - Target.log target + Target.log (Duration.FromSeconds 1L) target >> Alt.afterFun (Expect.isOk "Should log successfully") let! ack = Message.gaugefs "web01.app" "signin" 3. |> logToTarget diff --git a/src/tests/Logary.Adapters.Facade.Tests/Program.fs b/src/tests/Logary.Adapters.Facade.Tests/Program.fs index b3bdf8bdf..601ae4ce1 100644 --- a/src/tests/Logary.Adapters.Facade.Tests/Program.fs +++ b/src/tests/Logary.Adapters.Facade.Tests/Program.fs @@ -23,11 +23,11 @@ let stubLogger (minLevel: LogLevel) (message: Message ref) name = :> Logger let stubLoggerReject name = - BaseLogger(Debug, name, Alt.always (Result.Error LogError.Rejected)) + BaseLogger(Debug, name, Alt.always (Result.Error (Message.event Info "Rejected"))) :> Logger -let stubLoggerFull name targetName = - BaseLogger(Debug, name, Alt.always (Result.Error (LogError.BufferFull targetName))) +let stubLoggerFull name (targetName: string) = + BaseLogger(Debug, name, Alt.always (Result.Error (Message.eventFormat("BufferFull {target}", targetName)))) :> Logger let stubLogManager (message: Message ref) = @@ -352,14 +352,14 @@ let tests = let properLogger = stubLoggerReject (PointName.parse "Adapters.Facade.v4") let subject = LoggerAdapter.createGeneric properLogger let! res = subject.logWithAck (false, Libryy.LoggingV4.LogLevel.Warn) (Libryy.LoggingV4.Message.eventX "Hello world") - res |> Flip.Expect.equal "Should eq rejected" (Result.Error Libryy.LoggingV4.LogError.Rejected) + res |> Flip.Expect.equal "Should eq rejected" (Result.Error "Rejected") } yield testCaseJob "end to end with buffer full result" <| job { let properLogger = stubLoggerFull (PointName.parse "Adapters.Facade.v4") "t1" let subject = LoggerAdapter.createGeneric properLogger let! res = subject.logWithAck (false, Libryy.LoggingV4.LogLevel.Warn) (Libryy.LoggingV4.Message.eventX "Hello world") - res |> Flip.Expect.equal "Should eq rejected" (Result.Error (Libryy.LoggingV4.LogError.BufferFull "t1")) + res |> Flip.Expect.equal "Should eq rejected" (Result.Error ("BufferFull \"t1\"")) } yield testCase "end to end with adapter, log method" <| fun _ ->