Skip to content
This repository was archived by the owner on Dec 13, 2018. It is now read-only.

Debug logger #207

Merged
merged 1 commit into from
Jul 1, 2015
Merged
Show file tree
Hide file tree
Changes from all 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
17 changes: 16 additions & 1 deletion Logging.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.22823.1
VisualStudioVersion = 14.0.23017.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Framework.Logging", "src\Microsoft.Framework.Logging\Microsoft.Framework.Logging.xproj", "{19D1B6C5-8A62-4387-8816-C54874D1DF5F}"
EndProject
Expand All @@ -23,6 +23,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{699DB330-009
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Framework.Logging.TraceSource", "src\Microsoft.Framework.Logging.TraceSource\Microsoft.Framework.Logging.TraceSource.xproj", "{1A3EB66F-9E64-4676-852F-24995549ED8A}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Framework.Logging.Debug", "src\Microsoft.Framework.Logging.Debug\Microsoft.Framework.Logging.Debug.xproj", "{FFEDC225-D5BD-44E0-B7A6-A98FCFECC694}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -105,6 +107,18 @@ Global
{1A3EB66F-9E64-4676-852F-24995549ED8A}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{1A3EB66F-9E64-4676-852F-24995549ED8A}.Release|x86.ActiveCfg = Release|Any CPU
{1A3EB66F-9E64-4676-852F-24995549ED8A}.Release|x86.Build.0 = Release|Any CPU
{FFEDC225-D5BD-44E0-B7A6-A98FCFECC694}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FFEDC225-D5BD-44E0-B7A6-A98FCFECC694}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FFEDC225-D5BD-44E0-B7A6-A98FCFECC694}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{FFEDC225-D5BD-44E0-B7A6-A98FCFECC694}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{FFEDC225-D5BD-44E0-B7A6-A98FCFECC694}.Debug|x86.ActiveCfg = Debug|Any CPU
{FFEDC225-D5BD-44E0-B7A6-A98FCFECC694}.Debug|x86.Build.0 = Debug|Any CPU
{FFEDC225-D5BD-44E0-B7A6-A98FCFECC694}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FFEDC225-D5BD-44E0-B7A6-A98FCFECC694}.Release|Any CPU.Build.0 = Release|Any CPU
{FFEDC225-D5BD-44E0-B7A6-A98FCFECC694}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{FFEDC225-D5BD-44E0-B7A6-A98FCFECC694}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{FFEDC225-D5BD-44E0-B7A6-A98FCFECC694}.Release|x86.ActiveCfg = Release|Any CPU
{FFEDC225-D5BD-44E0-B7A6-A98FCFECC694}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -117,5 +131,6 @@ Global
{550E0247-0BDD-4016-A29B-250F075686FD} = {8C1F5D80-88EA-4961-84DC-7AC6E13951F4}
{75A4DE6D-BBAA-4D59-829D-94009E759A18} = {699DB330-0095-4266-B7B0-3EAB3710CA49}
{1A3EB66F-9E64-4676-852F-24995549ED8A} = {699DB330-0095-4266-B7B0-3EAB3710CA49}
{FFEDC225-D5BD-44E0-B7A6-A98FCFECC694} = {699DB330-0095-4266-B7B0-3EAB3710CA49}
EndGlobalSection
EndGlobal
77 changes: 77 additions & 0 deletions src/Microsoft.Framework.Logging.Debug/DebugLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections;
using System.Diagnostics;
using System.Text;

