zobelrob
Occasional Observer

Logging mit slf4j funktioniert nicht im SiteArchitect

Jump to solution

Hallo zusammen,

wir haben das Problem, dass unsere Module im SiteArchitect keine Infos ins Log schreiben.

Wir benutzen in unseren Java-Programmen die Logging Facade slf4j ( https://www.slf4j.org/ ). Der Hintergrund ist der, das wir unsere Eigenentwicklungen in verschiedenen Systemen benutzen, die  meistens eigene Logging-Mechanismen haben (wie ja auch FirstSpirit). Durch slf4j müssen wir unseren Quellcode nicht pro System anpassen und können diesen einfach wieder verwenden.

Dieses Vorgehen hat bei FirstSpirit-Version 5.1.2.515 funktioniert. Aktuell sind wir auf 5.1.2.1714 und hier funktioniert es nicht mehr.

Eine Analyse hat gezeigt, dass in der fs-client.jar nun auch die Datei "org.slf4j.impl.StaticLoggerBinder" existiert und somit das Logging übernimmt. Bei slf4j darf es nur eine StaticLoggerBinder-Klasse geben, daher habe ich unsere eigene Implementierung dieser Klasse verworfen.

Das Logging auf dem FirstSpirit-Server funktioniert, ohne das wir die Protokollierungseinstellungen ändern mussten.

Jedoch funktioniert es nicht im SiteArchitect. Im SiteArchitect-Log steht gar nichts von meinem Programm. Ich habe auch verschiede Log-Level versucht, ohne Erfolg.

Wenn ich den SiteArchitect aus Eclipse heraus aufrufe, bekomme ich zumindest folgende Warnung:

log4j:WARN No appenders could be found for logger (com.grozbeckert.firstspirit.XXX).

log4j:WARN Please initialize the log4j system properly.

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

Es kommt also log4j zum Einsatz und dieses hat keinen Log-Appender für meine Klasse. Daher wird auch nichts geloggt.

Meine Frage ist nun, warum gibt es diesen Unterschied zwischen SiteArchitect und FirstSpirit-Server beim Logging? Warum funktioniert es auf dem Server und im Client nicht?

Und wie bekomme ich es hin, dass auch im SiteArchitect mit slf4j geloggt werden kann? Es ist sicherlich nur eine Konfiguration, jedoch verstehe ich die Arbeitsweise von FirstSpirit hier nicht.

Ich hoffe die Frage ist nicht zu speziell.

Beste Grüße

Robert Zobel

1 Solution

Accepted Solutions
hbarthel
New Responder

Hallo Robert,

dasselbe Problem haben wir auch und hatten dazu den Support angefragt:

wir fragen uns, warum im fs-client.jar log4j usw. mit drin steckt, wenn es gar nicht funktioniert:
log4j:WARN No appenders could be found for logger (Hallo).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

Hintergrund: wir wollen unseren Code gegen slf4j schreiben und slf4j ist im fs-client.jar auf log4j umgebogen. Auf dem Server funktioniert das auch, aber auf dem Client nicht. Das Vorhandensein im fs-client.jar sagt uns, dass das gehzen soll. Daher bitten wir um einen Fix.

Nachzustellen ganz einfach mit einem leeren Projekt, Skript anlegen:
//org.apache.log4j.BasicConfigurator.configure();
log = org.slf4j.LoggerFactory.getLogger("Hallo");
log.info("Test");

(Wenn man die auskommentierte Zeile reinnimmt, wird log4j auf stdout aktiviert. Würden wir machen, wenn man irgendwo sicher wüsste, dass man beim SA-Start aufgerufen wird...)

Danke und Gruß
Heiko

Es kam folgende Antwort und wir haben es dabei belassen (Thema verfehlt):

"Das Log4J ist im Klassenpfad enthalten, weil das FirstSpirit-Logging Gebrauch davon macht.

Wenn zwingend eigene Librarys verwendet werden sollen, ist der Isolated Mode (RISO) die richtige Wahl."

Unser Workaround:

Wir haben ein JavaClientPermanentPlugin und WebeditPermanentPlugin und setzen dort:

org.apache.log4j.BasicConfigurator.configure(new ConsoleAppender(new PatternLayout("%5p %d (%c): %m%n")));

Damit gehts Logging, nachdem dieser Codeteil durchlaufen wurde. In den Bootstrap des SA kann man sich ja leider nich reinhängen, ist mir zumindest keine Möglichkeit bekannt.

So long Heiko

View solution in original post

0 Kudos
9 Replies
hbarthel
New Responder

Hallo Robert,

dasselbe Problem haben wir auch und hatten dazu den Support angefragt:

wir fragen uns, warum im fs-client.jar log4j usw. mit drin steckt, wenn es gar nicht funktioniert:
log4j:WARN No appenders could be found for logger (Hallo).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

Hintergrund: wir wollen unseren Code gegen slf4j schreiben und slf4j ist im fs-client.jar auf log4j umgebogen. Auf dem Server funktioniert das auch, aber auf dem Client nicht. Das Vorhandensein im fs-client.jar sagt uns, dass das gehzen soll. Daher bitten wir um einen Fix.

Nachzustellen ganz einfach mit einem leeren Projekt, Skript anlegen:
//org.apache.log4j.BasicConfigurator.configure();
log = org.slf4j.LoggerFactory.getLogger("Hallo");
log.info("Test");

(Wenn man die auskommentierte Zeile reinnimmt, wird log4j auf stdout aktiviert. Würden wir machen, wenn man irgendwo sicher wüsste, dass man beim SA-Start aufgerufen wird...)

Danke und Gruß
Heiko

Es kam folgende Antwort und wir haben es dabei belassen (Thema verfehlt):

"Das Log4J ist im Klassenpfad enthalten, weil das FirstSpirit-Logging Gebrauch davon macht.

Wenn zwingend eigene Librarys verwendet werden sollen, ist der Isolated Mode (RISO) die richtige Wahl."

Unser Workaround:

Wir haben ein JavaClientPermanentPlugin und WebeditPermanentPlugin und setzen dort:

org.apache.log4j.BasicConfigurator.configure(new ConsoleAppender(new PatternLayout("%5p %d (%c): %m%n")));

Damit gehts Logging, nachdem dieser Codeteil durchlaufen wurde. In den Bootstrap des SA kann man sich ja leider nich reinhängen, ist mir zumindest keine Möglichkeit bekannt.

So long Heiko

0 Kudos
mikula
Crownpeak employee

Hallo Robert,

zunächst einmal der Hinweis: Das FS, dass ihr da benutzt, ist eig. schon aus dem Support raus.

Ich habe mit dem Kollegen aus der Entwicklung gesprochen und einfach mal nachgefragt, warum das so ist. Seine Antwort war recht eindeutig: Es kann sein, dass es mal so war. Mittlerweile gibt es ja ein Logging, dass Client und Serverseitig gleich sein sollte und man hat die Möglichkeit Client logs direkt zum Server zu senden und auch dort zu loggen.

Der Hinweis mit dem Riso Modus muss man wie folgt verstehen: Dass die Log4j klassen mit auf dem Classpath liegen, ist FirstSpirit seitig nicht gewollt und wird deshalb auch im Riso Modus unterbunden.

Viele Grüße

0 Kudos
mikula
Crownpeak employee

Nach Rücksprache mit den Kollegen kann ich nun nochmal folgenden Hinweis geben:

In der Entwicklerdokumentation für die Modulentwicklung sind die Logging-Mechanismen beschrieben, die in FirstSpirit verwendet werden und verwendet werden können.

0 Kudos
groth
Crownpeak employee

Hallo Robert,

benötigst Du noch weitere Hilfe oder haben Dir die Antworten von Martin bereits geholfen? In diesem Fall wäre es super, wenn Du die "richtige Antwort" entsprechend markierst, damit auch andere Community-Teilnehmer diese auf den ersten Blick finden. Solltest Du zwischenzeitlich eine eigene Lösung gefunden haben, wäre es nett, wenn Du diese hier bereitstellst.

Beste Grüße

Christian

0 Kudos
zobelrob
Occasional Observer

Hallo Christian,

wir werden eine Workaround versuchen, so wie Heiko ihn beschrieben hat.

Es wäre schön wenn wir beim Einsatz von slf4j keine Workarounds bräuchten und FirstSpirit sich hier gleich verhalten würde (auf dem Server und dem SiteArchitect).

Trotzdem Danke für die Unterstützung.

Beste Grüße

Robert

mikula
Crownpeak employee

Ich kann nur nochmal darauf hinweisen, dass wir dieses Logging nicht offiziell unterstützen.

0 Kudos
zobelrob
Occasional Observer

Ich würde es begrüßen wenn es so wäre 🙂

Ich habe slf4j in vielen Java-Projekten gesehen und für uns ist es ein Standard fürs Logging.

Ich habe auch das Gefühl das "nur" eine Konfiguration angepasst oder noch einmal die StaticLoggerBinder-Klasse angeschaut werden muss. Auf dem Server funktioniert es ja bereits.

0 Kudos
hbarthel
New Responder

Hallo zusammen, ich hole das Thema nochmal aus der Versenkung, weil in den Release Notes von 2023.12 folgendes stand/steht:

"Seit der Version 2023.12 wird FirstSpirit mit einem SLF4JAdapter ausgeliefert, der Logging über SLF4J an das Base-Logging weiterreicht. ..."

Ich war nun natürlich der Annahme, dass ich mit FS 2024.7 unseren Hack für den SA rausnehmen kann, aber wenn ich z.B. in einem ValueService im SiteArchitect slf4j benutzen will, bekomme ich folgenden Fehler (Anmerkung: habe die slf4j-api nicht mit in das Modul aufgenommen, sondern in der Gradle-dependency nur so: implementation 'org.slf4j:slf4j-api:2.0.13'😞

 

org/slf4j/LoggerFactory
FSVersion=5.2.240712.9c4af73#7623;JDK=17.0.11 64bit Eclipse Adoptium;OS=Windows 3.11 amiga64;Date=15.07.2024 14:09:44 (I)
java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
at com.sample.valueservice.TestIdValueService.<clinit>(TestIdValueService.java:31)

 

Wenn ich's wie oben schonmal beschrieben wie folgt in einem Script nutze:

 

log = org.slf4j.LoggerFactory.getLogger("Hallo");
log.info("log via slf4j");
context.logInfo("log via context");

 

erscheint nur der Logeintrag, der über den Kontext erzeugt wurde. log ist ein Objekt der Klasse "org.apache.logging.slf4j.Log4jLogger". Sollte es nicht stattdessen "de.espirit.firstspirit.logging.SLF4JLogger" sein? Denn log4j scheint auch mit 2024.7 im SA nicht sauber initialisiert zu werden.

Weiß jemand, was man genau machen muss, damit slf4j im SA funktioniert?

0 Kudos
hbarthel
New Responder

Achja... der oben beschriebene Hack mit dem BasicConfigurator hatte im isolated mode dann auch nicht mehr funktioniert, so dass wir uns wie folgt aus der Patsche geholfen haben:

 

        try {
            // redirect console log messages to file
            String clientHomeDir = System.getProperty("CLIENT_HOME_DIR");
            if (clientHomeDir != null) {
                String logFile = clientHomeDir.replace("~", System.getProperty("user.home")) + "/logs/console-"
                        + DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH-mm-ss.SSS").format(LocalDateTime.now()) + ".log";
                PrintStream out = new PrintStream(new FileOutputStream(logFile));
                System.setOut(out);
            }
        } catch (Exception e) {
            Logging.logError("Could not initialize logging", e, getClass());
        }

 

 

0 Kudos