/usr/lib/python2.7/dist-packages/oops_amqp/publisher.py is in python-oops-amqp 0.0.7-0ubuntu2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | # Copyright (c) 2011, Canonical Ltd
#
# This program 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, version 3 only.
#
# 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# GNU Lesser General Public License version 3 (see the file LICENSE).
"""Publish OOPS reports over amqp."""
__metaclass__ = type
from hashlib import md5
from threading import local
from amqplib import client_0_8 as amqp
from anybson import dumps
from utils import (
amqplib_error_types,
is_amqplib_connection_error,
)
__all__ = [
'Publisher',
]
class Publisher:
"""Publish OOPS reports over AMQP.
Messages are published as bson dicts via durable messages sent to a
supplied exchange + routing key.
"""
def __init__(self, connection_factory, exchange_name, routing_key,
inherit_id=False):
"""Create a publisher.
:param connection_factory: A callable which creates an amqplib
Connection when called. This is used to create connections - one
per thread which OOPS publishing happens in. This is because
amqplib is not threadsafe and recommends not sharing connections
across threads.
:param exchange_name: The name of the exchange to publish to.
:param routing_key: The routing key for messages.
:param inherit_id: If True any 'True' 'id' in an OOPS report is
preserved. Handy if an id that has already been shown to a user is
being published (but uniqueness cannot be guaranteed).
"""
self.connection_factory = connection_factory
self.exchange_name = exchange_name
self.routing_key = routing_key
self.channels = local()
self.inherit_id = inherit_id
def get_channel(self):
if getattr(self.channels, 'channel', None) is None:
try:
self.channels.channel = self.connection_factory().channel()
except amqplib_error_types, e:
if is_amqplib_connection_error(e):
# Could not connect
return None
# Unknown error mode : don't hide it.
raise
return self.channels.channel
def __call__(self, report):
# Don't mess with the passed in report.
report = dict(report)
if not self.inherit_id or not report.get('id'):
# Discard any existing id.
original_id = report.pop('id', None)
# Hash it, to make an ID
oops_id = "OOPS-%s" % md5(dumps(report)).hexdigest()
# Store the id in what we send on the wire, so that the recipient
# has it.
report['id'] = oops_id
message = amqp.Message(dumps(report))
# We don't want to drop OOPS on the floor if rabbit is restarted.
message.properties["delivery_mode"] = 2
channel = self.get_channel()
if channel is None:
return []
try:
channel.basic_publish(
message, self.exchange_name, routing_key=self.routing_key)
except amqplib_error_types, e:
self.channels.channel = None
if is_amqplib_connection_error(e):
# Could not connect / interrupted connection
return []
# Unknown error mode : don't hide it.
raise
return [report['id']]
|