Skip to content

Commit ecbd2e4

Browse files
committed
Initial stab at adding a logging facility
Borrowing from the way that Caliburn.Micro does logging internal, and building on some ideas from FervantCoder (Rob Reynolds), I've added a basic set of logging classes, and an initial test. These should allow for the actual logging implementation to be swapped out by a consumer of the lib.
1 parent d1861d1 commit ecbd2e4

11 files changed

Lines changed: 389 additions & 1 deletion

File tree

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using csharp_github_api.Logging;
6+
using VS = System.Diagnostics.Debug;
7+
8+
namespace csharp_github_api.IntegrationTests
9+
{
10+
public struct Categories
11+
{
12+
public static string DEBUG = "Debug";
13+
public static string INFO = "Info";
14+
public static string WARN = "Warn";
15+
public static string ERROR = "Error";
16+
public static string FATAL = "Fatal";
17+
}
18+
public class DebugLogger : ILog, ILog<DebugLogger>
19+
{
20+
private static Type _typeBeingLogged;
21+
22+
private readonly Action<string, string, object[]> _writeWithFormatting
23+
= (category, message, objects) =>
24+
{
25+
var formatted = string.Format(message, objects);
26+
var output = string.Format("{0} - {1}", _typeBeingLogged.FullName, formatted);
27+
VS.WriteLine(output, category);
28+
};
29+
30+
private readonly Action<string, Func<string>> _write = (category, message) =>
31+
{
32+
var output = string.Format("{0} - {1}",
33+
_typeBeingLogged.
34+
FullName,
35+
message.Invoke());
36+
VS.WriteLine(output, category);
37+
};
38+
39+
private static void WriteWithFormatting(string category, string message, params object[] formatting)
40+
{
41+
throw new NotImplementedException();
42+
}
43+
44+
public DebugLogger()
45+
{
46+
}
47+
48+
public DebugLogger(Type type)
49+
{
50+
_typeBeingLogged = type;
51+
}
52+
53+
/// <summary>
54+
/// Debug level of the specified message. The other method is preferred since the execution is deferred.
55+
/// </summary>
56+
/// <param name="message">The message.</param>
57+
/// <param name="formatting">The formatting.</param>
58+
public void Debug(string message, params object[] formatting)
59+
{
60+
_writeWithFormatting(Categories.DEBUG, message, formatting);
61+
}
62+
63+
/// <summary>
64+
/// Debug level of the specified message.
65+
/// </summary>
66+
/// <param name="message">The message.</param>
67+
public void Debug(Func<string> message)
68+
{
69+
_write(Categories.DEBUG, message);
70+
}
71+
72+
/// <summary>
73+
/// Info level of the specified message. The other method is preferred since the execution is deferred.
74+
/// </summary>
75+
/// <param name="message">The message.</param>
76+
/// <param name="formatting">The formatting.</param>
77+
public void Info(string message, params object[] formatting)
78+
{
79+
_writeWithFormatting(Categories.INFO, message, formatting);
80+
}
81+
82+
/// <summary>
83+
/// Info level of the specified message.
84+
/// </summary>
85+
/// <param name="message">The message.</param>
86+
public void Info(Func<string> message)
87+
{
88+
_write(Categories.INFO, message);
89+
}
90+
91+
/// <summary>
92+
/// Warn level of the specified message. The other method is preferred since the execution is deferred.
93+
/// </summary>
94+
/// <param name="message">The message.</param>
95+
/// <param name="formatting">The formatting.</param>
96+
public void Warn(string message, params object[] formatting)
97+
{
98+
throw new NotImplementedException();
99+
}
100+
101+
/// <summary>
102+
/// Warn level of the specified message.
103+
/// </summary>
104+
/// <param name="message">The message.</param>
105+
public void Warn(Func<string> message)
106+
{
107+
_write(Categories.WARN, message);
108+
}
109+
110+
/// <summary>
111+
/// Error level of the specified message. The other method is preferred since the execution is deferred.
112+
/// </summary>
113+
/// <param name="message">The message.</param>
114+
/// <param name="formatting">The formatting.</param>
115+
public void Error(string message, params object[] formatting)
116+
{
117+
throw new NotImplementedException();
118+
}
119+
120+
/// <summary>
121+
/// Error level of the specified message.
122+
/// </summary>
123+
/// <param name="message">The message.</param>
124+
public void Error(Func<string> message)
125+
{
126+
_write(Categories.ERROR, message);
127+
}
128+
129+
/// <summary>
130+
/// Fatal level of the specified message. The other method is preferred since the execution is deferred.
131+
/// </summary>
132+
/// <param name="message">The message.</param>
133+
/// <param name="formatting">The formatting.</param>
134+
public void Fatal(string message, params object[] formatting)
135+
{
136+
throw new NotImplementedException();
137+
}
138+
139+
/// <summary>
140+
/// Fatal level of the specified message.
141+
/// </summary>
142+
/// <param name="message">The message.</param>
143+
public void Fatal(Func<string> message)
144+
{
145+
_write(Categories.FATAL, message);
146+
}
147+
}
148+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using NUnit.Framework;
6+
7+
namespace csharp_github_api.IntegrationTests
8+
{
9+
[TestFixture]
10+
public class TestLogging
11+
{
12+
private const string GitHubUrl = @"https://api.github.com";
13+
14+
[Test]
15+
public void Should_SeeDebugOutputInVSConsole()
16+
{
17+
var github = new Github(GitHubUrl).WithLogger(type => new DebugLogger(type));
18+
}
19+
}
20+
}

csharp-github-api.IntegrationTests/UsersTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public class UsersTests
1111
[TestFixtureSetUp]
1212
public void Setup()
1313
{
14-
_github = new Github(GitHubUrl);
14+
_github = new Github(GitHubUrl).WithLogger(type => new DebugLogger(type));
1515
}
1616

1717
[Test]

csharp-github-api.IntegrationTests/csharp-github-api.IntegrationTests.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@
7676
</ItemGroup>
7777
<ItemGroup>
7878
<Compile Include="Authentication\BasicAuthenticationTest.cs" />
79+
<Compile Include="DebugLogger.cs" />
7980
<Compile Include="Properties\AssemblyInfo.cs" />
81+
<Compile Include="TestLogging.cs" />
8082
<Compile Include="UsersTests.cs" />
8183
</ItemGroup>
8284
<ItemGroup>

csharp-github-api/Github.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@
1616
// </copyright>
1717
//----------------------------------------------------------------------
1818

19+
using System;
20+
1921
namespace csharp_github_api
2022
{
2123
using RestSharp;
24+
using Logging;
2225

2326
/// <summary>
2427
/// Access the Github.com API.
@@ -36,6 +39,14 @@ public Github(string baseUrl)
3639
BaseUrl = baseUrl;
3740
}
3841

42+
public Github WithLogger(Func<Type, ILog> logger)
43+
{
44+
LogManager.GetLog = logger;
45+
46+
this.Log().Debug(() => "Initialised with Logger.");
47+
return this;
48+
}
49+
3950
/// <summary>
4051
/// Instantiates a new instance of the Github class.
4152
/// </summary>

csharp-github-api/Logging/ILog.cs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+

2+
3+
namespace csharp_github_api.Logging
4+
{
5+
using System;
6+
7+
/// <summary>
8+
/// Custom interface for logging messages
9+
/// </summary>
10+
/// <remarks>
11+
/// Taken from https://gist.github.com/3099122
12+
/// </remarks>
13+
public interface ILog
14+
{
15+
/// <summary>
16+
/// Debug level of the specified message. The other method is preferred since the execution is deferred.
17+
/// </summary>
18+
/// <param name="message">The message.</param>
19+
/// <param name="formatting">The formatting.</param>
20+
void Debug(string message, params object[] formatting);
21+
/// <summary>
22+
/// Debug level of the specified message.
23+
/// </summary>
24+
/// <param name="message">The message.</param>
25+
void Debug(Func<string> message);
26+
/// <summary>
27+
/// Info level of the specified message. The other method is preferred since the execution is deferred.
28+
/// </summary>
29+
/// <param name="message">The message.</param>
30+
/// <param name="formatting">The formatting.</param>
31+
void Info(string message, params object[] formatting);
32+
/// <summary>
33+
/// Info level of the specified message.
34+
/// </summary>
35+
/// <param name="message">The message.</param>
36+
void Info(Func<string> message);
37+
/// <summary>
38+
/// Warn level of the specified message. The other method is preferred since the execution is deferred.
39+
/// </summary>
40+
/// <param name="message">The message.</param>
41+
/// <param name="formatting">The formatting.</param>
42+
void Warn(string message, params object[] formatting);
43+
/// <summary>
44+
/// Warn level of the specified message.
45+
/// </summary>
46+
/// <param name="message">The message.</param>
47+
void Warn(Func<string> message);
48+
/// <summary>
49+
/// Error level of the specified message. The other method is preferred since the execution is deferred.
50+
/// </summary>
51+
/// <param name="message">The message.</param>
52+
/// <param name="formatting">The formatting.</param>
53+
void Error(string message, params object[] formatting);
54+
/// <summary>
55+
/// Error level of the specified message.
56+
/// </summary>
57+
/// <param name="message">The message.</param>
58+
void Error(Func<string> message);
59+
/// <summary>
60+
/// Fatal level of the specified message. The other method is preferred since the execution is deferred.
61+
/// </summary>
62+
/// <param name="message">The message.</param>
63+
/// <param name="formatting">The formatting.</param>
64+
void Fatal(string message, params object[] formatting);
65+
/// <summary>
66+
/// Fatal level of the specified message.
67+
/// </summary>
68+
/// <param name="message">The message.</param>
69+
void Fatal(Func<string> message);
70+
}
71+
72+
/// <summary>
73+
/// Ensures a default constructor for the logger type
74+
/// </summary>
75+
/// <typeparam name="T"></typeparam>
76+
public interface ILog<T> where T : new()
77+
{
78+
}
79+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
6+
namespace csharp_github_api.Logging
7+
{
8+
public static class LogExtensions
9+
{
10+
public static ILog Log<T>(this T type)
11+
{
12+
return LogManager.GetLog(typeof (T));
13+
}
14+
}
15+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
*
3+
The MIT License
4+
5+
Copyright (c) 2010 Blue Spire Consulting, Inc.
6+
7+
Permission is hereby granted, free of charge, to any person obtaining a copy
8+
of this software and associated documentation files (the "Software"), to deal
9+
in the Software without restriction, including without limitation the rights
10+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
copies of the Software, and to permit persons to whom the Software is
12+
furnished to do so, subject to the following conditions:
13+
14+
The above copyright notice and this permission notice shall be included in
15+
all copies or substantial portions of the Software.
16+
17+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
THE SOFTWARE.
24+
*
25+
* */
26+
27+
namespace csharp_github_api.Logging
28+
{
29+
using System;
30+
31+
/// <summary>
32+
/// Used to manage logging.
33+
/// </summary>
34+
/// <remarks>
35+
/// This class is inspired entirely by the LogManager in Caliburn.Micro, see: http://caliburnmicro.codeplex.com/SourceControl/changeset/view/1c05274733b7#src/Caliburn.Micro.Silverlight/Logging.cs
36+
/// </remarks>
37+
public static class LogManager
38+
{
39+
static readonly ILog NullLogInstance = new NullLogger();
40+
41+
/// <summary>
42+
/// Creates an <see cref="ILog"/> for the provided type.
43+
/// </summary>
44+
public static Func<Type, ILog> GetLog = type => NullLogInstance;
45+
}
46+
}

0 commit comments

Comments
 (0)