How to log exceptions with network targets in NLog - exception

I am using the NLog logging framework and am trying to get exception and stacktrace information showing up in any UDP logger appliaction, such as Sentinel and Log2Console, but can only get the log message part displayed. Outputting to a file works well as most examples do just that, so the problem revolves around using network targets with NLog.
Bonus if a custom format can be applied on inner exceptions and stacktrace, but this is not required. Exception.ToString() would go a long way.
Note on the example code: With Log2Console I found an article on how to send exception as a separate log entry. Although this worked, I was not happy with the solution.
Example exception logging code:
Logger Log = LogManager.GetCurrentClassLogger();
try
{
throw new InvalidOperationException("My ex", new FileNotFoundException("My inner ex1", new AccessViolationException("Innermost ex")));
}
catch (Exception e)
{
Log.ErrorException("TEST", e);
}
Example NLog.config:
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets async="true">
<!-- Send by UDP to Sentinel with NLogViewer protocol -->
<target name="network" xsi:type="NLogViewer" address="udp://192.168.1.3:9999" layout="${message}${onexception:inner=${newline}${exception:format=tostring}}" />
<!-- Send message by UDP to Log2Console with Chainsaw protocol -->
<target name="network2" xsi:type="Chainsaw" address="udp://192.168.1.3:9998" appinfo="Grocelist"/>
<!-- Send exception/stacktrace by UDP to Log2Console with generic network protocol -->
<target name="network2ex" xsi:type="Network" address="udp4://192.168.1.3:9998" layout="${exception:format=ToString}" />
<target name="logfile" xsi:type="File" layout="${longdate}|${level:uppercase=true}|${logger}|${message}|${exception:format=tostring}"
createDirs="true"
fileName="${basedir}/logs/${shortdate}.log"
/>
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="logfile" />
<logger name="*" minlevel="Debug" writeTo="network" />
<logger name="*" minlevel="Debug" writeTo="network2" />
<logger name="*" minlevel="Warn" writeTo="network2ex" />
</rules>
</nlog>
Some links:
http://nlog-project.org
http://nlog-project.org/wiki/Targets
http://nlog-project.org/wiki/Exception_layout_renderer
http://nlog-project.org/2011/04/20/exception-logging-enhancements.html
http://nlog-project.org/wiki/How_to_properly_log_exceptions%3F
How to tell NLog to log exceptions?
https://stackoverflow.com/a/9684111/134761
http://nlog-forum.1685105.n2.nabble.com/How-to-send-stacktrace-of-exceptions-to-Chainsaw-or-Log2Console-td5465045.html
Edit:
After searching some more this seems to be a limitation on NLog's end. A recent patch is apparently out there: log4jxmlevent does not render Exception
Edit2:
I rebuilt NLog with patch, but it did not seem to help in Sentinel or Log2Console apps. I might have to try log4net to make sure those apps really do support what I am trying to achieve.
Edit3:
I currently use string.Format() to join and format message and exception text myself. This works well, but is not what I'm looking for here.

You can also extend NLog to include exceptions for network logging.
Create an extended layout:
[Layout("Log4JXmlEventLayoutEx")]
public class Log4JXmlEventLayoutEx : Log4JXmlEventLayout
{
protected override string GetFormattedMessage(LogEventInfo logEvent)
{
string msg = logEvent.Message + " ${exception:format=Message,Type,ToString,StackTrace}";
msg = SimpleLayout.Evaluate(msg, logEvent);
LogEventInfo updatedInfo;
if (msg == logEvent.Message) {
updatedInfo = logEvent;
} else {
updatedInfo = new LogEventInfo(
logEvent.Level, logEvent.LoggerName,
logEvent.FormatProvider, msg,
logEvent.Parameters, logEvent.Exception);
}
return base.GetFormattedMessage(updatedInfo);
}
}
Create a target that uses that layout
[Target("NLogViewerEx")]
public class NLogViewerTargetEx : NLogViewerTarget
{
private readonly Log4JXmlEventLayoutEx layout = new Log4JXmlEventLayoutEx();
public override Layout Layout { get { return layout; } set {} }
}
Update NLog.config:
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<extensions>
<add assembly="Assembly.Name.That.Contains.Extended.Target"/>
</extensions>
<targets>
<target name="logViewer"
xsi:type="NLogViewerEx"
address="udp://localhost:7071">
</targets>
...
</nlog>

