I'm using a liftweb service over Jetty with log4j for logging.
here is how I setup the logger in Boot class:
val config = Properties.envOrElse("log4j.configuration","/props/syslog.log4j.xml")
val configFile = getClass.getResource(config)
Logger.setup = Full(Log4j.withFile(configFile))
When running the app as service (service jetty start), I can't see any log files written.
What am I doing wrong here?
This is my syslog.log4j.xml configuration file:
<root>
<level value="trace"/>
<appender-ref ref="CA"/>
<appender-ref ref="CA2"/>
</root>
Please read this wiki page to set up log4j:
https://www.assembla.com/spaces/liftweb/wiki/Logging
Related
I'm using the Logback SDK for Java to send events to Sentry as described in the documentation.
Snippet:
<conversionRule conversionWord="CUSTOM_CONVERSION_RULE"
converterClass="clazz..." />
...
<property scope="context" name="myEnc" value="%d{ISO8601,UTC} | %-5level | %-50thread | %-55logger{55} | %CUSTOM_CONVERSION_RULE" />
...
<appender name="SENTRY" class="io.sentry.logback.SentryAppender">
<dsn>...</dsn>
<encoder>${myEnc}</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
</appender>
....
The initial problem was that the events sent to Sentry were not converted by my custom conversion rule. All the other appenders such as Console that use the property myEnc containing the conversion rule parse the data as expected. But it seems that the io.sentry.logback.SentryAppender in combination with the encoder somehow doesn't do that. The filter property is working as well as the dsn one, so I get the errors in Sentry but not with my custom parsing.
The version that I use for io.sentry.sentry-logback (and transitively sentry) is 1.7.24.
I then read about before-send hook from Sentry docs which is what I want to control what data is sent to Sentry and I had to upgrade to latest for that which is 3.1.3 at the time of writing this.
The Logback XML config changed a bit:
<appender name="SENTRY" class="io.sentry.logback.SentryAppender">
<options>
<dsn>...</dsn>
<beforeSend>????</beforeSend>
</options>
...
</appender>
From what I can see the before-send hook is exactly what I need to scrub the data when required because I don't want some info to be sent to Sentry. docs
Now, the second issue is that I don't know how to ref here a method. In the Java config there is a BiFunction that takes the event and can alter it. But I want to apply this hook to all my log events, that's why the only place it is configured is in the Logback SDK.
In Spring Boot for example there is a starter for Sentry and, off course, a bean that you can inject in the auto-configuration.
But, I'm using Scala with no Spring Boot.
Also, the project is already in prod so I cannot change lots of things and I'm looking for the smallest one that will allow me to add a hook to Logback's SDK for Sentry.
Here is the appender and it looks like (I'm not sure how it works) the options can be populated from XML and than pass to init that will take all them into account, including my before send hook.
I don't know if it's accepted to have two questions and only one referenced in the title but I didn't find a nicer way to ask/explain the problem, because one thing lead to another.
To summarize the questions:
Why that custom rule is not working with Logback Sentry's appender.
How can I let the appender know about my hook and use it.
Thanks in advance!
You can configure Sentry independently from appender configuration in logback.xml. For example:
public class Main {
private static final Logger LOGGER = LoggerFactory.getLogger(Main.class);
static {
Sentry.init(options -> {
options.setDsn("PUT YOUR DSN HERE");
options.setBeforeSend((sentryEvent, o) -> {
sentryEvent.setTag("custom", "tag");
return sentryEvent;
});
});
}
public static void main(String[] args) {
LOGGER.error("oops");
}
}
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="sentry" class="io.sentry.logback.SentryAppender" />
<root level="debug">
<appender-ref ref="console"/>
<appender-ref ref="sentry"/>
</root>
</configuration>
Check complete code sample in github repo: https://github.com/maciej-scratches/sentry-logback-custom-config
but the problem is my application is running before my server started (WebLogic server).
Your question seems to be in reference to Log4j 1. Log4j 1 has been end-of-life since August of 2015.
Upgrading to Log4j 2.13.0 would allow you to use the Kubernetes Lookup which would allow you to configure your log file name as:
<File name="MyFile" filename="${path}/app_${k8s:containerName}.${date:MM-dd-yyyy}.log>
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
</File>
I have a scala app which uses the AWS Kinesis Client Library.
I am using logback with the logstash encoder to format the logs from my app and the KCL as JSON.
My App is also written using cats.effects.IO.
import cats.effects._
object Main extends App {
run(args.toList).unsafeRunSync
def run(args: List[String]): IO[ExitCode] = { .. }
}
When the above code runs, logs from my app and from the KCL are correctly formatted through my JSON appender.
The problem arises when I try to use cats.effects.IOApp:
import cats.effects._
object Main extends IOApp {
def run(args: List[String]): IO[ExitCode] = { .. }
}
When this version runs, the logs from my app are still correctly formatted through my JSON appender, but the logs from the KCL revert back to the default basic logger.
I have narrowed this down to the use of Fiber under the hood, and can reproduce the problem if I use run(args.toList).start.flatMap(_.join).unsafeRunSync which is essentially what IOApp is doing under the hood. I am running on the JVM, so this is the code that is running under the hood.
My logback.xml:
<appender name="json" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<pattern>
<pattern>
{
"level": "%level",
"message": "%message"
}
</pattern>
</pattern>
<nestedField>
<fieldName>properties</fieldName>
<providers>
<timestamp>
<fieldName>utcTimestamp</fieldName>
<pattern>yyyy-MM-dd'T'HH:mm:ss'Z'</pattern>
<timeZone>UTC</timeZone>
</timestamp>
<arguments/>
</providers>
</nestedField>
<stackTrace/>
</providers>
</encoder>
</appender>
<root level="info">
<appender-ref ref="json" />
</root>
</configuration>
Relying on the auto discovery of the logback.xml when there are multiple conflicting dependencies on the class path means there is no guarantee as to which will load first.
Since there is already a dependency for:
libraryDependencies += "org.slf4j" % "jcl-over-slf4j" % "1.7.21"
You just need to exclude the commons logger:
excludeDependencies += "commons-logging" % "commons-logging"
This way the KCL is forced to use the correct logger instead of having to choose.
I deployed usergrid in tomcat, I see it is using slf4j binds to log4j, I tried to put log4j.properties in /var/lib/tomcat7/webapps/ROOT/WEB-INF/classes$ , but still not seeing log file created? anyone could help?
Usergrid is here, github.com/apache/incubator-usergrid
I built it myself and put the ROOT.war in tomcat /var/lib/tomcat7/webapps/, trying to enable logs in usergrid, I see a lot of log.info in usergrid's code, then I put log4j.properties in /var/lib/tomcat7/webapps/ROOT/WEB-INF/classes, but log file is not created
# Root logger option
log4j.rootLogger=INFO, file
# Direct log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
#Redirect to Tomcat logs folder
log4j.appender.file.File=${catalina.home}/logs/logging.log
log4j.appender.file.MaxFileSize=10MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
I've been able to configure Log4j logging in Usergrid by adding the following to Tomcat's CATALINA_OPTS environment variable:
-Dlog4j.configuration=file:/${path}/log4j.properties
Where ${path} is the path to your Log4j properties file.
The Lift wiki page on logging states that a lot of setup is done automatically. Right now my problem is that I already have a running backend with its own logging configuration and a log4j.properties file in my classpath which should be used. There are also dependencies to log4j and SLF4j already in the classpath.
The main problem is that I get complete debug output for everything. Hibernate in particular -- which is very annoying.
I am using Lift 2.3-M1 and tried doing the following in the beginning of boot():
Logger.setup = Full(Log4j.withFile(getClass().getResource("/props/log4j.xml")))
The log4j.xml I am currently using is quickly hacked together to simply suppress DEBUG output.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
<log4j:configuration threshold="info" xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="CA" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%p] %c{2} %m%n"/>
</layout>
</appender>
<root>
<level value="info"/>
<appender-ref ref="CA"/>
</root>
</log4j:configuration>
When I create an errornous log4j.xml I also get an error from the SAXParser so it must be parsed. However I am still getting all DEBUG output. A second try was doing the following:
LiftRules.configureLogging = () => ()
Logger.setup = Full(Logback.withFile(getClass().getResource("/props/log4j.xml")))
Since I do not want to have Lift configure logging for me since the backend is already configured I would like to turn it completely off now. Oh and I also tried LogBoot.logSetup = () => false with no luck.
I would greatly appreciate any help on this issue.
The question got answered on the Lift mailing list.
The fix is to remove the logback dependency and to include both log4j and slf4j-log4j. No other configuration in boot() is required besides a valid default.log4j.xml.
I had a similar problem and came upon the following solution:
import net.liftweb.common.{ Empty, Logger }
import net.liftweb.http.Bootable
class BootLoader extends Bootable {
def boot = {
// other boot configuration ...
// prevent Lift from messing up my log4j config
Logger.setup = Empty
}
}