Skip to content

Commit

Permalink
Merge pull request #25 from dojo90/24-Does-it-possible-to-create-NLog…
Browse files Browse the repository at this point in the history
…Viewer

24 does it possible to create n log viewer
  • Loading branch information
djonasdev authored Aug 24, 2020
2 parents 52fe2ed + 69db6d3 commit 62a545c
Show file tree
Hide file tree
Showing 12 changed files with 237 additions and 39 deletions.
147 changes: 136 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
[3]: https://github.com/yarseyah/sentinel#nlogs-nlogviewer-target-configuration

[p1]: doc/images/control.png "NLogViewer"
[p2]: doc/images/preview.gif "NLogViewer"
[p3]: doc/images/control2.png "NLogViewer"
[p2]: doc/images/overview.gif "NLogViewer"
[p3]: doc/images/colors.png "NLogViewer"
[p4]: doc/images/openpopup.gif "NLogViewer"
[p5]: doc/images/newtask.gif "NLogViewer"

[nuget]: https://nuget.org/packages/Sentinel.NlogViewer/

Expand All @@ -20,16 +22,9 @@ NlogViewer

NlogViewer is a ui control library to visualize NLog logs in your personal application. It is mainly based on [Sentinel][1] and its controls.

![NLogViewer][p2]

Actually it contains the following controls:

- `NLogViewer`
supported Frameworks: `.NETCoreApp v3.0`, `.NETCoreApp v3.1`, `.NET Framework 4.6.1`

Visual Studio

![NLogViewer][p1]
![NLogViewer][p3]
![NLogViewer][p2]

## Quick Start

Expand Down Expand Up @@ -72,6 +67,136 @@ If you want to customize the `loggingPattern` and `LogLevel`, add the following
</nlog>
```

## Customize

### Colors

Customize `foreground` or `background` of every `logLevel`

![NLogViewer][p3]

### Multi targeting

Use more than one instance of `NLogViewer` to match different `rules`.

Create 2 `targets` with their own `rules`.

```xml
<targets async="true">
<target xsi:type="CacheTarget" name="target1"/>
<target xsi:type="CacheTarget" name="target2"/>
</targets>

<rules>
<logger name="*" writeTo="target1" maxlevel="Info"/>
<logger name="*" writeTo="target2" minlevel="Warn"/>
</rules>
```

Set `TargetName` property to link them.

```xml
<dj:NLogViewer TargetName="target1"/>
<dj:NLogViewer TargetName="target2"/>
```

### Format output (ILogEventInfoResolver)

To format the output of a `LogEventInfo`, implement a new instance of `ILogEventInfoResolver` and bind it to the `Resolver` you want to customize:

```csharp
/// <summary>
/// Reformat the DateTime
/// </summary>
public class FooTimeStampResolver : ILogEventInfoResolver
{
public string Resolve(LogEventInfo logEventInfo)
{
return logEventInfo.TimeStamp.ToUniversalTime().ToString();
}
}
```

```csharp
NLogViewer1.TimeStampResolver = new FooTimeStampResolver();
```

## Samples

### open on a new window

![NLogViewer][p4]

Create a new `Window` and add a default `NLogViewer`

```csharp
<dj:NLogViewer TargetName="target1"/>
```

Open the new `Window`

```csharp
TestPopup popup = new TestPopup();
popup.Show();
```

### seperate logger for a task

![NLogViewer][p5]

Below is a sample how you could create a `NLogViewer` for a task

```csharp
// create unique target name
var taskNumber = _RandomTaskCounter++;
string targetName = $"task{taskNumber}";
// create a unique logger
var loggerName = $"MyFoo.Logger.{taskNumber}";
var logger = LogManager.GetLogger(loggerName);

// create new CacheTarget
CacheTarget target = new CacheTarget
{
Name = targetName
};

// get config // https://stackoverflow.com/a/3603571/6229375
var config = LogManager.Configuration;

// add target
config.AddTarget(targetName, target);

