Skip to content

Commit 1c34f54

Browse files
committed
Initial version
0 parents  commit 1c34f54

22 files changed

+1108
-0
lines changed

.github/workflows/dotnet.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: build
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
workflow_dispatch:
9+
10+
jobs:
11+
build:
12+
13+
runs-on: windows-latest
14+
15+
steps:
16+
- uses: actions/checkout@v4
17+
- uses: nuget/setup-nuget@v2
18+
- name: Add msbuild to PATH
19+
uses: microsoft/setup-msbuild@v2
20+
- name: Update version
21+
run: |
22+
(Get-Content -Path src\LoggerVisualizerVsix\source.extension.vsixmanifest) |
23+
ForEach-Object {$_ -Replace '0.1.0', '0.1.${{ github.run_number }}'} |
24+
Set-Content -Path src\LoggerVisualizerVsix\source.extension.vsixmanifest
25+
- name: Restore
26+
run: nuget restore
27+
- name: Build
28+
run: msbuild /p:configuration=Release /p:DeployExtension=false /p:ZipPackageCompressionLevel=normal /v:m
29+
- uses: actions/upload-artifact@v3
30+
with:
31+
name: LoggerVisualizer.vsix
32+
path: src\LoggerVisualizerVsix\bin\Release\net8.0-windows\LoggerVisualizerVsix.vsix
33+
- name: Create Release
34+
id: create_release
35+
if: ${{ github.event_name == 'push' }}
36+
uses: actions/create-release@v1.1.4
37+
env:
38+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
39+
with:
40+
tag_name: 0.1.${{ github.run_number }}
41+
release_name: Release 0.1.${{ github.run_number }}
42+
draft: false
43+
- name: Upload VSIX
44+
if: ${{ github.event_name == 'push' }}
45+
uses: actions/upload-release-asset@v1.0.2
46+
env:
47+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
48+
with:
49+
upload_url: ${{ steps.create_release.outputs.upload_url }}
50+
asset_path: src\LoggerVisualizerVsix\bin\Release\net8.0-windows\LoggerVisualizerVsix.vsix
51+
asset_name: LoggerVisualizerVsix.vsix
52+
asset_content_type: application/zip

.gitignore

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
2+
[Bb]in/
3+
[Oo]bj/
4+
5+
# mstest test results
6+
TestResults
7+
8+
## Ignore Visual Studio temporary files, build results, and
9+
## files generated by popular Visual Studio add-ons.
10+
11+
# User-specific files
12+
*.suo
13+
*.user
14+
*.sln.docstates
15+
16+
# Build results
17+
[Dd]ebug/
18+
[Rr]elease/
19+
x64/
20+
*_i.c
21+
*_p.c
22+
*.ilk
23+
*.meta
24+
*.obj
25+
*.pch
26+
*.pdb
27+
*.pgc
28+
*.pgd
29+
*.rsp
30+
*.sbr
31+
*.tlb
32+
*.tli
33+
*.tlh
34+
*.tmp
35+
*.log
36+
*.vspscc
37+
*.vssscc
38+
.builds
39+
40+
# Visual C++ cache files
41+
ipch/
42+
*.aps
43+
*.ncb
44+
*.opensdf
45+
*.sdf
46+
47+
# Visual Studio profiler
48+
*.psess
49+
*.vsp
50+
*.vspx
51+
52+
# Guidance Automation Toolkit
53+
*.gpState
54+
55+
# ReSharper is a .NET coding add-in
56+
_ReSharper*
57+
58+
# dotCover
59+
*.DotSettings
60+
61+
# NCrunch
62+
*.ncrunch*
63+
.*crunch*.local.xml
64+
65+
# Installshield output folder
66+
[Ee]xpress
67+
68+
# DocProject is a documentation generator add-in
69+
DocProject/buildhelp/
70+
DocProject/Help/*.HxT
71+
DocProject/Help/*.HxC
72+
DocProject/Help/*.hhc
73+
DocProject/Help/*.hhk
74+
DocProject/Help/*.hhp
75+
DocProject/Help/Html2
76+
DocProject/Help/html
77+
78+
# Click-Once directory
79+
publish
80+
81+
# Publish Web Output
82+
*.Publish.xml
83+
84+
# NuGet Packages Directory
85+
packages
86+
87+
# Windows Azure Build Output
88+
csx
89+
*.build.csdef
90+
91+
# Windows Store app package directory
92+
AppPackages/
93+
94+
# Others
95+
[Bb]in
96+
[Oo]bj
97+
sql
98+
TestResults
99+
[Tt]est[Rr]esult*
100+
*.Cache
101+
ClientBin
102+
[Ss]tyle[Cc]op.*
103+
~$*
104+
*.dbmdl
105+
Generated_Code #added for RIA/Silverlight projects
106+
107+
# Backup & report files from converting an old project file to a newer
108+
# Visual Studio version. Backup files are not needed, because we have git ;-)
109+
_UpgradeReport_Files/
110+
Backup*/
111+
UpgradeLog*.XML
112+
.vs/

