/***************************************************************************** * * Copyright (C) Zenoss, Inc. 2010, all rights reserved. * * This content is made available according to terms specified in * License.zenoss under the directory where your Zenoss product is installed. * ****************************************************************************/ package org.zenoss.zep.impl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.context.ApplicationListener; import org.zenoss.amqp.AmqpException; import org.zenoss.amqp.Channel; import org.zenoss.protobufs.zep.Zep.ZepRawEvent; import org.zenoss.zep.EventProcessor; import org.zenoss.zep.events.EventIndexQueueSizeEvent; public class RawEventQueueListener extends AbstractQueueListener implements ApplicationListener<EventIndexQueueSizeEvent>, ApplicationEventPublisherAware { private static final Logger logger = LoggerFactory.getLogger(RawEventQueueListener.class); private int prefetchCount = 100; private EventProcessor eventProcessor; public void setPrefetchCount(int prefetchCount) { this.prefetchCount = prefetchCount; } private boolean throttleConsumer = true; private volatile boolean indexQueueLag = false; private int indexQueueThreshold = 10000; private int consumerSleepTime = 1000; @Override public void onApplicationEvent(EventIndexQueueSizeEvent event) { if (this.throttleConsumer && event.getTableName().startsWith("event_summary")) { int localThreshold = this.indexQueueThreshold; if (localThreshold == 0) { // autoset the threshold // event.getLimit() contains the current batch size localThreshold = Math.max(event.getLimit(), 100) * 2; } final int size = (int) event.getSize(); // If already throttling, we wont resume until we are // 50% below the threshold if (this.indexQueueLag==true) { localThreshold = (int) (localThreshold - 0.5*localThreshold); } if (size > localThreshold) { // enable the throttle if (this.indexQueueLag != true) { logger.warn("Enabling zenevents consumer throttling. Queue Size: {}.", size); this.indexQueueLag = true; } } else { if (this.indexQueueLag != false) { logger.info("Disabling zenevents consumer throttling. Queue Size: {}.", size); this.indexQueueLag = false; } } } } @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; } @Override protected void configureChannel(Channel channel) throws AmqpException { logger.debug("Using prefetch count: {} for queue: {}", this.prefetchCount, getQueueIdentifier()); channel.setQos(0, this.prefetchCount); } @Override protected String getQueueIdentifier() { return "$ZepZenEvents"; } public void setEventProcessor(EventProcessor eventProcessor) { this.eventProcessor = eventProcessor; } private ApplicationEventPublisher applicationEventPublisher; public void setThrottleConsumer(boolean throttleConsumer) { this.throttleConsumer = throttleConsumer; } public void setIndexQueueThreshold(int indexQueueThreshold) { this.indexQueueThreshold = indexQueueThreshold; } public void setConsumerSleepTime(int consumerSleepTime) { this.consumerSleepTime = consumerSleepTime; } @Override public void handle(com.google.protobuf.Message message) throws Exception { if (!(message instanceof ZepRawEvent)) { logger.warn("Unexpected message type: {}", message); } else { while (this.indexQueueLag && this.throttleConsumer) { Thread.sleep(this.consumerSleepTime); } this.eventProcessor.processEvent((ZepRawEvent) message); } } }