Skip to content

Commit

Permalink
Baseline NLog4 port
Browse files Browse the repository at this point in the history
  • Loading branch information
kendallmiller committed Jan 13, 2017
1 parent 535b75a commit 5211926
Show file tree
Hide file tree
Showing 21 changed files with 1,189 additions and 0 deletions.
34 changes: 34 additions & 0 deletions Agent.NLog4.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dependencies", "Dependencies", "{B021ADBF-C603-473F-AA2A-1B1F4BDFB6A1}"
ProjectSection(SolutionItems) = preProject
dependencies\NuGet.exe = dependencies\NuGet.exe
README.md = README.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Agent.NLog4", "src\Agent.NLog4\Agent.NLog4.csproj", "{AA3FC450-1152-4FA7-BB7F-E878B1C15D6D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NLog4Test", "src\NLog4Test\NLog4Test.csproj", "{A289FA07-A56B-4A81-AC75-E142E7A29976}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AA3FC450-1152-4FA7-BB7F-E878B1C15D6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AA3FC450-1152-4FA7-BB7F-E878B1C15D6D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AA3FC450-1152-4FA7-BB7F-E878B1C15D6D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AA3FC450-1152-4FA7-BB7F-E878B1C15D6D}.Release|Any CPU.Build.0 = Release|Any CPU
{A289FA07-A56B-4A81-AC75-E142E7A29976}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A289FA07-A56B-4A81-AC75-E142E7A29976}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A289FA07-A56B-4A81-AC75-E142E7A29976}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A289FA07-A56B-4A81-AC75-E142E7A29976}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
78 changes: 78 additions & 0 deletions src/Agent.NLog4/Agent.NLog4.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{AA3FC450-1152-4FA7-BB7F-E878B1C15D6D}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Gibraltar.Agent.NLog</RootNamespace>
<AssemblyName>Gibraltar.Agent.NLog4</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>3.5</OldToolsVersion>
<UpgradeBackupLocation />
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Gibraltar.Agent, Version=4.0.0.0, Culture=neutral, PublicKeyToken=ca42a1ee8d2e42d3, processorArchitecture=MSIL">
<HintPath>..\..\packages\Gibraltar.Agent.4.0.0.3015\lib\net40\Gibraltar.Agent.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\..\packages\NLog.4.0.0\lib\net40\NLog.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="GibraltarTarget.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="content\app.config.transform" />
<None Include="content\web.config.transform" />
<None Include="Gibraltar.Agent.NLog4.nuspec" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>if $(ConfigurationName) == Release $(ProjectDir)..\..\dependencies\NuGet.exe Pack $(ProjectPath) -Prop Configuration=Release</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
21 changes: 21 additions & 0 deletions src/Agent.NLog4/Gibraltar.Agent.NLog4.nuspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Gibraltar.Agent.NLog4</id>
<version>$version$</version>
<title>Loupe Agent for NLog 4.0</title>
<authors>Gibraltar Software</authors>
<owners>Gibraltar Software</owners>
<copyright>Copyright © 2008-2017 Gibraltar Software, Inc.</copyright>
<licenseUrl>https://github.com/GibraltarSoftware/Gibraltar.Agent.NLog2/blob/master/LICENSE.txt</licenseUrl>
<projectUrl>https://github.com/GibraltarSoftware/Gibraltar.Agent.NLog2</projectUrl>
<iconUrl>http://www.gibraltarsoftware.com/loupe.ico</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>NLog is a powerful, flexible logging system available for all .NET platforms. It's a great choice when you need very sophisticated log gathering capabilities such as sending log messages from clients to servers, multiple logging levels used simultaneously in the application, and a range of other sophisticated features. This package enables NLog message to route into Loupe - a black box recorder for your application that can gather data from wherever your application is run and get it back to you, anywhere in the world.</description>
<summary>Connects NLog with Loupe - a black box recorder for your application that can gather data from wherever your application is run and get it back to you, anywhere in the world.</summary>
<tags>Loupe Logging</tags>
</metadata>
<files>
<file src="content\*.*" target="content" />
</files>
</package>
217 changes: 217 additions & 0 deletions src/Agent.NLog4/GibraltarTarget.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
using System;
using System.Diagnostics;
using System.Reflection;
using NLog;
using NLog.LayoutRenderers;
using NLog.Targets;

