Problems setting up LogEntries on App Engine

25 views
Skip to first unread message

MarkLC via StackOverflow

unread,
Dec 29, 2014, 7:04:53 AM12/29/14
to google-appengin...@googlegroups.com

I believe you need to place your config, either the xml or the properties inside src/main/resources for it to be picked up by log4j. You can just create that resources folder alongside java and webapp. Your config looks fine. Hope that helps.



Please DO NOT REPLY directly to this email but go to StackOverflow:
http://stackoverflow.com/questions/27650125/problems-setting-up-logentries-on-app-engine/27688486#27688486

Dv_MH via StackOverflow

unread,
Dec 30, 2014, 5:57:10 PM12/30/14
to google-appengin...@googlegroups.com

I'm trying to setup logentries on App Engine backend Java on Android Studio

I keep getting this error message whatever I did

log4j:WARN No appenders could be found for logger (root).

log4j:WARN Please initialize the log4j system properly.

log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

Here's my file structure

File structure in Android Studio

log4j.properties

log4j.rootLogger=ALL,le
log4j.appender.le=com.logentries.log4j.LogentriesAppender
log4j.appender.le.layout=org.apache.log4j.PatternLayout
log4j.appender.le.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss ZZZ} %-5p: %F:%L  %m
log4j.appender.le.Token=HIDDEN
log4j.appender.le.Debug=True
log4j.appender.le.Ssl=False

log4j.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd" >
<log4j:configuration debug="true">
    <appender name="le" class="com.logentries.log4j.LogentriesAppender">
        <param name="Token" value="HIDDEN"/>
        <param name="Ssl" value="false"/>
        <param name="Debug" value="true"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d{EEE MMM dd HH:mm:ss ZZZ yyyy}, (%F:%L) %-5p: %m"/>
        </layout>
    </appender>
    <logger name="example">
        <level value="debug"/>
    </logger>
    <root>
        <priority value="debug"></priority>
        <appender-ref ref="le"/>
    </root>
</log4j:configuration>

appengine-web.xml

<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
    <application>HIDDEN/application>
    <version>1</version>
    <threadsafe>true</threadsafe>

    <system-properties>
        <property name="java.util.logging.config.file" value="WEB-INF/classes/log4j.properties"/>
        <property name="log4j.configuration" value="WEB-INF/classes/log4j.properties"/>
        <property name="gcm.api.key" value="HIDDEN"/>
    </system-properties>
</appengine-web-app>

Update

I found a very helpful tip in this question Where to place log4j.xml, basically put -Dlog4j.debug in the Java VM arguments and run App Engine in debug mode. It told me exactly whether it found log4j.xml or not. After much trial and error, It found it when I put it under WEB-INF/classes, now I can see precisely the full stack trace of the error I am having

INFO: Dev App Server is now running
log4j: Trying to find [log4j.xml] using context classloader com.google.appengine.tools.development.IsolatedAppClassLoader@560cbf1a.
log4j: Using URL [file:/C:/_Folder/_Code/AppNameHidden/backend/build/exploded-app/WEB-INF/classes/log4j.xml] for automatic log4j configuration.
log4j: Preferred configurator class: org.apache.log4j.xml.DOMConfigurator
log4j: System property is :null
log4j: Standard DocumentBuilderFactory search succeded.
log4j: DocumentBuilderFactory is: com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
log4j: debug attribute= "true".
log4j: reset attribute= "false".
log4j: Threshold ="null".
log4j: Retreiving an instance of org.apache.log4j.Logger.
log4j: Setting [example] additivity to [true].
log4j: Level value for example is  [debug].
log4j: example level set to DEBUG
log4j: Level value for root is  [debug].
log4j: root level set to DEBUG
log4j: Class name: [com.logentries.log4j.LogentriesAppender]
log4j:ERROR Could not create an Appender. Reported error follows.
java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "modifyThreadGroup")
    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:457)
    at java.security.AccessController.checkPermission(AccessController.java:884)
    at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
    at com.google.appengine.tools.development.DevAppServerFactory$CustomSecurityManager.checkPermission(DevAppServerFactory.java:429)
    at com.google.appengine.tools.development.DevAppServerFactory$CustomSecurityManager.checkAccess(DevAppServerFactory.java:454)
    at java.lang.ThreadGroup.checkAccess(ThreadGroup.java:315)
    at java.lang.Thread.init(Thread.java:391)
    at java.lang.Thread.init(Thread.java:349)
    at java.lang.Thread.<init>(Thread.java:508)
    at com.logentries.net.AsyncLogger$SocketAppender.<init>(AsyncLogger.java:496)
    at com.logentries.net.AsyncLogger.<init>(AsyncLogger.java:336)
    at com.logentries.net.AsyncLogger.<init>(AsyncLogger.java:343)
    at com.logentries.log4j.LogentriesAppender.<init>(LogentriesAppender.java:24)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
    at java.lang.Class.newInstance(Class.java:438)
    at org.apache.log4j.xml.DOMConfigurator.parseAppender(DOMConfigurator.java:247)
    at org.apache.log4j.xml.DOMConfigurator.findAppenderByName(DOMConfigurator.java:176)
    at org.apache.log4j.xml.DOMConfigurator.findAppenderByReference(DOMConfigurator.java:191)
    at org.apache.log4j.xml.DOMConfigurator.parseChildrenOfLoggerElement(DOMConfigurator.java:523)
    at org.apache.log4j.xml.DOMConfigurator.parseRoot(DOMConfigurator.java:492)
    at org.apache.log4j.xml.DOMConfigurator.parse(DOMConfigurator.java:1006)
    at org.apache.log4j.xml.DOMConfigurator.doConfigure(DOMConfigurator.java:872)
    at org.apache.log4j.xml.DOMConfigurator.doConfigure(DOMConfigurator.java:778)
    at org.apache.log4j.helpers.OptionConverter.selectAndConfigure(OptionConverter.java:526)
    at org.apache.log4j.LogManager.<clinit>(LogManager.java:127)
    at org.apache.log4j.Logger.getLogger(Logger.java:104)
    at hello.edu.appnamehidden.backend.RegistrationEndpoint.<clinit>(RegistrationEndpoint.java:36)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:344)
    at com.google.api.server.spi.ServletInitializationParameters.getClassForName(ServletInitializationParameters.java:82)
    at com.google.api.server.spi.ServletInitializationParameters.fromServletConfig(ServletInitializationParameters.java:51)
    at com.google.api.server.spi.SystemServiceServlet.init(SystemServiceServlet.java:102)
    at org.mortbay.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:440)
    at org.mortbay.jetty.servlet.ServletHolder.getServlet(ServletHolder.java:339)
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
    at com.googlecode.objectify.cache.AsyncCacheFilter.doFilter(AsyncCacheFilter.java:59)
    at com.googlecode.objectify.ObjectifyFilter.doFilter(ObjectifyFilter.java:49)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.api.socket.dev.DevSocketFilter.doFilter(DevSocketFilter.java:74)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.tools.development.ResponseRewriterFilter.doFilter(ResponseRewriterFilter.java:127)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:34)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:63)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:125)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectRequest(DevAppServerModulesFilter.java:366)
    at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectModuleRequest(DevAppServerModulesFilter.java:349)
    at com.google.appengine.tools.development.DevAppServerModulesFilter.doFilter(DevAppServerModulesFilter.java:116)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
    at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:98)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:491)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at org.mortbay.jetty.Server.handle(Server.java:326)
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
    at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938)
    at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755)
    at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
    at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
