We have a huge application using our custom RollingFileAppender (extended from org.apache.log4j.RollingFileAppender in log4j 1.x). We have overridden few methods, but two major methods are rollOver() and subAppend() as follows:
public void rollOver()
{
// Custom Code to specify how rolled-over files should be numbered and which file should be
// overwritten when MaxBackupIndex is reached
}
public void subAppend(LoggingEvent event)
{
// Custom Code to encrypt message before writing it
String data = this.layout.format(event);
if (isEncryptionOn())
{
data = PlatformEncryptDecrypt.encrypt2Way(data);
data = toUnicodeHexString(data);
}
this.qw.write(data);
.
.
.
// Other code taken from parent class
.
.
.
}
While migrating this to log4j2, I want to leverage log4j2's RollingFileAppender as much as possible, while overriding only selected methods. Since RollingFileAppender is final class, I would prefer to use builder for creating custom appender. I went through few other similar posts, but they are talking about logging few extra attributes with RollingFileAppender.
What would be the best way to achieve this using current latest version of log4j2 i.e. 2.13? Any help is highly appreciated.
If you are just wanting to encrypt the data then don't override the RollingFileAppender. Implement your own Layout instead. In fact, I would be open to adding an EncryptingLayout that wraps another Layout if you would create a Jira issue with your requirements.
In the meantime, just create a Layout that accepts another Layout as a configuration attribute. Then the methods in your Layout call that Layout's corresponding method and then encrypt the result.
Related
I am trying to do one example with ArchUnit where passing the AnalyzeClasses can be dynamic based on for which Adapter Application the test need run.
For Example:
#AnalyzeClasses(packages = "${archtest.scan.package}", importOptions = { ImportOption.DoNotIncludeTests.class, ImportOption.DoNotIncludeJars.class })
public class ArchitectureTests {
}
And from application.properties file it should allow to pass the packages to analyze dynamically, so any application using this Application as Jar library can provide the scan classes in its properties file. As below.
archtest.scan.package=com.example.pkgname
I am not sure what is the right way to pick up the dynamic value from property and pass that into #AnalyzeClasses Annotation. I am looking for some help or any example in this regard.
I don't think that ArchUnit's JUnit 4 & 5 support – in the current version 0.23.1 – allows for dynamic packages configured via an application.properties.
But instead of using #AnalyzeClasses, you can always just invoke new ClassFileImporter().import… and pass any dynamic runtime values you like.
(Note that ArchUnit's JUnit support also introduces a clever cache to reuse imported JavaClasses by multiple #ArchTests, but storing JavaClasses in a static field may be also good enough.)
This actually should be possible using a custom LocationProvider within #AnalyzeClasses. E.g.
#AnalyzeClasses(locations = ApplicationPropertiesLocationProvider.class)
public class ExampleTest {
// ...
}
class ApplicationPropertiesLocationProvider implements LocationProvider {
#Override
public Set<Location> get(Class<?> testClass) {
String packageToScan = readFromApplicationProperties();
return Locations.ofPackage(packageToScan);
}
}
But be aware of caching limitations! The caching mechanism assumes that your LocationProvider is "idempotent", i.e. it always returns the same locations. The caching mechanism will only take the type of the LocationProvider into consideration as cache key. This should not be a problem for a static application.properties as source though.
I need to filter Log4j output to remove "sensitive" information like passwords from the log messages. The goal is to do something like this:
Replace:
05-Jan-2018 INFO [org.my.application] Username=Bob Password=myWeakPassword
With:
05-Jan-2018 INFO [org.my.application] Username=Bob Password=*********
This is fairly easy to do in Log4j V1, by extending the PatternLayout class:
public class CustomPatternLayout extends org.apache.log4j.PatternLayout {
#Override
public String format(LoggingEvent event) {
String temp = super.format(event);
return doFilteringStuff(temp);
}
}
However, in Log4j V2 the PatternLayout class was made "final" and the whole architecture was changed. There no longer seems to be a simple way to intercept/override the calls to the PatternLayout object. I looked at the Apache documentation but there's not much information.
I checked this question and this question but neither one has much help to offer.
I realize this is a very "general" question but does anyone know a straightforward way to do this in Log4j V2, or have any advice on this?
I think what you’re looking for is the RewriteAppender. From the manual:
The RewriteAppender allows the LogEvent to manipulated before it is processed by another Appender. This can be used to mask sensitive information such as passwords or to inject information into each event.
Please refer to this answer for a full example of using the RewriteAppender to mask sensitive content.
I want to implement the logging to openlog.nsf functionality from the domino api in an application.
However in the current setup of the application logging (to Domino console) only occurs when this is enabled for the whole application via a configuration property e.g.
public static void writeToConsole(String msg){
if (getDeugMode() ==true) {
System.out.println(msg);
}
}
usage:
writeToConsole("hello world");
I am wondering how I could rewrite the writeToConsole method to utilize the XspOpenLogLogUtil class?
XspOpenLogUtil.logErrorEx(Throwable, String, Level, Document) will allow you to pass a custom message.
Also XspOpenLogUtil.getOpenLogItem() gets a handle on the OpenLogItem object. From there you can use any of the inner methods.
See this page https://wiki.openntf.org/pages/viewpage.action?pageId=6586418 (all the method names are the same, the class in ODA is just XspOpenLogUtil instead of OpenLogUtil.
In my apps I usually have a wrapper method handleException(Throwable t) which calls XspOpenLogUtil.logError()` anyway and that's what I would recommend. It gives greater flexibility for handling e.g. different logging levels like this or changing the logging framework, should you so wish in the future.
I have a Java web application which use Spring and Hibernate and I plan to use lightadmin to provide an administration interface.
However, I found very little information about the logging part of lightadmin : if I have such an adminsitration interface, I would like that any operation made to our data (such as create, update or delete) is logged in our custom logger (it's not on a file but on a table on the database, this choice has already been made and implemented long time ago).
My need is to have a log entry containing some information (might be just the id) about the modified rows. Is there a global way to configure it?
Or can I add a logging annotation somewhere in each class which extends AdministrationConfiguration? If yes, where?
You can use the class AbstractRepositoryEventListener like it's show on the LightAdmin documentation here
Add you logger insertion by overiding onAfterSave, onAfterCreate and onAfterDelete into your own RepositoryEventListener.
After you just need to register your listener like this
public class YourAdministration extends AdministrationConfiguration<YourObject> {
public EntityMetadataConfigurationUnit configuration(EntityMetadataConfigurationUnitBuilder configurationBuilder) {
return configurationBuilder
.repositoryEventListener(YourRepositoryEventListener.class)
.build();
}
}
I'm configuring the logging for a Java application. What I'm aiming for is two logs: one for all messages and one for just messages above a certain level.
The app uses the java.util.logging.* classes: I'm using it as is, so I'm limited to configuration through a logging.properties file.
I don't see a way to configure two FileHandlers differently: the docs and examples I've seen set properties like:
java.util.logging.FileHandler.level = INFO
While I want two different Handlers logging at different levels to different files.
Any suggestions?
http://java.sun.com/j2se/1.4.2/docs/guide/util/logging/overview.html is helpful. You can only set one Level for any individual logger (as you can tell from the setLevel() method on the logger). However, you can take the lowest of the two common levels, and then filter programmatically.
Unfortunately, you can't do this just with the configuration file. To switch with just the configuration file you would have to switch to something like log4j, which you've said isn't an option.
So I would suggest altering the logging in code, with Filters, with something like this:
class LevelFilter implements Filter {
private Level Level;
public LevelFilter(Level level) {
this.level = level;
}
public boolean isLoggable(LogRecord record) {
return level.intValue() < record.getLevel().intValue();
}
}
And then on the second handler, do setFilter(new LevelFilter(Level.INFO)) or whatever. If you want it file configurable you could use a logging properties setting you've made up yourself, and use the normal Properties methods.
I think the configuration code for setting up the two file handlers ad the programmatic code is fairly simple once you have the design, but if you want more detail add a comment and I'll edit.
I think you should be able to just subclass a handler and then override the methods to allow output to go to multiple files depending on the level of the message. This would be done by overriding the publish() method.
Alternatively, if you have to use the system-provided FileHandler, you could do a setFilter() on it to inject your own filter into the mix and, in that filter code, send ALL messages to your other file and return true if the LogRecord level if INFO or higher, causing the FileHandler.publish() to write it to the real file.
I'm not sure this is the way you should be using filters but I can't see why it won't work.