an efficient logger for app-engine on android studio - java

For comparison, android has a kick-ass logger, where in one line I can do
Log.d("TAG", "Something important is happening here.");
Using eclipse on app engine, I have been doing
private static final Logger LOG = Logger.getLogger(MyClass.class.getName());
…
//inside method
LOG.info("I don’t want to have two lines");
I am moving to android studio, is there a way to do something as cool as the one on android? I imagine I might have to add a dependency to Gradle. Any ideas how I might do this?

Not sure what you're asking. How is your logging dependent on your IDE?
But to answer your question: When using Java on AppEngine you should use java.util.logging. Only java.util.logging logs will go into the Monitoring -> Logs section of your cloud console. We're using slf4j in our projects, which is nice if you have multiple projects with different logging mechanisms but what to use the same syntax.
Actually, you could also use a different logger and write the logs to System.out but i don't recommend it. You should use the facilities App Engine provides.
If you must, you could do something similar as you have in Android Studio. That would probably work with a static import of a Log class and a lot of reflection / stack unwinding to get the logging class name. Since reflection is the opposite of performance, i wouldn't do that.

Unfortunately no, the Log you mention (the cool one) is part of the Android framework and it's independent of your IDE.
You could build your own log "utils" and either extend it or call it statically to reduce logging code.
eg.
public class LogAware {
protected void log(Level level, String message){
Logger.getLogger(this.getClass().getName()).log(level,message);
}
protected void logInfo(String message){
log(Level.INFO,message);
}
protected void logFine(String message){
log(Level.FINE,message);
}
protected void logWarning(String message){
log(Level.WARNING,message);
}
protected void logSevere(String message){
log(Level.SEVERE,message);
}
protected void logException(Exception e){
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE,"Exception Thrown",e);
}

Related

log4j2 without catching or exception

I am beginner of java
I am making some program with excel(poi)
and I've been trying to use log4j2
to log what is wrong when run jar or exe
so I got a question
when I searched how to use log4j2 on internet
there is only a usage which like
try{some method}
catch(exception ex)
{logger.catching(ex)}
is it the only way to log ?
is there a way to log without using try catch?
for now ,I think if I use try and catch
I need to use a lot of try catch or throws..
thank you in advance!
Sure. You can invoke logger.whatever() anywhere. E.g. logger.info(); Method catching() is used to log an exception or error that has been caught. That's why in your example it's used with try-catch block. Read more in docs.
Yes, you can log things other than exceptions. In fact you can log anything you want. Please see the log4j2 manual, in particular the page called Java API
You simply create your logger and invoke one of the methods specific to the level you want for your event, or if you're using a custom level use the log method. See the architecture page of the manual for more on log levels.
The code below is from the Java API page of the manual and shows you how to log the message "Hello, World!" at INFO level.
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class HelloWorld {
private static final Logger logger = LogManager.getLogger("HelloWorld");
public static void main(String[] args) {
logger.info("Hello, World!");
}
}

How to persist spring-boot metrics as log?

I am running a spring-boot application, that measures the standard and custom metrics. Now I want those metrics to be persisted in elasticsearch for further examination. I have a functioning ELK-stack in place, so the obvious solution to me was persisting the measures in a log file and let filebeat collect it.
I have found an example, that could have achieved this, but it was using MetricRepository, which is no longer supported in java 8.
The official documentation is not helpful. All shown examples use some proprietary format or are writing into a database.
Can anyone please provide a way to persist metrics as log files?
Sounds like you just have to write a MetricWriter implementation and mark the bean with #ExportMetricWriter Should be a piece of cake. Implement the three methods by just writing to the log and that's it.
Something like:
#Component
#ExportMetricWriter
public class MyMetricWriter implements MetricWriter, Closeable {
private static final Log logger = LogFactory.getLog(MyMetricWriter.class);
#Override
public void increment(Delta<?> delta) {
// record increment to log
}
#Override
public void set(Metric<?> value) {
// record set metric to log
}
#Override
public void reset(String name) {
// Not implemented
}
#Override
public void close() {
/// ...
}
}
The docs mentioned a few others you can refer to their implementations for inspiration.

