/******************************************************************************* * ALMA - Atacama Large Millimeter Array * Copyright (c) COSYLAB - Control System Laboratory, 2011 * (in the framework of the ALMA collaboration). * All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *******************************************************************************/ package com.cosylab.cdb.jdal.logging; import org.slf4j.impl.ACSLoggerFactory; import org.slf4j.impl.StaticLoggerBinder; import org.slf4j.impl.HibernateLoggerHelper; import alma.acs.logging.AcsLogger; import alma.acs.logging.ClientLogManager; import alma.acs.logging.config.LogConfig; import alma.acs.logging.level.AcsLogLevelDefinition; /** * Creates a shared logger called "CDB-RDB" to be used by all hibernate DAL code. * Its log level defaults to INFO for local and remote logging. * <p> * @TODO We should make the log levels configurable in the future. * <p> * Note 1: The hibernate framework will get its own ACS Loggers via a tapped slf4j framework. * There are two loggers called "hibernate@CDB-RDB" and "hibernateSQL@CDB-RDB". * Their log levels are configured here, to DEBUG for SQL logs, and WARNING for other logs, * both for local and remote logs. * <p> * Note 2: Remote logging is disabled for the time being. * * @author hsommer */ public class AcsLoggerHelper { /** * Logger name used by default. Can be changed */ public static final String loggerNameDefault = "CDB-RDB"; /** * Logger name can be set in {@link #setLoggerName(String)} before calling {@link AcsLoggerHelper#getSharedLogger()}. * Otherwise defaults to {@link #loggerNameDefault}. */ private static String loggerName = null; /** * Singleton instance */ private static AcsLoggerHelper instance; /** * The instance's logger, to be shared by the whole application using {@link #getSharedLogger()}; */ private AcsLogger sharedLogger; /** * Singleton */ public static synchronized AcsLoggerHelper getInstance() { if (instance == null) { if (loggerName == null) { loggerName = loggerNameDefault; } instance = new AcsLoggerHelper(loggerName); } return instance; } private AcsLoggerHelper(String sharedLoggerName) { // @TODO instead of the following line, call ClientLogManager#initRemoteLogging(orb, manager, managerHandle, retry) // as soon as the service dependency issues are sorted out (same in the CDB and alarm service) ClientLogManager.getAcsLogManager().suppressRemoteLogging(); // default config for hibernate loggers (which are created outside of this class) LogConfig logConfig = ClientLogManager.getAcsLogManager().getLogConfig(); String hibernateDefaultLoggerName = HibernateLoggerHelper.HIBERNATE_LOGGER_NAME_PREFIX + '@' + sharedLoggerName; if (!logConfig.hasCustomConfig(hibernateDefaultLoggerName)) { setHibernateLogLevels(AcsLogLevelDefinition.WARNING, AcsLogLevelDefinition.WARNING); } String hibernateSqlLoggerName = HibernateLoggerHelper.HIBERNATE_SQL_LOGGER_NAME_PREFIX + '@' + sharedLoggerName; if (!logConfig.hasCustomConfig(hibernateSqlLoggerName)) { setHibernateSqlLogLevels(AcsLogLevelDefinition.DEBUG, AcsLogLevelDefinition.DEBUG); } } /** * Returns a shared Logger, creating on demand. * The logger name will be {@link #loggerNameDefault} or the name given in {@link #setLoggerName(String)} * prior to the first call to this method. */ public AcsLogger getSharedLogger() { if (sharedLogger == null) { sharedLogger = ClientLogManager.getAcsLogManager().getLoggerForApplication(loggerName, true); } return sharedLogger; } /** * Sets levels for normal loggers, which otherwise are configured by xsd defaults, $ACS_LOG_STDOUT etc, * but not by this class. */ public void setDefaultLogLevels(AcsLogLevelDefinition localLevel, AcsLogLevelDefinition remoteLevel) { LogConfig logConfig = ClientLogManager.getAcsLogManager().getLogConfig(); logConfig.setDefaultMinLogLevelLocal(localLevel); logConfig.setDefaultMinLogLevel(remoteLevel); } public void setHibernateLogLevels(AcsLogLevelDefinition localLevel, AcsLogLevelDefinition remoteLevel) { LogConfig logConfig = ClientLogManager.getAcsLogManager().getLogConfig(); String name = HibernateLoggerHelper.HIBERNATE_LOGGER_NAME_PREFIX + '@' + loggerName; logConfig.setMinLogLevelLocal(localLevel, name); logConfig.setMinLogLevel(remoteLevel, name); } public void setHibernateSqlLogLevels(AcsLogLevelDefinition localLevel, AcsLogLevelDefinition remoteLevel) { LogConfig logConfig = ClientLogManager.getAcsLogManager().getLogConfig(); String name = HibernateLoggerHelper.HIBERNATE_SQL_LOGGER_NAME_PREFIX + '@' + loggerName; logConfig.setMinLogLevelLocal(localLevel, name); logConfig.setMinLogLevel(remoteLevel, name); } /** * Mainly thought for general hibernate layer test code, * which does not like to use the application logger name "CDB-RDB". */ synchronized public void setLoggerName(String loggerName) { this.loggerName = loggerName; } /** * JUnit tests need to call this if they don't want the logger to be reused * between two tests. For some reason junit's classloader tricks fail here. */ public void shutdown() { try { ((ACSLoggerFactory)StaticLoggerBinder.getSingleton().getLoggerFactory()).clearDelegateLoggers(); } catch (ClassCastException ex) { this.sharedLogger.info("hibernate uses slf4j binding different than for ACS."); } instance = null; loggerName = null; } }