Retrieve Log's Thread in Logback Filter - logback

Using ch.qos.logback:logback-core:1.2.3 I've added TurboFilter to the LoggerContext sniffing for all the logs that go through the loggers:
loggerContext.addTurboFilter(filter);
But I can't find a way to figure out the log Thread. It actually doesn't seem to be passed in to the TurboFilter function:
public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) {
}
Any suggestions how to get the whole info from the loggers including the Threads?

It seems it wasn't so difficult at all. I figured it out that the decide method is called on the same Thread where the log has occurred, so Thread.currentThread().getName() gives the information I need.

Related

Need to perform RequestBasedLogging

I have a need to implement request based logging.
Based on header - log-level-header.
In my code, I am using JAX-RS and have implemented ContainerRequestFilter.
#Override
public void filter(final ContainerRequestContext context) throws IOException {
String log_level = context.getHeaderString("log-level-header");
//translate to actual log level
Logger root = (Logger)LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
root.setLevel(logLevelToSet);
}
I am using Logback and slf4j API.
The problem is that i am setting the log level to the RootLogger which is a singleton and hence ends up modifying the log level across application.
Instead I intend to change the log level for a particular thread (RequestBasedLogging). Is it achievable and how?
Yes, this is achievable via TurboFilters and MDC. The code in MDCFilter should be helpful as well.
The key is to understand MDC.

session-specific info to comet's "onEvent" method

I have two questions about using the Comet feature with Glassfish. I'm
pretty new at this, so if there's an easy answer or some documentation
I should read please let me know! Thanks.
I'm building a system that has multiple microcontrollers sending data
to a central DB. Users view the data via their browsers ... in formats
(metric vs. English, say) of their own choosing. The display needs to
be updated without user action. It looks like Glassfish + Comet should
be perfect. And so I started with Oracle's "hidden_Comet" example, and
that works great.
So question #1 is this: how can one get session-specific information
into the "onEvent" method?
As context, here's the code; it’s straight from the Oracle example:
private class CounterHandler implements CometHandler<HttpServletResponse> {
private HttpServletResponse response;
public void onEvent(CometEvent event) throws IOException
{
if (CometEvent.NOTIFY == event.getType())
{
PrintWriter writer = response.getWriter();
writer.write("<script type='text/javascript'>");
[... etc. Here is where I need to pass some session-specific
info to the JavaScript]
event.getCometContext().resumeCometHandler(this);
}
}
It would seem that session attributes would be perfect, but it looks
like you can't get the 'session' variable from the "HttpServletResponse".
I thought about using cookies, but they seem to be accessible only with
HttpServletRequest, not "...Response", and, as above, only ‘response’
is available in the “onEvent” method.
So question #1 is: how do you do this?
Question #2 is: is this just the wrong way to attack this problem and is
there a better way?
I'm not sure I understand the data structures and control flow of Comet very well yet, but it seems that this works:
Add a constructor to "class CounterHandler" and pass in the 'session' variable from 'doGet()' where "new CounterHandler" is called. Specifically, change:
CometHandler handler = new CometHandler();
to
HttpSession session = request.getSession();
CometHandler handler = new CometHandler(session);
Have the constructor save the session variable in a class instance variable. And then the "onEvent()" method has access to session attributes. And Bob's your uncle.
(It seems straightforward enough ... well, now.)

Clean up failed maps

My mapper will write some data to local disks and clean it up when mapper finishes. However, the cleanup() method won't be called if error occurs (exception happens).
I can catch exception inside my mapper but I can't handle the exception which is not invoked in my mapper ( Ex: Job tracker failover to standby node).
Is there any way that I can cleanup when the mapper get fails?
You can override the run method of mapper to include a try / catch around the iteration of input keys from the context and ensure that cleanup is called:
#Override
public void run() {
setup(context);
try {
while (context.nextKeyValue()) {
map(context.getCurrentKey(), context.getCurrentValue(), context);
}
} finally {
cleanup(context);
}
}
You'll need to make sure that your cleanup method doesn't have any logic in it to try and output records, or set a flag in your mapper to denote that an error occurred.
This may not protect against all types of task failure (JVM crash for example), for which i don't think you have any other method, other than to maybe run a job after the original job whose role is to ensure the resources used are properly cleaned up.
Using the job class you can definitely delete some folders if the job finishes, even if the directories are in the local filesystem, use the FileSystem class
More on filesystems in hadoop

entity and repository pattern with ninject, Dispose Issue

I have build my site using entity and repository pattern with ninject injection. My problem is my connections don't seem to get disposed. I have around 30 repositories (one for each table) and I get sql expiration timout preety quick. I can't use the regular using statement because the code recognize only the interface before the injection.
(in each controler I have my repositories interface instances which get injected via ninject).
I have searched the net but couldn't find a solution that was accurate for me.
can anyone please help me?
code example:
this is in the ninject controller under addBindings():
ninjectKernel.Bind<IMovieRepository>().To<MovieRepository>().InRequestScope();
and one of my repositories:
public class MovieRepository : IMovieRepository, IDisposable
{
private Entities dataContext = new Entities();
public System.Data.Entity.DbContext DbContext
{
get { return dataContext ?? (dataContext = new Entities()); }
}
public void Dispose() { dataContext.Dispose(); }
}
and in the Global.asax file:
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory() as IControllerFactory);
I would guess that your repositories (and therefore presumably your DbContexts) are being bound in transient scope, which I believe means a new one will be created every time Ninject needs to inject one somewhere. I'm not certain but I'm guessing then that these are all staying around for the lifetime of your application and maybe not being disposed.
Try binding your repositories in request scope, so that they are created and disposed per web request.
e.g.
Bind<IFooRepository>().To<ConcreteFooRepository>().InRequestScope();
From the Ninject wiki:
There are four built-in scopes available in Ninject:
Transient - A new instance of the type will be created each time one is requested. (This is the default scope). Binding method is .InTransientScope()
Singleton - Only a single instance of the type will be created, and the same instance will be returned for each subsequent request. Binding method is .InSingletonScope()
Thread - One instance of the type will be created per thread. Binding method is .InThreadScope()
Request - One instance of the type will be created per web request, and will be destroyed when the request ends. Binding method is .InRequestScope()
This kind of problem usually occur if long living objects depend on shorter living objects. E.g. A singleton service uses a repository in request scope.

