I am using Serilog library in a C# Console Application to build a Scheduler, which logs messages in a Log File for each day. The filenames are created dynamically using below code.
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.File("logs\\log-scheduler-.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
How can I get to know the Name of File that my Console application has created? At the end of my program, I want to email the log file as attachment.
Serilog doesn't expose a way to inspect the name of the file(s) that were created, as of this writing.
If you don't use a RollingInterval and have the log messages be written to a single file, then you know exactly what the name of the file is, because you already specified it in the log pipeline configuration: logs\\log-scheduler-.txt.
But if you want to use a RollingInterval then you what you could do, is to inspect the folder where your log files are being written to, and find the log file(s) that were updated since your application started, by capturing the current timestamp when your app starts, and then looking at the LastWriteTimeUtc attribute of the log files in the file system to see anything that has changed since that time.
e.g.
DateTime appStartTime = DateTime.UtcNow;
// ... (app code)
// Ensure that all messages are flushed to the file
Log.CloseAndFlush();
// Get all log files modified since the app started
var logFilesUpdatedInThisSession = new DirectoryInfo(#"C:\Temp\logs\")
.EnumerateFileSystemInfos("log-scheduler-*.txt")
.Where(f => f.LastWriteTimeUtc >= appStartTime)
.OrderBy(f => f.LastWriteTimeUtc)
.ToList();
if (logFilesUpdatedInThisSession.Any())
{
// Send all files via e-mail ...
}
Another alternative (better IMO) would be to not send e-mails at all from your app, and just ship the logs to a server, such as a Seq server which allows you to easily browse the logs, apply filters, etc., which is a much better experience than opening a log file attached to an e-mail on a text editor.
Related
I am writing an uwp app with C# and I would like to use serilog to write logfiles.
When I do it in a .NET Core Console application it creates the file with the wanted content.
In the uwp I can show the log messages on the GUI, but no log file is created (yes, I have broadFileSystemAccess).
My code:
Log.Logger = new LoggerConfiguration().WriteTo.File("log.txt").CreateLogger();
Log.Debug("TEST");
Log.CloseAndFlush();
I would expect that it creates log.txt file in the directory which can be get with Windows.Storage.ApplicationData.Current.LocalFolder like
storageFolder.CreateFileAsync("test.txt", CreationCollisionOption.ReplaceExisting);
does.
Can anyone tell me what I have to change or to consider to log to a file with serilog in my uwp app?
One of the great things about Serilog is that it's open-source and you can look at its source code and see what it is doing / how it works.
If you peek at the source code of the File sink, you'll notice that it is simply opening a file via System.IO.File.Open on the same folder where your app is running, which running from Visual Studio is probably going to be something like C:\Users\augustoproiete\MyApp\MyUwpApp\bin\x64\Debug\AppX\ where you don't have access to write file.
That means you have to be explicit about where to store the file, for example in the application data folder of your app. E.g.:
var logFilePath = Path.Combine(ApplicationData.Current.LocalFolder.Path, "log.txt");
Log.Logger = new LoggerConfiguration().WriteTo.File(logFilePath).CreateLogger();
Log.Debug("TEST");
Log.CloseAndFlush();
I'd recommend you read the Debugging and Diagnostics page on Serilog's docs, as it explains how you see error messages from Serilog - which you'd have seen that it was failing to create a file and the path it was using.
Thank yu for your answer!
I thought that the local folder path is automatically used, so I did not try that.
I jus had to modify the code as follows
var logFilePath = Path.Combine(ApplicationData.Current.LocalFolder.Path, "log.txt");
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose() //otherwise Debug is not logged
.WriteTo.File(logFilePath)
.CreateLogger();
Log.Debug("TEST");
Log.CloseAndFlush();
then it woked and wrote the Debug message to the log file :)
Thank you very much!
I want to be able to send application logs to Cloud Watch Log. and I got to know that there is a Cloud Watch Agent service that runs in the background and reads logs from log file and send only the delta (extra logs) to Cloud Watch Log. All this makes sense to me. Then I got to know about NLog a C# logging framework, and wrote below POC to send logs.
static void Main(string[] args)
{
ConfigureNLog();
var logger = NLog.LogManager.GetCurrentClassLogger();
logger.Info("Hello World");
logger.Log(LogLevel.Info, "Sample informational message");
}
static void ConfigureNLog()
{
var accessKey = ConfigurationManager.AppSettings.Get("AWSAccessKey");
var secretKey = ConfigurationManager.AppSettings.Get("AWSSecretKey");
var config = new LoggingConfiguration();
var awsTarget = new AWSTarget()
{
LogGroup = "NLog.ProgrammaticConfigurationExample",
Region = "us-east-1",
Credentials = new BasicAWSCredentials(accessKey, secretKey)
};
config.AddTarget("aws", awsTarget);
config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, awsTarget));
LogManager.Configuration = config;
}
Now when I run above code, I am able to send log to Cloud Watch. But I am confused now, where is the significance of Cloud Watch Agent?
Since I am directly sending log data, does that mean I don't need Cloud Watch Agent in my scenario?
In case I want to use Cloud Watch Agent then I need to use FILE as a target for logs by NLog and then tell Cloud Watch Agent to send that log file to Cloud Watch Log??
Is my understanding correct? Please help me in understanding the flow.
Is below flow correct?
NLog write log to File -> Cloud Agent read log from there -> Send log
to Cloud Watch
Question: How to use Cloud Watch Agent in above POC to send data via NLog?
Cloud Watch Agent runs on your server and can watch logs files that are produced. These log files can be anything, IIS Logs, Time Logs, Event Log, Etc. When the log file is updated, CWA will grab the updates and send to Cloud Watch. This is the generic behavior of the CWA and is great for Event Logs and OS logging.
By modifying the AWS.EC2.Windows.CloudWatch.json CWA json file, you can configure it to watch log files for certain formats and send changes to CW outside the standard/example ones it does by default. You can update the json to your NLog entry layout format and have it watch for that specific format in the file. CW Does have a delay sending.
Now you have Nlog which writes log files. You can have NLog send the log entries to a file and have the Cloud Watch Agent watch that file, pick up the change and send it or you can have NLog send the entries directly to CW. Since you are writing directly to CW through a NLog target, you don't need the Cloud Agent for your NLog files. I suggest keeping CWA for other log files like IIS or event logs.
I guess it is a matter a preference on how you do it. I think NLog Targets with layouts is easier than dealing with the CloudWatch json file to try and match the log format. I only use CWA to send log files I have no control over and use a NLog Target to send my NLog entries.
I can post an example CWA json snippet for a 3rd party log file I monitor with CWA if you need an example.
When an application just have to write to a file, then it lives a very simple life with few problems.
When an application suddenly have to handle network traffic (with timeouts, disconnects, retries, connectivity, latency, etc.) then it suddenly will have issues with things queuing up, taking memory, using sockets, causing garbage collections, stalls, etc. (And loosing all pending logevents on crash)
Depending on the lifetime of your application and the critically of your applications, then it can be useful to give it a simple life. And let a friend like Cloud Watch Agent worry about the network-stuff.
See also https://github.com/NLog/NLog.Extensions.Logging/wiki/NLog-cloud-logging-with-Azure-function-or-AWS-lambda
All log files need to be written per day in a rolling mode.
However, I have a question how can I implement the rolling log file for the current file without date,
we need the following logic:
.log => current log file
.log.date => old log files,
This the code what I implement however after executing I found the current file with the date.
var log = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.RollingFile(#"C:\project\SerilogFile.txt", retainedFileCountLimit: 7)
.CreateLogger();
I am trying to create an event log for a Windows Universal Application.
Earlier we had System.Diagnostics EventLog to log events, but I could not find anything similar on the Windows 10 Universal Apps platform.
Is it possible to create logs for Windows 10 and can these logs be written to a file for accessing it later?
I searched a lot, but could not find anything.
FileLoggingSession
Since Windows 8.1 there are FileLoggingSession and LoggingChannel classes in the Windows.Foundation.Diagnostics namespace, which can perform logging to files when configured to do so. You can read more in the official documentation.
Initialization, usage and retrieving the log file can be done like in the following snippet, of course you need to create interfaces, singletons etc. to make it usable:
// Initialization
FileLoggingSession fileLoggingSession = new FileLoggingSession("session");
var loggingChannel = new LoggingChannel("channel");
fileLoggingSession.AddLoggingChannel(loggingChannel);
// Log messages
loggingChannel.LogMessage("error message", LoggingLevel.Error);
// When file is needed
var file = await fileLoggingSession.CloseAndSaveToFileAsync();
// Do anything with file
LoggingSession
Just as FileLoggingSession writes logs to a file but the main difference is that FileLoggingSession writes logs immediately to the file, and LoggingSession does not, and you need to manually request writing the logs to a file with the SaveToFileAsync method. From the documentation:
The FileLoggingSession class sends logged messages to disk files as they are logged. The FileLoggingSession class uses sequential logging, which means that all messages are sent to a disk file, and a sequential history of messages is retained. This is distinct from the LoggingSession class, which sends logged messages to disk on-demand, and this happens when there's a problem and the immediate history of in-memory messages is needed for analysis.
MetroLog
You have another alternatives if you do not wan't to use FileLoggingSession or LoggingSession classes. One good solution is MetroLog which has a FileStreamingTarget target that makes it very simple to log in a Windows/Phone app.
You create the logger when you need it, for example in a page:
public sealed partial class LogSamplePage : Win8Sample.Common.LayoutAwarePage
{
private ILogger Log = LogManagerFactory.DefaultLogManager.GetLogger<LogSamplePage>();
}
Then you can use it in the page like this:
// flat strings...
if (this.Log.IsInfoEnabled)
this.Log.Info("I've been navigated to.");
// formatting...
if (this.Log.IsDebugEnabled)
this.Log.Debug("I can also format {0}.", "strings");
// errors...
try
{
this.DoMagic();
}
catch(Exception ex)
{
if (this.Log.IsWarnEnabled)
this.Log.Warn("You can also pass in exceptions.", ex);
}
MetroEventSource
The second solution is this logging sample on MSDN sample gallery by Can Bilgin where you have the MetroEventSource class. You can log messages for example an error like this:
MetroEventSource.Log.Error("Here is the error message");
If you use this logger don't forget to initialize it on application run, as described in the sample project.
I have a recent problem . I can upload file in my intetpub/wwwrooot/folder
But I can't write a log file in this same folder ...
I have all the permissions for the network service. Everything is on my server.
DirectoryInfo di = new DirectoryInfo(~/);
// Get a reference to each file in that directory.
FileInfo[] fiArr = di.GetFiles();
string strLogText = di;
// Create a writer and open the file:
StreamWriter log;
if (!System.IO.File.Exists("C:\\inetpub\\wwwroot\\logfile.txt"))
{
log = new StreamWriter("C:\\inetpub\\wwwroot\\logfile.txt");
}
else
{
log = System.IO.File.AppendText("C:\\inetpub\\wwwroot\\logfile.txt");
}
// Write to the file:
log.WriteLine(DateTime.Now);
log.WriteLine(strLogText);
log.WriteLine();
// Close the stream:
log.Close();
The error is the access is denied !
It works locally , but on my server it doesnt. On the folder Inetpub , I just need to allow writting for Network service ? That is strange because I can upload file and writting is already enable
Emged in case of exceptions your code does not close the streams on the log file and this is surely not good.
You should use a using statement around the streams so in any case streams are closed and disposed also in case of exceptions.
As Chris has suggested I would absolutely opt for a logging Framework and I would also avoid writing in that wwwroot folder.
ELMAH or NLog or Log4Net are good and easy alternatives far better than any custom logging lie you are doing right now and the big advantage of these technologies/libraries is that you can change the behaviour at runtime simply by editing the configuration file, no need to rebuild or redeploy anything...
my favourite is actually Log4Net, check these ones for a simple example on how to use it:
http://logging.apache.org/log4net/release/manual/configuration.html
Log4Net in App object?
Depending on the version of your server (windows 2008 and above), that directory has additional protection against writes.
I'd highly recommend you look into ELMAH to do your logging. It gives you a number of options including in memory or database backed and collects a LOT of additional data you might want.
Further, opening up various physical directory locations for write access is a HUGE security no-no.
On the server, is the web app running under an Application Pool that has alternate credentials, other than the normal network service account? If you haven't done so already, try turning on Auditing to see what user is trying to access the file.