log4j: Appender named [le] not found.
Dec 31, 2014 1:50:36 AM com.google.api.server.spi.SystemServiceServlet init
INFO: SPI restricted: true
log4j: Finalizing appender named [null].

MarkLC via StackOverflow

unread,
Jan 2, 2015, 6:41:02 AM1/2/15
to google-appengin...@googlegroups.com

I believe you need to place your config, either the xml or the properties inside src/main/resources for it to be picked up by log4j. You can just create that resources folder alongside java and webapp. Your config looks fine. Hope that helps.

Update

After looking into App Engines sandbox, it seems it doesn't allow threads that outlive the request that spawned it. Your stack trace shows a RuntimePermission issue as that library spawns a background thread to send the log events to Logentries asynchronously. So this comes down to this library not being compatible with AppEngines sandbox.

You should be able to use log4j's built-in SyslogAppender to send logs synchronously to Logentries. I've successfully tested this locally but not from AppEngines sandbox with the below log4j.properties file:

log4j.rootLogger=DEBUG, syslog
log4j.appender.syslog=org.apache.log4j.net.SyslogAppender
log4j.appender.syslog.Facility=LOCAL7
log4j.appender.syslog.SyslogHost=api.logentries.com:10000
log4j.appender.syslog.layout=org.apache.log4j.PatternLayout
log4j.appender.syslog.layout.ConversionPattern=SECRET_TOKEN%p: (%F:%L) %x %m %n


Please DO NOT REPLY directly to this email but go to StackOverflow:
http://stackoverflow.com/questions/27650125/problems-setting-up-logentries-on-app-engine/27688486#27688486

Dv_MH via StackOverflow

unread,
Jan 2, 2015, 9:46:11 AM1/2/15
to google-appengin...@googlegroups.com

Working workaround solution

Thanks to @MarkLC help I was able to get LogEntries working on the local machine, check the answer and comments http://stackoverflow.com/a/27688486/546439, however, this never worked on the deployed App Engine.

I had to resort to using this gist https://gist.github.com/anlcan/9348751 and modifying it a little bit, it worked perfectly with App Engine when deployed.

Here's my code

public class LogEntriesHelper
{
    private static Socket socket = null;
    private static Lock lock = new ReentrantLock();
    private static Condition condition = lock.newCondition();

    private static final String LOG_TOKEN = "HIDDEN;

    public static void log(String message)
    {
        try
        {
            if (socket == null || !socket.isConnected())
            {
                if (lock.tryLock())
                {
                    socket = new Socket("data.logentries.com", 10000);
                    condition.signalAll();
                    lock.unlock();
                }
                else
                {
                    condition.await();
                }
            }

            Writer out = new OutputStreamWriter(socket.getOutputStream(), "UTF-8");
            socket.setSoTimeout(10000);
            out.write(LOG_TOKEN);
            out.write(" ");
            out.write(message);
            out.write("\r\n");
            out.flush();
        }
        catch (UnknownHostException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }
}

Dv_MH via StackOverflow

unread,
Jan 2, 2015, 12:51:18 PM1/2/15
to google-appengin...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages