/* * NOTE: This copyright does *not* cover user programs that use HQ * program services by normal system calls through the application * program interfaces provided as part of the Hyperic Plug-in Development * Kit or the Hyperic Client Development Kit - this is merely considered * normal use of the program, and does *not* fall under the heading of * "derived work". * * Copyright (C) [2004-2008], Hyperic, Inc. * This file is part of HQ. * * HQ is free software; you can redistribute it and/or modify * it under the terms version 2 of the GNU General Public License as * published by the Free Software Foundation. This program 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 General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. */ package org.hyperic.hq.events.server.session; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import javax.annotation.PreDestroy; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hyperic.hibernate.PageInfo; import org.hyperic.hq.appdef.shared.AppdefEntityID; import org.hyperic.hq.authz.server.session.AuthzSubject; import org.hyperic.hq.authz.server.session.Resource; import org.hyperic.hq.authz.server.session.ResourceGroup; import org.hyperic.hq.authz.server.shared.ResourceDeletedException; import org.hyperic.hq.authz.shared.AuthzConstants; import org.hyperic.hq.authz.shared.ResourceManager; import org.hyperic.hq.events.AbstractEvent; import org.hyperic.hq.events.AlertFiredEvent; import org.hyperic.hq.events.EventLogStatus; import org.hyperic.hq.events.ResourceEventInterface; import org.hyperic.hq.events.server.session.EventLogDAO.ResourceEventLog; import org.hyperic.hq.events.shared.EventLogManager; import org.hyperic.hq.measurement.MeasurementConstants; import org.hyperic.hq.product.TrackEvent; import org.hyperic.util.timer.StopWatch; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; /** * <p> * Stores Events to and deletes Events from storage * </p> * */ @Service @Transactional public class EventLogManagerImpl implements EventLogManager { private static final int MSGMAX = TrackEvent.MESSAGE_MAXLEN; private static final int SRCMAX = TrackEvent.SOURCE_MAXLEN; private final Log log = LogFactory.getLog(EventLogManagerImpl.class.getName()); private final Log traceLog = LogFactory.getLog(EventLogManagerImpl.class.getName() + "Trace"); private EventLogDAO eventLogDAO; @Autowired private ResourceManager resourceManager; @Autowired public EventLogManagerImpl(EventLogDAO eventLogDAO) { this.eventLogDAO = eventLogDAO; } /** * Create a new vanilla log item. * * @param event The event to log. * @param subject The log item subject. * @param status The log item status. * @param save <code>true</code> to persist the log item; <code>false</code> * to create a transient log item only. * * */ public EventLog createLog(AbstractEvent event, String subject, String status, boolean save) throws ResourceDeletedException { String detail = event.toString(); if (detail.length() > MSGMAX) { detail = detail.substring(0, MSGMAX - 1); } if (subject != null) { if (subject.length() > SRCMAX) { subject = subject.substring(0, SRCMAX - 1); } } Resource r = null; if (event instanceof ResourceEventInterface) { AppdefEntityID aeId = ((ResourceEventInterface) event).getResource(); r = resourceManager.findResource(aeId); if (r == null || r.isInAsyncDeleteState()) { final String m = aeId + " has already been deleted"; throw new ResourceDeletedException(m); } } EventLog e = new EventLog(r, subject, event.getClass().getName(), detail, event.getTimestamp(), status, event.getInstanceId()); if (save) { return eventLogDAO.create(e); } else { return e; } } /** * Insert the event logs in batch. * * @param eventLogs The event logs. * * */ public void insertEventLogs(EventLog[] eventLogs) { eventLogDAO.insertLogs(eventLogs); } /** * Finds a unique log entry with the specified event type, instance ID, and timestamp. Returns null if no such entry found. * If multiple entries are found, returns first one found. * */ @Transactional(readOnly=true) public EventLog findLog(String typeClass, int instanceId, long timestamp) { return eventLogDAO.findLog(typeClass, instanceId, timestamp); } /** * Find the last event logs of all the resources of a given prototype. (i.e. * 'Linux' or 'FileServer File') * * */ @Transactional(readOnly=true) public List<EventLog> findLastLogs(Resource proto) { return eventLogDAO.findLastByType(proto); } /** * Find the last unfixed AlertFiredEvents for each alert definition in the list * * * @return {@link Map} of alert definition id {@link Integer} to {@link AlertFiredEvent} * */ @Transactional(readOnly=true) public Map<Integer,AlertFiredEvent> findLastUnfixedAlertFiredEvents() { final boolean debug = log.isDebugEnabled(); StopWatch watch = new StopWatch(); if (debug) watch.markTimeBegin("findUnfixedAlertFiredEventLogs"); Map<Integer,AlertFiredEvent> alertFiredMap = eventLogDAO.findUnfixedAlertFiredEventLogs(); if (debug) { watch.markTimeEnd("findUnfixedAlertFiredEventLogs"); if (traceLog.isDebugEnabled()) { watch.markTimeBegin("get mapping"); for (Integer key: alertFiredMap.keySet()) { AlertFiredEvent val = alertFiredMap.get(key); traceLog.debug( "alertFiredMap alertDefId=" + key + ", alertFiredEvent=" + val + ", alert id=" + val.getAlertId() + ", timestamp=" + val.getTimestamp()); } watch.markTimeEnd("get mapping"); } log.debug("findLastUnfixedAlertFiredEvents[" + alertFiredMap.size() + "]: " + watch); } return alertFiredMap; } /** * Get a list of {@link ResourceEventLog}s in a given interval, with the * maximum specified status. * * If specified, typeClass dictates the full classname of the rows to check * (i.e. org.hyperic.hq.....ResourceLogEvent) * * If specified, inGroups must be a collection of {@link ResourceGroup}s * which the resulting logs will be associated with. * * */ @Transactional(readOnly=true) public List<ResourceEventLog> findLogs(AuthzSubject subject, long begin, long end, PageInfo pInfo, EventLogStatus maxStatus, String typeClass, Collection<ResourceGroup> inGroups) { return eventLogDAO.findLogs(subject, begin, end, pInfo, maxStatus, typeClass, inGroups); } /** * Get a list of log records based on resource, event type and time range. * All resources which are descendents of the passed resource will also have * their event logs included * * */ @Transactional(readOnly=true) @SuppressWarnings("unchecked") public List<EventLog> findLogs(AppdefEntityID ent, AuthzSubject user, String[] eventTypes, long begin, long end) { Resource r = resourceManager.findResource(ent); if (r == null || r.isInAsyncDeleteState()) { return new ArrayList<EventLog>(0); } Collection<String> eTypes; if (eventTypes == null) { eTypes = Collections.EMPTY_LIST; } else { eTypes = Arrays.asList(eventTypes); } if (r.getResourceType().getId().equals(AuthzConstants.authzGroup)) { return eventLogDAO.findByGroup(r, begin, end, eTypes); } else { return eventLogDAO.findByEntity(user, r, begin, end, eTypes); } } /** * Get a list of log records based on resource, status and time range. All * resources which are descendants of the passed resource will also have * their event logs included * * */ @Transactional(readOnly=true) public List<EventLog> findLogs(AppdefEntityID ent, AuthzSubject user, String status, long begin, long end) { Resource r = resourceManager.findResource(ent); return eventLogDAO.findByEntityAndStatus(r, user, begin, end, status); } /** * Retrieve the total number of event logs. * * @return The total number of event logs. * */ @Transactional(readOnly=true) public int getTotalNumberLogs() { return eventLogDAO.getTotalNumberLogs(); } /** * Get an array of booleans, each element indicating whether or not there * are log records for that respective interval, for a particular entity * over a given time range. * * This method also takes descendents of the passed-resource into * consideration. * * @param entityId The entity. * @param begin The begin timestamp for the time range. * @param end The end timestamp for the time range. * @param intervals The number of intervals. * @return The boolean array with length equal to the number of intervals * specified. * */ @Transactional(readOnly=true) public boolean[] logsExistPerInterval(AppdefEntityID entityId, AuthzSubject subject, long begin, long end, int intervals) { Resource r = resourceManager.findResource(entityId); return eventLogDAO.logsExistPerInterval(r, subject, begin, end, intervals); } /** * Delete event logs for the given resource TODO: Authz check. * */ public int deleteLogs(Resource r) { return eventLogDAO.deleteLogs(r); } /** * Purge old event logs. * * @param from Delete all records starting from (and including) this time. * If set to -1, then this method will delete all records from the * earliest record forward. * @param to Delete all records up to (and including) this time. If set to * -1, then this method will delete all records up to and including * the most recent record. * @return The number of records removed. * */ public int deleteLogs(long from, long to) { if (log.isDebugEnabled()) { log.debug("deleteLogs(" + from + ", " + to + ")"); } if (from == -1) { from = eventLogDAO.getMinimumTimeStamp(); if (from == -1) { return 0; } } if (to == -1) { to = System.currentTimeMillis(); } if (log.isDebugEnabled()) { log.debug("updated deleteLogs(" + from + ", " + to + ")"); } if (from > to) { log.debug("deleteLogs range has (from > to). There are no rows to delete."); return 0; } // Now that we have valid from/to values, figure out what the // interval is (don't loop more than 60 times) long interval = Math.max(MeasurementConstants.DAY, (to - from) / 60); return eventLogDAO.deleteLogs(from, to, interval); } @PreDestroy public final void destroy() { this.eventLogDAO = null ; }//EOM }