diff --git a/LOGGING/src/NLogTarget/ApplicationInsightsTarget.cs b/LOGGING/src/NLogTarget/ApplicationInsightsTarget.cs index 7d5e65d079..706173441e 100644 --- a/LOGGING/src/NLogTarget/ApplicationInsightsTarget.cs +++ b/LOGGING/src/NLogTarget/ApplicationInsightsTarget.cs @@ -13,6 +13,7 @@ namespace Microsoft.ApplicationInsights.NLogTarget using Microsoft.ApplicationInsights.Channel; using Microsoft.ApplicationInsights.DataContracts; + using Microsoft.ApplicationInsights.Extensibility; using Microsoft.ApplicationInsights.Extensibility.Implementation; using Microsoft.ApplicationInsights.Implementation; @@ -31,6 +32,7 @@ public sealed class ApplicationInsightsTarget : TargetWithLayout private TelemetryClient telemetryClient; private DateTime lastLogEventTime; private NLog.Layouts.Layout instrumentationKeyLayout = string.Empty; + private NLog.Layouts.Layout connectionStringLayout = string.Empty; /// /// Initializers a new instance of ApplicationInsightsTarget type. @@ -50,6 +52,15 @@ public string InstrumentationKey set => this.instrumentationKeyLayout = value ?? string.Empty; } + /// + /// Gets or sets the Application Insights connectionstring for your application + /// + public string ConnectionString + { + get => (this.connectionStringLayout as NLog.Layouts.SimpleLayout)?.Text ?? null; + set => this.connectionStringLayout = value ?? string.Empty; + } + /// /// Gets the array of custom attributes to be passed into the logevent context. /// @@ -118,10 +129,24 @@ protected override void InitializeTarget() this.telemetryClient = new TelemetryClient(); #pragma warning restore CS0618 // Type or member is obsolete - string instrumentationKey = this.instrumentationKeyLayout.Render(LogEventInfo.CreateNullEvent()); - if (!string.IsNullOrWhiteSpace(instrumentationKey)) + string connectionString = this.connectionStringLayout.Render(LogEventInfo.CreateNullEvent()); + + // Check if nlog application insights target has connectionstring in config file then + // configure telemetryclient with the connectionstring otherwise using instrumentationkey. + if (!string.IsNullOrWhiteSpace(connectionString)) { - this.telemetryClient.Context.InstrumentationKey = instrumentationKey; + var configuration = TelemetryConfiguration.CreateDefault(); + configuration.ConnectionString = connectionString; + + this.telemetryClient.TelemetryConfiguration.ConnectionString = connectionString; + } + else + { + string instrumentationKey = this.instrumentationKeyLayout.Render(LogEventInfo.CreateNullEvent()); + if (!string.IsNullOrWhiteSpace(instrumentationKey)) + { + this.telemetryClient.Context.InstrumentationKey = instrumentationKey; + } } this.telemetryClient.Context.GetInternalContext().SdkVersion = SdkVersionUtils.GetSdkVersion("nlog:"); diff --git a/LOGGING/test/NLogTarget.Tests/NLogTargetTests.cs b/LOGGING/test/NLogTarget.Tests/NLogTargetTests.cs index 92a6604fd7..55c6be0651 100644 --- a/LOGGING/test/NLogTarget.Tests/NLogTargetTests.cs +++ b/LOGGING/test/NLogTarget.Tests/NLogTargetTests.cs @@ -226,11 +226,11 @@ public void TraceHasCustomProperties() var telemetry = (TraceTelemetry)this.adapterHelper.Channel.SentItems.FirstOrDefault(); Assert.IsNotNull(telemetry, "Didn't get the log event from the channel"); - Assert.AreEqual("Value", telemetry.Properties["Name"]); + Assert.AreEqual("Value", telemetry.Properties["Name"]); } - [TestMethod] + [TestMethod] [TestCategory("NLogTarget")] public void GlobalDiagnosticContextPropertiesAreAddedToProperties() { @@ -260,8 +260,8 @@ public void GlobalDiagnosticContextPropertiesSupplementEventProperties() aiLogger.Log(eventInfo); var telemetry = (TraceTelemetry)this.adapterHelper.Channel.SentItems.FirstOrDefault(); - Assert.AreEqual("global_value", telemetry.Properties["global_prop"]); - Assert.AreEqual("Value", telemetry.Properties["Name"]); + Assert.AreEqual("global_value", telemetry.Properties["global_prop"]); + Assert.AreEqual("Value", telemetry.Properties["Name"]); } [TestMethod] @@ -280,10 +280,10 @@ public void EventPropertyKeyNameIsAppendedWith_1_IfSameAsGlobalDiagnosticContext aiLogger.Log(eventInfo); var telemetry = (TraceTelemetry)this.adapterHelper.Channel.SentItems.FirstOrDefault(); - Assert.IsTrue(telemetry.Properties.ContainsKey("Name")); - Assert.AreEqual("Global Value", telemetry.Properties["Name"]); - Assert.IsTrue(telemetry.Properties.ContainsKey("Name_1"), "Key name altered"); - Assert.AreEqual("Value", telemetry.Properties["Name_1"]); + Assert.IsTrue(telemetry.Properties.ContainsKey("Name")); + Assert.AreEqual("Global Value", telemetry.Properties["Name"]); + Assert.IsTrue(telemetry.Properties.ContainsKey("Name_1"), "Key name altered"); + Assert.AreEqual("Value", telemetry.Properties["Name_1"]); } [TestMethod] @@ -459,6 +459,62 @@ public void NLogTargetFlushesTelemetryClient() Assert.AreEqual("Flush called", flushException.Message); } + [TestMethod] + [TestCategory("NLogTarget")] + public void NLogInfoIsSentAsInformationTraceItemWithAIConnectionString() + { + var aiLogger = this.CreateTargetWithGivenConnectionString("Your_ApplicationInsights_ConnectionString"); + aiLogger.Info("Info message"); + + var telemetry = (TraceTelemetry)this.adapterHelper.Channel.SentItems.First(); + Assert.AreEqual($"Info message", telemetry.Message); + } + + [TestMethod] + [TestCategory("NLogTarget")] + public void NLogTraceIsSentAsVerboseTraceItemWithAIConnectionString() + { + var aiLogger = this.CreateTargetWithGivenConnectionString("Your_ApplicationInsights_ConnectionString"); + aiLogger.Trace("Trace message"); + + var telemetry = (TraceTelemetry)this.adapterHelper.Channel.SentItems.FirstOrDefault(); + Assert.AreEqual("Trace message", telemetry.Message); + } + + [TestMethod] + [TestCategory("NLogTarget")] + public void NLogDebugIsSentAsVerboseTraceItemWithAIConnectionString() + { + var aiLogger = this.CreateTargetWithGivenConnectionString("Your_ApplicationInsights_ConnectionString"); + aiLogger.Debug("Debug Message"); + + var telemetry = (TraceTelemetry)this.adapterHelper.Channel.SentItems.FirstOrDefault(); + Assert.AreEqual("Debug Message", telemetry.Message); + } + + [TestMethod] + [TestCategory("NLogTarget")] + public void NLogWarnIsSentAsWarningTraceItemWithAIConnectionString() + { + var aiLogger = this.CreateTargetWithGivenConnectionString("Your_ApplicationInsights_ConnectionString"); + + aiLogger.Warn("Warn message"); + + var telemetry = (TraceTelemetry)this.adapterHelper.Channel.SentItems.FirstOrDefault(); + Assert.AreEqual("Warn message", telemetry.Message); + } + + [TestMethod] + [TestCategory("NLogTarget")] + public void NLogErrorIsSentAsVerboseTraceItemWithAIConnectionString() + { + var aiLogger = this.CreateTargetWithGivenConnectionString("Your_ApplicationInsights_ConnectionString"); + aiLogger.Error("Error Message"); + + var telemetry = (TraceTelemetry)this.adapterHelper.Channel.SentItems.FirstOrDefault(); + Assert.AreEqual("Error Message", telemetry.Message); + } + private void VerifyMessagesInMockChannel(Logger aiLogger, string instrumentationKey) { aiLogger.Trace("Sample trace message"); @@ -504,5 +560,38 @@ private Logger CreateTargetWithGivenInstrumentationKey( return aiLogger; } + + private Logger CreateTargetWithGivenConnectionString( + string connectionString = "Your_ApplicationInsights_ConnectionString", + Action loggerAction = null) + { + // Mock channel to validate that our appender is trying to send logs +#pragma warning disable CS0618 // Type or member is obsolete + TelemetryConfiguration.Active.TelemetryChannel = this.adapterHelper.Channel; +#pragma warning restore CS0618 // Type or member is obsolete + + ApplicationInsightsTarget target = new ApplicationInsightsTarget + { + ConnectionString = connectionString + }; + + LoggingRule rule = new LoggingRule("*", LogLevel.Trace, target); + LoggingConfiguration config = new LoggingConfiguration(); + config.AddTarget("AITarget", target); + config.LoggingRules.Add(rule); + + LogManager.Configuration = config; + Logger aiLogger = LogManager.GetLogger("AITarget"); + + if (loggerAction != null) + { + loggerAction(aiLogger); + target.Dispose(); + return null; + } + + return aiLogger; + } + } } diff --git a/LOGGING/test/Shared/AdapterHelper.cs b/LOGGING/test/Shared/AdapterHelper.cs index 9b926f8599..a59dcac7bf 100644 --- a/LOGGING/test/Shared/AdapterHelper.cs +++ b/LOGGING/test/Shared/AdapterHelper.cs @@ -19,6 +19,8 @@ public class AdapterHelper : IDisposable { public string InstrumentationKey { get; } + public string ConnectionString { get; } + #if NET452 || NET46 private static readonly string ApplicationInsightsConfigFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ApplicationInsights.config"); @@ -27,16 +29,19 @@ public class AdapterHelper : IDisposable Path.Combine(Path.GetDirectoryName(typeof(AdapterHelper).GetTypeInfo().Assembly.Location), "ApplicationInsights.config"); #endif - public AdapterHelper(string instrumentationKey = "F8474271-D231-45B6-8DD4-D344C309AE69") + public AdapterHelper(string instrumentationKey = "F8474271-D231-45B6-8DD4-D344C309AE69", + string connectionString= "Your_ApplicationInsights_ConnectionString") { this.InstrumentationKey = instrumentationKey; + this.ConnectionString = connectionString; string configuration = string.Format(InvariantCulture, @" {0} + {1} ", - instrumentationKey); + instrumentationKey, connectionString); File.WriteAllText(ApplicationInsightsConfigFilePath, configuration); this.Channel = new CustomTelemetryChannel();