Beispiel #1
0
def get_outgoing_sessions_by_address(
        server_url: Optional[str] = None) -> MutableMapping[str, list]:
    """Retrieve outgoing sessions from AMQP broker.

    Args:
        server_url: Comma-separated list of urls to connect to.
            Multiple can be specified for connection fallback, the first
            should be the primary server.

    Returns:
        defaultdict: A dict mapping between address name and list of sessions.

    Example:
        >>> get_outgoing_sessions_by_address()
        {'8152f68b-c74a-4d22-8630-a89cf194d067_8152f68b-\
c74a-4d22-8630-a89cf194d067-2d808664-fe81-4da4-8258-288a7ff531ac': [{\
'session_id': 'org.apache.qpid.broker:session:0x7fb8bc021ab0','transfers': \
ulong(0)}]}
    """
    client_subscriptions: MutableMapping[str, list] = defaultdict(list)

    def _update_results(message: Message):
        for value in (item['_values'] for item in message.body):
            client_subscriptions[value['source'].decode()].append({
                'session_id': value['sessionRef']['_object_name'].decode(),
                'transfers': value['transfers']
            })
        return True

    rpc = RemoteProcedure(_update_results, 'qmf.default.direct',
                          server_url)
    binding_query_message = create_QMF2_query('org.apache.qpid.broker',
                                              'outgoing')
    rpc.call(binding_query_message, timedelta(seconds=5))
    return dict(client_subscriptions)
Beispiel #2
0
def get_sessions(server_url: Optional[str] = None) -> dict:
    """Retrieve sessions from AMQP broker.

    Args:
        server_url: Comma-separated list of urls to connect to.
            Multiple can be specified for connection fallback, the first
            should be the primary server.

    Returns:
        dict: A dict mapping between session id and it's address.

    Example:
        >>> get_sessions()
        {'org.apache.qpid.broker:session:0x7fb8bc021ab0': {'address': '10.0.0.2:34814'}}
    """
    sessions = {}

    def _update_sessions(message: Message):
        for item in message.body:
            values = item['_values']
            connectionRef = values['connectionRef']['_object_name'].decode()
            sessions[item['_object_id']['_object_name'].decode()] = {
                'address': connectionRef.rsplit('-', 1)[1]}
        return True

    rpc = RemoteProcedure(_update_sessions, 'qmf.default.direct',
                          server_url)
    binding_query_message = create_QMF2_query('org.apache.qpid.broker',
                                              'session')
    rpc.call(binding_query_message, timedelta(seconds=5))
    return sessions
Beispiel #3
0
def queue_statistics(queue_name: Optional[str] = None,
                     include_autodelete: bool = False,
                     server_url: Optional[str] = None) -> dict:
    """Retrieve total messages count and depth for all queues from AMQP broker.

    Args:
        queue_name: Name of queue.
        include_autodelete: Include autodelete queues to output.
        server_url: Comma-separated list of urls to connect to.
            Multiple can be specified for connection fallback, the first
            should be the primary server.

    Returns:
        dict: A dict mapping between queue address and dict with total messages
        and queue depth.

    Example:
        >>> queue_statistics(queue_name='examples')
        {'org.apache.qpid.broker:queue:examples': {'name': 'examples', 'total': 96, 'depth': 12}}
    """
    queues = {}

    def _update_queue_stats(message: Message):
        for item in message.body:
            values = item['_values']
            if values['autoDelete'] and not include_autodelete:
                continue  # We are not interested in temp reply queues

            current_queue_name = values['name'].decode()

            if queue_name and current_queue_name != queue_name:
                continue

            queues[item['_object_id']['_object_name'].decode()] = {
                'name': values['name'].decode(),
                'total': int(values['msgTotalEnqueues']),
                'depth': int(values['msgDepth'])
            }
        return True

    rpc = RemoteProcedure(_update_queue_stats, 'qmf.default.direct',
                          server_url)
    queue_query_message = create_QMF2_query('org.apache.qpid.broker',
                                            'queue')
    rpc.call(queue_query_message, timedelta(seconds=15))
    return queues
Beispiel #4
0
def get_binding_keys(exchange_name: str, queue_name: str = None,
                     server_url: Optional[str] = None
                    ) -> Set[Tuple[str, str, str]]:
    """Retrieve all bindings for specified exchange.

    Args:
        exchange_name: Name of exchange.
        queue_name: Name of queue.
        server_url: Comma-separated list of urls to connect to.
            Multiple can be specified for connection fallback, the first
            should be the primary server.

    Returns:
        Set of binding keys.
    """
    result = set()

    def _filter_bindings(message: Message):
        for item in message.body:
            values = item['_values']
            queue_id = values['queueRef']['_object_name'].decode()
            qpid_queue_name = queue_id.rsplit(':', 1)[-1]
            exchange_id = values['exchangeRef']['_object_name'].decode()
            qpid_exchange_name = exchange_id.rsplit(':', 1)[-1]
            if exchange_name == qpid_exchange_name:
                if not queue_name or (queue_name == qpid_queue_name):
                    result.add((
                        qpid_exchange_name,
                        qpid_queue_name,
                        values['bindingKey'].decode()
                    ))
        return True

    rpc = RemoteProcedure(_filter_bindings, 'qmf.default.direct', server_url)
    binding_query_message = create_QMF2_query('org.apache.qpid.broker',
                                              'binding')
    rpc.call(binding_query_message, timedelta(seconds=5))
    return result