How to make a library act as a no-op in Debug mode?

This question pertains specifically to Flurry, but I'd be curious how to do it for any 3rd party language.
Essentially, Flurry is causing a crash in Robolectric (as per: https://github.com/robolectric/robolectric-gradle-plugin/issues/144) and the only way I can get my unit tests to work is to remove all calls to Flurry (e.g. FlurryAgent.init, FlurryAgent.onStartSession, etc...).
Short of putting all of these under a BuildConfig.Debug 'if' block (which means having a lot of them), is there any way to globally cause all calls to FlurryAgent compile as no-ops in debug mode, for example?
LeakCanary is a good example of the effect I would like to see.
dependencies {
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1'
}
We are also using Flurry. So for the rest of application Flurry is hidden by our Analytics class and this helps us easy to mock it and verify interaction with it.
To test Analytics itself we use another technics:
public class Analytics {
...
protected startFlurry(Context context, String apiKey) {
FlurryAgent.onStartSession(context, apiKey);
}
...
}
And the test:
public class AnalyticsTest {
...
#Before
protected setUp() {
analytics = new Analytics();
analyticsSpy = spy(analytics);
doNothing().when(analyticsSpy).startFlurry(any(Context.class), anyString());
}
...
}
This is workaround but I don't have better solution for now.

gwt-log and gwt-test-utils not playing nice together

I've got a project that has gwt-log logging lines scattered throughout. Now I'm trying to write some unit tests and nothing seems to be working.
Any class I test that uses the gwt-log facility causes the following exception to be raised:
Caused by: com.googlecode.gwt.test.exceptions.GwtTestConfigurationException:
A custom Generator should be used to instanciate
'com.allen_sauer.gwt.log.client.LogMessageFormatter',
but gwt-test-utils does not support GWT compiler API,
so you have to add our own GwtCreateHandler with
'GwtTest.addGwtCreateHandler(..)' method or to declare your
tested object with #Mock
I have no need for the logger to function during unit tests, I'd prefer to mock it away.
I've attempted to use Mockito to mock the logger, in a few different ways... obviously I have no idea what I'm doing here, none of the following code snippets helped the situation:
public class ClockTest extends GwtTest {
#Mock private LogMessageFormatter lmf;
...
or
...
#Before
public void init() throws Exception {
LogMessageFormatter lmf = mock(LogMessageFormatter.class);
...
Any clues on how to work this out would be most appreciated!
Colin is right, you have 2 ways to deal with your error :
1) Mock the LogMessageFormatter, or at a higher level, mock your Logger instance. gwt-test-utils provides a simple API for mocking with both Mockito or EasyMock : http://code.google.com/p/gwt-test-utils/wiki/MockingClasses
2) provide your own GwtCreateHandler to instanciate the LogMessageFormatter, or at a higher your own Logger instance.
Internally, gwt-log relies on GWT's deferred binding to instanciate a LogMessageFormatter object based on your configuration, which is parsed at compile time. It use GWT's generator API to create the LogMessageFormatter class, but gwt-test-utils is not able to use those kind of Generators.
You'll have to do it "by hand", with gwt-test-utils deferred binding support : GwtCreateHandlers.
Your "LoggerGwtCreateHandler" could use JDK's InvocationHandler and Proxy classes to write a proxy for the Logger interface which would simply silent each method call, since I guess you won't care about any log call in your tests.
Here is a discussion on how to write a GwtCreateHandler : https://groups.google.com/forum/?fromgroups#!topic/gwt-test-utils-users/r_cbPsw9nIE
From the error message you posted:
you have to add our own GwtCreateHandler with
'GwtTest.addGwtCreateHandler(..)' method or to declare your
tested object with #Mock
These are the two options you have to proceed. I've only just begun to work with gwt-test-utils, but the main premise is that it doesn't run the GWT compiler or Dev Mode, so it needs other ways to handle implementing 'magic' features like GWT.create. Its method is to either require you to mock the instance (this should be a fairly common idea in most of your tests for other objects involved in testing) or to provide something like a generator, and hook it up using GwtTest.addGwtCreateHandler.
Building a mock logger shouldn't be too bad, nor should implementing GwtCreateHandler - you just need to make something that has all the log methods. If you want the logging to work, then those methods need to actually invoke some other logger, like java.util.Logger, log4j, slf4j, etc but that is not required for just getting the tests to run (but may be handy for making sure that you logging works, or finding out why your test is failing.
for those still in pain with this damn problem here is what I managed to get (With a lot of pain too ...). It'll solve the conflict between Gwt-test-utils and Gwt-log.
You're of course welcome to modify the format method ;) :
#Before
public void correctLog() {
this.addGwtCreateHandler(new GwtCreateHandler() {
#Override
public Object create(Class<?> classLiteral) throws Exception {
if (classLiteral.isAssignableFrom(LogMessageFormatter.class)) {
return new LogMessageFormatter() {
#Override
public String format(String logLevelText, String category,
String message, Throwable throwable) {
return message + " : " + throwable.getLocalizedMessage();
}
};
}
return null;
}
});
}

a way to use log4j pass set flags in my code

I need to pass some value to enable certain code in may app (in this case is to optionally enable writing some stats to a file in certain conditions, but it might be anything generally).
My java app is installed as a service. So every way I have thought of has some drawbacks:
Add another param to main(): cumbersome as customers already have the tool installed, and the command line would need to be changed every time.
Adding java -DmyEnvVar=A_VALUE to my command line: same as above.
Set an environment variable: service should at least be restarted, and even then you must take care of what user is the service running under etc.
Adding the property in the config file: I prefer not to have this visible on the config file so the user does not see it, it is something for debugging etc.
So I thought maybe there is some way (or hack) to use log4j loggers to pass that value to my code. I have thought of one way already, although is very limited:
Add a dummy class to my codebase com.dummy.DevOptions
public class DevOptions {
public static final Logger logger = Logger.getLogger(DevOptions.class);
In my code, use it like this:
if (DevOptions.logger.isInfoEnabled()){
//do my optional stuff
}
//...
if (DevOptions.logger.isDebugEnabled()){
//do other stuff
}
This allows me to use discriminate among various values, and I could increase the number by adding more loggers to DevOptions. But I wonder whether there is a cleaner way, possibly by configuring the loggers only in log4j.xml??
In log4j you dont need Java classes at all to create loggers (This may come as a surprise). All you need is a package qualified string and not a Java class to create logger category. If I were you I would do the following
PS: Code not guaranteed to compile/run
public class SomeAppCode {
public static final Logger specialLogger = Logger.getLogger("com.mypackage.mysubpackage.speciallogger");
public void someMethod() {
if(specialLogger.isDebugEnabled()) {
//do low level stuff
}
}
}
In your log4j.xml add a category for this string mentioned and if you want you could set "additivity" to be true/false (depending on whether you want to propogate this log message to multiple loggerS)
PS: Note specialLogger is public static and such can be used by 100s of classes like it were their own loggers.
ok I think I found what I needed, wasn't that difficult actually...
public class DevOptions{
public static boolean isEnabled(String myvalue){
Logger logger = Logger.getLogger(myvalue);
return logger.isDebugEnabled();
}
}
public class SomeAppCode {
public void someMethod() {
if(DevOptions.isEnabled("value.A")) {
//do low level stuff
}
}
}
And I can add as many values like value.A in log4j.xml:
<logger name="value.A" additivity="true"><level value="debug" /></logger>
This way I can add as many values as I want by only modifying log4j.xml, no need to add more loggers to DevOptions, only one is sufficient.

Categories