1

私が理解している限り、Log4j を使用する Hadoop を使用する Java アプリケーションを作成しています。私のアプリケーションでは、Log4J は正常に動作します。JDBCAppender を使用して Oracle データベースに書き込みます。何が起こっているのかというと、アプリケーションを実行していると、Hadoop jar で log4j 呼び出し中にアプリケーションがクラッシュし、コンマが見つからないというエラーが発生します。プログラムの私の部分では機能しますが、Hadoop のものでクラッシュするので奇妙です。log4j でデバッグをオンにすると、すべてが正常に見えます。

私の質問は次のとおりです。1) どうにかして JDBCAppender 内で追加のロギングを有効にして、問題のある SQL ステートメントを確認することはできますか? 2) いったいどうやってこれにアプローチすればいいのでしょう! :)

例外と log4j.properties ファイルを次に示します。

log4j:ERROR Failed to excute sql
java.sql.SQLSyntaxErrorException: ORA-00917: missing comma

at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:447)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:879)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:505)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:223)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531)
at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:193)
at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:1033)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1328)
at oracle.jdbc.driver.OracleStatement.executeUpdateInternal(OracleStatement.java:1837)
at oracle.jdbc.driver.OracleStatement.executeUpdate(OracleStatement.java:1802)
at         oracle.jdbc.driver.OracleStatementWrapper.executeUpdate(OracleStatementWrapper.java:294)
at org.apache.log4j.jdbc.JDBCAppender.execute(JDBCAppender.java:218)
at org.apache.log4j.jdbc.JDBCAppender.flushBuffer(JDBCAppender.java:289)
at org.apache.log4j.jdbc.JDBCAppender.append(JDBCAppender.java:186)
at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251)
at     org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:66)
at org.apache.log4j.Category.callAppenders(Category.java:206)
at org.apache.log4j.Category.forcedLog(Category.java:391)
at org.apache.log4j.Category.log(Category.java:856)
at org.apache.commons.logging.impl.Log4JLogger.info(Log4JLogger.java:199)
at     org.apache.hadoop.mapreduce.lib.output.FileOutputCommitter.commitTask(FileOutputCommitter.java:173)
at org.apache.hadoop.mapred.Task.commit(Task.java:1012)
at org.apache.hadoop.mapred.Task.done(Task.java:882)
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:374)
at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:212)
I/O error: Read timed out

そして、プロパティファイル...

log4j.rootLogger=INFO, DB

log4j.appender.DB = org.apache.log4j.jdbc.JDBCAppender

log4j.appender.DB.URL = jdbc:oracle:thin:@//192.168.0.18:1521/dev01.home.net
log4j.appender.DB.driver = oracle.jdbc.OracleDriver
log4j.appender.DB.user = syslog
log4j.appender.DB.password = syslog
log4j.appender.DB.sql = INSERT INTO SERVICELOG values (log4net_seq.nextVal, sysdate, '%p', null, '%m','')
log4j.appender.DB.layout = org.apache.log4j.PatternLayout

編集 0

実際、私は何かに取り組んでいる可能性があると思います。印刷しようとしている文字列に一重引用符があります。それはオラクルにとって絶対に許されないことです。今、私はそれを削除する方法を理解する必要があります:)。

/EDIT 0

4

2 に答える 2

2

わかった。Hadoop のログには一重引用符が含まれていたため、Oracle への書き込みがうまくいきませんでした。ハックを実装し、単一引用符を削除するように log4j を変更しました。変更は、forcedLog 関数の Category.java にありました。着信オブジェクトが文字列のインスタンスであるかどうかを確認します。次に、その文字列を取得して replaceAll("'","") を実行します。replaceAll("'","''") を実行して、単一引用符をオラクルに適したものにすることもできましたが、それは私にとっては問題ではありません。

于 2013-03-06T22:07:38.047 に答える
0

1:発生者のログレベルを非常に簡単に定義できます:log4j.appender.DB=DEBUG
このように特定のパッケージのログレベルを設定することもできますcom.foobar = DEBUG

2log4jでバージョンの競合が発生している可能性があります。最も簡単な方法は、Hadoopで使用されているものとまったく同じバージョンを使用することです。もう1つは、ログバックなど、アプリの別のロガー実装に切り替えることです。

最後の1つは、両方のプロジェクトがmavenを使用しているが、結果が保証されていない場合に、hadoopのlog4j推移的依存関係を除外することです。

于 2013-03-06T21:08:38.220 に答える