namespace Gibraltar.Agent.NLog
{
/// <summary>
/// A specialized adapter Target for sending NLog event messages to Loupe's central log.
/// </summary>
[Target("Gibraltar")]
public class GibraltarTarget : Target
{
private const string ThisLogSystem = "NLog";
private readonly CallSiteLayoutRenderer m_Renderer = new CallSiteLayoutRenderer() {IncludeSourcePath = true, FileName = true, MethodName = true};

/// <summary>
/// A renderer property just to force NLog to include stack trace info
/// </summary>
public CallSiteLayoutRenderer Renderer
{
get { return m_Renderer; }
}

/// <summary>
/// Write the log event received by this Target into the Loupe central log.
/// </summary>
/// <param name="logEvent">The LogEventInfo for a log event.</param>
protected override void Write(LogEventInfo logEvent)
{
if (logEvent == null)
return;

LogMessageSeverity severity = GetSeverityLevel(logEvent.Level);
IMessageSourceProvider sourceProvider = new NLogSourceProvider(logEvent);
string category = GetCategory(logEvent);
Exception exception = GetException(logEvent);

// By passing null for caption it will automatically get the caption from the first line of the formatted message.
Gibraltar.Agent.Log.Write(severity, ThisLogSystem, sourceProvider, null, exception, LogWriteMode.Queued,
null, category, null, logEvent.FormattedMessage);
}

/// <summary>
/// A helper method to determine the "category" for a log event when sending it to Loupe.
/// </summary>
/// <param name="logEvent">The LogEventInfo for a log event.</param>
/// <returns>A dot-delimited hierarchy string similar to a namespace. (By default just returns the LoggerName.)</returns>
private static string GetCategory(LogEventInfo logEvent)
{
string category = logEvent.LoggerName; // Default to just the logger name, but this is normally just the class name.

/*
* Loupe already captures the class name, so the convention of using the logging class as the logger name
* would mean that the default "category" may be redundant information. If you would like to capture some other
* property from the LogEventInfo as the log event's category (a dot-delimited hierarchy, similar to a namespace)
* then you can add that code here.
*/

return category;
}

/// <summary>
/// A helper method to find any Exception provided with the log event.
/// </summary>
/// <remarks>Loupe allows an Exception to be attached to any log message, but the NLog methods for logging
/// exceptions don't support format parameters (only a simple string). This logic will allow any Exception passed
/// among the format parameters of a log event (even one ignored by the format string) to be specified to Loupe,
/// so you can log an Exception to Loupe with a formatted message. However, only the first Exception among the
/// format parameters will be attached to the message in Loupe, and other NLog targets will not necessarily
/// act on an Exception included among the format parameters, beyond the normal format expansion.</remarks>
/// <param name="logEvent">The LogEventInfo for a log event.</param>
/// <returns>The Exception specified in the LogEventInfo, or else the first Exception found among the Parameters.</returns>
private static Exception GetException(LogEventInfo logEvent)
{
Exception exception = logEvent.Exception;
object[] parameters = logEvent.Parameters;

// If an Exception wasn't already specified, see if an Exception is among the format parameters.
if (exception == null && parameters != null && parameters.Length > 0)
{
foreach (object parameter in parameters)
{
Exception exceptionParameter = parameter as Exception;
if (exceptionParameter != null)
{
exception = exceptionParameter;
break; // Exit after finding first one.
}
}
}

return exception;
}

/// <summary>
/// A helper method to translate an NLog's log event level into a Loupe log message severity.
/// </summary>
/// <param name="level"></param>
/// <returns></returns>
private static LogMessageSeverity GetSeverityLevel(LogLevel level)
{
LogMessageSeverity severity = LogMessageSeverity.None;

// Check from most-frequent first, but round any unrecognized levels down to the best Loupe severity match.
if (level < LogLevel.Info)
severity = LogMessageSeverity.Verbose;
else if (level < LogLevel.Warn)
severity = LogMessageSeverity.Information;
else if (level < LogLevel.Error)
severity = LogMessageSeverity.Warning;
else if (level < LogLevel.Fatal)
severity = LogMessageSeverity.Error;
else if (level < LogLevel.Off)
severity = LogMessageSeverity.Critical;

return severity;
}

/// <summary>
/// A conversion class to extract full message source information from LogEventInfo and provide it for Loupe.
/// </summary>
private class NLogSourceProvider : IMessageSourceProvider
{
private readonly string m_MethodName;
private readonly string m_ClassName;
private readonly string m_FileName;
private readonly int m_LineNumber;

/// <summary>
/// Construct an NLogSourceProvider for a given log event.
/// </summary>
/// <param name="logEvent">The LogEventInfo of the log event.</param>
public NLogSourceProvider(LogEventInfo logEvent)
{
m_MethodName = null;
m_ClassName = null;
m_FileName = null;
m_LineNumber = 0;

try
{
StackFrame frame = logEvent.UserStackFrame;
if (frame != null)
{
MethodBase method = frame.GetMethod();
if (method != null)
{
m_MethodName = method.Name;
m_ClassName = method.ReflectedType.FullName;

try
{
// Now see if we also have file information.
m_FileName = frame.GetFileName();
if (string.IsNullOrEmpty(m_FileName) == false)
{
m_LineNumber = frame.GetFileLineNumber();
}
else
{
m_LineNumber = 0; // Not meaningful if there's no file name!
}
}
catch
{
m_FileName = null;
m_LineNumber = 0;
}
}
}
}
catch
{
m_MethodName = null;
m_ClassName = null;
m_FileName = null;
m_LineNumber = 0;
}
}

/// <summary>
/// Should return the simple name of the method which issued the log message.
/// </summary>
public string MethodName
{
get { return m_MethodName; }
}

/// <summary>
/// Should return the full name of the class (with namespace) whose method issued the log message.
/// </summary>
public string ClassName
{
get { return m_ClassName; }
}

/// <summary>
/// Should return the name of the file containing the method which issued the log message.
/// </summary>
public string FileName
{
get { return m_FileName; }
}

/// <summary>
/// Should return the line within the file at which the log message was issued.
/// </summary>
public int LineNumber
{
get { return m_LineNumber; }
}
}
}
}
37 changes: 37 additions & 0 deletions src/Agent.NLog4/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("NLog 2 Target")]
[assembly: AssemblyDescription("Extends Loupe Agent for NLog 2")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Gibraltar Software, Inc.")]
[assembly: AssemblyProduct("Loupe")]
[assembly: AssemblyCopyright("Copyright © 2008-2015 Gibraltar Software, Inc.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("f239c46b-95e2-464f-938b-e94d922079b0")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("4.0.0.0")]
[assembly: AssemblyFileVersion("4.0.0.3015")]
[assembly: AssemblyInformationalVersionAttribute("4.0.0.3015")]
Loading

0 comments on commit 5211926

Please sign in to comment.