Assume I have a config file which looks like this:
...
<system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="Warning,ActivityTracing" propagateActivity="true">
<listeners>
<add name="ServiceModelTraceListener" />
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add name="ServiceModelTraceListener" />
</listeners>
</source>
</sources>
<sharedListeners>
<add initializeData="LogServer.svclog" type="System.Diagnostics.XmlWriterTraceListener" name="ServiceModelTraceListener" />
</sharedListeners>
<trace autoflush="true" />
</system.diagnostics>
When using this config file every activity the caller performs against the service and each corresponding message that's sent to the service will be logged in the svclog file. Everything fine so far.
If I modify the 3rd line from the above listing to <source name="System.ServiceModel" switchValue="Warning" propagateActivity="true"> (the ActivityTracing is removed) then only those activities are logged that are at least labeled level warning. But it's still every message logged...
So is there a way to only log those message that correspond to those activities that are at least warnings? Those messages that succeeded aren't very interesting in that moment, but those messages that belong to the unsuccessful activities are!
Edit
To filter messages beyond the options below you may want to look into writing your own TraceSource.
Below is one I am using for a project. You could easily customize it to filter out the messages you want or perhaps hide activity if it is not in DEBUG, etc.
class DB : TraceSource
{
public DB(string name) : base(name)
{
}
public DB(string name, SourceLevels sourceLevels) : base (name, sourceLevels)
{
}
public void Log(object value)
{
WriteLine(value);
}
public void Error(object value)
{
WriteLine(value, TraceEventType.Error);
}
public void Error(RecordingResponseData errorResponse)
{
string errorMessage = "[Error] Code: "+errorResponse.ErrorCode +" Message: "+errorResponse.ErrorMessage;
WriteLine(errorMessage, TraceEventType.Error);
}
public void Warn(object value)
{
WriteLine(value, TraceEventType.Warning);
}
public void WriteLine(object value, TraceEventType type = TraceEventType.Information)
{
TraceEvent(type, 0, value.ToString());
}
}
Original
Your options are:
Critical
Error
Warning
Information
ActivityTracing
Verbose
All
Or a combination there of. If you have it set to Warning but are still getting too many messages then you may want to try Error or Critical.
ref: https://msdn.microsoft.com/en-us/library/ms733025%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
There's a switchValue available for the System.ServiceModel.MessageLogging trace switch as well. Just add that attribe to that source element and set it to Warning also and you will only see messages logged that are related to warnings.
Get rid of System.ServiceModel.MessageLogging source to get rid of logging messages to resolve "still every message logged".
Related
I'm using system.diagnostic to log all the errors to a log file
Web.Config:
<system.diagnostics>
<trace autoflush="true" indentsize="4">
<listeners>
<add name="MyListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="MyListenerLog.txt" />
<remove name="Default" />
</listeners>
</trace>
</system.diagnostics>
Code:
private static void AddToMyListner(string message)
{
try
{
System.Diagnostics.Trace.WriteLine("Text: " +message + "," + DateTime.UtcNow);
System.Diagnostics.Trace.Close();
}
catch (Exception ex)
{
throw ex;
}
}
In the Log file the first log i got was
no configuration section <common/logging> found - suppressing logging output
This log is printed only once i.e. only when I create a new log file. I'm not using Common.Logging so i was wondering what is causing this issue.
Common.Logging is commonly integrated with tracing. If you're getting this error and you're not deliberately referencing Common.Logging then you're probably referencing some external library that uses Common.Logging and subscribes to the trace by default. If there's no configuration in place (reasonable, since you're not intending to use Common.Logging) then this would happen when Common.Logging receives a notification that something was written to the trace and doesn't know what to do about it.
I've built a windows forms client application which makes a WCF call. I'd like to be able to display the actual request and response, includeing SOAP header, and information about the POST/Get, from within the application. Is there a way to configure a trace listener on the client and consume it from within the client, displaying the contents in a text box?
I've configured tracing which outputs messages to a file. This configuration is on my client application, so it's logging all calls it is making to the wcf service and the response. So the sources have been added and for each source is an XmlTraceListener, which handles writing to an xml log file. What I'm looking to do now is utilize a trace listener from within the client application itself and write to a textbox control.
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="All">
<listeners>
<add name="xmlTraceListener" />
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging"
switchValue="All">
<listeners>
<add name="xmlTraceListener" />
</listeners>
</source>
</sources>
<sharedListeners>
<add name="xmlTraceListener"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="ClientLogBasic.svclog" />
</sharedListeners>
<trace autoflush="true" />
</system.diagnostics>
<!-- child of the <system.serviceModel> element -->
<diagnostics>
<messageLogging maxMessagesToLog="10000"
logEntireMessage="true"
logMessagesAtServiceLevel="true"
logMalformedMessages="true"
logMessagesAtTransportLevel="true">
<filters>
<clear/>
</filters>
</messageLogging>
</diagnostics>
So now that I've got message logging working, I create my own trace listener that can write to a textbox:
public class MyTraceListender : System.Diagnostics.TraceListener
{
private TextBox txt_m;
public MyTraceListender(TextBox txt)
: base()
{
txt_m = txt;
}
private delegate void delWrite(string sText);
public override void Write(string message)
{
txt_m.Invoke(new delWrite(AsyncWrite), message);
}
public override void WriteLine(string message)
{
this.Write(message + System.Environment.NewLine);
}
private void AsyncWrite(string sMessage)
{
this.txt_m.AppendText(sMessage);
}
}
Now that I've got my trace listener, I want to try using it from my windows forms client application.
public partial class Form1 : Form
{
private MyTraceListender listener_m;
public Form1()
{
InitializeComponent();
listener_m = new MyTraceListender(this.txtOutput);
System.Diagnostics.Trace.Listeners.Add(listener_m);
}
private void button1_Click(object sender, EventArgs e)
{
ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
string sValue = client.GetData(1234);
}
}
At this point, I'm still not seeing logging to the textbox control. I'm thinking that the listener is not associated to the source, so I tried the following:
public partial class Form1 : Form
{
private MyTraceListender listener_m;
public static System.Diagnostics.TraceSource source = new System.Diagnostics.TraceSource("System.ServiceModel.MessageLogging", System.Diagnostics.SourceLevels.All);
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
string sValue = client.GetData(1234);
}
private void Form1_Load(object sender, EventArgs e)
{
listener_m = new MyTraceListender("test", this.txtOutput);
source.Listeners.Add(listener_m);
}
}
After all of this, messages are not being logged to the textbox on the form. They are being logged to the file via the XmlTraceListener, so I'm assuming the issue is how I'm adding my custom listener via System.Diagnostics.Trace.Listeners.Add(). Is this the correct approach?
Edit the Configuration file using WCF Configuration Editor, and enable tracing as shown below
This solution is mostly through app.config. Let me know if you prefer a code-based solution.
In app.config, add your listener to the list of shared listeners, as well as a listener for the message logging source. In 'listeners' list, the name must match the name later on in the 'sharedListeners' list. In 'sharedListeners' list, the 'type' must include full class name with namespace, as well as assembly name:
<system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="All">
<listeners>
<add name="xmlTraceListener"/>
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging" switchValue="All">
<listeners>
<add name="xmlTraceListener"/>
<add name="textBoxListener"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add name="xmlTraceListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData="ClientLogBasic.svclog"/>
<add name="textBoxListener" type="WinTransmitterClient.MyTraceListener, WinTransmitterClient" initializeData=""/>
</sharedListeners>
<trace autoflush="true"/>
Because MyTraceListener will be constructed by the framework, its constructor must match the base class. So instead, make the textbox a property that can be set when needed.
In MyTraceListener.cs:
public class MyTraceListener : System.Diagnostics.TraceListener
{
public TextBox txt_m
{
get;set;
}
public MyTraceListener()
: base()
{}
// rest as before ...
In Form1.cs, grab the custom listener after the client is created, and set the text box. No other code is needed. This is the entire Form1.cs, excluding 'using' and 'namespace' lines:
public partial class Form1 : Form
{
public static System.Diagnostics.TraceSource source = new System.Diagnostics.TraceSource("System.ServiceModel.MessageLogging", System.Diagnostics.SourceLevels.All);
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ServiceReference1.ContactManagerTextServiceClient client = new ServiceReference1.ContactManagerTextServiceClient();
// identifier in quotes must match name from config file
MyTraceListener mtl = source.Listeners["textBoxListener"] as MyTraceListener;
// of course this doesn't need to be done at every button click, but you get the idea
mtl.txt_m = this.txtOutput;
string sValue = client.GetData(1234);
}
}
Try creating a message inspector. On the client side you'd have to implement IClientMessageInspector which will allow you to intercept the message before it is being sent as well as the response which is received prior to passing it further into the application. You'll find more information on MSDN
I've made a basic WCF Service Library and created one method called GetResult(). I've set up WCF trace logging to log Warnings to a file. This is correctly logging all exceptions thrown except, for some strange reason, System.Exception itself. For instance, this logs fine:
[OperationContract]
public string GetResult()
{
// exception is logged in file:
throw new DivideByZeroException();
// or
// throw new ApplicationException();
// or
// throw new FileNotFoundException();
// or anything else, it seems
}
But this does not log anything:
[OperationContract]
public string GetResult()
{
// exception is not logged!
throw new Exception();
// or
// throw new Exception("my message");
}
In the latter case, the log file doesn't even get created. If it already exists then it doesn't get written to.
What am I doing wrong?
Here is my app.config setup:
<system.diagnostics>
<sources>
<source name="System.ServiceModel.MessageLogging" switchValue="Warning">
<listeners>
<add name="ServiceModelTraceListener" />
</listeners>
</source>
<source name="System.ServiceModel" switchValue="Warning">
<listeners>
<add name="ServiceModelTraceListener" />
</listeners>
</source>
<source name="System.Runtime.Serialization" switchValue="Warning">
<listeners>
<add name="ServiceModelTraceListener" />
</listeners>
</source>
</sources>
<trace autoflush="true" />
<sharedListeners>
<add initializeData="c:\temp\logs\wcf.svclog"
type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
name="ServiceModelTraceListener"
traceOutputOptions="Timestamp" />
</sharedListeners>
</system.diagnostics>
I have created a WCF service with 2 methods :
[ServiceContract(Namespace = "")]
[SilverlightFaultBehavior]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class MyDataService
{
[OperationContract]
public IQueryable<object> Service1()
{
PivotData pivot = new PivotData();
IQueryable<object> list = pivot.GeneratePivotData();
return list;
}
[OperationContract]
public string Service2()
{
return "hello";
}
}
The Service2 works perfectly fine. However , service1 returns the dreaded
"the remote server has returned an error : not found"
I believe it has to do with the return type IQueryable<object> , but I don't know what I should change to make it work. I tried List<string> , ObservableCollection<object> and a few others but to no avail.
What should I do the get my data back to the client ?
Thanks
depending on the question and conversation with Aron.
I supposed it is a WCF-Ria Services If so please retag the question, otherwise you may ignore this answer.
Try the below code.
Beside if you use ria services. you should use , [Association("FK_assos_name", "field", "field")] [Include] for complex properties and your base class should have at least one [Key] attributed field. Such as ID.
[OperationContract]
public BaseClass[] ServiceMethod1()
{
PivotData pivot = new PivotData();
IQueryable<object> list = pivot.GeneratePivotData();
return list.ToArray();
}
If you still get errors trace it;In your web.config add the lines below. Then open WcfDetailTrace.svclog with svclog viewer. Red parts will show you what goes wrong.
<system.diagnostics>
<trace autoflush="true">
<listeners>
</listeners>
</trace>
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="sdt"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData= "WcfDetailTrace.svclog" />
</listeners>
</source>
</sources>
I want to write CustomTraceListener which writes all data to SQL Server DB.
Here's the stub for it:
public class SqlTraceListener : TraceListener
{
public SqlTraceListener()
: base()
{ }
public SqlTraceListener(String name)
: base(name)
{ }
protected override string[] GetSupportedAttributes()
{
List<string> attributes = new List<string>();
attributes.Add("connectionString");
attributes.Add("actionFilter");
attributes.Add("hostFilter");
return base.GetSupportedAttributes();
}
public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
{ }//Other empty methods...
}
In overridden method TraceData I want to catch SOAP messages sent to my WCF service. But when I check what is in "data" parameter I get this: (sorry for posting xml as pictures - it seems SO editor doesn't allow some xml keywords in posts):
But according to standard XmlWriterTraceListener I should get this:
How to configure TraceListener not to eliminate SOAP messages?
My config is here:
<system.diagnostics>
<sources>
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add name="xml"/>
<add name="sql"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add initializeData="C:\logs\StockPriceService.svclog" type="System.Diagnostics.XmlWriterTraceListener" name="xml"/>
<add type="SqlTraceListener.SqlTraceListener, SqlTraceListener" name="sql"/>
</sharedListeners>
<trace autoflush="true"/>
Is there any reason you're not using the out of the box database trace listener? See: Enterprise Library Database Trace Listener?.