How to Log the jar file location in log file.
Say I am printing some message from LogTest.java which is in myLog.jar , is there any way to print in log file as below.
INFO 2013-10-30 15:58:07,227 [log] (LogTest.java:235:myLog.jar) - Some Log Message
Various jar in a legacy project contain similar kind of log message with the same class name,
It is taking time to investigate any issue.
Is there any way to handle this please give your suggestion.
There is no an option to include the source file with the standar org.apache.log4j.PatternLayout. However, you can create your own layout to include it the source. The following may be of use.
public class MyLayout extends org.apache.log4j.Layout {
public void activateOptions() {
// None action
}
public String format(LoggingEvent event) {
StringBuilder sb = new StringBuilder();
sb.append(event.getLevel());
sb.append(" (");
sb.append(event.getLoggerName());
sb.append(":");
sb.append(event.getLocationInformation().getLineNumber());
sb.append(":");
sb.append(getSource(event.getLoggerName()));
sb.append(") - ");
sb.append(event.getMessage());
sb.append(LINE_SEP);
return sb.toString();
}
public boolean ignoresThrowable() {
return true;
}
public static String getSource(String className) {
try {
ClassLoader loader = MyLayout.class.getClassLoader();
String name = className.replace('.', '/').concat(".class");
URL url = loader.getResource(name);
return url.getPath();
} catch (Exception e) {
return null;
}
}
}
Related
The goal is to block access to the page from the list of IP addresses. This list is in the file list.txt.
I made the service that checks IP from request and with HashSet of "unwanted" addresses, but subgoal is "catch on the fly" this list.txt. What I mean: if I add some IP to this file, it should be blocked without restarting application. And I have not ideas how to solve this, cause my app refreshes this list only after restart. My code is below
#Service
public class BlackListService {
public Set<String> loadBlackList() {
java.util.Set<java.lang.String> blackList = new HashSet<>();
InputStream resource = null;
try {
resource = new ClassPathResource(
"blacklist.txt").getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
try (BufferedReader reader = new BufferedReader(new InputStreamReader(resource))) {
blackList = reader.lines().collect(Collectors.toSet());
for (java.lang.String address:
blackList) {
System.out.println(address);
}
} catch (IOException e) {
e.printStackTrace();
}
return blackList;
}
public boolean isNowAllowedIP(Set<String> blackList, String requestIP) {
return blackList.contains(requestIP);
}
}
And controller:
#Controller
public class MainController {
private final BlackListService blackListService;
public MainController(BlackListService blackListService) {
this.blackListService = blackListService;
}
#GetMapping("/")
public String mainPage(HttpServletRequest request, Model model) {
Set<String> blackList = blackListService.loadBlackList();
if (blackListService.isNowAllowedIP(blackList, request.getRemoteAddr())) {
Logger logger = Logger.getLogger("Access logs");
logger.warning("Access disallowed");
model.addAttribute("message", request.getRemoteAddr() + ": Access disallowed");
return "index";
}
model.addAttribute("message", "Access allowed");
return "index";
}
}
Can someone help with this "subgoal"?
In loadBlackList() you are reading a resource from the classpath. Could this be picking up a file built into your jar file or build dir which is not the file you are editing? I would try changing loadBlackList() to use FileReader and a path on the file system rather than a path within the classpath instead of InputStreamReader.
What you need is a recurring background job that will reload your blacklist after you change it. This blog will discusses a "modern" approach for doing it with Spring.
Save the last modified time for the file when your program starts and you first load it. See this for checking the file modified time.
Schedule the background job to run every minute (or 5 or whatever is frequent enough for your needs).
When the job runs check the current last updated time on the file and if its different than the saved one, then its time to reload your list.
I have a logger code in Java. It is not creating a log file. Though when I am using Logger.println in another class it is printing. But I am not sure if it is logging or not.
I have written a logger class and I am using this in another class to log my code.
My logger class looks like below:
public class Logger{
private static String logFile=null;
public static boolean setLogFile(String newLogFile, Boolean b){
boolean done = false;
if (logFile ==null){
logFile = newLogFile;
File file = new File(logFile);
try{
done = file.createNewFile();
}
catch(IOException e){Logger.println("Error in creating log file" +logFile);
}
}
else {
File fromFile = new File(logFile);
File toFile = new File(newLogFile);
if(fromFile.exists()){
done = fromFile.renameTo(tofile);
if (done){
logFile = newLogFile;
}
else{
logger.println("can not move file");
}
}else{
Logger.println("file not exist";
}}
return done;
}
public static void print(String data){
system.out.println(data);
try{
FileWriter logger = new FileWriter (logFile, true);
logger.write(data);
logger.close();
}
catch(IOException e){System.out.println("can not write to file");
}}
where is logger.print saving to?
where are the logs being saved or how can i specify the location of my logs?
You no need to reinvent the wheel again. You can easily integrate one of the loggers that can write a log file at your convenient location.
Try Log4j, SL4j or available dependencies based on your need.
These existing implementations give you fine-grained loggings. You can print info, error, debug, config and warnings. It would be easier to integrate as well as developer can concentrate on business logic.
Here is what I would like to achieve. We have an application that is running as a servlet on an IBM Domino server.
The application uses resource bundle to get translated messages and labels according to the browser language.
We want to enable customers to override some of the values.
We cannot modify the bundle_lang.properties files in the .jar at runtime.
So the idea was to provide additional bundleCustom_lang.properties files along with the .jar
This bundle could be loaded at runtime using
private static void addToClassPath(String s) throws Exception {
File file = new File(s);
URLClassLoader cl = (URLClassLoader) ClassLoader.getSystemClassLoader();
java.lang.reflect.Method m = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class });
m.setAccessible(true);
m.invoke(cl, new Object[] { file.toURI().toURL() });
}
So far, so good, this works in Eclipse. Here I had the bundleCustom files in a directory outside the workspace ( /volumes/DATA/Temp/ )
Once the addition ResourceBundle is available, We check this bundle for the key first. If it returns a value than this value is being used for the translation. If no value is returned, or the file does not exist, the value from the bundle inside the .jar is used.
My full code is here
public class BundleTest2 {
static final String CUSTOM_BUNDLE_PATH = "/volumes/DATA/Temp/";
static final String CUSTOM_BUNDLE_MODIFIER = "Custom";
public static void main(String[] args) {
try {
addToClassPath(CUSTOM_BUNDLE_PATH);
System.out.println(_getTranslation("LabelBundle", "OutlineUsersAllVIP"));
} catch (Exception e) {
}
}
private static String _getTranslation(String bundle, String translation) {
return _getTranslation0(bundle, new Locale("de"), translation);
}
private static String _getTranslation0(String bundle, Locale locale, String key) {
String s = null;
try {
try {
ResourceBundle custom = ResourceBundle.getBundle(bundle + CUSTOM_BUNDLE_MODIFIER, locale);
if (custom.containsKey(key)) {
s = custom.getString(key);
}
} catch (MissingResourceException re) {
System.out.println("CANNOT FIND CUSTOM RESOURCE BUNDLE: " + bundle + CUSTOM_BUNDLE_MODIFIER);
}
if (null == s || "".equals(s)) {
s = ResourceBundle.getBundle(bundle, locale).getString(key);
}
} catch (Exception e) {
}
return s;
}
private static void addToClassPath(String s) throws Exception {
File file = new File(s);
URLClassLoader cl = (URLClassLoader) ClassLoader.getSystemClassLoader();
java.lang.reflect.Method m = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class });
m.setAccessible(true);
m.invoke(cl, new Object[] { file.toURI().toURL() });
}
}
When I try the same from inside the servlet, I get a MissingResourceException.
I also tried to put the .properties files into a customization.jar and provide the full path ( incl. the .jar ) when invoking addToClassPath().
Apparently, the customization.jar is loaded ( it is locked in the file system ), but I still get the MissingResourceException.
We already use the same code in addToClassPath to load a Db2 driver and this is working as expected.
What am I missing?
Why don't you use Database to store the overriden translations? Persisting something crated by client in the local deployment of application is generally not a good idea, what will happen if you redeploy the app, will these resources be deleted? What if you have to run another node of your app, how will you replicate the custom properties file?
Below I have a code snippet for a custom API manager mediator, I'm suppose to modify this code for our use. I'm having trouble though getting the logs out of the code when I'm running it in our wso2 environment. What would be the process to be able to the outputs of these logs. This is going to be a jar file I add to the repository/components/lib/ directory of the APIM. The jar file name is com.domain.wso2.apim.extensions. I need to be able to see whats being passed and what parts of the code are being hit for testing
public class IdentifiersLookup extends AbstractMediator implements ManagedLifecycle {
private static Log log = LogFactory.getLog(IdentifiersLookup.class);
private String propertyPrefix = "";
private String netIdPropertyToUse = "";
private DataSource ds = null;
private String DsName = null;
public void init(SynapseEnvironment synapseEnvironment) {
if (log.isInfoEnabled()) {
log.info("Initializing IdentifiersLookup Mediator");
}
if (log.isDebugEnabled())
log.debug("IdentifiersLookup: looking up datasource" + DsName);
try {
this.ds = (DataSource) new InitialContext().lookup(DsName);
} catch (NamingException e) {
e.printStackTrace();
}
if (log.isDebugEnabled())
log.debug("IdentifiersLookup: acquired datasource");
}
Add the below line to log4j.properties file resides wso2am-2.0.0/repository/conf/ folder and restart the server.
log4j.logger.com.domain.wso2.apim.extensions=INFO
I want to create and store log files in a particular folder in every hour. How to approach?
Any example will be helpful.
No extra effort required. Use DailyRollingFileAppender where set Datepattern - '.'yyyy-MM-dd-HH - Rollover at the top of every hour.
Example -
log4j.appender.LOGFILE = org.apache.log4j.DailyRollingFileAppender
log4j.appender.LOGFILE.DatePattern = '.'yyyy-MM-dd-HH
...
Reference - DailyRollingFileAppender
Note : Do not use the colon ":" character in anywhere in the DatePattern option. The text before the colon is interpeted as the protocol specificaion of a URL which is probably not what you want.
You can use logger API(log4j) for generating the log files in every hour.
Something like that :
public void run(){
while(true){
synchronize(this){
if(timeLap==1hr)
file.writeLine();
}
else
Thread.sleep(1hour);
}
}
or you can use the API http://www.vogella.com/articles/Logging/article.html
You can create a custom FileAppender, somthing like
public class TestFileAppender extends WriterAppender {
String pattern;
public void setFile(String file) {
this.pattern = file;
}
public synchronized void update() {
try {
closeWriter();
String folder = new SimpleDateFormat("yyyyMMddHH").format(new Date());
File file = new File(String.format(pattern, folder));
file.getParentFile().mkdirs();
setWriter(new BufferedWriter(new FileWriter(file, true)));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
use it it log4j config
log4j.appender.file = test.TestFileAppender
log4j.appender.file.file = xxx/%s/1.log
log4j.appender.file.layout = org.apache.log4j.SimpleLayout
and run a FolderNameChanger once an hour
class FolderNameChanger extends TimerTask {
FolderNameChanger() {
run();
}
public void run() {
Enumeration<Appender> e = Logger.getRootLogger().getAllAppenders();
while (e.hasMoreElements()) {
Appender a = e.nextElement();
if (a instanceof TestFileAppender) {
((TestFileAppender) a).update();
}
}
}
}
this task finds all TestFileAppenders and changes their paths