Logging component using log4j in java/java EE application - log4j

I'm trying to build a component for application level (java/java ee) logging using log4j.where i can create the jar of the component and put it in class path of any application and use it. Below approach i have followed
I override log method like debug , trace, info etc.
single and multiple argument substutution e.g. MessageFormatter.format("Hi {}. My name is {}.", "Alice", "Bob"); will return the string "Hi Alice. My name is Bob.".
say for example for trace message
public boolean isTraceEnabled() { return logger.isTraceEnabled();}
public void trace(String msg, Throwable throwable, Object... args) {
log(isTraceEnabled(),throwable,msg,args);//
}
private void log(boolean isEnabled, Throwable throwable, String msg,Object... args)
{
if(throwable!=null){
String message=MessageFormatter.getFormattedMessage(throwable);//Formated the exception message
msg=msg+message;
throwable=null;
}
if (args == null || args.length == 0) {
logger.log(FQCN,LEVELmsg, throwable);
} else {
if (isEnabled) {
String formattedMsg = MessageFormatter.arrayFormat(msg, args);//single and multiple argument substutution
logger.log(FQCN, UtilConstant. Level.TRACEformattedMsg, throwable);
}
}
}
My aim is to build the component which can cater all the Java EE applications. Is that two approach sufficient or I need to do more on that. Please help.

It seems to me you're reinventing the wheel. Check out the SLF4J, it can do the things that you're aiming to implement, and it shields you from underlying messaging system, which you can change at any time (it works with log4j out of the box, too).

Related

Memory Leak Issue with spring-cloud-starter-hystrix and spring-cloud-starter-archaius integration

