Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Log using Microsoft.Extensions.Logging.Abstractions; implement WpfProgram #255

Merged
merged 16 commits into from
Aug 11, 2020
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -296,3 +296,29 @@ let save text =
#### Can I bind to events and use behaviors?

Sure! Check out the [EventBindingsAndBehaviors sample](https://github.com/elmish/Elmish.WPF/tree/master/src/Samples). Note that you have to install the NuGet package `Microsoft.Xaml.Behaviors.Wpf`.

#### How can I control logging?

Elmish.WPF uses `Microsoft.Extensions.Logging`. To see Elmish.WPF output in your favorite logging framework, use `WpfProgram.withLogger` to pass an `ILoggerFactory`:

```f#
WpfProgram.mkSimple init update bindings
|> WpfProgram.withLogger yourLoggerFactory
|> WpfProgram.runWindow window
```

For example, in Serilog, you need to install Serilog.Extensions.Logging and instantiate `SerilogLoggerFactory`. The samples demonstrate this.

Elmish.WPF logs to these categories:

* `Elmish.WPF.Update`: Logs exceptions (Error level) and messages/models (Trace/Verbose level) during `update`.
* `Elmish.WPF.Bindings`: Logs events related to bindings. Some logging is done at the Error level (e.g. developer errors such as duplicated binding names, using non-existent bindings in XAML, etc.), but otherwise it’s generally just Trace/Verbose for when you really want to see everything that’s happening (triggering `PropertyChanged`, WPF getting/setting bindings, etc.)
* `Elmish.WPF.Performance`: Logs the performance of the functions you pass when creating bindings (`get`, `set`, `map`, `equals`, etc.) at the Trace/Verbose level. Use `WpfProgram.withPerformanceLogThreshold` to set the minimum duration to log.

The specific method of controlling what Elmish.WPF logs depends on your logging framework. For Serilog you can use `.MinimumLevel.Override(...)` to specify the minimum log level per category, like this:

```f#
myLoggerConfiguration
.MinimumLevel.Override("Elmish.WPF.Bindings", LogEventLevel.Verbose)
...
```
7 changes: 7 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,17 @@
* **Breaking:** Removed the obsolete binding functions in the `BindingFn` module
* **Breaking:** Removed the obsolete function `Elmish.WPF.Cmd.showWindow`
* **Breaking:** Removed all occurrences of the argument `wrapDispatch` from the methods used to create a binding. There is currently no migration path. Please create an issue if this is a negative impact for you.
* **Breaking:** App initialization is now done using the `WpfProgram` module instead of the `Program` module
* **Breaking:** Removed `ElmConfig`. For controlling logging, see below. For specifying a binding performance log threshold (corresponding to the old `ElmConfig.MeasureLimitMs` field), use `WpfProgram.withBindingPerformanceLogThreshold`
* Added binding mapping functions
* Added `mapModel`, `mapMsg`, and `mapMsgWithModel` in both the `Binding` and `Bindings` modules
* These functions enable common model and message mapping logic to be extracted
* See the `SubModelSeq` sample for an excellent use of `mapModel` and `mapMsgWithMsg`
* Improved logging:
* Now uses `Microsoft.Extensions.Logging` for wide compatibility and easy integration into common log frameworks
* Use `WpfProgram.WithLogger` to pass an `ILoggerFactory` for your chosen log framework
* Can control specific log categories
* See the samples for a demonstration using Serilog

#### 3.5.6

Expand Down
3 changes: 2 additions & 1 deletion src/Elmish.WPF.Tests/ViewModelTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ open System.Collections.ObjectModel
open System.Collections.Specialized
open System.ComponentModel
open System.Windows.Input
open Microsoft.Extensions.Logging.Abstractions
open FSharp.Interop.Dynamic
open Xunit
open Hedgehog
Expand All @@ -26,7 +27,7 @@ module Extensions =


type internal TestVm<'model, 'msg>(model, bindings) as this =
inherit ViewModel<'model, 'msg>(model, (fun x -> this.Dispatch x), bindings, ElmConfig.Default, "")
inherit ViewModel<'model, 'msg>(model, (fun x -> this.Dispatch x), bindings, 1, "", NullLogger.Instance, NullLogger.Instance)

let pcTriggers = ConcurrentDictionary<string, int>()
let ecTriggers = ConcurrentDictionary<string, int>()
Expand Down
17 changes: 0 additions & 17 deletions src/Elmish.WPF/Config.fs

This file was deleted.

4 changes: 2 additions & 2 deletions src/Elmish.WPF/Elmish.WPF.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,16 @@
<Compile Include="AssemblyInfo.fs" />
<Compile Include="InternalUtils.fs" />
<Compile Include="InternalTypes.fs" />
<Compile Include="Config.fs" />
<Compile Include="Binding.fs" />
<Compile Include="Utils.fs" />
<Compile Include="ViewModel.fs" />
<Compile Include="ViewModelModule.fs" />
<Compile Include="Program.fs" />
<Compile Include="WpfProgram.fs" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Elmish" Version="[3.0.3, 4)" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.6" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net461'">
Expand Down
101 changes: 0 additions & 101 deletions src/Elmish.WPF/Program.fs

This file was deleted.

Loading