Final managed exception handler in a mixed native/managed executable?

I have an MFC application compiled with /clr and I'm trying to implement a final handler for otherwise un-caught managed exceptions. For native exceptions, overriding CWinApp::ProcessWndProcException works.
The two events suggested in Jeff's CodeProject article,Application.ThreadException and AppDomain.CurrentDomain.UnhandledException, are not raised.
Can anyone suggest a way to provide a final managed exception handler for a mixed executable?
Update:
It appears that these exception handlers are only triggered downstream of Application.Run or similar (there's a worker thread flavor, can't remember the name.) If you want to truly globally catch a managed exception you do need to install an SEH filter. You're not going to get a System.Exception and if you want a callstack you're going to have to roll your own walker.
In an MSDN forum question on this topic it was suggested to override a sufficiently low-level point of the main MFC thread in a try ... catch (Exception^). For instance, CWinApp::Run. This may be a good solution but I haven't looked at any perf or stability implications. You'll get a chance to log with a call stack before you bail and you can avoid the default windows unahndled exception behavior.
Taking a look around the internets, you'll find that you need to install a filter to get the unmanaged exceptions passing the filters on their way to your AppDomain. From CLR and Unhandled Exception Filters:
The CLR relies on the SEH unhandled exception filter mechanism to catch unhandled exceptions.
Using those two exception handlers should work.
Why "should?"
The events are not raised using the below:
extern "C" void wWinMainCRTStartup();
// managed entry point
[System::STAThread]
int managedEntry( void )
{
FinalExceptionHandler^ handler = gcnew FinalExceptionHandler();
Application::ThreadException += gcnew System::Threading::ThreadExceptionEventHandler(
handler,
&FinalExceptionHandler::OnThreadException);
AppDomain::CurrentDomain->UnhandledException += gcnew UnhandledExceptionEventHandler(
handler,
&FinalExceptionHandler::OnAppDomainException);
wWinMainCRTStartup();
return 0;
}
// final thread exception handler implementation
void FinalExceptionHandler::OnThreadException( Object^ /* sender */, System::Threading::ThreadExceptionEventArgs^ t )
{
LogWrapper::log->Error( "Unhandled managed thread exception.", t->Exception );
}
// final appdomain exception handler implementation
void FinalExceptionHandler::OnAppDomainException(System::Object ^, UnhandledExceptionEventArgs ^args)
{
LogWrapper::log->Error( "Unhandled managed appdomain exception.", (Exception^)(args->ExceptionObject) );
}
BOOL CMyApp::InitInstance()
{
throw gcnew Exception("test unhandled");
return TRUE;
}
Using those two exception handlers should work. Are you sure you've added them in a place where they're going to be called and properly set (ie, in your application's managed entry point -- you did put one in, right?)