We are using spring-cloud-starter-hystrix with spring-cloud-starter-archaius where we are unable to stop the poolingconfigurationSource thread of archaius once the war is un-deployed. But spring-cloud-starter-archaius is working fine without hystrix and thread is stopped once war is un-deployed.
Try reseting Hystrix before the Spring Application shuts down
#EnableCircuitBreaker
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#PreDestroy
public void cleanUp() {
Hystrix.reset();
}
}
**Issue resolved permanently.**
**There are 2 approach :**
1) Create ContextListener in Servlet and in destroy method , copy below code.
2) If you are using Histrix + Spring Boot + Archaius then on main spring application java file , copy below code in method annonated with #PreDestory annotations.
**Solution :**
try {
if (ConfigurationManager.getConfigInstance() instanceof DynamicConfiguration) {
DynamicConfiguration config = (DynamicConfiguration) ConfigurationManager.getConfigInstance();
config.stopLoading();
} else if (ConfigurationManager.getConfigInstance() instanceof ConcurrentCompositeConfiguration) {
ConcurrentCompositeConfiguration configInst = (ConcurrentCompositeConfiguration) ConfigurationManager
.getConfigInstance();
List<AbstractConfiguration> configs = configInst.getConfigurations();
if (configs != null) {
for (AbstractConfiguration config : configs) {
if (config instanceof DynamicConfiguration) {
((DynamicConfiguration) config).stopLoading();
break;
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
both Davin and Ashish Patel are right: there are multiple leaks caused by Spring cloud.
The presence of a some threads named pollingConfigurationSource can be partially fixed by the solution proposed by Davin. You also need to make sure not to have any file named config.properties in your classpath because com.netflix.config.sources.URLConfigurationSource (look in the source for all the cases) will search for common patsh and start an exectutor thread. there are multiple path in the code that causes an executorservice on thread "pollingConfigurationSource" to be started (an not be always stopped). In my case removing "config.properties" solved this leak
The other leak I'm aware of is caused by Hystrix/RjJava. Instead of calling Histrix.reset call rx.schedulers.Schedulers.shutdown(); this will force threads "RxIoScheduler-" to exit.

Log4Net with castle windsor

I am configuring logging for my application and for logging I am using log4net and castle windsor for DI.
I want logging framework to be wrap inside custom implementation so it can be changed in future.
public interface ICustomLogger
{
void Debug(object message, Exception ex = null);
void Info(object message, Exception ex = null);
void Warn(object message, Exception ex = null);
void Error(object message, Exception ex = null);
void Fatal(object message, Exception ex = null);
}
public class CustomLogger : ICustomLogger
{
private readonly log4net.ILog _log;
private readonly log4net.ILog _log1;
public CustomLogger()
{
//approach1
var stack = new StackTrace();
var frame = stack.GetFrame(1);
var method = frame.GetMethod();
Type type = method.DeclaringType;
_log = log4net.LogManager.GetLogger(type);
//approach2
var dtype = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType;
_log1 = log4net.LogManager.GetLogger(dtype);
}
public CustomLogger(string name)
{
_log = log4net.LogManager.GetLogger(name);
}
public CustomLogger(Type type)
{
_log = log4net.LogManager.GetLogger(type);
}
public void Debug(object message, Exception ex = null)
{
if (_log.IsDebugEnabled)
{
if (ex == null)
{
_log.Debug(message);
}
else
{
_log.Debug(message, ex);
}
}
}
public void Info(object message, Exception ex = null)
{
if (_log.IsInfoEnabled)
{
if (ex == null)
{
_log.Info(message);
}
else
{
_log.Info(message, ex);
}
}
}
public void Warn(object message, Exception ex = null)
{
if (_log.IsWarnEnabled)
{
if (ex == null)
{
_log.Warn(message);
}
else
{
_log.Warn(message, ex);
}
}
}
public void Error(object message, Exception ex = null)
{
if (_log.IsErrorEnabled)
{
if (ex == null)
{
_log.Error(message);
}
else
{
_log.Error(message, ex);
}
}
}
public void Fatal(object message, Exception ex = null)
{
if (_log.IsFatalEnabled)
{
if (ex == null)
{
_log.Fatal(message);
}
else
{
_log.Fatal(message, ex);
}
}
}
}
To register this custom implementation with DI...
container.Register(Component.For<ICustomLogger>()
.ImplementedBy<CustomLogger>()
.LifeStyle.Transient);
Problem comes when I ask DI to resolve logger, then it always return logger for Customlogger type not the class where I want to use it.
class ABC
{
ICustomLogger _logger;
public ABC(ICustomLogger logger)
{
_logger = logger; // type of this logger is CustomLogger not ABC
}
}
Both the approach are not working to resolve logger as ABC.
Can anyone help me to understand what's wrong here and how to fix the issue.
You can do this via a custom dependency resolver.
You first need to create an implementation of ISubDependencyResolver that can resolve dependencies of type ICustomLogger:
public class LoggerResolver : ISubDependencyResolver
{
public bool CanResolve(
CreationContext context,
ISubDependencyResolver contextHandlerResolver,
ComponentModel model,
DependencyModel dependency)
{
//We can only handle dependencies of type ICustomLogger
return dependency.TargetType == typeof (ICustomLogger);
}
public object Resolve(
CreationContext context,
ISubDependencyResolver contextHandlerResolver,
ComponentModel model,
DependencyModel dependency)
{
//We pass the requested type, e.g. ABC, to the constructor of CustomLogger
return new CustomLogger(context.RequestedType);
}
}
You then need to register this resolver with the container like this:
container.Kernel.Resolver.AddSubResolver(new LoggerResolver());
For your specific question - in both approaches you never really leave the "scope" of your class. With the first you are creating a new StackTrace and in the other the declaring type of a constructor is that class itself.
But you implemented a constructor that can receive a type so why not use it. Currently your CustomLogger is registered with your default constructor:
//There is no place here that you tell castle to resolve using the constructor
//that receives `ABS`
container.Register(Component.For<ICustomLogger>()
.ImplementedBy<CustomLogger>()
.LifeStyle.Transient);
See Castle Windsor passing constructor parameters to understand how to pass the parameters and that way invoke the constructor you want
In addition - Worth re-thinking:
Though it is a good idea to create such abstraction between your code and external source in this case I would not do it and I will explain why:
From my experience one doesn't really change the logging framework after the code is up and running. Especially since you are working with a mature and excellent framework - Log4Net. It has many built in abilities and is very adaptable for ones needs: From different formatting of the messaged to outputting the logs to different sources such as databases, files and if I'm not wrong there are also appenders for things like elastic search.
You are using Castle Windsor which has a good integration with Log4Net and has for you a ready made Logging Facility to Log4Net. See this question for how simple it is to add it.
Last point is that if you already write good SOLID code and pass your logger as ILogger to all the components (and not a specific implementation) all they will probably do is call the different Debug/Info/Warn/Error/Fatal methods - which any other mature logging framework will have. So on the day you will have to change (which I think won't happen) you can write an interface that looks like the Log4Net's interface and an implementation that will adapt that to your new logging framework.

Spring + ibatis + String matching

I have a Spring application integrated with ibatis.
I am calling some third party application from where I am getting a String message (a message is combination of messages, there are Strings concatenated with \ delimiter to concatenate the different messages from the third party) as output.
I have to filter this output based on String matching. There are some 150 other Strings. If the output message contains any string out of 150 messages, i have to add some functionality.
I need suggestions to implement it. I am thinking to put 150 Strings in table as the count may increase in future. The Output may contain either no message out of this 150, or any number of combinations with these 150 messages.
I am new to Spring. please tell me how to get these messages from database, since i do not have an id to fetch them or shall I get all of them as list and then compare the output string from the third party. Also please tell me If it wise to keep these messages in database or I can keep them in some property file as well, which one will be better in performance.
Thanks in advance.
Ok, let's start with some possibilities:
IF you will only be adding a few messages in the future and only do so with new releases, then storing the messages in an enum would be a viable choice:
enum ErrorMessage {
SOME_MESSAGE("something, bla bla"),
SOME_OTHER_MESSAGE("something_else"),
...;
private String message;
private ErrorMessage(String message) {
this.message = message;
}
public static ErrorMessage getByErrorMessage(String message) {
for(ErrorMessage errorMessage: message) {
if (errorMessage.message.equals(message)) {
return errorMessage;
}
}
return null;
}
public static boolean exists(String message) {
return getByErrorMessage(message) != null;
}
}
Please note that this version is quite primitive and could be improved by adding all the messages into a static Set:
static Set<String> messagesCache = new Hashset<String>();
//in constructor:
messagesCache.add( message );
// better exists() method:
public static boolean exists(String message) {
return messagesCache.contains(message);
}
Or, as with other solutions, you could only store the actual hashcode of your strings. A hashcode is simple a numeric representation of your string and will be unique enough for you to identify it. Same solution as above:
static Set<String> messagesHashCodes = new Hashset<String>();
//in constructor:
messagesHashCodes .add( message.hashCode() );
// better exists() method:
public static boolean exists(String message) {
return messagesHashCodes .contains(message.hashCode());
}
(Of course, it would be a good idea to check for null values, etc.)
The enum version has one big advantage, if you want to have DIFFERENT actions taken for some of the actions, you can code them into the enum, for example...
SOME_MESSAGE_REQUIRING_AN_ACTION("...") {
#Override
public void doAction(StringBuilder finalString) {
...doSomething.
}
}
...
public void doAction(StringBuilder finalString) {
finalString.append( this.message );
finalString.append( SOME_SEPERATOR );
}
public void static doAction(StringBuilder builder, String errorMessage) {
if (exists(errorMessage)) {
}
}
In this example, you CAN override the doAction method in each enum value, if it should do more/something else than append the message to the StringBuilder. It would also be a nice touch to add some "NULL_MESSAGE" to the enum List that does nothing and is only there to allow easier handling:
UNKNOWN_MESSAGE(null) {
#Override
public void doAction(StringBuilder finalString) {
// do nothing here
}
}
public static ErrorMessage getByErrorMessage(String message) {
for(ErrorMessage errorMessage: message) {
if (errorMessage.message != null && errorMessage.message.equals(message)) {
return errorMessage;
}
}
return UNKNOWN_MESSAGE;
}
This way, you can simple give every single string into your enum method doAction(StringBuilder, String) and get the result: If a message fits, it is added (and some other action taken), if not, it will be ignored, null checks included.
On the other hand, if you messages change quite often, then you might not do a release for such a change but keep the values in a database. In this case, I would use the hashCode() of the message as an id (as I said, unique enough, typically) and load the whole thing into memory when the application starts, allowing you, for example, to build again a Set of hashcodes to compare your errorMessages' hashcodes against.
protected void init() {
// load all error Messages from the database
// put them into a Map<String, String> (hashCode -> Value) or even just a Set<String> (hashcodes)
}

Spring Integration logging with sensitive information

I recently add si to my project and have been very happy with it. I'm having an issue with my logging. I am using logback and all works ok; however, I have sensitive information flowing through the system that cannot be logged "as is". Certain data must be intercepted and masked before logging. If I configure my log level below WARN then I see this sensitive info. What is the best way to filter all messages bound for logging? I am using a inbound gateway with a service activator for an si server. I am using an async outbound gateway for an si client.
It isn't clear how the logging is relevant to the Spring Integration.
Seems for me it's enough to write some custom Appender accodrding to your logging framework.
From other side you can filter messages before log them using SI <filter> and <logging-channel-adapter> after <filter>.
But in this case you can't use logger.debug() (or similar) from your code: you alway should send the message to the channel for logging.
Please, explain further from where and how you want to filter (or mask) logging messages.
Using logback and slf4j I used this to mask the si messages...
public class LoggingFilter extends TurboFilter {
private static final Marker secured = MarkerFactory.getMarker("secured");
#Override
public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) {
if (format != null && logger.getName().startsWith("org.springframework.integration")) {
boolean isSecured = marker != null && (marker.equals(secured) || marker.contains(secured));
if (isSecured) {
return NEUTRAL;
} else {
if (marker == null) {
marker = secured;
} else {
marker.add(secured);
}
String message = MessageFormatter.arrayFormat(format, params).getMessage();
//TODO: mask message here.
logger.log(marker, logger.getName(), toLocationAwareLoggerInteger(level), message, null, t);
return DENY;
}
} else {
return NEUTRAL;
}
}
}

Spec fails when run by mspec.exe, but passes when run by TD.NET

I wrote about this topic in another question.
However, I've since refactored my code to get rid of configuration access, thus allowing the specs to pass. Or so I thought. They run fine from within Visual Studio using TestDriven.Net. However, when I run them during rake using the mspec.exe tool, they still fail with a serialization exception. So I've created a completely self-contained example that does basically nothing except setup fake security credentials on the thread. This test passes just fine in TD.Net, but blows up in mspec.exe. Does anybody have any suggestions?
Update: I've discovered a work-around. After researching the issue, it seems the cause is that the assembly containing my principal object is not in the same folder as the mspec.exe. When mspec creates a new AppDomain to run my specs, that new AppDomain has to load the assembly with the principal object in order to deserialize it. That assembly is not in the same folder as the mspec EXE, so it fails. If I copied my assembly into the same folder as mspec, it works fine.
What I still don't understand is why ReSharper and TD.Net can run the test just fine? Do they not use mspec.exe to actually run the tests?
using System;
using System.Security.Principal;
using System.Threading;
using Machine.Specifications;
namespace MSpecTest
{
[Subject(typeof(MyViewModel))]
public class When_security_credentials_are_faked
{
static MyViewModel SUT;
Establish context = SetupFakeSecurityCredentials;
Because of = () =>
SUT = new MyViewModel();
It should_be_initialized = () =>
SUT.Initialized.ShouldBeTrue();
static void SetupFakeSecurityCredentials()
{
Thread.CurrentPrincipal = CreatePrincipal(CreateIdentity());
}
static MyIdentity CreateIdentity()
{
return new MyIdentity(Environment.UserName, "None", true);
}
static MyPrincipal CreatePrincipal(MyIdentity identity)
{
return new MyPrincipal(identity);
}
}
public class MyViewModel
{
public MyViewModel()
{
Initialized = true;
}
public bool Initialized { get; set; }
}
[Serializable]
public class MyPrincipal : IPrincipal
{
private readonly MyIdentity _identity;
public MyPrincipal(MyIdentity identity)
{
_identity = identity;
}
public bool IsInRole(string role)
{
return true;
}
public IIdentity Identity
{
get { return _identity; }
}
}
[Serializable]
public class MyIdentity : IIdentity
{
private readonly string _name;
private readonly string _authenticationType;
private readonly bool _isAuthenticated;
public MyIdentity(string name, string authenticationType, bool isAuthenticated)
{
_name = name;
_isAuthenticated = isAuthenticated;
_authenticationType = authenticationType;
}
public string Name
{
get { return _name; }
}
public string AuthenticationType
{
get { return _authenticationType; }
}
public bool IsAuthenticated
{
get { return _isAuthenticated; }
}
}
}
Dan,
thank you for providing a reproduction.
First off, the console runner works differently than the TestDriven.NET and ReSharper runners. Basically, the console runner has to perform a lot more setup work in that it creates a new AppDomain (plus configuration) for every assembly that is run. This is required to load the .dll.config file for your spec assembly.
Per spec assembly, two AppDomains are created:
The first AppDomain (Console) is created
implicitly when mspec.exe is
executed,
a second AppDomain is created by mspec.exe for the assembly containing the specs (Spec).
Both AppDomains communicate with each other through .NET Remoting: For example, when a spec is executed in the Spec AppDomain, it notifies the Console AppDomain of that fact. When Console receives the notification it acts accordingly by writing the spec information to the console.
This communiciation between Spec and Console is realized transparently through .NET Remoting. One property of .NET Remoting is that some properties of the calling AppDomain (Spec) are automatically included when sending notifications to the target AppDomain (Console). Thread.CurrentPrincipal is such a property. You can read more about that here: http://sontek.vox.com/library/post/re-iprincipal-iidentity-ihttpmodule-serializable.html
The context you provide will run in the Spec AppDomain. You set Thread.CurrentPrincipal in the Because. After Because ran, a notification will be issued to the Console AppDomain. The notification will include your custom MyPrincipal that the receiving Console AppDomain tries to deserialize. It cannot do that since it doesn't know about your spec assembly (as it is not included in its private bin path).
This is why you had to put your spec assembly in the same folder as mspec.exe.
There are two possible workarounds:
Derive MyPrincipal and MyIdentity from MarshalByRefObject so that they can take part in cross-AppDomain communication through a proxy (instead of being serialized)
Set Thread.CurrentPrincipal transiently in the Because
(Text is required for formatting to work -- please ignore)
Because of = () =>
{
var previousPrincipal = Thread.CurrentPrincipal;
try
{
Thread.CurrentPrincipal = new MyPrincipal(...);
SUT = new MyViewModel();
}
finally
{
Thread.CurrentPrincipal = previousPrincipal;
}
}
ReSharper, for example, handles all the communication work for us. MSpec's ReSharper Runner can hook into the existing infrastructure (that, AFAIK, does not use .NET Remoting).

Resources