سؤال

لديّ Java Webapp يجب نشره على آلات Win أو Linux. أريد الآن إضافة log4j للتسجيل وأرغب في استخدام مسار نسبي لملف السجل لأنني لا أريد تغيير مسار الملف على كل نشر. من المرجح أن تكون الحاوية تومكات ولكن ليس بالضرورة.

ما هي أفضل طريقة للقيام بذلك؟

هل كانت مفيدة؟

المحلول 2

لقد فعلت ذلك أخيرًا بهذه الطريقة.

تمت إضافة ServletContextListener الذي يقوم بما يلي:

public void contextInitialized(ServletContextEvent event) {
    ServletContext context = event.getServletContext();
    System.setProperty("rootPath", context.getRealPath("/"));
}

ثم في ملف log4j.properties:

log4j.appender.file.File=${rootPath}WEB-INF/logs/MyLog.log

من خلال القيام بذلك بهذه الطريقة ، سوف يكتب Log4J في المجلد الصحيح طالما أنك لا تستخدمه قبل تعيين خاصية نظام "Contpath". هذا يعني أنه لا يمكنك استخدامه من ServletContextListener نفسه ولكن يجب أن تكون قادرًا على استخدامه من أي مكان آخر في التطبيق.

يجب أن تعمل على كل حاوية ويب ونظام التشغيل لأنها لا تعتمد على خاصية نظام محددة للحاوية ولا تتأثر بمشكلات مسار محددة لنظام التشغيل. تم اختباره باستخدام حاويات الويب Tomcat و Orion وعلى Windows و Linux ويعمل بشكل جيد حتى الآن.

ماذا تعتقد؟

نصائح أخرى

Tomcat يضع خاصية نظام catalina.home. يمكنك استخدام هذا في ملف خصائص log4j الخاص بك. شيء من هذا القبيل:

log4j.rootCategory=DEBUG,errorfile

log4j.appender.errorfile.File=${catalina.home}/logs/LogFilename.log

على ديبيان (بما في ذلك أوبونتو) ، ${catalina.home} لن تعمل لأن هذه النقاط على/usr/share/tomcat6 والتي لا تحتوي على رابط لـ/var/log/tomcat6. هنا فقط استخدم ${catalina.base}.

إذا كنت تستخدم حاوية أخرى ، فحاول العثور على خاصية نظام مماثلة ، أو تحديد خاص بك. سيختلف تعيين خاصية النظام حسب النظام الأساسي والحاوية. ولكن بالنسبة إلى Tomcat على Linux/Unix ، سأقوم بإنشاء setenv.sh في دليل Catalina_home/bin. سوف تحتوي على:

export JAVA_OPTS="-Dcustom.logging.root=/var/log/webapps"

ثم سيكون log4j.properties:

log4j.rootCategory=DEBUG,errorfile

log4j.appender.errorfile.File=${custom.logging.root}/LogFilename.log

إذا كنت تستخدم الربيع يمكنك:

1) إنشاء ملف تكوين log4j ، على سبيل المثال "/web-inf/classes/log4j-myapp.properties" لا تسميها "log4j.properties"

مثال:

log4j.rootLogger=ERROR, stdout, rollingFile

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n

log4j.appender.rollingFile=org.apache.log4j.RollingFileAppender
log4j.appender.rollingFile.File=${myWebapp-instance-root}/WEB-INF/logs/application.log
log4j.appender.rollingFile.MaxFileSize=512KB
log4j.appender.rollingFile.MaxBackupIndex=10
log4j.appender.rollingFile.layout=org.apache.log4j.PatternLayout
log4j.appender.rollingFile.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.rollingFile.Encoding=UTF-8

سنحدد "mywebapp-instance-root" في وقت لاحق على النقطة (3)

2) حدد موقع التكوين في web.xml:

<context-param>
  <param-name>log4jConfigLocation</param-name>
  <param-value>/WEB-INF/classes/log4j-myapp.properties</param-value>
</context-param>

3) حدد أ فريدة من نوعها اسم متغير لجذر WebApp الخاص بك ، على سبيل المثال "MyWebapp-Instance-Root"

<context-param>
  <param-name>webAppRootKey</param-name>
  <param-value>myWebapp-instance-root</param-value>
</context-param>

4) إضافة log4jconfigListener:

<listener>
  <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

إذا اخترت اسمًا مختلفًا ، تذكر تغييره في log4j-myapp.properties أيضًا.

انظر مقالتي (الإيطالية فقط ... ولكن يجب أن تكون مفهومة):http://www.megadix.it/content/configurare-path-relativi-log4j-tilizzando-spring

تحديث (2009/08/01)لقد ترجمت مقالتي إلى اللغة الإنجليزية:http://www.megadix.it/node/136

مجرد تعليق على إيكر المحلول.

ServletContext هو حل جيد لمشكلتك. لكنني لا أعتقد أنه من الجيد للحفاظ على. معظم ملفات سجل الوقت مطلوبة لتوفيرها لفترة طويلة.

حيث ServletContext يجعل الملف أسفل الملف المنشور ، سيتم إزالته عند إعادة نشر الخادم. اقتراحي هو الذهاب مع المجلد الوالد في Rootpath بدلاً من الطفل.

ألا تستخدم Log4J فقط دليل جذر التطبيق إذا لم تحدد دليلًا جذريًا في خاصية مسار FileAppender الخاصة بك؟ لذلك يجب أن تكون قادرًا على استخدام:

log4j.appender.file.file = سجلات/mylog.log

لقد كان الوقت لحظة منذ أن قمت بتطوير الويب Java ، ولكن يبدو أن هذا هو الأكثر سهولة ، كما أنه لا يصطدم مع الآخرين للأسف Logs Writing to the $ {catalina.home}/logs directory.

