adding nlog, strongly typed config in DI
This commit is contained in:
parent
ab8687b41e
commit
e7fbb23376
10
Selector.CLI/Options.cs
Normal file
10
Selector.CLI/Options.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
namespace Selector.CLI
|
||||||
|
{
|
||||||
|
class RootOptions
|
||||||
|
{
|
||||||
|
public const string Key = "Selector";
|
||||||
|
|
||||||
|
public int Number { get; set; } = 2;
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ using Microsoft.Extensions.DependencyInjection;
|
|||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using NLog.Extensions.Logging;
|
||||||
|
|
||||||
namespace Selector.CLI
|
namespace Selector.CLI
|
||||||
{
|
{
|
||||||
@ -18,17 +19,24 @@ namespace Selector.CLI
|
|||||||
static IHostBuilder CreateHostBuilder(string[] args)
|
static IHostBuilder CreateHostBuilder(string[] args)
|
||||||
=> Host.CreateDefaultBuilder(args)
|
=> Host.CreateDefaultBuilder(args)
|
||||||
.ConfigureServices((context, services) => {
|
.ConfigureServices((context, services) => {
|
||||||
|
|
||||||
|
// CONFIG
|
||||||
|
services.Configure<RootOptions>(options =>
|
||||||
|
context.Configuration.GetSection(RootOptions.Key).Bind(options)
|
||||||
|
);
|
||||||
|
|
||||||
|
// SERVICES
|
||||||
services.AddTransient<IPlayerWatcher, PlayerWatcher>();
|
services.AddTransient<IPlayerWatcher, PlayerWatcher>();
|
||||||
services.AddTransient<IWatcherCollection, WatcherCollection>();
|
services.AddTransient<IWatcherCollection, WatcherCollection>();
|
||||||
|
services.AddTransient<IEqual, UriEqual>();
|
||||||
|
|
||||||
|
// HOSTED SERVICES
|
||||||
services.AddHostedService<WatcherService>();
|
services.AddHostedService<WatcherService>();
|
||||||
})
|
})
|
||||||
.ConfigureLogging(builder => {
|
.ConfigureLogging((context, builder) => {
|
||||||
builder
|
builder.ClearProviders();
|
||||||
.AddSimpleConsole(options => {
|
builder.SetMinimumLevel(LogLevel.Trace);
|
||||||
options.IncludeScopes = true;
|
builder.AddNLog(context.Configuration);
|
||||||
options.SingleLine = true;
|
|
||||||
options.TimestampFormat = "yyyy-mm-dd hh:mm:ss ";
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
|
||||||
|
<PackageReference Include="NLog" Version="4.7.11" />
|
||||||
|
<PackageReference Include="NLog.Extensions.Logging" Version="1.7.4" />
|
||||||
<PackageReference Include="SpotifyAPI.Web" Version="6.2.2" />
|
<PackageReference Include="SpotifyAPI.Web" Version="6.2.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@ -23,6 +25,9 @@
|
|||||||
<None Update="appsettings.json">
|
<None Update="appsettings.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
<None Update="nlog.config">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Selector.CLI
|
|
||||||
{
|
|
||||||
class SelectorOptions
|
|
||||||
{
|
|
||||||
public const string Options = "Selector";
|
|
||||||
|
|
||||||
public int Number { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,35 +7,25 @@ using System.Threading.Tasks;
|
|||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Selector.CLI
|
namespace Selector.CLI
|
||||||
{
|
{
|
||||||
class WatcherService : IHostedService
|
class WatcherService : IHostedService
|
||||||
{
|
{
|
||||||
private readonly ILogger<WatcherService> Logger;
|
private readonly ILogger<WatcherService> Logger;
|
||||||
private readonly IConfiguration Config;
|
private readonly RootOptions Config;
|
||||||
|
|
||||||
public WatcherService(ILogger<WatcherService> logger, IConfiguration config)
|
public WatcherService(ILogger<WatcherService> logger, IOptions<RootOptions> config)
|
||||||
{
|
{
|
||||||
Logger = logger;
|
Logger = logger;
|
||||||
Config = config;
|
Config = config.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task StartAsync(CancellationToken cancellationToken)
|
public Task StartAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
Logger.LogInformation("Starting up");
|
Logger.LogInformation("Starting up");
|
||||||
|
|
||||||
foreach ((var key, var pair) in Config.AsEnumerable())
|
|
||||||
//foreach ((var key, var pair) in Config.GetSection("Selector").AsEnumerable())
|
|
||||||
{
|
|
||||||
Logger.LogInformation($"{key} => {pair}");
|
|
||||||
}
|
|
||||||
|
|
||||||
using(Logger.BeginScope("A New Scope!"))
|
|
||||||
{
|
|
||||||
Logger.LogError("From the scope!");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,20 +1,11 @@
|
|||||||
{
|
{
|
||||||
"string config": "asdf",
|
//"Selector": {
|
||||||
"Selector": {
|
// "Number2": 4,
|
||||||
"Number": 4
|
// "Number": 4
|
||||||
},
|
//},
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Information",
|
"Default": "Information"
|
||||||
"Microsoft": "Warning",
|
|
||||||
"Microsoft.Hosting.Lifetime": "Information"
|
|
||||||
},
|
|
||||||
"Console": {
|
|
||||||
"LogLevel": {
|
|
||||||
"Default": "Information",
|
|
||||||
"Microsoft": "Warning",
|
|
||||||
//"Microsoft.Hosting.Lifetime": "Information"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
28
Selector.CLI/nlog.config
Normal file
28
Selector.CLI/nlog.config
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<!-- XSD manual extracted from package NLog.Schema: https://www.nuget.org/packages/NLog.Schema-->
|
||||||
|
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
autoReload="true"
|
||||||
|
internalLogFile=".\selector.nlog.log"
|
||||||
|
internalLogLevel="Info" >
|
||||||
|
|
||||||
|
<variable name="format"
|
||||||
|
value="${longdate}|${level:uppercase=true}|${callsite}:${callsite-linenumber}|${message}${onexception:inner=${newline}}${exception:format=tostring,data:exceptionDataSeparator=\r\n}"/>
|
||||||
|
|
||||||
|
<!-- the targets to write to -->
|
||||||
|
<targets>
|
||||||
|
<!-- write logs to file -->
|
||||||
|
<target xsi:type="File"
|
||||||
|
name="logfile"
|
||||||
|
fileName=".\selector.log"
|
||||||
|
layout="${format}" />
|
||||||
|
<target xsi:type="Console"
|
||||||
|
name="logconsole"
|
||||||
|
layout="${format}" />
|
||||||
|
</targets>
|
||||||
|
|
||||||
|
<!-- rules to map from logger name to target -->
|
||||||
|
<rules>
|
||||||
|
<logger name="Selector.*" minlevel="Trace" writeTo="logfile,logconsole" />
|
||||||
|
</rules>
|
||||||
|
</nlog>
|
24
Selector/Helpers/SpotifyExtensions.cs
Normal file
24
Selector/Helpers/SpotifyExtensions.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
using SpotifyAPI.Web;
|
||||||
|
|
||||||
|
namespace Selector.Helpers
|
||||||
|
{
|
||||||
|
public static class SpotifyExtensions
|
||||||
|
{
|
||||||
|
public static string ToString(this FullTrack track) => $"{track.Name} - {track.Album.Name} - {track.Artists}";
|
||||||
|
public static string ToString(this SimpleAlbum album) => $"{album.Name} - {album.Artists}";
|
||||||
|
public static string ToString(this SimpleArtist artist) => $"{artist.Name}";
|
||||||
|
|
||||||
|
public static string ToString(this FullEpisode ep) => $"{ep.Name} - {ep.Show}";
|
||||||
|
public static string ToString(this SimpleShow show) => $"{show.Name} - {show.Publisher}";
|
||||||
|
|
||||||
|
public static string ToString(this CurrentlyPlayingContext context) => $"{context.IsPlaying}, {context.Item}, {context.Device}";
|
||||||
|
public static string ToString(this Device device) => $"{device.Id}: {device.Name} {device.VolumePercent}%";
|
||||||
|
|
||||||
|
public static string ToString(this IEnumerable<SimpleArtist> artists) => string.Join("/", artists.Select(a => a.Name));
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
|
||||||
<PackageReference Include="SpotifyAPI.Web" Version="6.2.2" />
|
<PackageReference Include="SpotifyAPI.Web" Version="6.2.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
@ -4,10 +4,14 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using SpotifyAPI.Web;
|
using SpotifyAPI.Web;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
|
|
||||||
namespace Selector
|
namespace Selector
|
||||||
{
|
{
|
||||||
public class PlayerWatcher: BaseWatcher, IPlayerWatcher
|
public class PlayerWatcher: BaseWatcher, IPlayerWatcher
|
||||||
{
|
{
|
||||||
|
private readonly ILogger<PlayerWatcher> Logger;
|
||||||
private readonly IPlayerClient spotifyClient;
|
private readonly IPlayerClient spotifyClient;
|
||||||
private readonly IEqual eq;
|
private readonly IEqual eq;
|
||||||
|
|
||||||
@ -26,10 +30,12 @@ namespace Selector
|
|||||||
|
|
||||||
public PlayerWatcher(IPlayerClient spotifyClient,
|
public PlayerWatcher(IPlayerClient spotifyClient,
|
||||||
IEqual equalityChecker,
|
IEqual equalityChecker,
|
||||||
|
ILogger<PlayerWatcher> logger = null,
|
||||||
int pollPeriod = 3000) {
|
int pollPeriod = 3000) {
|
||||||
|
|
||||||
this.spotifyClient = spotifyClient;
|
this.spotifyClient = spotifyClient;
|
||||||
eq = equalityChecker;
|
eq = equalityChecker;
|
||||||
|
Logger = logger ?? NullLogger<PlayerWatcher>.Instance;
|
||||||
PollPeriod = pollPeriod;
|
PollPeriod = pollPeriod;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,12 +70,14 @@ namespace Selector
|
|||||||
if(previous is null
|
if(previous is null
|
||||||
&& (Live.Item is FullTrack || Live.Item is FullEpisode))
|
&& (Live.Item is FullTrack || Live.Item is FullEpisode))
|
||||||
{
|
{
|
||||||
|
Logger.LogDebug($"Playback started: {Live}");
|
||||||
OnPlayingChange(ListeningChangeEventArgs.From(previous, Live));
|
OnPlayingChange(ListeningChangeEventArgs.From(previous, Live));
|
||||||
}
|
}
|
||||||
// STOPPED PLAYBACK
|
// STOPPED PLAYBACK
|
||||||
else if((previous.Item is FullTrack || previous.Item is FullEpisode)
|
else if((previous.Item is FullTrack || previous.Item is FullEpisode)
|
||||||
&& Live is null)
|
&& Live is null)
|
||||||
{
|
{
|
||||||
|
Logger.LogDebug($"Playback stopped: {previous}");
|
||||||
OnPlayingChange(ListeningChangeEventArgs.From(previous, Live));
|
OnPlayingChange(ListeningChangeEventArgs.From(previous, Live));
|
||||||
}
|
}
|
||||||
// CONTINUING PLAYBACK
|
// CONTINUING PLAYBACK
|
||||||
@ -79,16 +87,18 @@ namespace Selector
|
|||||||
if(previous.Item is FullTrack previousTrack
|
if(previous.Item is FullTrack previousTrack
|
||||||
&& Live.Item is FullTrack currentTrack)
|
&& Live.Item is FullTrack currentTrack)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(!eq.IsEqual(previousTrack, currentTrack)) {
|
if(!eq.IsEqual(previousTrack, currentTrack)) {
|
||||||
|
Logger.LogDebug($"Track changed: {previousTrack} -> {currentTrack}");
|
||||||
OnItemChange(ListeningChangeEventArgs.From(previous, Live));
|
OnItemChange(ListeningChangeEventArgs.From(previous, Live));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!eq.IsEqual(previousTrack.Album, currentTrack.Album)) {
|
if(!eq.IsEqual(previousTrack.Album, currentTrack.Album)) {
|
||||||
|
Logger.LogDebug($"Album changed: {previousTrack.Album} -> {currentTrack.Album}");
|
||||||
OnAlbumChange(ListeningChangeEventArgs.From(previous, Live));
|
OnAlbumChange(ListeningChangeEventArgs.From(previous, Live));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!eq.IsEqual(previousTrack.Artists[0], currentTrack.Artists[0])) {
|
if(!eq.IsEqual(previousTrack.Artists[0], currentTrack.Artists[0])) {
|
||||||
|
Logger.LogDebug($"Artist changed: {previousTrack.Artists[0]} -> {currentTrack.Artists[0]}");
|
||||||
OnArtistChange(ListeningChangeEventArgs.From(previous, Live));
|
OnArtistChange(ListeningChangeEventArgs.From(previous, Live));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,6 +106,7 @@ namespace Selector
|
|||||||
else if((previous.Item is FullTrack && Live.Item is FullEpisode)
|
else if((previous.Item is FullTrack && Live.Item is FullEpisode)
|
||||||
|| (previous.Item is FullEpisode && Live.Item is FullTrack))
|
|| (previous.Item is FullEpisode && Live.Item is FullTrack))
|
||||||
{
|
{
|
||||||
|
Logger.LogDebug($"Media type changed: {previous.Item}, {previous.Item}");
|
||||||
OnContentChange(ListeningChangeEventArgs.From(previous, Live));
|
OnContentChange(ListeningChangeEventArgs.From(previous, Live));
|
||||||
OnItemChange(ListeningChangeEventArgs.From(previous, Live));
|
OnItemChange(ListeningChangeEventArgs.From(previous, Live));
|
||||||
}
|
}
|
||||||
@ -104,6 +115,7 @@ namespace Selector
|
|||||||
&& Live.Item is FullEpisode currentEp)
|
&& Live.Item is FullEpisode currentEp)
|
||||||
{
|
{
|
||||||
if(!eq.IsEqual(previousEp, currentEp)) {
|
if(!eq.IsEqual(previousEp, currentEp)) {
|
||||||
|
Logger.LogDebug($"Podcast changed: {previousEp} -> {currentEp}");
|
||||||
OnItemChange(ListeningChangeEventArgs.From(previous, Live));
|
OnItemChange(ListeningChangeEventArgs.From(previous, Live));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,21 +125,25 @@ namespace Selector
|
|||||||
|
|
||||||
// CONTEXT
|
// CONTEXT
|
||||||
if(!eq.IsEqual(previous.Context, Live.Context)) {
|
if(!eq.IsEqual(previous.Context, Live.Context)) {
|
||||||
|
Logger.LogDebug($"Context changed: {previous.Context} -> {Live.Context}");
|
||||||
OnContextChange(ListeningChangeEventArgs.From(previous, Live));
|
OnContextChange(ListeningChangeEventArgs.From(previous, Live));
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEVICE
|
// DEVICE
|
||||||
if(!eq.IsEqual(previous?.Device, Live?.Device)) {
|
if(!eq.IsEqual(previous?.Device, Live?.Device)) {
|
||||||
|
Logger.LogDebug($"Device changed: {previous?.Device} -> {Live?.Device}");
|
||||||
OnDeviceChange(ListeningChangeEventArgs.From(previous, Live));
|
OnDeviceChange(ListeningChangeEventArgs.From(previous, Live));
|
||||||
}
|
}
|
||||||
|
|
||||||
// IS PLAYING
|
// IS PLAYING
|
||||||
if(previous.IsPlaying != Live.IsPlaying) {
|
if(previous.IsPlaying != Live.IsPlaying) {
|
||||||
|
Logger.LogDebug($"Playing state changed: {previous.IsPlaying} -> {Live.IsPlaying}");
|
||||||
OnPlayingChange(ListeningChangeEventArgs.From(previous, Live));
|
OnPlayingChange(ListeningChangeEventArgs.From(previous, Live));
|
||||||
}
|
}
|
||||||
|
|
||||||
// VOLUME
|
// VOLUME
|
||||||
if(previous.Device.VolumePercent != Live.Device.VolumePercent) {
|
if(previous.Device.VolumePercent != Live.Device.VolumePercent) {
|
||||||
|
Logger.LogDebug($"Volume changed: {previous.Device.VolumePercent}% -> {Live.Device.VolumePercent}%");
|
||||||
OnVolumeChange(ListeningChangeEventArgs.From(previous, Live));
|
OnVolumeChange(ListeningChangeEventArgs.From(previous, Live));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -10,12 +12,13 @@ namespace Selector
|
|||||||
{
|
{
|
||||||
public class WatcherCollection: IWatcherCollection, IDisposable, IEnumerable<WatcherContext>
|
public class WatcherCollection: IWatcherCollection, IDisposable, IEnumerable<WatcherContext>
|
||||||
{
|
{
|
||||||
|
private readonly ILogger<WatcherCollection> Logger;
|
||||||
public bool IsRunning { get; private set; } = true;
|
public bool IsRunning { get; private set; } = true;
|
||||||
private List<WatcherContext> Watchers { get; set; } = new();
|
private List<WatcherContext> Watchers { get; set; } = new();
|
||||||
|
|
||||||
public WatcherCollection()
|
public WatcherCollection(ILogger<WatcherCollection> logger = null)
|
||||||
{
|
{
|
||||||
|
Logger = logger ?? NullLogger<WatcherCollection>.Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Count => Watchers.Count;
|
public int Count => Watchers.Count;
|
||||||
@ -42,6 +45,7 @@ namespace Selector
|
|||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
|
Logger.LogDebug($"Starting {Count} watchers");
|
||||||
foreach(var watcher in Watchers)
|
foreach(var watcher in Watchers)
|
||||||
{
|
{
|
||||||
watcher.Start();
|
watcher.Start();
|
||||||
@ -51,7 +55,8 @@ namespace Selector
|
|||||||
|
|
||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
foreach(var watcher in Watchers)
|
Logger.LogDebug($"Stopping {Count} watchers");
|
||||||
|
foreach (var watcher in Watchers)
|
||||||
{
|
{
|
||||||
watcher.Stop();
|
watcher.Stop();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user