// create a logging rule for the new logger
LoggingRule loggingRule = new LoggingRule(loggerName, LogLevel.Trace, target);

// add the logger to the existing configuration
config.LoggingRules.Add(loggingRule);

// reassign config back to NLog
LogManager.Configuration = config;

// create a new NLogViewer Control with the unique logger target name
NLogViewer nLogViewer = new NLogViewer
{
TargetName = targetName,
};

// add it to the tab control
var tabItem = new TabItem { Header = $"Task {taskNumber}", Content = nLogViewer };
TabControl1.Items.Add(tabItem);
TabControl1.SelectedItem = tabItem;

// create task which produces some output
var task = new Task(async () =>
{
while (true)
{
logger.Info($"Hello from task nr. {taskNumber}. It's {DateTime.Now.ToLongTimeString()}");
await Task.Delay(1000);
}
});
```

## Why CacheTarget?

There is already a `NLogViewerTarget`, which is used for [Sentinel][1]. See [here][3]
Expand Down
Binary file added doc/images/colors.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed doc/images/control.png
Binary file not shown.
Binary file removed doc/images/control2.png
Binary file not shown.
Binary file added doc/images/newtask.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/images/openpopup.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/images/overview.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed doc/images/preview.gif
Binary file not shown.
40 changes: 23 additions & 17 deletions src/NLogViewer.TestApp/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,30 @@
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="5" />
<RowDefinition Height="*" />
<RowDefinition Height="5" />
<RowDefinition Height="Auto" />
<RowDefinition Height="5" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TabControl Grid.RowSpan="10" x:Name="TabControl1">
<TabItem Header="Messages">
<dj:NLogViewer x:Name="NLogViewer1" Grid.Row="2" MaxCount="1000" TargetName="target1" />
</TabItem>
<TabItem Header="Warnings/Errors">
<dj:NLogViewer Grid.Row="6" MaxCount="1000" TargetName="target2" />
</TabItem>
</TabControl>
<!--<TextBlock Grid.Row="0" Text="Target 1" FontSize="18" />
<TextBlock Grid.Row="4" Text="Target 2 (Warn and Error)" FontSize="18" />
<Button Grid.Row="0" Grid.RowSpan="2" Margin="5" Content="Open Popup" HorizontalAlignment="Right"
VerticalAlignment="Top" Click="ButtonBase_OnClick" />-->
<WrapPanel Grid.Row="0" Margin="5">
<Button DockPanel.Dock="Left" Width="120" Content="Open Popup" Click="Button_OpenPopup_Click" />
<Button DockPanel.Dock="Left" Width="120" Content="Add new Task" Click="Button_AddTask_Click" Margin="5,0,0,0"/>
</WrapPanel>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="5" />
<RowDefinition Height="*" />
<RowDefinition Height="5" />
<RowDefinition Height="Auto" />
<RowDefinition Height="5" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TabControl Grid.RowSpan="10" x:Name="TabControl1">
<TabItem Header="Messages">
<dj:NLogViewer x:Name="NLogViewer1" Grid.Row="2" MaxCount="1000" TargetName="target1" />
</TabItem>
<TabItem Header="Warnings/Errors">
<dj:NLogViewer Grid.Row="6" MaxCount="1000" TargetName="target2" />
</TabItem>
</TabControl>
</Grid>
</Grid>
</Window>
83 changes: 75 additions & 8 deletions src/NLogViewer.TestApp/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
using System;
using System.Diagnostics;
using System.Reactive.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using DJ;
using DJ.Resolver;
using DJ.Targets;
using NLog;
using NLog.Config;
using NLog.Filters;

namespace TestApplication
{
Expand All @@ -13,7 +19,7 @@ namespace TestApplication
public partial class MainWindow : Window
{
public const string LOREM_IPSUM = @"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";

private readonly Logger _Logger = LogManager.GetCurrentClassLogger();
private readonly Logger _Logger2 = LogManager.GetLogger("Lorem.Ipsum.Foo.Hello.World.Lorem.Ipsum");

Expand All @@ -26,15 +32,15 @@ public MainWindow()
Title = $"Testing v{AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName}";
InitializeComponent();
DataContext = this;

NLogViewer1.TimeStampResolver = new FooTimeStampResolver();
Stopwatch stopwatch = Stopwatch.StartNew();
Random random = new Random();
Observable.Interval(TimeSpan.FromMilliseconds(200)).ObserveOnDispatcher().Subscribe(l =>
Observable.Interval(TimeSpan.FromMilliseconds(200)).ObserveOnDispatcher().Subscribe(l =>
{
if((_CntMessage == 10 || _CntError == 20) && TabControl1.Items.Count > 0)
TabControl1.Items.RemoveAt(0);
switch (random.Next(1,6))
//if((_CntMessage == 10 || _CntError == 20) && TabControl1.Items.Count > 0)
// TabControl1.Items.RemoveAt(0);
switch (random.Next(1, 6))
{
case 1:
_CntMessage++;
Expand All @@ -50,6 +56,7 @@ public MainWindow()
{
_Logger.Debug($"Hello everyone: {_CntMessage}");
}

break;
case 3:
_CntMessage++;
Expand All @@ -72,6 +79,7 @@ public MainWindow()
{
_Logger.Error(ex, $"There was an error on divison :/ {_CntError}");
}

break;
case 6:
_CntError++;
Expand All @@ -81,11 +89,70 @@ public MainWindow()
});
}

private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
private void Button_OpenPopup_Click(object sender, RoutedEventArgs e)
{
TestPopup popup = new TestPopup();
popup.Show();
}

private void Button_AddTask_Click(object sender, RoutedEventArgs e)
{
AddNewTabWithLogger().Start();
}

private int _RandomTaskCounter;
private Task AddNewTabWithLogger()
{
// create unique target name
var taskNumber = _RandomTaskCounter++;
string targetName = $"task{taskNumber}";
// create a unique logger
var loggerName = $"MyFoo.Logger.{taskNumber}";
var logger = LogManager.GetLogger(loggerName);

// create new CacheTarget
CacheTarget target = new CacheTarget
{
Name = targetName
};

// get config // https://stackoverflow.com/a/3603571/6229375
var config = LogManager.Configuration;

// add target
config.AddTarget(targetName, target);

// create a logging rule for the new logger
LoggingRule loggingRule = new LoggingRule(loggerName, LogLevel.Trace, target);

// add the logger to the existing configuration
config.LoggingRules.Add(loggingRule);

// reassign config back to NLog
LogManager.Configuration = config;

// create a new NLogViewer Control with the unique logger target name
NLogViewer nLogViewer = new NLogViewer
{
TargetName = targetName,
};

// add it to the tab control
var tabItem = new TabItem { Header = $"Task {taskNumber}", Content = nLogViewer };
TabControl1.Items.Add(tabItem);
TabControl1.SelectedItem = tabItem;

// create task which produces some output
var task = new Task(async () =>
{
while (true)
{
logger.Info($"Hello from task nr. {taskNumber}. It's {DateTime.Now.ToLongTimeString()}");
await Task.Delay(1000);
}
});
return task;
}
}

/// <summary>
Expand All @@ -98,4 +165,4 @@ public string Resolve(LogEventInfo logEventInfo)
return logEventInfo.TimeStamp.ToUniversalTime().ToString();
}
}
}
}
2 changes: 1 addition & 1 deletion src/NLogViewer.TestApp/NLogViewer.TestApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="NLog" Version="4.5.0" />
<PackageReference Include="NLog" Version="4.6.8" />
</ItemGroup>

<ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions src/NLogViewer/NLogViewer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="NLog" Version="4.5.0" />
<PackageReference Include="System.Reactive" Version="4.2.0" />
<PackageReference Include="NLog" Version="4.6.8" />
<PackageReference Include="System.Reactive" Version="4.3.2" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
Expand Down

0 comments on commit 62a545c

Please sign in to comment.