Skip to content

Commit 080059b

Browse files
authored
Add MSBuild logging capability
1 parent 9ef860f commit 080059b

File tree

2 files changed

+172
-0
lines changed

2 files changed

+172
-0
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#region License
2+
// Copyright (c) 2024, Fluent Migrator Project
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
#endregion
16+
17+
using System;
18+
19+
using Microsoft.Build.Framework;
20+
21+
using Microsoft.Build.Utilities;
22+
using Microsoft.Extensions.Logging;
23+
24+
using ILogger = Microsoft.Extensions.Logging.ILogger;
25+
26+
namespace FluentMigrator.MSBuild
27+
{
28+
/// <summary>
29+
/// A Serilog sink that redirects events to MSBuild.
30+
/// </summary>
31+
public class MicrosoftBuildLogger : ILogger
32+
{
33+
private readonly TaskLoggingHelper _loggingHelper;
34+
35+
/// <summary>
36+
/// Creates an <see cref="MicrosoftBuildLogger"/> from an <see cref="ITask"/>.
37+
/// </summary>
38+
/// <param name="task">The <see cref="ITask"/> inside which events are sent.</param>
39+
public MicrosoftBuildLogger(ITask task)
40+
{
41+
if (task is null)
42+
ThrowArgumentNullException(nameof(task));
43+
_loggingHelper = task is Task taskConcrete ? taskConcrete.Log : new TaskLoggingHelper(task);
44+
}
45+
46+
/// <summary>
47+
/// Creates an <see cref="MicrosoftBuildLogger"/> from a <see cref="TaskLoggingHelper"/>.
48+
/// </summary>
49+
/// <param name="loggingHelper">The <see cref="TaskLoggingHelper"/> to which events are sent.</param>
50+
public MicrosoftBuildLogger(TaskLoggingHelper loggingHelper)
51+
{
52+
if (loggingHelper is null)
53+
ThrowArgumentNullException(nameof(loggingHelper));
54+
_loggingHelper = loggingHelper;
55+
}
56+
57+
/// <inheritdoc />
58+
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
59+
{
60+
if (!IsEnabled(logLevel))
61+
{
62+
return;
63+
}
64+
65+
switch (logLevel)
66+
{
67+
case LogLevel.Trace:
68+
_loggingHelper.LogMessage(GetMessageImportance(logLevel), $"{formatter(state, exception)}");
69+
break;
70+
case LogLevel.Debug:
71+
_loggingHelper.LogMessage(GetMessageImportance(logLevel), $"{formatter(state, exception)}");
72+
break;
73+
case LogLevel.Information:
74+
_loggingHelper.LogMessage(GetMessageImportance(logLevel), $"{formatter(state, exception)}");
75+
break;
76+
case LogLevel.Warning:
77+
LogWarning(state, exception, formatter);
78+
break;
79+
case LogLevel.Error:
80+
case LogLevel.Critical:
81+
LogError(state, exception, formatter);
82+
break;
83+
default:
84+
throw new ArgumentOutOfRangeException();
85+
}
86+
}
87+
88+
private MessageImportance GetMessageImportance(LogLevel logLevel)
89+
{
90+
switch (logLevel)
91+
{
92+
case LogLevel.Trace: return MessageImportance.Low;
93+
case LogLevel.Debug: return MessageImportance.Normal;
94+
case LogLevel.Information: return MessageImportance.High;
95+
case LogLevel.Warning: return MessageImportance.High;
96+
case LogLevel.Error: return MessageImportance.High;
97+
case LogLevel.Critical: return MessageImportance.High;
98+
default: return MessageImportance.High;
99+
}
100+
}
101+
102+
/// <inheritdoc />
103+
public bool IsEnabled(LogLevel logLevel)
104+
{
105+
return _loggingHelper.LogsMessagesOfImportance(GetMessageImportance(logLevel));
106+
}
107+
108+
public IDisposable BeginScope<TState>(TState state) => default;
109+
110+
private static void ThrowArgumentNullException(string paramName) =>
111+
throw new ArgumentNullException(paramName);
112+
113+
// MSBuild versions earlier than 16.8 do not support help links, so we will try to call the new overload and if
114+
// it does not exist we will catch the MissingMethodException and call the old overload.
115+
private void LogWarning<TState>(TState state, Exception exception, Func<TState, Exception, string> formatter)
116+
{
117+
_loggingHelper.LogWarning($"{formatter(state, exception)}");
118+
}
119+
120+
private void LogError<TState>(TState state, Exception exception, Func<TState, Exception, string> formatter)
121+
{
122+
_loggingHelper.LogError($"{formatter(state, exception)}");
123+
}
124+
}
125+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#region License
2+
// Copyright (c) 2024, Fluent Migrator Project
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
#endregion
16+
17+
using System;
18+
19+
using Microsoft.Build.Framework;
20+
using Microsoft.Extensions.Logging;
21+
22+
using ILogger = Microsoft.Extensions.Logging.ILogger;
23+
24+
namespace FluentMigrator.MSBuild
25+
{
26+
public class MicrosoftBuildLoggerProvider : ILoggerProvider
27+
{
28+
private readonly ITask _task;
29+
30+
public MicrosoftBuildLoggerProvider(ITask task)
31+
{
32+
_task = task ?? throw new ArgumentNullException(nameof(task));
33+
}
34+
35+
/// <inheritdoc />
36+
public void Dispose()
37+
{
38+
39+
}
40+
41+
/// <inheritdoc />
42+
public ILogger CreateLogger(string categoryName)
43+
{
44+
return new MicrosoftBuildLogger(_task);
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)