Search in sources :

Example 1 with AgentRestartedWorkItem

use of org.apache.qpid.qmf2.console.AgentRestartedWorkItem in project qpid by apache.

the class ConnectionAudit method onEvent.

/**
     * Handles WorkItems delivered by the Console.
     * <p>
     * If we receive an EventReceivedWorkItem check if it is a subscribe event. If it is we check if the whitelist has 
     * changed, and if it has we re-read it. We then extract the queue name, exchange name, binding, connection address
     * and timestamp and validate with the whitelsist.
     * <p>
     * If we receive an AgentRestartedWorkItem we revalidate all subscriptions as it's possible that a client connection
     * could have been made to the broker before ConnectionAudit has successfully re-established its own connections.
     * @param wi a QMF2 WorkItem object
     */
public void onEvent(final WorkItem wi) {
    if (wi instanceof EventReceivedWorkItem) {
        EventReceivedWorkItem item = (EventReceivedWorkItem) wi;
        QmfEvent event = item.getEvent();
        String className = event.getSchemaClassId().getClassName();
        if (className.equals("subscribe")) {
            readWhitelist();
            String queueName = event.getStringValue("qName");
            String address = event.getStringValue("rhost");
            String timestamp = new Date(event.getTimestamp() / 1000000l).toString();
            validateQueue(queueName, address, timestamp);
        }
    } else if (wi instanceof AgentRestartedWorkItem) {
        checkExistingSubscriptions();
    }
}
Also used : AgentRestartedWorkItem(org.apache.qpid.qmf2.console.AgentRestartedWorkItem) EventReceivedWorkItem(org.apache.qpid.qmf2.console.EventReceivedWorkItem) QmfEvent(org.apache.qpid.qmf2.common.QmfEvent) Date(java.util.Date)

Example 2 with AgentRestartedWorkItem

use of org.apache.qpid.qmf2.console.AgentRestartedWorkItem in project qpid by apache.

the class ConnectionLogger method onEvent.

/**
     * Listener for QMF2 WorkItems
     * <p>
     * This method looks for clientConnect or clientDisconnect Events and uses these as a trigger to log the new
     * connection state when the next Heartbeat occurs.
     * <p>
     * There are a couple of reasons for using this approach rather than just calling logConnectionInformation()
     * as soon as we see the clientConnect or clientDisconnect Event.
     * <p>
     * 1. We could potentially have lots of connection Events and redisplaying all of the connections for each
     *    Event is likely to be confusing.
     * <p>
     * 2. When a clientConnect Event occurs we don't have all of the informatin that we might need, for example this
     *    application checks the Session and Subscription information and also optionally Queue and Binding information.
     *    Creating Sessions/Subscriptions won't generally occur until some (possibly small, but possibly not) time
     *    after the Connection has been made. The approach taken here reduces spurious assertions that a Session is
     *    probably a "producer only" Session. As one of the use-cases for this tool is to attempt to flag up "producer
     *    only" Sessions we want to try and make it as reliable as possible.
     *
     * @param wi a QMF2 WorkItem object
     */
public void onEvent(final WorkItem wi) {
    if (wi instanceof EventReceivedWorkItem) {
        EventReceivedWorkItem item = (EventReceivedWorkItem) wi;
        Agent agent = item.getAgent();
        QmfEvent event = item.getEvent();
        String className = event.getSchemaClassId().getClassName();
        if (className.equals("clientConnect") || className.equals("clientDisconnect")) {
            _stateChanged = true;
        }
    } else if (wi instanceof AgentRestartedWorkItem) {
        _stateChanged = true;
    } else if (wi instanceof AgentHeartbeatWorkItem) {
        AgentHeartbeatWorkItem item = (AgentHeartbeatWorkItem) wi;
        Agent agent = item.getAgent();
        if (_stateChanged && agent.getName().contains("qpidd")) {
            logConnectionInformation();
            _stateChanged = false;
        }
    }
}
Also used : Agent(org.apache.qpid.qmf2.console.Agent) AgentRestartedWorkItem(org.apache.qpid.qmf2.console.AgentRestartedWorkItem) EventReceivedWorkItem(org.apache.qpid.qmf2.console.EventReceivedWorkItem) AgentHeartbeatWorkItem(org.apache.qpid.qmf2.console.AgentHeartbeatWorkItem) QmfEvent(org.apache.qpid.qmf2.common.QmfEvent)

