<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    honzeland

    記錄點(diǎn)滴。。。

    常用鏈接

    統(tǒng)計(jì)

    Famous Websites

    Java

    Linux

    P2P

    最新評(píng)論

    Svn revision retrieve and logging to database

    最近接到兩個(gè)很小的tickets,兩個(gè)都是為了項(xiàng)目開發(fā)時(shí)的方便:一是將logs寫入到數(shù)據(jù)庫中,以方便日志的查詢;一是在build時(shí),在war包加入svn revision info。
    1) logging to database
    經(jīng)過調(diào)查,決定采用log4j的org.apache.log4j.jdbc.JDBCAppender,于是采用:
    # logging to db
    log4j.logger.com.example=DEBUG, DATABASE
    log4j.additivity.com.example=false
    log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
    log4j.appender.DATABASE.url=jdbc:postgresql://localhost:5432/test
    log4j.appender.DATABASE.driver=org.postgresql.Driver
    log4j.appender.DATABASE.user=pguser
    log4j.appender.DATABASE.password=post
    log4j.appender.DATABASE.sql=INSERT INTO debug_log(created, logger, priority, message) VALUES (to_timestamp('%d{ISO8601}','YYYY-MM-DD HH:MI:SS.MS'),'%c.%M:%L','%p','%m')
    log4j.appender.DB.layout=org.apache.log4j.PatternLayout
    log4j.appender.DATABASE.layout.ConversionPattern=%d{ISO8601} %p %c.%M:%L %m
    很直觀,用起來還很方便,但是不久就出現(xiàn)了問題,tomcat拋出了exception。只好把之前fixed ticket reopen,提交新的comments:Unfortunately, org.apache.log4j.jdbc.JDBCAppender that ships with the Log4j distribution is not able to process logging messages that have characters like ' (single quote) and , (comma) in it. When logging messages contains characters like single quote or comma, the program will throw an exception.
    重新google了,找到了一個(gè)plusjdbc,Looking further, I found an alternative JDBCAppender package (org.apache.log4j.jdbcplus.JDBCAppender) from http://www.dankomannhaupt.de/projects/index.html. It can solve this problem. 長嘆了一下。

    最后采用:
    log4j.appender.DATABASE=org.apache.log4j.jdbcplus.JDBCAppender
    log4j.appender.DATABASE.url=jdbc:postgresql://localhost:5432/test
    log4j.appender.DATABASE.dbclass=org.postgresql.Driver
    log4j.appender.DATABASE.username=pguser
    log4j.appender.DATABASE.password=post
    log4j.appender.DATABASE.sql=INSERT INTO debug_log(created, logger, priority, message) VALUES (to_timestamp('@LAYOUT:1@', 'YYYY-MM-DD HH:MI:SS.MS'),'@LAYOUT:3@','@LAYOUT:2@','@LAYOUT:4@')
    log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
    log4j.appender.DATABASE.layout.ConversionPattern=%d{ISO8601}#%p#%c.%M:%L#%m
    log4j.appender.DATABASE.layoutPartsDelimiter=#
    log4j.appender.DATABASE.buffer=1
    log4j.appender.DATABASE.commit=true
    log4j.appender.DATABASE.quoteReplace=true
    問題解決,但是中間有點(diǎn)小波折,在我的項(xiàng)目中,log4j.jar(>1.2.9)重復(fù)了,在$CATALINA_HOME/lib下有一份,在web工程下的WEB-INF/lib下也有一份,而plus-jdbc.jar放置在$CATALINA_HOME/lib下,結(jié)果啟動(dòng)Tomcat,出現(xiàn)
    log4j:ERROR A "org.apache.log4j.jdbcplus.JDBCAppender" object is not assignable to a "org.apache.log4j.Appender" variable.
    log4j:ERROR The class "org.apache.log4j.Appender" was loaded by
    log4j:ERROR [WebappClassLoader^M
      delegate: false^M
      repositories:^M
    ----------> Parent Classloader:^M
    org.apache.catalina.loader.StandardClassLoader@1ccb029^M
    ] whereas object of type
    log4j:ERROR "org.apache.log4j.jdbcplus.JDBCAppender" was loaded by [org.apache.catalina.loader.StandardClassLoader@1ccb029].
    log4j:ERROR Could not instantiate appender named "DATABASE".
    原來是兩個(gè)JDBCAppender實(shí)例不在同一個(gè)classlaoder里面,將WEB-INF/lib下的log4j.jar刪除掉,重啟就沒問題了,按理,將$CATALINA_HOME/lib下的plus-jdbc.jar移到WEB-INF/lib下,應(yīng)該也沒問題,沒有測(cè)試。

    2)Add build revision info in war file and read it on tomcat startup
    這個(gè)經(jīng)歷比較慘痛,兩個(gè)問題,如何獲取revision? And how to read it when tomcat startup? 第二個(gè)問題倒是沒什么,采用javax.servlet.ServletContextListener就可以實(shí)現(xiàn),很簡單,走彎路的是第一個(gè)問題,google后發(fā)現(xiàn)有兩種常見的實(shí)現(xiàn):
    As I have learned, there are totally two solutions to get svn revision info.

    First, retrieve the svn revision from local file($BASE_HOME/.svn/entries). Just parsing the xml file, get the revision property and write it to a properties file.(就是該死的xml,遠(yuǎn)在烏克蘭的同事,該文件卻不是xml的,也只怪自己調(diào)研不充分,還得折騰了半天,后來發(fā)現(xiàn),最新版的svn為了performance的考慮,采用meta data來實(shí)現(xiàn)entries)

    Second, retrieve the svn revision from the remote repository. The solution always use a svn client to perform a demand with remote server to retrieve the revision info. Installing a snv client and using SvnAnt? are most commonly used at present. SvnAnt? is an ant task that provides an interface to Subversion revision control system and encapsulates the svn client. It uses javahl - a native (JNI) java interface for the subversion api if it can find the corresponding library. javahl is platform-dependent.

    Because of needing interaction with the server(服務(wù)器在國外,更新很慢), now I employ the first solution. But I found a flaw of this method when i was going off duty. Generally, we may update our project with svn before committing. This may make a mismatch with svn revision between remote server and local file. Svn revision in local file is usually updated when we update our project. But when we take a commit after update, the svn revision in the remote server will change to a new one.

    So, the case is that if we update, commit, and then build, we may get a mismatch with the newest svn revision, and build the error revision into our ROOT.war. If we update , then build ,without commit, we can get right revision info.

    下面是第一版實(shí)現(xiàn):
        <!--  retrieve the svn revision from the remote repository
        <path id="svnant.lib" >
            <fileset dir="${lib.dir}">
                <include name="svnant.jar"/>
                <include name="svnClientAdapter.jar"/>
                <include name="svnjavahl.jar"/>
            </fileset>
        </path>
       
        <taskdef name="svn" classpathref="svnant.lib" classname="org.tigris.subversion.svnant.SvnTask" />
       
        <target name="get-svn-revision">
            <svn username="*******" password="******" javahl="true">
                    <status urlProperty="https://example.com" path="." revisionProperty="svn.revision" />
            </svn>
            <echo>svn revision: ${svn.revision}</echo>
        </target>   
        -->
       
        <!--  retrieve the svn revision from local file(.svn/entries). The file may contain several  'wc-entries.entry.revision' elements.
        The property will get several values seperated by ',' when using xmlproperty task.  Then the svn revison expected will be the
        max one of these property values.
         -->
        <property name="svn.revision.file" value=".svn/entries" />
        <!-- This property is used to run xmlproperty task successfully with a low version of svn client (under 1.3.1). Don't  sure whether it really makes sense -->
        <property name="build.id" value="foo" />
        <target name="get-svn-revision">
            <xmlproperty file="${svn.revision.file}" collapseAttributes="true"/>
            <echo>svn revision: ${wc-entries.entry.revision}</echo>
        </target>

        <!--
            If the file doesn't contain any 'wc-entries.entry.revision' element, the content of the property file will be: revision = ${wc-entries.entry.revision};
            If contain a 'wc-entries.entry.revision' element, mark this value as $revision_value, then  the content will be: revision = $revision_value;
            If contain several 'wc-entries.entry.revision' elements, mark these values as $value1, $value2, ..., respectively, then the content will be: revision = $value1,$value2,..., seperated by a ',';
        -->
        <property name="svn.revision.propertyfile" value="${build.dir}/revision.properties" />
        <target name="write-svn-revision-to-file" depends="get-svn-revision">
            <delete file="${svn.revision.propertyfile}"/>
            <propertyfile file="${svn.revision.propertyfile}" comment="record svn revision">
                <entry  key="revision" value="${wc-entries.entry.revision}"/>
            </propertyfile>
        </target>

    結(jié)果write-svn-revision-to-file這個(gè)在我這倒是可以獲取本地的svn revision,但是遠(yuǎn)方的同事可急了,build老失敗,只好把這部分build注釋了,還好,到周末了,可以在家好好研究一下,很快找了一個(gè)新的工具:
    It's my fault. In my version of svn, the entries file is xml formatted. So i parse it using ant task - 'xmlproperty'. Now i have fix this problem by using 'svnkit' tools, a pure java svn toolkit. Now there are two ways to retrieve svn revision. One is from remote repository server. For this one, before building, you should set your own username and password for the remote repository server('remote.repository.username' and 'remote.repository.password' properties in build.xml,respectively). Another one is retrieving revision from local working copy. If using this one, you should set 'local.repository' property in build.xml to your own directory.
    利用svnkit,從服務(wù)器上獲取revision大概是:
                repository = SVNRepositoryFactory.create(SVNURL.parseURIDecoded(urlStr));
                ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(username, password);
                repository.setAuthenticationManager(authManager);
                headRevision = repository.getLatestRevision();
    從本地working copy獲取revision:
                SVNClientManager clientManager = SVNClientManager.newInstance();
                SVNWCClient wcClient = clientManager.getWCClient();   
                SVNInfo info = wcClient.doInfo(new File(fileUrl), SVNRevision.WORKING);
                headRevision = info.getRevision().getNumber(); 

    利用ant task將獲取的revision寫入到一個(gè)配置文件中(如revision.properties),在tomcat啟動(dòng)的時(shí)候加載進(jìn)來,就可以了。   

    posted on 2008-04-28 15:43 honzeland 閱讀(2180) 評(píng)論(2)  編輯  收藏 所屬分類: Java

    評(píng)論

    # re: Svn revision retrieve and logging to database 2008-04-28 23:23 lformat

    log4j.appender.DATABASE.url=jdbc:postgresql://localhost:5432/test
    log4j.appender.DATABASE.username=pguser
    log4j.appender.DATABASE.password=post

    地址和用戶名密碼都暴露了,有沒有其他辦法?  回復(fù)  更多評(píng)論   

    # re: Svn revision retrieve and logging to database 2008-04-29 11:45 honzeland

    可以設(shè)置在build時(shí)讓用戶輸入用戶名和密碼,或者把它們放在一個(gè)單獨(dú)的屬性文件里面(該文件只對(duì)個(gè)人可見),另外就比較復(fù)雜了,加密后存入文件  回復(fù)  更多評(píng)論   

    主站蜘蛛池模板: 亚洲成在人线aⅴ免费毛片| 四虎影院永久免费观看| 亚洲国产人成在线观看| 免费无码又爽又高潮视频| 成人免费网站久久久| 亚洲国产另类久久久精品黑人| 亚洲欧美国产国产一区二区三区| 青青青青青青久久久免费观看| 牛牛在线精品观看免费正| 青青草原亚洲视频| 四虎国产精品永久免费网址| 亚洲成AV人综合在线观看| 四虎成人精品一区二区免费网站| 男性gay黄免费网站| 久久影视国产亚洲| 99久久99久久精品免费观看 | 高清免费久久午夜精品| 国产亚洲一区区二区在线| 免费人成视频在线观看网站 | 免费播放在线日本感人片| 久久综合九九亚洲一区| 午夜免费福利小电影| 亚洲人成自拍网站在线观看| 青青草原亚洲视频| aa级一级天堂片免费观看| 免费看黄网站在线看 | 免费精品99久久国产综合精品| 亚洲国产精品成人久久久| av无码东京热亚洲男人的天堂| 国产一区二区免费视频| 亚洲最大av资源站无码av网址| 亚洲国产精品无码久久青草| 最近2019中文字幕免费大全5| 亚洲av无码成人精品国产| 亚洲AV人无码综合在线观看| 免费观看的av毛片的网站| a毛片在线看片免费| 亚洲成av人无码亚洲成av人| 亚洲大尺度无码专区尤物| 成人最新午夜免费视频| 久爱免费观看在线网站|