Beispiel #5
0
def exchange_statistics(server_url: Optional[str] = None) -> dict:
    """Retrieve total and dropped amount of messages for exchanges from AMQP broker.

    Args:
        server_url: Comma-separated list of urls to connect to.
            Multiple can be specified for connection fallback, the first
            should be the primary server.

    Returns:
        dict: A dict mapping between exchange address and dict with exchange
            name, total messages count and dropped messages count.

    Example:
        >>> exchange_statistics()
        {'org.apache.qpid.broker:exchange:': {'name': '', 'total': ulong(236), 'dropped': ulong(0)}}
    """
    exchanges = {}

    def _update_exchange_stats(message: Message):
        for item in message.body:
            values = item['_values']
            name = values['name'].decode()
            if name.startswith(('qmf', 'qpid', 'amq')):
                continue  # Don't export Qpid/QMF related stats

            exchanges[item['_object_id']['_object_name'].decode()] = {
                'name': name,
                'total': values['msgReceives'],
                'dropped': values['msgDrops']
            }
        return True

    rpc = RemoteProcedure(_update_exchange_stats, 'qmf.default.direct',
                          server_url)
    exchange_query_message = create_QMF2_query('org.apache.qpid.broker',
                                               'exchange')
    rpc.call(exchange_query_message, timedelta(seconds=5))
    return exchanges
Beispiel #6
0
def get_exchange_bindings(server_url: Optional[str] = None) -> dict:
    """Retrieve all exchanges and bindings associated with these exchanges.

    Args:
        server_url: Comma-separated list of urls to connect to.
            Multiple can be specified for connection fallback, the first
            should be the primary server.

    Returns:
        dict: A dict mapping between exchange it's bindings.

    Example:
        >>> get_exchange_bindings()
        {'org.apache.qpid.broker:exchange:': [\
{'queue_id': 'org.apache.qpid.broker:queue:examples', 'headers_match': {}}]}
    """
    results: defaultdict = defaultdict(list)

    def _update_bindings(message: Message):
        for item in message.body:
            logger.info("Got binding: %s", item)
            values = item['_values']

            exchange_id = values['exchangeRef']['_object_name'].decode()
            results[exchange_id].append({
                'queue_id': values['queueRef']['_object_name'].decode(),
                'headers_match': values.get('arguments')
            })

        return True

    rpc = RemoteProcedure(_update_bindings, 'qmf.default.direct',
                          server_url)
    binding_query_message = create_QMF2_query('org.apache.qpid.broker',
                                              'binding')
    rpc.call(binding_query_message, timedelta(seconds=5))
    return results
Beispiel #7
0
def get_connection_ids(server_url: Optional[str] = None) -> list:
    """Retrieve connection ids of all established connections to AMQP broker.

    Args:
        server_url: Comma-separated list of urls to connect to.
            Multiple can be specified for connection fallback, the first
            should be the primary server.

    Returns:
        List of connections
    """
    connections = []

    def _update_connections(message: Message):
        for item in message.body:
            connections.append(item['_object_id']['_object_name'])
        return True

    rpc = RemoteProcedure(_update_connections, 'qmf.default.direct',
                          server_url)
    binding_query_message = create_QMF2_query('org.apache.qpid.broker',
                                              'connection')
    rpc.call(binding_query_message, timedelta(seconds=5))
    return connections
Beispiel #8
0
def gather_statistics(server_url: Optional[str] = None) -> dict:
    """Retrieve statistics about exchanges and queues from AMQP broker.

    Statistics data includes exchanges and queues. Exchange information
    includes exchange name, total and dropped amount of messages. Queue
    information includes messages count, depth and bindings to exchange.

    Args:
        server_url: Comma-separated list of urls to connect to.
            Multiple can be specified for connection fallback, the first
            should be the primary server.

    Returns:
        dict: Exchange and queue statistics.

    Example:
        >>> gather_statistics()
        {'exchanges': {'org.apache.qpid.broker:exchange:': {'dropped': \
ulong(0), 'name': '', 'total': ulong(251)}}, 'queues': {\
'org.apache.qpid.broker:queue:examples': {'bindings': [{'exchange_id': \
'org.apache.qpid.broker:exchange:', 'name': 'default_route', 'total': 96}], \
'depth': 12, 'name': 'examples', 'total': 96}}}
    """
    stats = {
        'queues': queue_statistics(server_url=server_url),
        'exchanges': exchange_statistics(server_url),
    }

    for queue in stats['queues'].values():
        queue['bindings'] = []

    def _update_binding_stats(message: Message):
        for item in message.body:
            values = item['_values']
            queue_id = values['queueRef']['_object_name'].decode()
            exchange_id = values['exchangeRef']['_object_name'].decode()
            if queue_id not in stats['queues']:
                continue  # Filtered queue
            if exchange_id not in stats['exchanges']:
                continue  # Filtered exchange
            if exchange_id == EXCHANGE_ID_PREFIX:
                continue  # Default exchange stats are broken, reconstruct

            exchange_stats = {
                'name': values['bindingKey'].decode(),
                'exchange_id': exchange_id,
                'total': values['msgMatched']
            }
            stats['queues'][queue_id]['bindings'].append(exchange_stats)
        return True

    rpc = RemoteProcedure(_update_binding_stats, 'qmf.default.direct',
                          server_url)
    binding_query_message = create_QMF2_query('org.apache.qpid.broker',
                                              'binding')
    rpc.call(binding_query_message, timedelta(seconds=15))

    # Reconstruct default route stats
    for queue in stats['queues'].values():
        total_routed = sum((binding['total'] for binding in queue['bindings']))
        queue['bindings'].append({
            'name': 'default_route',
            'exchange_id': EXCHANGE_ID_PREFIX,
            'total': queue['total'] - total_routed
        })

    return stats