| /* | |
| * Licensed to the Apache Software Foundation (ASF) under one or more | |
| * contributor license agreements. See the NOTICE file distributed with | |
| * this work for additional information regarding copyright ownership. | |
| * The ASF licenses this file to You under the Apache License, Version 2.0 | |
| * (the "License"); you may not use this file except in compliance with | |
| * the License. You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| package org.apache.log4j.db; | |
| import org.apache.logging.log4j.Level; | |
| import org.apache.logging.log4j.LogManager; | |
| import org.apache.logging.log4j.Logger; | |
| import org.apache.log4j.scheduler.Job; | |
| import org.apache.log4j.spi.ComponentBase; | |
| import org.apache.logging.log4j.core.LogEvent; | |
| import org.apache.logging.log4j.core.impl.Log4jLogEvent; | |
| import org.apache.logging.log4j.core.impl.ThrowableProxy; | |
| import org.apache.logging.log4j.message.SimpleMessage; | |
| import org.apache.logging.log4j.spi.MutableThreadContextStack; | |
| import java.sql.Connection; | |
| import java.sql.PreparedStatement; | |
| import java.sql.ResultSet; | |
| import java.sql.SQLException; | |
| import java.util.Arrays; | |
| import java.util.HashMap; | |
| import java.util.Map; | |
| import java.util.Vector; | |
| /** | |
| * Actual retrieval of data is made by the instance of DBReceiverJob associated | |
| * with DBReceiver. | |
| * | |
| * @author Ceki Gülcü | |
| */ | |
| class DBReceiverJob extends ComponentBase implements Job { | |
| String sqlException = "SELECT trace_line FROM logging_event_exception where event_id=? ORDER by i ASC"; | |
| String sqlProperties = "SELECT mapped_key, mapped_value FROM logging_event_property WHERE event_id=?"; | |
| String sqlSelect = | |
| "SELECT " + | |
| "sequence_number, timestamp, rendered_message, logger_name, " + | |
| "level_string, ndc, thread_name, reference_flag, " + | |
| "caller_filename, caller_class, caller_method, caller_line, " + | |
| "event_id " + | |
| "FROM logging_event " + | |
| "WHERE event_id > ? ORDER BY event_id ASC"; | |
| long lastId = Short.MIN_VALUE; | |
| DBReceiver parentDBReceiver; | |
| DBReceiverJob(DBReceiver parent) { | |
| parentDBReceiver = parent; | |
| } | |
| public void execute() { | |
| getLogger().debug("DBReceiverJob.execute() called"); | |
| Connection connection = null; | |
| try { | |
| connection = parentDBReceiver.connectionSource.getConnection(); | |
| PreparedStatement statement = connection.prepareStatement(sqlSelect); | |
| statement.setLong(1, lastId); | |
| ResultSet rs = statement.executeQuery(); | |
| //rs.beforeFirst(); | |
| while (rs.next()) { | |
| Logger logger = null; | |
| long timeStamp = 0L; | |
| String level = null; | |
| String threadName = null; | |
| String message = null; | |
| String ndc = null; | |
| String className = null; | |
| String methodName = null; | |
| String fileName = null; | |
| String lineNumber = null; | |
| Map<String, String> properties = new HashMap<>(); | |
| //event.setSequenceNumber(rs.getLong(1)); | |
| timeStamp = rs.getLong(2); | |
| message = rs.getString(3); | |
| logger = LogManager.getLogger(rs.getString(4)); | |
| level = rs.getString(5); | |
| Level levelImpl = Level.toLevel(level.trim()); | |
| ndc = rs.getString(6); | |
| threadName = rs.getString(7); | |
| short mask = rs.getShort(8); | |
| fileName = rs.getString(9); | |
| className = rs.getString(10); | |
| methodName = rs.getString(11); | |
| lineNumber = rs.getString(12).trim(); | |
| StackTraceElement locationInfo; | |
| if (fileName.equals("?")) { | |
| locationInfo = null; | |
| } else { | |
| locationInfo = new StackTraceElement(fileName, className, | |
| methodName, Integer.parseInt(lineNumber)); | |
| } | |
| long id = rs.getLong(13); | |
| //LogLog.info("Received event with id=" + id); | |
| lastId = id; | |
| ThrowableProxy throwableInfo = null; | |
| if ((mask & DBHelper.EXCEPTION_EXISTS) != 0) { | |
| throwableInfo = getException(connection, id); | |
| } | |
| // Scott asked for this info to be | |
| properties.put("log4jid", Long.toString(id)); | |
| LogEvent event = Log4jLogEvent.newBuilder() | |
| .setLoggerFqcn(logger.getName()) | |
| .setLoggerName(logger.getName()) | |
| .setTimeMillis(timeStamp) | |
| .setLevel(levelImpl) | |
| .setMessage(new SimpleMessage(message)) | |
| .setThreadName(threadName) | |
| .setThrownProxy(throwableInfo) | |
| .setContextStack(new MutableThreadContextStack(Arrays.asList(ndc.split(" ")))) | |
| .setContextMap(properties) | |
| .setSource(locationInfo) | |
| .build(); | |
| if ((mask & DBHelper.PROPERTIES_EXIST) != 0) { | |
| getProperties(connection, id, event); | |
| } | |
| if (!parentDBReceiver.isPaused()) { | |
| parentDBReceiver.doPost(event); | |
| } | |
| } // while | |
| statement.close(); | |
| statement = null; | |
| } catch (SQLException sqle) { | |
| getLogger().error("Problem receiving events", sqle); | |
| } finally { | |
| closeConnection(connection); | |
| } | |
| } | |
| void closeConnection(Connection connection) { | |
| if (connection != null) { | |
| try { | |
| //LogLog.warn("closing the connection. ", new Exception("x")); | |
| connection.close(); | |
| } catch (SQLException sqle) { | |
| // nothing we can do here | |
| } | |
| } | |
| } | |
| /** | |
| * Retrieve the event properties from the logging_event_property table. | |
| * | |
| * @param connection | |
| * @param id | |
| * @param event | |
| * @throws SQLException | |
| */ | |
| void getProperties(Connection connection, long id, LogEvent event) | |
| throws SQLException { | |
| PreparedStatement statement = connection.prepareStatement(sqlProperties); | |
| try { | |
| statement.setLong(1, id); | |
| ResultSet rs = statement.executeQuery(); | |
| while (rs.next()) { | |
| String key = rs.getString(1); | |
| String value = rs.getString(2); | |
| event.getContextMap().put(key, value); | |
| } | |
| } finally { | |
| statement.close(); | |
| } | |
| } | |
| /** | |
| * Retrieve the exception string representation from the | |
| * logging_event_exception table. | |
| * | |
| * @param connection | |
| * @param id | |
| * @throws SQLException | |
| */ | |
| ThrowableProxy getException(Connection connection, long id) | |
| throws SQLException { | |
| PreparedStatement statement = null; | |
| try { | |
| statement = connection.prepareStatement(sqlException); | |
| statement.setLong(1, id); | |
| ResultSet rs = statement.executeQuery(); | |
| Vector v = new Vector(); | |
| while (rs.next()) { | |
| //int i = rs.getShort(1); | |
| v.add(rs.getString(1)); | |
| } | |
| int len = v.size(); | |
| String[] strRep = new String[len]; | |
| for (int i = 0; i < len; i++) { | |
| strRep[i] = (String) v.get(i); | |
| } | |
| // we've filled strRep, we now attach it to the event | |
| return new ThrowableProxy(strRep); | |
| } finally { | |
| if (statement != null) { | |
| statement.close(); | |
| } | |
| } | |
| } | |
| } |