Example 3 with AgentRestartedWorkItem

use of org.apache.qpid.qmf2.console.AgentRestartedWorkItem in project qpid by apache.

the class Console method onMessage.

/**
     * MessageListener for QMF2 Agent Events, Hearbeats and Asynchronous data indications
     *
     * @param message the JMS Message passed to the listener
     */
public void onMessage(Message message) {
    try {
        String agentName = QmfData.getString(message.getObjectProperty("qmf.agent"));
        String content = QmfData.getString(message.getObjectProperty("qmf.content"));
        String opcode = QmfData.getString(message.getObjectProperty("qmf.opcode"));
        if (opcode.equals("_agent_heartbeat_indication") || opcode.equals("_agent_locate_response")) {
            // This block handles Agent lifecycle information (discover, register, delete)
            if (_agents.containsKey(agentName)) {
                // This block handles Agents that have previously been registered
                Agent agent = _agents.get(agentName);
                long originalEpoch = agent.getEpoch();
                // If we already know about an Agent we simply update the Agent's state using initialise()
                agent.initialise(AMQPMessage.getMap(message));
                // If the Epoch has changed it means the Agent has been restarted so we send a notification
                if (agent.getEpoch() != originalEpoch) {
                    // Clear cache to force a lookup
                    agent.clearSchemaCache();
                    List<SchemaClassId> classes = getClasses(agent);
                    // Discover the schema for this Agent and cache it
                    getSchema(classes, agent);
                    _log.info("Agent {} has been restarted", agentName);
                    if (_discoverAgents && (_agentQuery == null || _agentQuery.evaluate(agent))) {
                        _eventListener.onEvent(new AgentRestartedWorkItem(agent));
                    }
                } else {
                    // Otherwise just send a heartbeat notification
                    _log.info("Agent {} heartbeat", agent.getName());
                    if (_discoverAgents && (_agentQuery == null || _agentQuery.evaluate(agent))) {
                        _eventListener.onEvent(new AgentHeartbeatWorkItem(agent));
                    }
                }
            } else {
                // This block handles Agents that haven't already been registered
                Agent agent = new Agent(AMQPMessage.getMap(message), this);
                List<SchemaClassId> classes = getClasses(agent);
                // Discover the schema for this Agent and cache it
                getSchema(classes, agent);
                _agents.put(agentName, agent);
                _log.info("Adding Agent {}", agentName);
                // the Agent more "user friendly" than using the full Agent name.
                if (agent.getVendor().equals("apache.org") && agent.getProduct().equals("qpidd")) {
                    _log.info("Recording {} as _brokerAgentName", agentName);
                    _brokerAgentName = agentName;
                }
                // wait for the broker Agent to become available.
                if (_brokerAgentName != null) {
                    synchronized (this) {
                        _agentAvailable = true;
                        notifyAll();
                    }
                }
                if (_discoverAgents && (_agentQuery == null || _agentQuery.evaluate(agent))) {
                    _eventListener.onEvent(new AgentAddedWorkItem(agent));
                }
            }
            // The broker Agent sends periodic heartbeats and that Agent should *always* be available given
            // a running broker, so we should get here every "--mgmt-pub-interval" seconds or so, so it's
            // a good place to periodically check for the expiry of any other Agents.
            handleAgentExpiry();
            return;
        }
        if (!_agents.containsKey(agentName)) {
            _log.info("Ignoring Event from unregistered Agent {}", agentName);
            return;
        }
        Agent agent = _agents.get(agentName);
        if (!agent.eventsEnabled()) {
            _log.info("{} has disabled Event reception, ignoring Event", agentName);
            return;
        }
        // If we get to here the Agent from whence the Event came should be registered and should
        // have Event reception enabled, so we should be able to send events to the EventListener
        Handle handle = new Handle(message.getJMSCorrelationID());
        if (opcode.equals("_method_response") || opcode.equals("_exception")) {
            if (AMQPMessage.isAMQPMap(message)) {
                _eventListener.onEvent(new MethodResponseWorkItem(handle, new MethodResult(AMQPMessage.getMap(message))));
            } else {
                _log.info("onMessage() Received Method Response message in incorrect format");
            }
        }
        // refresh() call on QmfConsoleData so the number of results in the returned list *should* be one.
        if (opcode.equals("_query_response") && content.equals("_data")) {
            if (AMQPMessage.isAMQPList(message)) {
                List<Map> list = AMQPMessage.getList(message);
                for (Map m : list) {
                    _eventListener.onEvent(new ObjectUpdateWorkItem(handle, new QmfConsoleData(m, agent)));
                }
            } else {
                _log.info("onMessage() Received Query Response message in incorrect format");
            }
        }
        // This block handles responses to createSubscription and refreshSubscription
        if (opcode.equals("_subscribe_response")) {
            if (AMQPMessage.isAMQPMap(message)) {
                String correlationId = message.getJMSCorrelationID();
                SubscribeParams params = new SubscribeParams(correlationId, AMQPMessage.getMap(message));
                String subscriptionId = params.getSubscriptionId();
                if (subscriptionId != null && correlationId != null) {
                    SubscriptionManager subscription = _subscriptionById.get(subscriptionId);
                    if (subscription == null) {
                        // This is a createSubscription response so the correlationId should be the consoleHandle
                        subscription = _subscriptionByHandle.get(correlationId);
                        if (subscription != null) {
                            _subscriptionById.put(subscriptionId, subscription);
                            subscription.setSubscriptionId(subscriptionId);
                            subscription.setDuration(params.getLifetime());
                            String replyHandle = subscription.getReplyHandle();
                            if (replyHandle == null) {
                                subscription.signal();
                            } else {
                                _eventListener.onEvent(new SubscribeResponseWorkItem(new Handle(replyHandle), params));
                            }
                        }
                    } else {
                        // This is a refreshSubscription response
                        params.setConsoleHandle(subscription.getConsoleHandle());
                        subscription.setDuration(params.getLifetime());
                        subscription.refresh();
                        _eventListener.onEvent(new SubscribeResponseWorkItem(handle, params));
                    }
                }
            } else {
                _log.info("onMessage() Received Subscribe Response message in incorrect format");
            }
        }
        // Subscription Indication - in other words the asynchronous results of a Subscription
        if (opcode.equals("_data_indication") && content.equals("_data")) {
            if (AMQPMessage.isAMQPList(message)) {
                String consoleHandle = handle.getCorrelationId();
                if (consoleHandle != null && _subscriptionByHandle.containsKey(consoleHandle)) {
                    // If we have a valid consoleHandle the data has come from a "real" Subscription.
                    List<Map> list = AMQPMessage.getList(message);
                    List<QmfConsoleData> resultList = new ArrayList<QmfConsoleData>(list.size());
                    for (Map m : list) {
                        resultList.add(new QmfConsoleData(m, agent));
                    }
                    _eventListener.onEvent(new SubscriptionIndicationWorkItem(new SubscribeIndication(consoleHandle, resultList)));
                } else if (_subscriptionEmulationEnabled && agentName.equals(_brokerAgentName)) {
                    // If the data has come from is the broker Agent we emulate a Subscription on the Console
                    for (SubscriptionManager subscription : _subscriptionByHandle.values()) {
                        QmfQuery query = subscription.getQuery();
                        if (subscription.getAgent().getName().equals(_brokerAgentName) && query.getTarget() == QmfQueryTarget.OBJECT) {
                            // Only evaluate broker Agent subscriptions with QueryTarget == OBJECT on the Console.
                            long objectEpoch = 0;
                            consoleHandle = subscription.getConsoleHandle();
                            List<Map> list = AMQPMessage.getList(message);
                            List<QmfConsoleData> resultList = new ArrayList<QmfConsoleData>(list.size());
                            for (Map m : list) {
                                // Evaluate the QmfConsoleData object against the query
                                QmfConsoleData object = new QmfConsoleData(m, agent);
                                if (query.evaluate(object)) {
                                    long epoch = object.getObjectId().getAgentEpoch();
                                    objectEpoch = (epoch > objectEpoch && !object.isDeleted()) ? epoch : objectEpoch;
                                    resultList.add(object);
                                }
                            }
                            if (resultList.size() > 0) {
                                // data from the restarted Agent (in case they need to reset any state).
                                if (objectEpoch > agent.getEpoch()) {
                                    agent.setEpoch(objectEpoch);
                                    // Clear cache to force a lookup
                                    agent.clearSchemaCache();
                                    List<SchemaClassId> classes = getClasses(agent);
                                    // Discover the schema for this Agent and cache it
                                    getSchema(classes, agent);
                                    _log.info("Agent {} has been restarted", agentName);
                                    if (_discoverAgents && (_agentQuery == null || _agentQuery.evaluate(agent))) {
                                        _eventListener.onEvent(new AgentRestartedWorkItem(agent));
                                    }
                                }
                                _eventListener.onEvent(new SubscriptionIndicationWorkItem(new SubscribeIndication(consoleHandle, resultList)));
                            }
                        }
                    }
                }
            } else {
                _log.info("onMessage() Received Subscribe Indication message in incorrect format");
            }
        }
        // The results of an Event delivered from an Agent
        if (opcode.equals("_data_indication") && content.equals("_event")) {
            // There are differences in the type of message sent by Qpid 0.8 and 0.10 onwards.
            if (AMQPMessage.isAMQPMap(message)) {
                // 0.8 broker passes Events as amqp/map encoded as MapMessages (we convert into java.util.Map)
                _eventListener.onEvent(new EventReceivedWorkItem(agent, new QmfEvent(AMQPMessage.getMap(message))));
            } else if (AMQPMessage.isAMQPList(message)) {
                // 0.10 and above broker passes Events as amqp/list encoded as BytesMessage (needs decoding)
                // 0.20 encodes amqp/list in a MapMessage!!?? AMQPMessage hopefully abstracts this detail.
                List<Map> list = AMQPMessage.getList(message);
                for (Map m : list) {
                    _eventListener.onEvent(new EventReceivedWorkItem(agent, new QmfEvent(m)));
                }
            } else {
                _log.info("onMessage() Received Event message in incorrect format");
            }
        }
    } catch (JMSException jmse) {
        _log.info("JMSException {} caught in onMessage()", jmse.getMessage());
    }
}
Also used : ArrayList(java.util.ArrayList) QmfEvent(org.apache.qpid.qmf2.common.QmfEvent) JMSException(javax.jms.JMSException) ArrayList(java.util.ArrayList) List(java.util.List) SchemaClassId(org.apache.qpid.qmf2.common.SchemaClassId) Handle(org.apache.qpid.qmf2.common.Handle) HashMap(java.util.HashMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) QmfQuery(org.apache.qpid.qmf2.common.QmfQuery)