كتعليق آخر على https://stackoverflow.com/a/218037/2279200 - قد ينهار هذا ، إذا بدأ تطبيق الويب بشكل ضمني ServletContextListener's ، والذي قد يتم استدعاؤه سابقًا والذي يحاول بالفعل استخدام Log4J - في هذه الحالة ، سيتم قراءة تكوين Log4J وتحليله بالفعل قبل تعيين الخاصية التي تحدد دليل جذر السجل => ستظهر ملفات السجل في مكان ما أسفل الدليل الحالي (الدليل الحالي عند بدء تشغيل TOMCAT).

لا يمكنني إلا أن أفكر في متابعة الحل لهذه المشكلة: - قم بإعادة تسمية ملف log4j.properties (أو logj4.xml) إلى شيء لن يقرأه Log4J تلقائيًا. - في مرشح السياق الخاص بك ، بعد تعيين الخاصية ، اتصل بفئة DOM/PropertyConfigurator Helper للتأكد من قراءة Log4J -.

هذه قوة وحشية بعض الشيء ، ولكن methinks هي الطريقة الوحيدة لجعلها محكمة الغلق.

في حال كنت تستخدم Maven لدي حل رائع لك:

  1. قم بتحرير ملف pom.xml الخاص بك لتضمين الأسطر التالية:

    <profiles>
        <profile>
            <id>linux</id>
            <activation>
                <os>
                    <family>unix</family>
                </os>
            </activation>
            <properties>
                <logDirectory>/var/log/tomcat6</logDirectory>
            </properties>
        </profile>
        <profile>
            <id>windows</id>
            <activation>
                <os>
                    <family>windows</family>
                </os>
            </activation>
            <properties>
                <logDirectory>${catalina.home}/logs</logDirectory>
            </properties>
        </profile>
    </profiles>
    

    هنا تحدد logDirectory خاصية على وجه التحديد لعائلة OS.

  2. استخدم محدد بالفعل logDirectory الممتلكات في log4j.properties ملف:

    log4j.appender.FILE=org.apache.log4j.RollingFileAppender
    log4j.appender.FILE.File=${logDirectory}/mylog.log
    log4j.appender.FILE.MaxFileSize=30MB
    log4j.appender.FILE.MaxBackupIndex=10
    log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
    log4j.appender.FILE.layout.ConversionPattern=%d{ISO8601} [%x] %-5p [%t] [%c{1}] %m%n
    
  3. هذا هو!

ملاحظة: أنا متأكد من أنه يمكن تحقيق ذلك باستخدام ANT ولكن للأسف ليس لدي خبرة كافية معها.

اقتراحي هو أن ملف السجل يجب أن يتم تسجيله دائمًا فوق سياق الجذر لـ WebApp ، لذلك في حالة إعادة نشر WebApp ، لا نريد تجاوز ملفات السجل الموجودة.

إن حلي مشابه لـ Iker Jimenez's المحلول, ، ولكن بدلا من الاستخدام System.setProperty(...) أنا أستعمل org.apache.log4j.PropertyConfigurator.configure(Properties). لذلك ، أحتاج أيضًا إلى عدم القدرة على العثور على تكوينه من تلقاء نفسه وأتحمله يدويًا (كلتا النقطتين الموصوفين في Wolfgang Liebich's إجابه).

هذا يعمل مع jetty و tomcat ، مستقلة أو تشغيل من IDE ، يتطلب تكوين صفر ، يسمح بوضع سجلات كل تطبيق في مجلدهم الخاص ، بغض النظر عن عدد التطبيقات داخل الحاوية (وهو المشكلة مع ال Systemحل قائم على القائمة). وبهذه الطريقة ، يمكن للمرء أيضًا وضع ملف تكوين log4j في أي مكان داخل تطبيق الويب (على سبيل المثال ، في مشروع واحد كان لدينا جميع ملفات التكوين في الداخل WEB-INF/).

تفاصيل:

  1. لدي عقاراتي في log4j-no-autoload.properties ملف في classpath (على سبيل المثال في مشروع Maven الخاص بي ، إنه في الأصل src/main/resources, ، يتم تعبئته في WEB-INF/classes),
  2. لقد تم تكوين ملحق الملف على سبيل المثال:

    log4j.appender.MyAppFileAppender = org.apache.log4j.FileAppender
    log4j.appender.MyAppFileAppender.file = ${webAppRoot}/WEB-INF/logs/my-app.log
    ...
    
  3. ولدي مستمع سياق مثل هذا (يصبح أقصر بكثير مع بناء جملة Java 7 "Try-With-Resource"):

    @WebListener
    public class ContextListener implements ServletContextListener {
        @Override
        public void contextInitialized(final ServletContextEvent event) {
            Properties props = new Properties();
            InputStream strm =
                ContextListener.class.getClassLoader()
                    .getResourceAsStream("log4j-no-autoload.properties");
            try {
                props.load(strm);
            } catch (IOException propsLoadIOE) {
                throw new Error("can't load logging config file", propsLoadIOE);
            } finally {
                try {
                    strm.close();
                } catch (IOException configCloseIOE) {
                    throw new Error("error closing logging config file", configCloseIOE);
                }
            }
            props.put("webAppRoot", event.getServletContext().getRealPath("/"));
            PropertyConfigurator.configure(props);
            // from now on, I can use LoggerFactory.getLogger(...)
        }
        ...
    }
    

يمكنك تحديد المسار النسبي إلى ملف السجل ، باستخدام ملف دليل العمل:

appender.file.fileName = ${sys:user.dir}/log/application.log

هذا مستقل عن حاوية servlet ولا يتطلب تمرير متغير مخصص لبيئة النظام.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top