namespace Microsoft.Framework.Logging.Debug
{
public class DebugLogger : ILogger
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add doc comments.

{
private readonly Func<string, LogLevel, bool> _filter;
private readonly string _name;

public DebugLogger(string name)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add doc comments.

: this(name, filter: null)
{
}

public DebugLogger(string name, Func<string, LogLevel, bool> filter)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add doc comments.

{
_name = string.IsNullOrEmpty(name) ? nameof(DebugLogger) : name;
_filter = filter ?? ((category, logLevel) => true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should just leave _filter as null and check for it in IsEnabled rather than assign a default true returning delegate. Why run anything at all when checking IsEnabled if we can just check for null?

}

public IDisposable BeginScopeImpl(object state)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add doc comments.

{
return null;
}

public bool IsEnabled(LogLevel logLevel)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add doc comments.

{
if (!Debugger.IsAttached)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem correct

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this seems like it could be simplified to:

return Debugger.IsAttached && (_filter == null || _filter(_name, logLevel))

{
return false;
}

return _filter(_name, logLevel);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per comment above:

return _filter == null || _filter(_name, logLevel);

}

public void Log(LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add doc comments (can possibly just /// <inheritdoc />)

{
if (!IsEnabled(logLevel))
{
return;
}

string message;
var values = state as ILogValues;
if (formatter != null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That attribute throws if the value is null, here it is actually optional.

{
message = formatter(state, exception);
}
else if (values != null)
{
message = LogFormatter.FormatLogValues(values);
if (exception != null)
{
message += Environment.NewLine + exception;
}
}
else
{
message = LogFormatter.Formatter(state, exception);
}

if (string.IsNullOrEmpty(message))
{
return;
}

message = $"{ logLevel }: {message}";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

take a look at the following recently merged in external PR and see if we should do something like that for log level:
400e191

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: extra whitespace in the placeholders here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kichalla that doesn't make as much sense here as we're passing the _name through to the underlying Debug.WriteLine call as the category, so we're not controlling the left-hand side "column" width like we do in the console logger.

System.Diagnostics.Debug.WriteLine(message, _name);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intentional that you excluded writing out loglevel as a prefix since we are in debug mode?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will add

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to fully qualify, System.Diagnostics is already imported at top of file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I knew I should have put a comment. Debug conflicts with the last part of this class' namespace Microsoft.Framework.Logging.Debug and it is not resolved as a class name.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah got it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❗ Ummmmm.......... this won't work, like ever, will it? Debug.WriteLine has [Conditional("DEBUG")] on it and won't even be in the code when we compile release, which is what we should be doing.

I think @davidfowl and I once came up with a trick to make this work by putting the code in a separate file and #undefing the DEBUG symbol unconditionally in that one file. I think if you do it with a partial class you can make it be ugly-but-not-horrible.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debug.WriteLine has [Conditional("DEBUG")] on it and won't even be in the code when we compile release, which is what we should be doing.

@Eilon for my own understanding, this logger is supposed(like the template will probably add this provider within the Development environment) to be used during development time and when in Debug mode and so curious as to why Release matters?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I think I got what you are saying...just tried in a sample app(in debug mode) referencing this package and since this package is built for Release, my log statement never spitted out the log statements(probably because of the reason you mentioned)..am i right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but this package is always compiled in release mode, and will never have the call to Debug.WriteLine in it. Completely orthogonal to what the user's project is doing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I was initially misled into believing this works as it is when I used the sample app present in Logging solution's samples and because the whole solution is built for debug it seemed working as it supposed to.

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using Microsoft.Framework.Logging.Debug;

namespace Microsoft.Framework.Logging
{
public static class DebugLoggerFactoryExtensions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add doc comments.

{
/// <summary>
/// Adds a debug logger that is enabled for <see cref="LogLevel"/>.Information or higher.
/// </summary>
public static ILoggerFactory AddDebug(this ILoggerFactory factory)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add doc comments for parameters.

{
return AddDebug(
factory,
(category, logLevel) => logLevel >= LogLevel.Information);
}

/// <summary>
/// Adds a debug logger that is enabled as defined by the filter function.
/// </summary>
public static ILoggerFactory AddDebug(this ILoggerFactory factory, Func<string, LogLevel, bool> filter)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add doc comments for parameters.

{
factory.AddProvider(new DebugLoggerProvider(filter));
return factory;
}

/// <summary>
/// Adds a debug logger that is enabled for <see cref="LogLevel"/>s of minLevel or higher.
/// </summary>
/// <param name="minLevel">The minimum <see cref="LogLevel"/> to be logged</param>
public static ILoggerFactory AddDebug(this ILoggerFactory factory, LogLevel minLevel)
{
return AddDebug(
factory,
(category, logLevel) => logLevel >= minLevel);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: rename category to _ as it's unused

}
}
}
22 changes: 22 additions & 0 deletions src/Microsoft.Framework.Logging.Debug/DebugLoggerProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;

namespace Microsoft.Framework.Logging.Debug
{
public class DebugLoggerProvider : ILoggerProvider
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add doc comments.

{
private readonly Func<string, LogLevel, bool> _filter;

public DebugLoggerProvider(Func<string, LogLevel, bool> filter)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add doc comments.

{
_filter = filter;
}

public ILogger CreateLogger(string name)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add doc comments.

{
return new DebugLogger(name, _filter);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>

<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>ffedc225-d5bd-44e0-b7a6-a98fcfecc694</ProjectGuid>
<RootNamespace>Microsoft.Framework.Logging.Debug</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>

<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
20 changes: 20 additions & 0 deletions src/Microsoft.Framework.Logging.Debug/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"version": "1.0.0-*",
"dependencies": {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a description to this.

"Microsoft.Framework.Logging.Abstractions": "1.0.0-*"
},

"frameworks": {
"net45": {
},
"dnx451": {
},
"dotnet": {
"dependencies": {
"System.Collections": "4.0.10-beta-*",
"System.Globalization": "4.0.10-beta-*",
"System.Linq": "4.0.0-beta-*"
}
}
}
}