I have the following code in my web.config file:
<system.diagnostics>
<trace autoflush="false" indentsize="4">
<listeners>
<add name="myListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="TextWriterOutput.log" />
<remove name="Default" />
</listeners>
</trace>
</system.diagnostics>
and somewhere in my code behind:
System.Diagnostics.Trace.WriteLine("From the trace");
After running the application, TextWriterOutput.log file was created successfully, but blank. However, after changing the autoflush attribute to true the trace wrote to TextWriterOutput.log.
I also noticed that I can make the trace write to TextWriteOutput.log by using
System.Diagnostics.Trace.Flush();
instead of modifying the autoflush attribute to true.
I read about it in
https://msdn.microsoft.com/en-us/library/system.diagnostics.trace.flush(v=vs.110).aspx
but it didn't make sense to me. Why the trace cannot write immediately to the output file? Can anyone explain in simple words why?
The Flush method forces the output to be written to the file. Setting the autoflush attribute to true causes Trace to always be written immediately to the file, instead of being buffered.
Related
I'm trying to debug what I believe is a WPF binding issue that is only happening on one machine in production -- I cannot repro on a developer machine. In order to do this, I've been trying to get the binding trace information to output to a log file. Following answers like this one, I've been able to get it to output to a hard-coded location by configuring it in App.config:
<system.diagnostics>
<sources>
<source name="System.Windows.Data" switchName="SourceSwitch" >
<listeners>
<add name="textListener" />
</listeners>
</source>
</sources>
<switches>
<add name="SourceSwitch" value="All" />
</switches>
<sharedListeners>
<add name="textListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="c:\BindingErrors.log" />
</sharedListeners>
<trace autoflush="true" indentsize="4"/>
</system.diagnostics>
This works fine on my machine where I have administrative rights to the c:\ drive. The problem is I want to write the log somewhere the user has rights to, e.g. their TEMP folder. So I want to do something like this, using the %TEMP% environmental variable:
initializeData="%TEMP%\BindingErrors.log"
This isn't working, though, and I guess it won't work -- see this answer; so, following the advice in that answer, I've attempted to configure the output via code instead of App.config. Here's what I've tried so far:
var listener = new
TextWriterTraceListener(Environment.ExpandEnvironmentVariables(
#"%TEMP%\BindingErrors.log"), "myListener");
Trace.Listeners.Add(listener);
Trace.WriteLine("foo"); // just to see if it works at all.
Trace.Flush();
But this only writes foo to the log file in the %TEMP% folder. It doesn't write the binding errors. I've tried to replicate what the App.config had, but there's no Sources collection, so when I instantiate a TraceSource, like this:
var source = new TraceSource("mySource", SourceLevels.Information);
I don't know what to do with it, and there's no Listeners collection to which I can add my listener instance.
MSDN doesn't seem to bring it all together for me, or I'm missing some critical details. Can someone please help me figure out what I'm doing wrong?
…there's no Listeners collection to which I can add my listener instance.
Actually, there is: PresentationTraceSources.DataBindingSource.Listeners
The property returns the TraceSource object that is used when data binding messages are output. You can add any listener to that source, such as a TextWriterTraceListener you've created in code-behind by expanding the %TEMP% environment variable and using that as the directory for your output file.
Note that the programmatic approach requires recompiling to change the output location, or the addition of some other configuration value that can be read at run-time. A different technique allows you to specify the entire configuration in the app.config file, by implementing a custom TraceListener that knows how to expand environment variables.
For example:
namespace TestSO39836570TraceListenerBindingErrors
{
class EnvironmentAwareTextWriterTraceListener : TextWriterTraceListener
{
public EnvironmentAwareTextWriterTraceListener(string path)
: base(Environment.ExpandEnvironmentVariables(path))
{ }
public EnvironmentAwareTextWriterTraceListener(string path, string name)
: base(Environment.ExpandEnvironmentVariables(path), name)
{ }
}
}
Then in the app.config file, you can specify the listener:
<system.diagnostics>
<sources>
<source name="System.Windows.Data" switchName="SourceSwitch">
<listeners>
<add name="textListener"/>
</listeners>
</source>
</sources>
<switches>
<add name="SourceSwitch" value="All"/>
</switches>
<sharedListeners>
<add name="textListener"
type="TestSO39836570TraceListenerBindingErrors.EnvironmentAwareTextWriterTraceListener, TestSO39836570TraceListenerBindingErrors"
initializeData="%temp%\BindingErrors.log"/>
</sharedListeners>
<trace autoflush="true" indentsize="4"/>
</system.diagnostics>
Note that when specifying a custom TraceListener type that is found in your own program assembly, you need to specify the assembly name in the type attribute, by following the fully-qualified type name with a comma and then the assembly name (in the example above, the type's namespace is identical to the assembly name, per the defaults for a project created in Visual Studio).
You may of course opt for shorter namespace and type names than the ones I've used here. :)
In a .Net 4.0 web-service I am using trace autoflush to write to a log file.
By adding the following in the web.config:
<trace autoflush="true" >
<listeners>
<add name="TextWriter"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="trace.log" >
</add>
</listeners>
</trace>
Am trying to find a way to log only Trace.TraceError("error info") and exclude Trace.TraceInformation("some verbose debugging stuff") without altering my code and just changing the web.config?
The information I have found on MSDN shows how this can be done by adding code that calls Trace.Flush() and adding sources, switches and sharedlisteners, however I would like to continue using auto-flush and not alter the code.
Many thanks in advance :)
Old answer:
This appears to be impossible. Trace auto-flush does not have the
capacity to have it's level set in the web.config.
Update:
The listener may have a filter applied as follows
<configuration>
<system.diagnostics>
<trace autoflush="true" >
<listeners>
<add name="TextWriter"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="trace4.log" >
<filter type="System.Diagnostics.EventTypeFilter" initializeData="Warning" />
</add>
</listeners>
</trace>
</system.diagnostics>
Note that the initializeData is a string and may take the values of Warning or Error. This filters the trace output accordingly.
Many thanks to Josip for following up on this question.
Maybe you can use "switchValue" for this purpose like this:
<system.diagnostics>
<trace autoflush="true">
</trace>
<sources>
<source name="SCInterface" switchType="System.Diagnostics.SourceSwitch" **switchValue**="All">
<listeners>
<remove name="default"/>
<add name="HSInterface"
type="XYZ.Diagnostics.CyclicTextTraceListener, XYZ.Base3x"
initializeData="D:\Trace\HSR.HSInterface.Trace.log, Size, 10, 5"
traceOutputOptions="DateTime,ThreadId,Callstack" />
</listeners>
</source>
</sources>
</system.diagnostics>
For switch value you would put Warning or Error...
Im using Microsoft Service Configuration Editor to setup diagnostics(WCF logging) and I can´t find any way to set the max file size?
I have found the MaxSizeOfMessageToLog but that do nothing about the file size?
Edit 1: According to this : http://msdn.microsoft.com/en-us/library/aa395205.aspx
There should be a maxFileSizeKB at the sharedListeners level but when hitting space in the add tag I do not get the possibility to type maxFileSizeKB?
Edit 2: When adding the maxFileSizeKB the serivce will not start anymore, instead I will get the following excetion :
'maxFileSizeKB' is not a valid configuration attribute for type 'System.Diagnostics.XmlWriterTraceListener'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Configuration.ConfigurationErrorsException: 'maxFileSizeKB' is not a valid configuration attribute for type 'System.Diagnostics.XmlWriterTraceListener'.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Edit 3 :
I had to download the Circular TraceListener sample and include it in my project, there is no built in fileSize limiter.
My config looks like this now :
<system.diagnostics>
<sources>
<source name="System.ServiceModel.MessageLogging" switchValue="Warning, ActivityTracing">
<listeners>
<add name="ServiceModelMessageLoggingListener"/>
</listeners>
</source>
<source name="System.ServiceModel" switchValue="Warning,ActivityTracing"
propagateActivity="false">
<listeners>
<add name="ServiceModelTraceListener"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add initializeData="C:\My\MyRelease 0.31\Host\My.Host.Dev\web_messages.svclog"
type="Microsoft.Samples.ServiceModel.CircularTraceListener,CircularTraceListener"
name="ServiceModelMessageLoggingListener" traceOutputOptions="Timestamp" maxFileSizeKB="1024">
<filter type="" />
</add>
<add initializeData="C:\My\MyRelease 0.31\Host\My.Host.Dev\web_tracelog.svclog"
type="Microsoft.Samples.ServiceModel.CircularTraceListener,CircularTraceListener"
name="ServiceModelTraceListener" traceOutputOptions="Timestamp" maxFileSizeKB="1024">
<filter type="" />
</add>
</sharedListeners>
This is limiting the message log file but not the trace log file?
It's because the link your gave use a custom trace listener ("Microsoft.ServiceModel.Samples.CircularTraceListener"), which have a "maxFileSizeKB" property.
There is no built-in functionnality to limit/roll svclog files, so you really need to use a custom trace listener.
You can use the sample used in your link (read at the end of the article how to download the code). Or here is another one that can be usefull.
Just want to add to #Fabske answer that inorder for this to work
1) Download WCF samples:
http://go.microsoft.com/fwlink/?LinkId=150780
2) Open
:\WF_WCF_Samples\WCF\Basic\Management\CircularTracing
3) Build the solution and grab the CircularTraceListener.dll
4) Add that dll to your project references
5) Update your configuration as shown http://msdn.microsoft.com/en-us/library/aa395205(v=vs.100).aspx
I'm using next method to add a trace record:
TraceSource.TraceEvent(TraceEventType, Int32, String)
where Int32 represents event id.
So how to filter in TraceSwitch to listen only by specified event id? Ir this is impossible?
<system.diagnostics>
<sources>
<source name="MyTraceSource" switchName="sourceSwitch" switchType="System.Diagnostics.SourceSwitch>"
<listeners>
<add name="console" type="System.Diagnostics.ConsoleTraceListener" />
</listeners>
</source>
</sources>
<switches>
<add name="sourceSwitch" value="?" />
</switches>
</system.diagnostics>
It's possible but you need to write a custom TraceFilter and override the ShouldTrace method. The id is passed to it, but no out-of-the-box filter supports it.
Then, you can declare it like this in a .config file:
<source name="MyTraceSource" switchName="sourceSwitch" switchType="System.Diagnostics.SourceSwitch">
<listeners>
<add name="console" type="System.Diagnostics.ConsoleTraceListener">
<filter type="YourNamespace.YourFilter, YourAssembly, ..." />
</add>
</listeners>
</source>
You can try Ukadc.Diagnostics from codeplex. This project provides some useful extensions for System.Diagnostics. The coolest thing, in my opinion, that they provide is a token based system that can be used to define log/trace output format similar to what you can achieve with log4net and NLog. It is a configuration-only dependency. That is, if you code is already using TraceSources, you only have to put Ukadc.Diagnostics on your machine and have your app.config point to their TraceListeners, PropertyTokens, etc.
You still instrument your code using System.Diagnostics.TraceSource objects.
To your point, using Ukadc.Diagnostics you can filter based on most property tokens (including EventId).
Note that the token system can only be used (as far as I know) with the corresponding TraceListeners provided in Ukadc.Diagnostics (or any TraceListener that you write based on their base TraceListener class).
I have not used this project in production, but I have fooled around with it quite a bit and have been quite impressed. It works well and is easy to extend.
Config file:
<system.diagnostics>
<trace>
<listeners>
<add name="Console" type="System.Diagnostics.ConsoleTraceListener" initializeData="false"></add>
<add name="Text" type="System.Diagnostics.TextWriterTraceListener" initializeData="D:\uat\logs\bifit.log" traceOutputOptions="DateTime"></add>
</listeners>
</trace>
</system.diagnostics>
The code:
static void Main(string[] args)
{
try
{
Trace.WriteLine("Running BiFit Test Server.");
}
}
I can see the text in cosole window. And the file is created, but it empty.
I remember there is something like Autoflush property somewhere?
You recall correctly - it is defined on the trace element:
<trace autoflush="true">
...
</trace>
autoflush - Optional attribute. Specifies whether the trace listeners automatically flush the output buffer after every write operation.
I think it's:
<system.diagnostics>
<trace autoflush="true">
...
</trace>
</system.diagnostics>
You could call Trace.Flush() once you are done with your Trace.Write type operations.