A few years later and this is pretty trivial, try adding
includeSourceInfo="true"
to your target file, so it looks like;
<target name="viewer"
xsi:type="NLogViewer"
includeSourceInfo="true"
address="udp://127.0.0.1:9999" />
Gives you Source File, Line, Class and Method info.

I had this problem, and just updated my NLog nuget package to 2.0.1.2
Now I have exceptions coming through to Log2Console just fine.

Have you tried the latest developer snapshot of Chainsaw? It will display stack traces and supports log4net/UDP appenders, and according to NLog you can use it as well:
http://nlog-project.org/wiki/Chainsaw_target
Try the latest developer snapshot, has a ton of features: http://people.apache.org/~sdeboy

Just download and build the latest (NLog-Build-2.0.0.2007-0-g72f6495) sources from GitHub: https://github.com/jkowalski/NLog/tree/
This issue is fixed there by NLog developer.

In your NLog.config modify the target like the following.
<target name="file" xsi:type="File" fileName="log.txt" layout="${longdate}:${message} ${exception:format=message,stacktrace:separator=*}" />
The part that you are looking for is
${exception:format=message,stacktrace:separator=*}
For more information on this look here.

Related

Can't access JSON output via URL

I get the service to respond when going to the URL /Resources/Feeder.svc on my localhost. However, I can't access /Resources/Feeder.svc/ping, although I'm using the following code.
[ServiceContract]
public interface IFeeder
{
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "ping")]
[OperationContract]
string Ping();
}
public class Feeder : IFeeder { public string Ping() { return "pung"; }
I've been trying with and without a bunch of attributes, trying to access the service with and without svc etc. Nada. I'm drawing blank.
I've tried to follow a guide or two but I simply can't see what I'm missing.
I'm getting empty hits - no text at all. The error says 400 bad request. Tells me nothing... What can I do to debug it? Most likely it's something really stupid because I'm tired. Sorry about that...
You haven't shown your web.config and my guess would be that you probably forgot to edit it. You need to do two things. First of all, declare an endpoint behavior. Second, add a protocol mapping. Like this.
<system.serviceModel>
<!-- Addition of protocol mapping -->
<protocolMapping>
<add scheme="http" binding="webHttpBinding"/>
</protocolMapping>
<!-- End of addition -->
<behaviors>
<!-- Addition of endpoint behavior -->
<endpointBehaviors>
<behavior>
<webHttp />
</behavior >
</endpointBehaviors>
<!-- End of addition -->
...
</behaviors>
...
</system.serviceModel>
Also, I don't think you actually need the attribute OperationContract if you're using WebGet. It's redundant.

No message body reader has been found [duplicate]

I have a jaxrs client configured like this:
<jaxrs:client id="opaRestProxy" name="opaRestProxy"
address="${endpoint}" serviceClass="com.test.RestProxy"
inheritHeaders="true" threadSafe="true">
<jaxrs:headers>
<entry key="Accept" value="application/json" />
<entry key="Content-Type" value="application/json" />
</jaxrs:headers>
</jaxrs:client>
But when I send a request I get the following exception:
Caused by: org.apache.cxf.interceptor.Fault: .No message body writer has been found for class : class com.test.RequestObject, ContentType : application/json.
at org.apache.cxf.jaxrs.client.ClientProxyImpl$BodyWriter.handleMessage(ClientProxyImpl.java:646)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
at org.apache.cxf.jaxrs.client.ClientProxyImpl.doChainedInvocation(ClientProxyImpl.java:527)
... 47 more
My RestProxy class looks like this:
#Component
public interface RestProxy {
#POST
#Path("/getSomething")
String getSomething(RequestObject RequestObject);
}
If you are using Jackson JSON library you need to add these xml tags to your application context.
<jaxrs:providers>
<bean id="jacksonProvider" class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" />
</jaxrs:providers>
If you are using any other library add that bean to the providers tag. Hope that helps!
If you are consuming using javax.ws.rs.client.Client, please register the provider using client.register(new JacksonJsonProvider());
This answers point me in the right direction, yet i had to add on two parts to make it work on web.xml
<init-param>
<param-name>jaxrs.providers</param-name>
<param-value>
org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider
(writeXsiType=false)
</param-value>
</init-param>
And on the client call:
List<Object> providers = new ArrayList<>();
// add custom providers if any
providers.add(new JacksonJaxbJsonProvider());
WebClient client = WebClient.create(ENDPOINT_ADDRESS,providers);

Struts2 Application hides my exceptions after adding Interceptor

So I have a Struts2 application that I'm working on. On my front page I have a section that will display any exceptions my application throws. This worked well until I added a custom Interceptor.
Here is my interceptor code:
public String intercept(ActionInvocation actionInvocation) throws Exception {
String result = actionInvocation.invoke();
return result;
}
This is the code in my Action class where the exception gets generated, it occurs where AuthService.Authorize() is called:
if(AuthService.Authorize(username, password)) {
if(AuthService.AdminAuthorized()) {
return "admin";
}
return SUCCESS;
}
This is inside of AuthService.Authorize(), it throws a null point exception when acc is accessed :
try {
acc = profileRepository.WhereSingle("Username", "=", username);
} catch (Exception e) {
return false;
}
if (acc.Password.equals(password)) {
However, when the page is loaded. This is not populated:
<s:property value="%{exception.message}"/>
I have tested it and it would work if I was simply throwing an exception from the Action class. I am not calling a redirectAction or anything
Here is the top of my default package definition which all my other packages extend
<package name="default" namespace="/" extends="struts-default">
<!-- Interceptors -->
<interceptors>
<interceptor name="conversation" class="global.ConversationInterceptor"/>
<interceptor-stack name="dils-stack">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="conversation"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="dils-stack"/>
<global-results>
<result name="Exception" >/index.jsp</result>
</global-results>
<global-exception-mappings>
<exception-mapping exception="java.lang.Exception" result="Exception"/>
<exception-mapping exception="java.lang.NullPointerException" result="Exception"/>
</global-exception-mappings>
How is your interceptor stack defined for that action? The ExceptionMappingInterceptor should be defined first in the stack. Can you post the interceptor stack configuration from your struts.xml? Your custom interceptor should not be interfering (it does nothing).
Updated:
I was able to reproduce this issue, however it occurs for me with or without your custom interceptor.
The reason is that you are specifically looking for the exception message, which is not set for NullPointerExceptions that are automatically thrown (as in your case). You can confirm this by instead displaying the stack trace, such as: %{exceptionStack}
%{exception.message} is null for the NullPointerException, and so it displays nothing. If instead you were to throw an exception with a message (e.g., throw new RuntimeException("OMG!");), then you will see the message.
Also, note that you must specify more specific exception mappings before less specific mappings in your struts.xml. Because NullPointerException is more specific than Exception, you must list it first. Note that this doesn't really matter in your example, because they map to the same thing. Just know that your NPE will map to the first entry, not the second.

Jetty - set system property [duplicate]

This question already has answers here:
How to portably read configuration data from a servlet
(4 answers)
Closed 7 years ago.
I run webapp on Jetty. The configuration for the app come from file that lives on the same server where Jetty is running. Inside the app I rely on the system property to obtain path to the file so I can parse it. E.g.
final String loc = System.getProperty(FACTORY);
Now I can start jetty with D switch to provide $FACTORY on the command line but I rather put it in jetty.xml if I can. I know there is <SystemProperty /> tag but that seems to just provide system value that already exists for the <Set/> tag. Can someone give me example how this can be achieved? (If it can be achieved)
For the record, if you really need to do this through system properties (I did) you can do this to append for example -Drun.mode=staging to the system properties:
<Call class="java.lang.System" name="setProperties">
<Arg>
<New class="java.util.Properties">
<Call name="putAll">
<Arg><Call class="java.lang.System" name="getProperties"/></Arg>
</Call>
<Call name="setProperty">
<Arg>run.mode</Arg>
<Arg>staging</Arg>
</Call>
</New>
</Arg>
</Call>
... and yes you can probably can program your application through this ;-)
If you're starting Jetty through its Java API for a testing or 'embedded' application, the following example shows actually setting Java System properties prior to the startup of your WebAppContext.
private void startJetty() {
try {
long startTime = System.currentTimeMillis();
server = new Server();
setUpSystemProperties(server);
Connector connector = new SelectChannelConnector();
connector.setPort(port);
server.addConnector(connector);
WebAppContext webAppContext = new WebAppContext();
webAppContext.setWar("src/main/webapp");
server.setHandler(webAppContext);
server.start();
}
catch (Exception e) {
throw new RuntimeException("Failed to set-up web server fixture", e);
}
}
private void setUpSystemProperties(Server jettyServer) {
final Properties systemProperties = new Properties();
// set your system properties...
systemProperties.setProperty("yourProperty", "yourValue");
jettyServer.addLifeCycleListener(new SystemPropertiesLifeCycleListener(systemProperties));
}
private class SystemPropertiesLifeCycleListener extends AbstractLifeCycleListener {
private Properties toSet;
public SystemPropertiesLifeCycleListener(Properties toSet) {
this.toSet = toSet;
}
#Override
public void lifeCycleStarting(LifeCycle anyLifeCycle) {
// add to (don't replace) System.getProperties()
System.getProperties().putAll(toSet);
}
}
Unlike most of these answers, I won't lecture you about whether this is 'proper' compared to JNDI or some other technology you didn't ask about.
I'm going to accept #vanje answer since it got me thinking into right direction. Here's what I ended up using:
Create jetty-web.xml outside of your WAR distro (no you don't want to package it with WAR if you want to configure the app from "outside")
Place jetty-web.xml alongside of jetty.xml
I needed just a single parameter so I ended up with the following:
jetty-web.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN"
"http://jetty.mortbay.org/configure.dtd">
<Configure class="org.mortbay.jetty.webapp.WebAppContext">
<New class="org.mortbay.jetty.plus.naming.EnvEntry">
<Arg>myOwnParam</Arg>
<Arg type="java.lang.String">//some/path/to/the/file</Arg>
</New>
</Configure>
Java snippet
InitialContext c = new InitialContext();
EnvEntry env = (EnvEntry)
c.lookup("org.mortbay.jetty.plus.naming.EnvEntry/myOwnParam");
final String myString = (String) env.getObjectToBind();
The biggest gotcha for me here was that I was trying to get myString from the defaul env which didn't work until I realized that JNDI was using local context. This is OK for me but will break portability if you try to move WAR on say Tomcat. If someone can post an example how this can be saved into default context that would be greatOwnParam
To configure a web application it is better to avoid system properties and to use JNDI instead.
Recently I posted an example on how to accomplish that with Jetty.

Filter on exception text in elmah

Is there a way to filter exceptions in elma using the exception message?
Examples:
"System.Web.HttpException: Request timed out." I don't want to filter out all HttpException, but only the timed-out requests.
"System.Web.HttpException: Maximum request length exceeded."
What I don't want to do is write own code for that. So is it possible to do this with the buildin-web.config configuration?
Thank you!
Yes you can. Just use a regular expression to interrogate the message. See the example below for details on how to compare the exception message.
<errorFilter>
<test>
<!-- http://groups.google.com/group/elmah/t/cbe82cee76cc6321 -->
<and>
<is-type binding='Exception'
type='System.Web.HttpException, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' />
<regex binding='Exception.Message'
pattern='invalid\s+viewstate'
caseSensitive='false' />
<regex binding='Context.Request.UserAgent'
pattern='Trident/4(\.[0-9])*'
caseSensitive='false' />
</and>
</test>
</errorFilter>
You can set up an event handler in your global.asax to avoid ugly configuration regex settings:
void ErrorMail_Filtering(object sender, Elmah.ExceptionFilterEventArgs e)
{
if (e.Exception.Message.Contains("Request timed out"))
e.Dismiss();
}
See Error Filtering.