LoggerVisualizer.sln

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.10.34916.146
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{09C88280-ACF9-4043-8326-9F8D891B375E}"
7+
EndProject
8+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LoggerVisualizer", "src\LoggerVisualizer\LoggerVisualizer.csproj", "{782FFF6B-3794-4082-BB88-869CE205B6EC}"
9+
EndProject
10+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LoggerVisualizerSource", "src\LoggerVisualizerSource\LoggerVisualizerSource.csproj", "{A1FF4041-D57C-431F-B349-B133BC77D579}"
11+
EndProject
12+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LoggerVisualizerVsix", "src\LoggerVisualizerVsix\LoggerVisualizerVsix.csproj", "{1BC66681-8DB1-4401-B9D3-A8DF34E072AC}"
13+
EndProject
14+
Global
15+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
16+
Debug|Any CPU = Debug|Any CPU
17+
Release|Any CPU = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
20+
{782FFF6B-3794-4082-BB88-869CE205B6EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21+
{782FFF6B-3794-4082-BB88-869CE205B6EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
22+
{782FFF6B-3794-4082-BB88-869CE205B6EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
23+
{782FFF6B-3794-4082-BB88-869CE205B6EC}.Release|Any CPU.Build.0 = Release|Any CPU
24+
{A1FF4041-D57C-431F-B349-B133BC77D579}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25+
{A1FF4041-D57C-431F-B349-B133BC77D579}.Debug|Any CPU.Build.0 = Debug|Any CPU
26+
{A1FF4041-D57C-431F-B349-B133BC77D579}.Release|Any CPU.ActiveCfg = Release|Any CPU
27+
{A1FF4041-D57C-431F-B349-B133BC77D579}.Release|Any CPU.Build.0 = Release|Any CPU
28+
{1BC66681-8DB1-4401-B9D3-A8DF34E072AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29+
{1BC66681-8DB1-4401-B9D3-A8DF34E072AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
30+
{1BC66681-8DB1-4401-B9D3-A8DF34E072AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
31+
{1BC66681-8DB1-4401-B9D3-A8DF34E072AC}.Release|Any CPU.Build.0 = Release|Any CPU
32+
EndGlobalSection
33+
GlobalSection(SolutionProperties) = preSolution
34+
HideSolutionNode = FALSE
35+
EndGlobalSection
36+
GlobalSection(NestedProjects) = preSolution
37+
{782FFF6B-3794-4082-BB88-869CE205B6EC} = {09C88280-ACF9-4043-8326-9F8D891B375E}
38+
{A1FF4041-D57C-431F-B349-B133BC77D579} = {09C88280-ACF9-4043-8326-9F8D891B375E}
39+
{1BC66681-8DB1-4401-B9D3-A8DF34E072AC} = {09C88280-ACF9-4043-8326-9F8D891B375E}
40+
EndGlobalSection
41+
GlobalSection(ExtensibilityGlobals) = postSolution
42+
SolutionGuid = {E2F3EFB2-8BF1-4571-A7D4-43F97741FF09}
43+
EndGlobalSection
44+
EndGlobal

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
Logger Visualizer
2+
====================
3+
4+
Logger Debug Visualizer for Visual Studio.
5+
6+
When debugging applications and an `ILogger` is available in the code you can view the logger configuration details in a more structured and visually pleasing form:
7+
8+
![Logger Visualizer](screenshot.png)
9+
10+
The extension shows all configured loggers with a set of default properties. For a range of known logging providers, the extension show a special UI. Like for `EventLog`:
11+
12+
![EventLog Logger Visualizer](screenshot2.png)
13+
14+
And elmah.io:
15+
16+
![ElmahIo Logger Visualizer](screenshot3.png)
17+
18+
Feel free to reach out or send a PR if you own a provider with additional content.
19+
20+
---
21+
22+
Sponsored by [elmah.io](https://elmah.io).

screenshot.png

39.1 KB
Loading

screenshot2.png

35 KB
Loading

screenshot3.png

35.5 KB
Loading
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
using Microsoft.VisualStudio.Extensibility;
3+
4+
namespace LoggerVisualizer
5+
{
6+
[VisualStudioContribution]
7+
public class ExtensionEntrypoint : Extension
8+
{
9+
public override ExtensionConfiguration ExtensionConfiguration => new()
10+
{
11+
Metadata = new(
12+
id: "LoggerVisualizer",
13+
version: this.ExtensionAssemblyVersion,
14+
publisherName: "elmah.io",
15+
displayName: "ILogger Debugger Visualizer Extension",
16+
description:"djlkæjklæ"),
17+
};
18+
19+
/// <inheritdoc />
20+
protected override void InitializeServices(IServiceCollection serviceCollection)
21+
{
22+
Telemetry.Initialize(ExtensionAssemblyVersion?.ToString());
23+
try
24+
{
25+
base.InitializeServices(serviceCollection);
26+
}
27+
catch (Exception ex)
28+
{
29+
Telemetry.TrackException(ex);
30+
throw;
31+
}
32+
33+
// You can configure dependency injection here by adding services to the serviceCollection.
34+
}
35+
}
36+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
using Microsoft.VisualStudio.Extensibility.DebuggerVisualizers;
2+
using Microsoft.VisualStudio.Extensibility;
3+
using Microsoft.VisualStudio.RpcContracts.RemoteUI;
4+
using Microsoft.Extensions.Logging;
5+
using LoggerVisualizerSource;
6+
using System.Collections.ObjectModel;
7+
using LoggerVisualizer.Models;
8+
using System.Windows.Media.Imaging;
9+
using System.Windows;
10+
11+
namespace LoggerVisualizer
12+
{
13+
[VisualStudioContribution]
14+
internal class LoggerDebuggerVisualizerProvider : DebuggerVisualizerProvider
15+
{
16+
public override DebuggerVisualizerProviderConfiguration DebuggerVisualizerProviderConfiguration => new("Logger Visualizer", typeof(Logger<>))
17+
{
18+
VisualizerObjectSourceType = new(typeof(LoggerObjectSource)),
19+
};
20+
public override async Task<IRemoteUserControl> CreateVisualizerAsync(VisualizerTarget visualizerTarget, CancellationToken cancellationToken)
21+
{
22+
LoggerModel? model = null;
23+
try
24+
{
25+
model = await visualizerTarget
26+
.ObjectSource
27+
.RequestDataAsync<LoggerModel?>(jsonSerializer: null, CancellationToken.None);
28+
}
29+
catch (Exception ex)
30+
{
31+
Telemetry.TrackException(ex);
32+
throw;
33+
}
34+
35+
return await Task.FromResult<IRemoteUserControl>(new LoggerVisualizerUserControl(ToViewModel(model)));
36+
}
37+
38+
private LoggerRootViewModel ToViewModel(LoggerModel logger)
39+
{
40+
if (logger == null) return null;
41+
var viewModel = new LoggerRootViewModel
42+
{
43+
Name = logger.Name,
44+
Enabled = logger.Enabled,
45+
MinLevel = logger.MinLevel,
46+
MinLevelColor = MinLevelColor(logger.MinLevel),
47+
Loggers = new ObservableCollection<LoggerViewModel>(logger.Loggers.Select(l => new LoggerViewModel
48+
{
49+
Name = l.Name,
50+
ExternalScope = l.ExternalScope,
51+
MinLevel = l.MinLevel,
52+
MinLevelColor = MinLevelColor(l.MinLevel),
53+
ShortName = "📄 " + l.Name[(1 + l.Name.LastIndexOf('.'))..].Replace("LoggerProvider", string.Empty),
54+
// Console
55+
IsConsole = l.Name == "Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider" ? Visibility.Visible : Visibility.Collapsed,
56+
FormatterName = l.FormatterName,
57+
DisableColors = l.DisableColors,
58+
LogToStandardErrorThreshold = l.LogToStandardErrorThreshold,
59+
MaxQueueLength = l.MaxQueueLength,
60+
QueueFullMode = l.QueueFullMode,
61+
TimestampFormat = l.TimestampFormat,
62+
UseUtcTimestamp = l.UseUtcTimestamp,
63+
// EventLog
64+
IsEventLog = l.Name == "Microsoft.Extensions.Logging.EventLog.EventLogLoggerProvider" ? Visibility.Visible : Visibility.Collapsed,
65+
MachineName = l.MachineName,
66+
SourceName = l.SourceName,
67+
LogName = l.LogName,
68+
// EventSource
69+
IsEventSource = l.Name == "Microsoft.Extensions.Logging.EventSource.EventSourceLoggerProvider" ? Visibility.Visible : Visibility.Collapsed,
70+
// ElmahIo
71+
IsElmahIo = l.Name == "Elmah.Io.Extensions.Logging.ElmahIoLoggerProvider" ? Visibility.Visible : Visibility.Collapsed,
72+
ApiKey = l.ApiKey,
73+
LogId = l.LogId,
74+
CanBrowse = !string.IsNullOrWhiteSpace(l.LogId) && Guid.TryParse(l.LogId, out Guid _),
75+
CanDiagnose = !string.IsNullOrWhiteSpace(l.LogId) && Guid.TryParse(l.LogId, out Guid _)
76+
&& !string.IsNullOrWhiteSpace(l.ApiKey) && l.ApiKey.Length == 32,
77+
})),
78+
};
79+
80+
return viewModel;
81+
}
82+
83+
private static string MinLevelColor(string minLevel)
84+
{
85+
return minLevel switch
86+
{
87+
"Critical" => "#993636",
88+
"Debug" => "#95c1ba",
89+
"Error" => "#e6614f",
90+
"Information" => "#0da58e",
91+
"Trace" => "#ccc",
92+
"Warning" => "#ffc936",
93+
_ => "#6c757d",
94+
};
95+
}
96+
}
97+
}

0 commit comments

Comments
 (0)