I have a WCF Service which is currently in Production. The code performance are not where we would like them to be and we are unable to reproduce in our Staging environment.
I was wondering if it is possible to log every single method call made to the service and by the service. Essentially I would like a sequential list of all the calls and time stamps (our code isn't multi-threaded).
Is there a way to achieve that without having to instrument the binaries. Is there a level of tracing under the system.diagnostic node in the web.config that we could change?
Have you configured tracing in your configuration file? This is a good article on the subject.
Here is a sample configuration you can use and modify for your needs:
<system.diagnostics>
<trace autoflush="true" />
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="ServiceModel"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="C:\ServiceModel.svclog" />
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add name="MessageLogging"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="C:\MessageLogging.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
<system.serviceModel>
<diagnostics>
<messageLogging logEntireMessage="True"
logMalformedMessages="False"
logMessagesAtServiceLevel="True"
logMessagesAtTransportLevel="False"
maxMessagesToLog="10000"
maxSizeOfMessageToLog="10000" />
</diagnostics>
</system.serviceModel>
Use the Service Trace Viewer Tool (SvcTraceViewer.exe) to view the resulting logs.
Check WCF Tracing and optionally also WCF message logging and use SvcTraceViewer to check collected data - you can alternatively build your trace listener for logging traces for example to database. WCF also provides performance counters.
Related
I would like to add a filter to my WCF tracing to either filter on an endpoint or on the content of the message.
It is not clear from what I have seen on how to do this. I am trying to do this in the web.config file.
Any ideas welcome.
Thanks
Ian
Please try the below configuration, tracing the WCF activity.
<system.diagnostics>
<sources>
<source name="System.ServiceModel" propagateActivity="true" switchValue="Information, ActivityTracing">
<listeners>
<add type="System.Diagnostics.XmlWriterTraceListener" name="xmlLog" initializeData="myLogs.svclog"/>
</listeners>
</source>
</sources>
</system.diagnostics>
<system.serviceModel>
<diagnostics>
<messageLogging logEntireMessage="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="false"/>
</diagnostics>
</system.serviceModel>
You can custom your configuration referring to the below link.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/samples/tracing-and-message-logging
https://learn.microsoft.com/en-us/dotnet/framework/wcf/diagnostics/tracing/configuring-tracing
After we get the tracing file, We could use Microsoft Service Trace Viewer to filter the WCF activity.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/service-trace-viewer-tool-svctraceviewer-exe
https://learn.microsoft.com/en-us/dotnet/framework/wcf/diagnostics/tracing/using-service-trace-viewer-for-viewing-correlated-traces-and-troubleshooting
Feel free to let me know if there is anything I can help with.
I have a basic WCF hosted in a console app, and a basic console WCF client. How do you look at the requests sent between the two apps (over localhost)?
Should I use something like 'Wireshark' or would it be possible to log out the incoming and outgoing response objects in visual Studio?
I'm already creating an log.svclog file by the system.diagnostics directive in the App.config file, but can't find the actual request and response xml:
<diagnostics>
<messageLogging logEntireMessage="true" logMalformedMessages="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" />
</diagnostics>
<system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="Information, ActivityTracing" propagateActivity="true">
<listeners>
<add name="traceListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData="C:\log\log.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
Which I got from Stack Overflow (I can't remember where)
You need to configure message logging, which is separate from just WCF tracing, which is what you have configured above. See https://msdn.microsoft.com/en-us/library/ms730064(v=vs.110).aspx.
After having turned on WCF Tracing to assist with finding a problem, I now wish to turn off tracing. So I have changed my config file to this...
<system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="Off" >
<!-- Information,ActivityTracing-->
<listeners>
<add name="xmlTraceListener" />
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging" switchValue="Off" >
<listeners>
<add name="xmlTraceListener" />
</listeners>
</source>
</sources>
<sharedListeners>
<add name="xmlTraceListener"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="C:\WCFLogs\DataPortalTrace.svclog" />
</sharedListeners>
<trace autoflush="true" />
</system.diagnostics>
Yet there is still trace output being send to the indicated output file. Why is that? What am I missing?
switchValue="Off" will only control System.ServiceModel. It does not control the System.ServiceModel.MessageLogging
As of my knowledge you can control via maxMessagesToLog="0" – you might have already <diagnostics> tag under <system.serviceModel>
<diagnostics>
<messageLogging
logEntireMessage="true"
logMalformedMessages="true"
logMessagesAtServiceLevel="true"
logMessagesAtTransportLevel="true"
maxMessagesToLog="0"
/>
</diagnostics>
.NET framework for Configuring Message Logging
The logging level, as well as the additional options, are discussed in the Logging Level and Options section.
The switchValue attribute of a source is only valid for tracing. If you specify a switchValue attribute for the System.ServiceModel.MessageLogging trace source as follows, it has no effect.
Copy
<source name="System.ServiceModel.MessageLogging" switchValue="Verbose">
If you want to disable the trace source, you should use the logMessagesAtServiceLevel, logMalformedMessages, and logMessagesAtTransportLevel attributes of the messageLogging element instead. You should set all these attributes to false. This can be done by using the configuration file in the previous code example, through the Configuration Editor UI interface, or using WMI. For more information about the Configuration Editor tool, see Configuration Editor Tool (SvcConfigEditor.exe). For more information about WMI, see Using Windows Management Instrumentation for Diagnostics.
I am building a web service client to interact with a (java-based) remote web service, out of my control. I can call the web service operation, and can tell by packet-sniffing that the service is responding with populated data. However, by the time that response makes it into the client code, the response is only a shell, with all the data null.
I suspect that an error is occurring in the web service "plumbing" that is causing the data to be silently dropped or ignored, but I can't find a way to enable debugging (or even logs or error messages?) during the receipt of the response before it hits my client code.
My App.config has Message Logging enabled, but only outgoing messages are being logged:
<system.diagnostics>
<sources>
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add name="messages"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="c:\messages.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
<system.serviceModel>
<diagnostics>
<messageLogging
logEntireMessage="true"
logMalformedMessages="true"
logMessagesAtServiceLevel="true"
logMessagesAtTransportLevel="true"
maxMessagesToLog="3000"
maxSizeOfMessageToLog="2000"/>
</diagnostics>
</system.serviceModel>
I really want to set a breakpoint during the actual parsing of the response message, but having the Message Logger actually log the response may also help a bit.
I've also configured a custom MessageEncoder which was necessary to work around a bug in the remote service's parser. I can add breakpoints to the ReadMessage methods on that MessageEncoder, and can see that the data is still there at that point. However, the next step jumps back into the client code, and the Response object is empty -- no warnings or messages. Is there any way to see what's going on in between?
So, I guess this ends up being a two-part question:
How/Where can I set a breakpoint to observe the SOAP message getting
processed, after the MessageEncoder, but before it is sent to the client code?
What's wrong with my logging config that only outgoing
messages are logged?
Here is how you can get the response tracing to work for you:
1. Configuration
<system.diagnostics>
<sharedListeners>
<add name="sharedListener"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="C:\LogFiles\messages.svclog" />
</sharedListeners>
<sources>
<source name="System.ServiceModel" switchValue="Verbose, ActivityTracing" >
<listeners>
<add name="sharedListener" />
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging" switchValue="Verbose">
<listeners>
<add name="sharedListener" />
</listeners>
</source>
</sources>
</system.diagnostics>
<system.serviceModel>
<diagnostics performanceCounters="All" wmiProviderEnabled="True">
<messageLogging
logEntireMessage="True"
logMalformedMessages="True"
logMessagesAtServiceLevel="True"
logMessagesAtTransportLevel="True"
maxMessagesToLog="3000"
maxSizeOfMessageToLog="30000"/>
</diagnostics>
</system.serviceModel>
This goes in your app.config / web.config under the configuration node.
2. Locating the Response
A quick validation to see that you actually receive service responses from the remote service is to open up the log file as an xml file in Visual studio and do a search for
Source="TransportReceive"
you should be able to see what the remote service has responded with within this MessageLogTraceRecord node.
3. Tooling
The recommended tool for viewing these messages is SvcTraceViewer.exe
You should be able to find this in either:
C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\x64
or
C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin
If you do not have this tool, you can find it in the Windows Sdk
How can I log what xml is sent to my WCF REST service prior to being deserialized into my datacontract class?
You can use WCF tracing to log the raw XML messages.
Tracing is not enabled by default. You can enable and configure tracing by editing the application’s configuration file. The following .config example enables WCF tracing with raw message logging:
<configuration>
<system.serviceModel>
<diagnostics>
<messageLogging maxMessagesToLog="30000"
logEntireMessage="true"
logMessagesAtServiceLevel="true"
logMalformedMessages="true"
logMessagesAtTransportLevel="true">
</messageLogging>
</diagnostics>
</system.serviceModel>
<system.diagnostics>
<sources>
<source name="System.IdentityModel"
switchValue="Verbose"
logKnownPii="true">
<listeners>
<add name="xml" />
</listeners>
</source>
<!-- Log all messages in the 'Messages' tab of SvcTraceViewer. -->
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add name="xml" />
</listeners>
</source>
<!-- ActivityTracing and propogateActivity are used to
flesh out the 'Activities' tab in SvcTraceViewer to
aid debugging. -->
<source name="System.ServiceModel"
switchValue="Error, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="xml" />
</listeners>
</source>
<!-- This records Microsoft.IdentityModel generated traces,
including exceptions thrown from the framework. -->
<source name="Microsoft.IdentityModel" switchValue="Warning">
<listeners>
<add name="xml" />
</listeners>
</source>
</sources>
<sharedListeners>
<add name="xml"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="C:\logs\trace.svclog" />
</sharedListeners>
<trace autoflush="true" />
</system.diagnostics>
</configuration>
You can read more about WCF Tracing from MSDN: Configuring Tracing.
Microsoft provides a Service Trace Viewer Tool to read .svclog files.
Make sure the path defined in initializeData is writable by your service.
If you want to look at the raw HTTP traffic, a proxy tool like Fiddler is the simplest way. You'll be able to see all the information that's been POST/PUT'd to your REST service.
If you mean "log" as in "always write the HTTP traffic to a specific location on file," then you can use the built-in tracing to do most of that. Here is a link to an example of doing this, otherwise just look for "WCF tracing" online. You'll find a ton of great examples.