Example 4 with AgentRestartedWorkItem

use of org.apache.qpid.qmf2.console.AgentRestartedWorkItem in project qpid by apache.

the class QpidQueueStats method onEvent.

/**
     * Main Event handler. Checks if the WorkItem is a SubscriptionIndicationWorkItem, if it is it stores the object
     * in a Map and uses this to maintain state so we can record deltas such as enqueue and dequeue rates.
     * <p>
     * The AgentHeartbeatWorkItem is used to periodically compare the elapsed time against the Subscription duration
     * so that we can refresh the Subscription (or create a new one if necessary) in order to continue receiving
     * queue Management Object data from the broker.
     * <p>
     * When the AgentRestartedWorkItem is received we clear the state to remove any stale queue Management Objects.
     * @param wi a QMF2 WorkItem object
     */
public void onEvent(final WorkItem wi) {
    if (wi instanceof AgentHeartbeatWorkItem && _subscriptionId != null) {
        long elapsed = (long) Math.round((System.currentTimeMillis() - _startTime) / 1000.0f);
        if (elapsed > _subscriptionDuration) {
            try {
                _console.refreshSubscription(_subscriptionId);
                _startTime = System.currentTimeMillis();
            } catch (QmfException qmfe) {
                System.err.println("QmfException " + qmfe.getMessage() + " caught in QpidQueueStats onEvent");
                createQueueSubscription();
            }
        }
    } else if (wi instanceof AgentRestartedWorkItem) {
        _objects.clear();
    } else if (wi instanceof SubscriptionIndicationWorkItem) {
        SubscriptionIndicationWorkItem item = (SubscriptionIndicationWorkItem) wi;
        SubscribeIndication indication = item.getSubscribeIndication();
        String correlationId = indication.getConsoleHandle();
        if (correlationId.equals("queueStatsHandle")) {
            // If it is (and it should be!!) then it's our queue object Subscription
            List<QmfConsoleData> data = indication.getData();
            for (QmfConsoleData record : data) {
                ObjectId id = record.getObjectId();
                if (record.isDeleted()) {
                    // If the object was deleted by the Agent we remove it from out Map
                    _objects.remove(id);
                } else {
                    if (_objects.containsKey(id)) {
                        // If the object is already in the Map it's likely to be a statistics push from the broker.
                        Stats stats = _objects.get(id);
                        String name = stats.getName();
                        boolean matches = false;
                        for (Pattern x : _filter) {
                            // Check the queue name against the regexes in the filter List (if any)
                            Matcher m = x.matcher(name);
                            if (m.find()) {
                                matches = true;
                                break;
                            }
                        }
                        if (_filter.isEmpty() || matches) {
                            // If there's no filter enabled or the filter matches the queue name we display statistics.
                            QmfConsoleData lastSample = stats.getData();
                            stats.setData(record);
                            float deltaTime = record.getUpdateTime() - lastSample.getUpdateTime();
                            if (deltaTime > 1000000000.0f) {
                                float deltaEnqueues = record.getLongValue("msgTotalEnqueues") - lastSample.getLongValue("msgTotalEnqueues");
                                float deltaDequeues = record.getLongValue("msgTotalDequeues") - lastSample.getLongValue("msgTotalDequeues");
                                long msgDepth = record.getLongValue("msgDepth");
                                float enqueueRate = deltaEnqueues / (deltaTime / 1000000000.0f);
                                float dequeueRate = deltaDequeues / (deltaTime / 1000000000.0f);
                                System.out.printf("%-46s%10.2f%11d%13.2f%13.2f\n", name, deltaTime / 1000000000, msgDepth, enqueueRate, dequeueRate);
                            }
                        }
                    } else {
                        // If the object isn't in the Map it's likely to be a properties push from the broker.
                        if (!record.hasValue("name")) {
                            // This probably won't happen, but if it does we refresh the object to get its full state.
                            try {
                                record.refresh();
                            } catch (QmfException qmfe) {
                            }
                        }
                        String queueName = record.getStringValue("name");
                        _objects.put(id, new Stats(queueName, record));
                    }
                }
            }
        }
    }
}
Also used : Pattern(java.util.regex.Pattern) AgentRestartedWorkItem(org.apache.qpid.qmf2.console.AgentRestartedWorkItem) SubscriptionIndicationWorkItem(org.apache.qpid.qmf2.console.SubscriptionIndicationWorkItem) ObjectId(org.apache.qpid.qmf2.common.ObjectId) Matcher(java.util.regex.Matcher) AgentHeartbeatWorkItem(org.apache.qpid.qmf2.console.AgentHeartbeatWorkItem) SubscribeIndication(org.apache.qpid.qmf2.console.SubscribeIndication) QmfConsoleData(org.apache.qpid.qmf2.console.QmfConsoleData) QmfException(org.apache.qpid.qmf2.common.QmfException)

Aggregations

QmfEvent (org.apache.qpid.qmf2.common.QmfEvent)3 AgentRestartedWorkItem (org.apache.qpid.qmf2.console.AgentRestartedWorkItem)3 AgentHeartbeatWorkItem (org.apache.qpid.qmf2.console.AgentHeartbeatWorkItem)2 EventReceivedWorkItem (org.apache.qpid.qmf2.console.EventReceivedWorkItem)2 ArrayList (java.util.ArrayList)1 Date (java.util.Date)1 HashMap (java.util.HashMap)1 List (java.util.List)1 Map (java.util.Map)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 Matcher (java.util.regex.Matcher)1 Pattern (java.util.regex.Pattern)1 JMSException (javax.jms.JMSException)1 Handle (org.apache.qpid.qmf2.common.Handle)1 ObjectId (org.apache.qpid.qmf2.common.ObjectId)1 QmfException (org.apache.qpid.qmf2.common.QmfException)1 QmfQuery (org.apache.qpid.qmf2.common.QmfQuery)1 SchemaClassId (org.apache.qpid.qmf2.common.SchemaClassId)1 Agent (org.apache.qpid.qmf2.console.Agent)1 QmfConsoleData (org.apache.qpid.qmf2.console.QmfConsoleData)1