/// <summary> /// Checks the and repairs BLOB name acording to the Azure naming rules. /// </summary> /// <param name="blobName">Name of the BLOB.</param> /// <returns></returns> private static string CheckAndRepairBlobNamingRules(string blobName) { /* https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/naming-and-referencing-containers--blobs--and-metadata * Blob Names * * A blob name must conforming to the following naming rules: * A blob name can contain any combination of characters. * A blob name must be at least one character long and cannot be more than 1,024 characters long. * Blob names are case-sensitive. * Reserved URL characters must be properly escaped. * * The number of path segments comprising the blob name cannot exceed 254. * A path segment is the string between consecutive delimiter characters (e.g., the forward slash '/') that corresponds to the name of a virtual directory. */ if (String.IsNullOrWhiteSpace(blobName) || blobName.Length > 1024) { var blobDefault = String.Concat("Log-", DateTime.UtcNow.ToString("yy-MM-dd"), ".log"); InternalLogger.Error("Invalid Blob Name provided: {0} | Using default: {1}", blobName, blobDefault); return(blobDefault); } InternalLogger.Trace("Using provided blob name: {0}", blobName); return(blobName); }
/// <summary> /// Closes this instance. /// </summary> public override void Close() { if (this._file == null) { return; } InternalLogger.Trace("Closing '{0}'", FileName); try { this._file.Close(); } catch (Exception ex) { // Swallow exception as the file-stream now is in final state (broken instead of closed) InternalLogger.Warn(ex, "Failed to close file '{0}'", FileName); System.Threading.Thread.Sleep(1); // Artificial delay to avoid hammering a bad file location } finally { this._file = null; } }
/// <summary> /// Closes this instance. /// </summary> public override void Close() { if (_file == null) { return; } InternalLogger.Trace("Closing '{0}'", FileName); try { _file.Close(); } catch (Exception ex) { // Swallow exception as the file-stream now is in final state (broken instead of closed) InternalLogger.Warn(ex, "Failed to close file '{0}'", FileName); AsyncHelpers.WaitForDelay(TimeSpan.FromMilliseconds(1)); // Artificial delay to avoid hammering a bad file location } finally { _file = null; } }
/// <summary> /// Closes all targets and releases any unmanaged resources. /// </summary> internal void Close() { InternalLogger.Debug("Closing logging configuration..."); foreach (ISupportsInitialize initialize in this.configItems.OfType <ISupportsInitialize>()) { InternalLogger.Trace("Closing {0}", initialize); try { initialize.Close(); } catch (Exception exception) { if (exception.MustBeRethrown()) { throw; } InternalLogger.Warn("Exception while closing {0}", exception); } } InternalLogger.Debug("Finished closing logging configuration."); }
/// <summary> /// Evaluate all the rules to get the filtering condition /// </summary> /// <param name="logEvents"></param> /// <returns></returns> private ConditionExpression EvaluateAllRules(IList <AsyncLogEventInfo> logEvents) { if (Rules.Count == 0) { return(null); } for (int i = 0; i < logEvents.Count; ++i) { for (int j = 0; j < Rules.Count; ++j) { var rule = Rules[j]; object v = rule.Exists.Evaluate(logEvents[i].LogEvent); if (boxedTrue.Equals(v)) { InternalLogger.Trace("PostFilteringWrapper(Name={0}): Rule matched: {1}", Name, rule.Exists); return(rule.Filter); } } } return(null); }
/// <summary> /// Closes this instance. /// </summary> public override void Close() { if (_fileStream == null) { return; } InternalLogger.Trace("Closing '{0}'", FileName); try { _fileStream?.Dispose(); } catch (Exception ex) { InternalLogger.Warn(ex, "Failed to close file '{0}'", FileName); Thread.Sleep(1); // Artificial delay to avoid hammering a bad file location } finally { _fileStream = null; } FileTouched(); }
/// <summary> /// Closes this instance. /// </summary> public override void Close() { if (_mutex == null && _fileStream == null) { return; } InternalLogger.Trace("{0}: Closing '{1}'", CreateFileParameters, FileName); try { _mutex?.Close(); } catch (Exception ex) { // Swallow exception as the mutex now is in final state (abandoned instead of closed) InternalLogger.Warn(ex, "{0}: Failed to close mutex: '{1}'", CreateFileParameters, FileName); } finally { _mutex = null; } try { _fileStream?.Close(); } catch (Exception ex) { // Swallow exception as the file-stream now is in final state (broken instead of closed) InternalLogger.Warn(ex, "{0}: Failed to close file: '{1}'", CreateFileParameters, FileName); AsyncHelpers.WaitForDelay(TimeSpan.FromMilliseconds(1)); // Artificial delay to avoid hammering a bad file location } finally { _fileStream = null; } }
private void RecursiveRollingRename(string fileName, string pattern, int archiveNumber) { if (archiveNumber >= this.MaxArchiveFiles) { File.Delete(fileName); return; } if (!File.Exists(fileName)) { return; } string newFileName = ReplaceNumber(pattern, archiveNumber); if (File.Exists(fileName)) { this.RecursiveRollingRename(newFileName, pattern, archiveNumber + 1); } InternalLogger.Trace("Renaming {0} to {1}", fileName, newFileName); try { File.Move(fileName, newFileName); } catch (IOException) { string dir = Path.GetDirectoryName(newFileName); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } File.Move(fileName, newFileName); } }
private void SendBatch(ICollection <AsyncLogEventInfo> events) { try { var logEvents = events.Select(e => e.LogEvent); var payload = FormPayload(logEvents); var result = _client.Bulk <byte[]>(payload); if (!result.Success) { var errorMessage = result.OriginalException?.Message ?? "No error message. Enable Trace logging for more information."; InternalLogger.Error($"Failed to send log messages to elasticsearch: status={result.HttpStatusCode}, message=\"{errorMessage}\""); InternalLogger.Trace($"Failed to send log messages to elasticsearch: result={result}"); if (result.OriginalException != null) { throw result.OriginalException; } } foreach (var ev in events) { ev.Continuation(null); } } catch (Exception ex) { InternalLogger.Error($"Error while sending log messages to elasticsearch: message=\"{ex.Message}\""); foreach (var ev in events) { ev.Continuation(ex); } } }
/// <summary> /// Evaluates all filtering rules to find the first one that matches. /// The matching rule determines the filtering condition to be applied /// to all items in a buffer. If no condition matches, default filter /// is applied to the array of log events. /// </summary> /// <param name="logEvents">Array of log events to be post-filtered.</param> protected override void Write(IList <AsyncLogEventInfo> logEvents) { InternalLogger.Trace("PostFilteringWrapper(Name={0}): Running on {1} events", Name, logEvents.Count); var resultFilter = EvaluateAllRules(logEvents) ?? DefaultFilter; if (resultFilter == null) { WrappedTarget.WriteAsyncLogEvents(logEvents); } else { InternalLogger.Trace("PostFilteringWrapper(Name={0}): Filter to apply: {1}", Name, resultFilter); var resultBuffer = ApplyFilter(logEvents, resultFilter); InternalLogger.Trace("PostFilteringWrapper(Name={0}): After filtering: {1} events.", Name, resultBuffer.Count); if (resultBuffer.Count > 0) { InternalLogger.Trace("PostFilteringWrapper(Name={0}): Sending to {1}", Name, WrappedTarget); WrappedTarget.WriteAsyncLogEvents(resultBuffer); } } }
/// <summary> /// Gets the bytes to be written. /// </summary> /// <param name="logEvent">Log event.</param> /// <returns>Byte array.</returns> protected virtual byte[] GetBytesToWrite(LogEventInfo logEvent) { if (OptimizeBufferReuse) { using (var localBuffer = _reusableEncodingBuffer.Allocate()) { if (!NewLine && logEvent.TryGetCachedLayoutValue(Layout, out var text)) { return(GetBytesFromString(localBuffer.Result, text?.ToString() ?? string.Empty)); } else { using (var localBuilder = ReusableLayoutBuilder.Allocate()) { Layout.RenderAppendBuilder(logEvent, localBuilder.Result, false); if (NewLine) { localBuilder.Result.Append(LineEnding.NewLineCharacters); } return(GetBytesFromStringBuilder(localBuffer.Result, localBuilder.Result)); } } } } else { var rendered = Layout.Render(logEvent); InternalLogger.Trace("NetworkTarget(Name={0}): Sending: {1}", Name, rendered); if (NewLine) { rendered += LineEnding.NewLineCharacters; } return(Encoding.GetBytes(rendered)); } }
private async Task Post(string payload) { var content = new StringContent(payload, Encoding.UTF8, _content); int?status = null; try { InternalLogger.Trace("Sending payload to Datadog: {0}", payload); var result = await _client.PostAsync(_url, content).ConfigureAwait(false); status = result == null ? null : (int?)result.StatusCode; InternalLogger.Trace("Statuscode: {0}", status); if (result?.IsSuccessStatusCode == true) { return; } } catch (Exception e) { InternalLogger.Error(status == null ? "Error sending payload (protocol=HTTP):\n{1}" : "Error sending payload (protocol=HTTP, status={0}):\n{1}", status, e); } throw new CannotSendLogEventException(); }
private void WaitForBelowRequestLimit() { long currentCount; bool lockTaken = false; try { // Attempt to yield using SpinWait currentCount = TrySpinWaitForLowerCount(); // If yield did not help, then wait on a lock while (currentCount > RequestLimit) { Interlocked.Decrement(ref _count); InternalLogger.Debug("Blocking because the overflow action is Block..."); if (!lockTaken) { Monitor.Enter(_logEventInfoQueue); } else { Monitor.Wait(_logEventInfoQueue); } lockTaken = true; InternalLogger.Trace("Entered critical section."); currentCount = Interlocked.Increment(ref _count); } } finally { if (lockTaken) { Monitor.Exit(_logEventInfoQueue); } } }
protected override void Write(AsyncLogEventInfo logEvent) { // This assertion is flawed. // If threads run slow, then AsyncTargetWrapper will flush multiple times. // We cannot expect FlushCount to be lower than WriteCount, since Flush run on a timer thread, whereas // Write run on a threadpool thread. //Assert.True(this.FlushCount <= this.WriteCount); Interlocked.Increment(ref this.WriteCount); if (this.WriteCount % 100 == 0) { InternalLogger.Trace("{0} - Writen 100", DateTime.UtcNow.ToString("yyyy-MM-dd hh:mm:ss.ffff")); } ThreadPool.QueueUserWorkItem( s => { try { if (this.ThrowExceptions) { logEvent.Continuation(new InvalidOperationException("Some problem!")); logEvent.Continuation(new InvalidOperationException("Some problem!")); } else { logEvent.Continuation(null); logEvent.Continuation(null); } } catch (Exception e) { InternalLogger.Trace("Unexopected Exception", e); logEvent.Continuation(e); } }); }
protected virtual void WriteEventToDatabase(LogEventInfo logEvent) { //Always suppress transaction so that the caller does not rollback logging if they are rolling back their transaction. using (TransactionScope transactionScope = new TransactionScope(TransactionScopeOption.Suppress)) { EnsureConnectionOpen(BuildConnectionString(logEvent)); using (IDbCommand command = _activeConnection.CreateCommand()) { command.CommandText = RenderLogEvent(CommandText, logEvent); command.CommandType = CommandType; InternalLogger.Trace("DatabaseTarget(Name={0}): Executing {1}: {2}", Name, command.CommandType, command.CommandText); AddParametersToCommand(command, Parameters, logEvent); int result = command.ExecuteNonQuery(); InternalLogger.Trace("DatabaseTarget(Name={0}): Finished execution, result = {1}", Name, result); } //not really needed as there is no transaction at all. transactionScope.Complete(); } }
/// <summary> /// Adds the specified log event to the buffer and flushes /// the buffer in case the buffer gets full. /// </summary> /// <param name="logEvent">The log event.</param> protected override void Write(AsyncLogEventInfo logEvent) { this.WrappedTarget.PrecalculateVolatileLayouts(logEvent.LogEvent); int count = this.buffer.Append(logEvent); if (count >= this.BufferSize) { InternalLogger.Trace("BufferingWrapper '{0}': writing {1} events because of exceeding buffersize ({0}).", Name, count); AsyncLogEventInfo[] events = this.buffer.GetEventsAndClear(); this.WrappedTarget.WriteAsyncLogEvents(events); } else { if (this.FlushTimeout > 0) { // reset the timer on first item added to the buffer or whenever SlidingTimeout is set to true if (this.SlidingTimeout || count == 1) { this.flushTimer.Change(this.FlushTimeout, -1); } } } }
/// <summary> /// Enqueues another item. If the queue is overflown the appropriate /// action is taken as specified by <see cref="OnOverflow"/>. /// </summary> /// <param name="logEventInfo">The log event info.</param> public void Enqueue(AsyncLogEventInfo logEventInfo) { lock (this) { if (this.logEventInfoQueue.Count >= this.RequestLimit) { InternalLogger.Debug("Async queue is full"); switch (this.OnOverflow) { case AsyncTargetWrapperOverflowAction.Discard: InternalLogger.Debug("Discarding one element from queue"); this.logEventInfoQueue.Dequeue(); break; case AsyncTargetWrapperOverflowAction.Grow: InternalLogger.Debug("The overflow action is Grow, adding element anyway"); break; #if !NET_CF case AsyncTargetWrapperOverflowAction.Block: while (this.logEventInfoQueue.Count >= this.RequestLimit) { InternalLogger.Debug("Blocking because the overflow action is Block..."); System.Threading.Monitor.Wait(this); InternalLogger.Trace("Entered critical section."); } InternalLogger.Trace("Limit ok."); break; #endif } } this.logEventInfoQueue.Enqueue(logEventInfo); } }
/// <summary> /// Implemented by subclasses to render request information and append it to the specified <see cref="StringBuilder" />. /// /// Won't be called if <see cref="AspNetLayoutRendererBase.HttpContextAccessor"/> of <see cref="IHttpContextAccessor.HttpContext"/> is <c>null</c>. /// </summary> /// <param name="builder">The <see cref="StringBuilder"/> to append the rendered data to.</param> /// <param name="logEvent">Logging event.</param> protected override void Append(StringBuilder builder, LogEventInfo logEvent) { InternalLogger.Trace("Using ${assembly-version} of NLog.Web"); var nameNotEmpty = !string.IsNullOrEmpty(Name); if (nameNotEmpty) { var assembly = Assembly.Load(new AssemblyName(Name)); if (assembly == null) { builder.Append("Could not find assembly " + Name); } else { builder.Append(assembly.GetName().Version.ToString()); } } else { string assemblyVersion = GetAssemblyVersion(); builder.Append(assemblyVersion ?? "Could not entry assembly"); } }
private void ProcessMessage(MessageRecord messageRecord) { InternalLogger.Trace(string.Format(Properties.Strings.WebEndpoint_ProcessingMessage, messageRecord.Id, messageRecord.ContentType), nameof(WebEndpoint)); var isPipelineFound = false; foreach (IMessagePipeline pipeline in pipelines) { if (pipeline.MessageTypes.Contains(messageRecord.Type)) { var converter = pipeline as IMessageRecordConverter; if (converter != null) { var pipelineService = new DefaultMessagePipelineService(); pipelineService.ServiceProvider = serviceProviderFactory.Create(); var message = converter.CreateMessageContext(pipelineService, messageRecord); try { pipeline.Invoke(message); } finally { var disposable = pipelineService.ServiceProvider as IDisposable; disposable?.Dispose(); } } isPipelineFound = true; } } if (!isPipelineFound) { InternalLogger.Warn(string.Format(Properties.Strings.WebEndpoint_PipelineNotFound, messageRecord.Type, messageRecord.Id, messageRecord.ContentType), nameof(WebEndpoint)); } }
private static AsyncContinuation CountedWrap(AsyncContinuation originalContinuation, int counter) { if (counter == 1) { return(originalContinuation); } var exceptions = new List <Exception>(); AsyncContinuation wrapper = ex => { if (ex != null) { lock (exceptions) { exceptions.Add(ex); } } int c = Interlocked.Decrement(ref counter); if (c == 0) { var combinedException = AsyncHelpers.GetCombinedException(exceptions); InternalLogger.Trace("Combined exception: {0}", combinedException); originalContinuation(combinedException); } else { InternalLogger.Trace("{0} remaining.", c); } }; return(wrapper); }
private void ProcessSingleMailMessage(List <AsyncLogEventInfo> events) { try { LogEventInfo firstEvent = events[0].LogEvent; LogEventInfo lastEvent = events[events.Count - 1].LogEvent; // unbuffered case, create a local buffer, append header, body and footer var bodyBuffer = new StringBuilder(); if (this.Header != null) { bodyBuffer.Append(this.Header.Render(firstEvent)); if (this.AddNewLines) { bodyBuffer.Append("\n"); } } foreach (AsyncLogEventInfo eventInfo in events) { bodyBuffer.Append(this.Layout.Render(eventInfo.LogEvent)); if (this.AddNewLines) { bodyBuffer.Append("\n"); } } if (this.Footer != null) { bodyBuffer.Append(this.Footer.Render(lastEvent)); if (this.AddNewLines) { bodyBuffer.Append("\n"); } } using (var msg = new MailMessage()) { this.SetupMailMessage(msg, lastEvent); msg.Body = bodyBuffer.ToString(); using (ISmtpClient client = this.CreateSmtpClient()) { client.Host = this.SmtpServer.Render(lastEvent); client.Port = this.SmtpPort; client.EnableSsl = this.EnableSsl; InternalLogger.Debug("Sending mail to {0} using {1}:{2} (ssl={3})", msg.To, client.Host, client.Port, client.EnableSsl); InternalLogger.Trace(" Subject: '{0}'", msg.Subject); InternalLogger.Trace(" From: '{0}'", msg.From.ToString()); if (this.SmtpAuthentication == SmtpAuthenticationMode.Ntlm) { InternalLogger.Trace(" Using NTLM authentication."); client.Credentials = CredentialCache.DefaultNetworkCredentials; } else if (this.SmtpAuthentication == SmtpAuthenticationMode.Basic) { string username = this.SmtpUserName.Render(lastEvent); string password = this.SmtpPassword.Render(lastEvent); InternalLogger.Trace(" Using basic authentication: Username='******' Password='******'", username, new string('*', password.Length)); client.Credentials = new NetworkCredential(username, password); } client.Send(msg); foreach (var ev in events) { ev.Continuation(null); } } } } catch (Exception exception) { if (exception.MustBeRethrown()) { throw; } foreach (var ev in events) { ev.Continuation(exception); } } }
private void RunInstallCommands(InstallationContext installationContext, IEnumerable <DatabaseCommandInfo> commands) { // create log event that will be used to render all layouts LogEventInfo logEvent = installationContext.CreateLogEvent(); try { foreach (var commandInfo in commands) { string cs; if (commandInfo.ConnectionString != null) { // if there is connection string specified on the command info, use it cs = RenderLogEvent(commandInfo.ConnectionString, logEvent); } else if (InstallConnectionString != null) { // next, try InstallConnectionString cs = RenderLogEvent(InstallConnectionString, logEvent); } else { // if it's not defined, fall back to regular connection string cs = BuildConnectionString(logEvent); } // Set ConnectionType if it has not been initialized already if (ConnectionType == null) { SetConnectionType(); } EnsureConnectionOpen(cs); using (var command = _activeConnection.CreateCommand()) { command.CommandType = commandInfo.CommandType; command.CommandText = RenderLogEvent(commandInfo.Text, logEvent); try { installationContext.Trace("Executing {0} '{1}'", command.CommandType, command.CommandText); command.ExecuteNonQuery(); } catch (Exception exception) { if (exception.MustBeRethrownImmediately()) { throw; } if (commandInfo.IgnoreFailures || installationContext.IgnoreFailures) { installationContext.Warning(exception.Message); } else { installationContext.Error(exception.Message); throw; } } } } } finally { InternalLogger.Trace("DatabaseTarget: close connection after install."); CloseConnection(); } }
/// <summary> /// Sends the /// rendered logging event over the network optionally concatenating it with a newline character. /// </summary> /// <param name="logEvent">The logging event.</param> protected override void Write(AsyncLogEventInfo logEvent) { string address = this.Address.Render(logEvent.LogEvent); byte[] bytes = this.GetBytesToWrite(logEvent.LogEvent); if (this.KeepConnection) { var senderNode = this.GetCachedNetworkSender(address); this.ChunkedSend( senderNode.Value, bytes, ex => { if (ex != null) { InternalLogger.Error(ex, "Error when sending."); this.ReleaseCachedConnection(senderNode); } logEvent.Continuation(ex); }); } else { NetworkSender sender; LinkedListNode <NetworkSender> linkedListNode; lock (this.openNetworkSenders) { //handle too many connections var tooManyConnections = this.openNetworkSenders.Count >= MaxConnections; if (tooManyConnections && MaxConnections > 0) { switch (this.OnConnectionOverflow) { case NetworkTargetConnectionsOverflowAction.DiscardMessage: InternalLogger.Warn("Discarding message otherwise to many connections."); logEvent.Continuation(null); return; case NetworkTargetConnectionsOverflowAction.AllowNewConnnection: InternalLogger.Debug("Too may connections, but this is allowed"); break; case NetworkTargetConnectionsOverflowAction.Block: while (this.openNetworkSenders.Count >= this.MaxConnections) { InternalLogger.Debug("Blocking networktarget otherwhise too many connections."); System.Threading.Monitor.Wait(this.openNetworkSenders); InternalLogger.Trace("Entered critical section."); } InternalLogger.Trace("Limit ok."); break; } } sender = this.SenderFactory.Create(address, MaxQueueSize); sender.Initialize(); linkedListNode = this.openNetworkSenders.AddLast(sender); } this.ChunkedSend( sender, bytes, ex => { lock (this.openNetworkSenders) { TryRemove(this.openNetworkSenders, linkedListNode); if (this.OnConnectionOverflow == NetworkTargetConnectionsOverflowAction.Block) { System.Threading.Monitor.PulseAll(this.openNetworkSenders); } } if (ex != null) { InternalLogger.Error(ex, "Error when sending."); } sender.Close(ex2 => { }); logEvent.Continuation(ex); }); } }
/// <summary> /// Evaluates all filtering rules to find the first one that matches. /// The matching rule determines the filtering condition to be applied /// to all items in a buffer. If no condition matches, default filter /// is applied to the array of log events. /// </summary> /// <param name="logEvents">Array of log events to be post-filtered.</param> protected override void Write(AsyncLogEventInfo[] logEvents) { ConditionExpression resultFilter = null; InternalLogger.Trace("Running {0} on {1} events", this, logEvents.Length); // evaluate all the rules to get the filtering condition for (var i = 0; i < logEvents.Length; ++i) { foreach (var rule in Rules) { var v = rule.Exists.Evaluate(logEvents[i].LogEvent); if (boxedTrue.Equals(v)) { InternalLogger.Trace("Rule matched: {0}", rule.Exists); resultFilter = rule.Filter; break; } } if (resultFilter != null) { break; } } if (resultFilter == null) { resultFilter = DefaultFilter; } if (resultFilter == null) { WrappedTarget.WriteAsyncLogEvents(logEvents); } else { InternalLogger.Trace("Filter to apply: {0}", resultFilter); // apply the condition to the buffer var resultBuffer = new List <AsyncLogEventInfo>(); for (var i = 0; i < logEvents.Length; ++i) { var v = resultFilter.Evaluate(logEvents[i].LogEvent); if (boxedTrue.Equals(v)) { resultBuffer.Add(logEvents[i]); } else { // anything not passed down will be notified about successful completion logEvents[i].Continuation(null); } } InternalLogger.Trace("After filtering: {0} events.", resultBuffer.Count); if (resultBuffer.Count > 0) { InternalLogger.Trace("Sending to {0}", WrappedTarget); WrappedTarget.WriteAsyncLogEvents(resultBuffer.ToArray()); } } }
/// <summary> /// Closes the target and releases any unmanaged resources. /// </summary> protected override void CloseTarget() { base.CloseTarget(); InternalLogger.Trace("DatabaseTarget: close connection because of CloseTarget"); CloseConnection(); }
public void WriteToStringWriterTests() { try { // Expected result is the same for both types of method invocation. const string expected = "Warn WWW\nError EEE\nFatal FFF\nTrace TTT\nDebug DDD\nInfo III\n"; InternalLogger.LogLevel = LogLevel.Trace; InternalLogger.IncludeTimestamp = false; { StringWriter writer1 = new StringWriter() { NewLine = "\n" }; InternalLogger.LogWriter = writer1; // Named (based on LogLevel) public methods. InternalLogger.Warn("WWW"); InternalLogger.Error("EEE"); InternalLogger.Fatal("FFF"); InternalLogger.Trace("TTT"); InternalLogger.Debug("DDD"); InternalLogger.Info("III"); TestWriter(expected, writer1); } { // // Reconfigure the LogWriter. StringWriter writer2 = new StringWriter() { NewLine = "\n" }; InternalLogger.LogWriter = writer2; // Invoke Log(LogLevel, string) for every log level. InternalLogger.Log(LogLevel.Warn, "WWW"); InternalLogger.Log(LogLevel.Error, "EEE"); InternalLogger.Log(LogLevel.Fatal, "FFF"); InternalLogger.Log(LogLevel.Trace, "TTT"); InternalLogger.Log(LogLevel.Debug, "DDD"); InternalLogger.Log(LogLevel.Info, "III"); TestWriter(expected, writer2); } { // // Reconfigure the LogWriter. StringWriter writer2 = new StringWriter() { NewLine = "\n" }; InternalLogger.LogWriter = writer2; // Invoke Log(LogLevel, string) for every log level. InternalLogger.Log(LogLevel.Warn, () => "WWW"); InternalLogger.Log(LogLevel.Error, () => "EEE"); InternalLogger.Log(LogLevel.Fatal, () => "FFF"); InternalLogger.Log(LogLevel.Trace, () => "TTT"); InternalLogger.Log(LogLevel.Debug, () => "DDD"); InternalLogger.Log(LogLevel.Info, () => "III"); TestWriter(expected, writer2); } } finally { InternalLogger.Reset(); } }
public void ExceptionTests() { using (new InternalLoggerScope()) { InternalLogger.LogLevel = LogLevel.Trace; InternalLogger.IncludeTimestamp = false; var ex1 = new Exception("e1"); var ex2 = new Exception("e2", new Exception("inner")); var ex3 = new NLogConfigurationException("config error"); var ex4 = new NLogConfigurationException("config error", ex2); var ex5 = new PathTooLongException(); ex5.Data["key1"] = "value1"; Exception ex6 = null; const string prefix = " Exception: "; { string expected = "Warn WWW1" + prefix + ex1 + Environment.NewLine + "Error EEE1" + prefix + ex2 + Environment.NewLine + "Fatal FFF1" + prefix + ex3 + Environment.NewLine + "Trace TTT1" + prefix + ex4 + Environment.NewLine + "Debug DDD1" + prefix + ex5 + Environment.NewLine + "Info III1" + Environment.NewLine; StringWriter consoleOutWriter = new StringWriter() { NewLine = Environment.NewLine }; // Redirect the console output to a StringWriter. InternalLogger.LogWriter = consoleOutWriter; // Named (based on LogLevel) public methods. InternalLogger.Warn(ex1, "WWW1"); InternalLogger.Error(ex2, "EEE1"); InternalLogger.Fatal(ex3, "FFF1"); InternalLogger.Trace(ex4, "TTT1"); InternalLogger.Debug(ex5, "DDD1"); InternalLogger.Info(ex6, "III1"); consoleOutWriter.Flush(); var strings = consoleOutWriter.ToString(); Assert.Equal(expected, strings); } { string expected = "Warn WWW2" + prefix + ex1 + Environment.NewLine + "Error EEE2" + prefix + ex2 + Environment.NewLine + "Fatal FFF2" + prefix + ex3 + Environment.NewLine + "Trace TTT2" + prefix + ex4 + Environment.NewLine + "Debug DDD2" + prefix + ex5 + Environment.NewLine + "Info III2" + Environment.NewLine; StringWriter consoleOutWriter = new StringWriter() { NewLine = Environment.NewLine }; // Redirect the console output to a StringWriter. InternalLogger.LogWriter = consoleOutWriter; // Named (based on LogLevel) public methods. InternalLogger.Warn(ex1, () => "WWW2"); InternalLogger.Error(ex2, () => "EEE2"); InternalLogger.Fatal(ex3, () => "FFF2"); InternalLogger.Trace(ex4, () => "TTT2"); InternalLogger.Debug(ex5, () => "DDD2"); InternalLogger.Info(ex6, () => "III2"); consoleOutWriter.Flush(); var strings = consoleOutWriter.ToString(); Assert.Equal(expected, strings); } { string expected = "Warn WWW3" + prefix + ex1 + Environment.NewLine + "Error EEE3" + prefix + ex2 + Environment.NewLine + "Fatal FFF3" + prefix + ex3 + Environment.NewLine + "Trace TTT3" + prefix + ex4 + Environment.NewLine + "Debug DDD3" + prefix + ex5 + Environment.NewLine + "Info III3" + Environment.NewLine; StringWriter consoleOutWriter = new StringWriter() { NewLine = Environment.NewLine }; // Redirect the console output to a StringWriter. InternalLogger.LogWriter = consoleOutWriter; // Named (based on LogLevel) public methods. InternalLogger.Log(ex1, LogLevel.Warn, "WWW3"); InternalLogger.Log(ex2, LogLevel.Error, "EEE3"); InternalLogger.Log(ex3, LogLevel.Fatal, "FFF3"); InternalLogger.Log(ex4, LogLevel.Trace, "TTT3"); InternalLogger.Log(ex5, LogLevel.Debug, "DDD3"); InternalLogger.Log(ex6, LogLevel.Info, "III3"); consoleOutWriter.Flush(); var strings = consoleOutWriter.ToString(); Assert.Equal(expected, strings); } { string expected = "Warn WWW4" + prefix + ex1 + Environment.NewLine + "Error EEE4" + prefix + ex2 + Environment.NewLine + "Fatal FFF4" + prefix + ex3 + Environment.NewLine + "Trace TTT4" + prefix + ex4 + Environment.NewLine + "Debug DDD4" + prefix + ex5 + Environment.NewLine + "Info III4" + Environment.NewLine; StringWriter consoleOutWriter = new StringWriter() { NewLine = Environment.NewLine }; // Redirect the console output to a StringWriter. InternalLogger.LogWriter = consoleOutWriter; // Named (based on LogLevel) public methods. InternalLogger.Log(ex1, LogLevel.Warn, () => "WWW4"); InternalLogger.Log(ex2, LogLevel.Error, () => "EEE4"); InternalLogger.Log(ex3, LogLevel.Fatal, () => "FFF4"); InternalLogger.Log(ex4, LogLevel.Trace, () => "TTT4"); InternalLogger.Log(ex5, LogLevel.Debug, () => "DDD4"); InternalLogger.Log(ex6, LogLevel.Info, () => "III4"); var strings = consoleOutWriter.ToString(); Assert.Equal(expected, strings); } } }
public void WriteToConsoleOutTests() { // Expected result is the same for both types of method invocation. const string expected = "Warn WWW\nError EEE\nFatal FFF\nTrace TTT\nDebug DDD\nInfo III\n"; using (var loggerScope = new InternalLoggerScope(true)) { InternalLogger.LogLevel = LogLevel.Trace; InternalLogger.IncludeTimestamp = false; InternalLogger.LogToConsole = true; { StringWriter consoleOutWriter1 = new StringWriter() { NewLine = "\n" }; // Redirect the console output to a StringWriter. loggerScope.SetConsoleOutput(consoleOutWriter1); // Named (based on LogLevel) public methods. InternalLogger.Warn("WWW"); InternalLogger.Error("EEE"); InternalLogger.Fatal("FFF"); InternalLogger.Trace("TTT"); InternalLogger.Debug("DDD"); InternalLogger.Info("III"); TestWriter(expected, consoleOutWriter1); } // // Redirect the console output to another StringWriter. { StringWriter consoleOutWriter2 = new StringWriter() { NewLine = "\n" }; loggerScope.SetConsoleOutput(consoleOutWriter2); // Invoke Log(LogLevel, string) for every log level. InternalLogger.Log(LogLevel.Warn, "WWW"); InternalLogger.Log(LogLevel.Error, "EEE"); InternalLogger.Log(LogLevel.Fatal, "FFF"); InternalLogger.Log(LogLevel.Trace, "TTT"); InternalLogger.Log(LogLevel.Debug, "DDD"); InternalLogger.Log(LogLevel.Info, "III"); TestWriter(expected, consoleOutWriter2); } //lambdas { StringWriter consoleOutWriter1 = new StringWriter() { NewLine = "\n" }; // Redirect the console output to a StringWriter. loggerScope.SetConsoleOutput(consoleOutWriter1); // Named (based on LogLevel) public methods. InternalLogger.Warn(() => "WWW"); InternalLogger.Error(() => "EEE"); InternalLogger.Fatal(() => "FFF"); InternalLogger.Trace(() => "TTT"); InternalLogger.Debug(() => "DDD"); InternalLogger.Info(() => "III"); TestWriter(expected, consoleOutWriter1); } } }
/// <summary> /// Parse {NLog} xml element. /// </summary> /// <param name="nlogElement"></param> /// <param name="filePath">path to config file.</param> /// <param name="autoReloadDefault">The default value for the autoReload option.</param> private void ParseNLogElement(NLogXmlElement nlogElement, string filePath, bool autoReloadDefault) { InternalLogger.Trace("ParseNLogElement"); nlogElement.AssertName("nlog"); if (nlogElement.GetOptionalBooleanAttribute("useInvariantCulture", false)) { this.DefaultCultureInfo = CultureInfo.InvariantCulture; } //check loglevel as first, as other properties could write (indirect) to the internal log. InternalLogger.LogLevel = LogLevel.FromString(nlogElement.GetOptionalAttribute("internalLogLevel", InternalLogger.LogLevel.Name)); #pragma warning disable 618 this.ExceptionLoggingOldStyle = nlogElement.GetOptionalBooleanAttribute("exceptionLoggingOldStyle", false); #pragma warning restore 618 bool autoReload = nlogElement.GetOptionalBooleanAttribute("autoReload", autoReloadDefault); if (filePath != null) { this.fileMustAutoReloadLookup[GetFileLookupKey(filePath)] = autoReload; } logFactory.ThrowExceptions = nlogElement.GetOptionalBooleanAttribute("throwExceptions", logFactory.ThrowExceptions); logFactory.ThrowConfigExceptions = nlogElement.GetOptionalBooleanAttribute("throwConfigExceptions", logFactory.ThrowConfigExceptions); InternalLogger.LogToConsole = nlogElement.GetOptionalBooleanAttribute("internalLogToConsole", InternalLogger.LogToConsole); InternalLogger.LogToConsoleError = nlogElement.GetOptionalBooleanAttribute("internalLogToConsoleError", InternalLogger.LogToConsoleError); InternalLogger.LogFile = nlogElement.GetOptionalAttribute("internalLogFile", InternalLogger.LogFile); #if !SILVERLIGHT && !__IOS__ && !__ANDROID__ InternalLogger.LogToTrace = nlogElement.GetOptionalBooleanAttribute("internalLogToTrace", InternalLogger.LogToTrace); #endif InternalLogger.IncludeTimestamp = nlogElement.GetOptionalBooleanAttribute("internalLogIncludeTimestamp", InternalLogger.IncludeTimestamp); logFactory.GlobalThreshold = LogLevel.FromString(nlogElement.GetOptionalAttribute("globalThreshold", logFactory.GlobalThreshold.Name)); var children = nlogElement.Children.ToList(); //first load the extensions, as the can be used in other elements (targets etc) var extensionsChilds = children.Where(child => child.LocalName.Equals("EXTENSIONS", StringComparison.InvariantCultureIgnoreCase)).ToList(); foreach (var extensionsChild in extensionsChilds) { this.ParseExtensionsElement(extensionsChild, Path.GetDirectoryName(filePath)); } //parse all other direct elements foreach (var child in children) { switch (child.LocalName.ToUpper(CultureInfo.InvariantCulture)) { case "EXTENSIONS": //already parsed break; case "INCLUDE": this.ParseIncludeElement(child, Path.GetDirectoryName(filePath), autoReloadDefault: autoReload); break; case "APPENDERS": case "TARGETS": this.ParseTargetsElement(child); break; case "VARIABLE": this.ParseVariableElement(child); break; case "RULES": this.ParseRulesElement(child, this.LoggingRules); break; case "TIME": this.ParseTimeElement(child); break; case "POOLING": this.ParsePoolingElement(child); break; default: InternalLogger.Warn("Skipping unknown node: {0}", child.LocalName); break; } } }
/// <summary> /// Registers the specified condition method under a specified name. /// </summary> /// <param name="name">Name of the condition method.</param> /// <param name="mi"><see cref="MethodInfo" /> of the method to be registered.</param> public static void AddConditionMethod(string name, MethodInfo mi) { InternalLogger.Trace("AddConditionMethod('{0}','{1}')", name, mi); _conditionMethods[name.ToLower(CultureInfo.InvariantCulture)] = mi; }