Source code for duct.outputs.graphite
"""
.. module:: logger
:synopsis: Output which sends events to the standard logging output
.. moduleauthor:: Colin Alston <colin@tamvera.com>
"""
import logging
import asyncio
from duct.objects import Output, Event
log = logging.getLogger(__name__)
[docs]
class Graphite(Output):
"""Graphite output.
By default events are named {prefix}.{hostname}.{source service} unless
prefix_hostname is set to False
:param server: Graphite server hostname (default: localhost)
:type server: str.
:param port: Graphite server port (default: 2003)
:type port: int.
:param prefix: Metric path prefix (default: None)
:type prefix: str.
:param prefix_hostname: Whether to append the event source hostname field to
the path (default: True)
:type prefix_hostname: bool.
"""
def __init__(self, *a, **kw):
super().__init__(*a, **kw)
self.server = self.config.get('server', 'localhost')
self.port = self.config.get('port', 2003)
self.prefix = self.config.get('prefix', None)
self.prefix_hostname = self.config.get('prefix_hostname', True)
[docs]
async def push_batch_to_graphite(self, metrics):
"""Sends a batch of metric lines to Graphite via a single TCP connection."""
try:
_reader, writer = await asyncio.open_connection(self.server, self.port)
for metric_path, value, timestamp in metrics:
message = f"{metric_path} {value} {timestamp}\n"
writer.write(message.encode())
await writer.drain()
writer.close()
await writer.wait_closed()
except Exception as e:
log.error("Failed to send batch to Graphite: %s", str(e))
[docs]
async def eventsReceived(self, events:list[Event]):
"""Called when events are routed to this output"""
metrics = []
for ev in events:
path = []
if self.prefix:
path.append(self.prefix)
if self.prefix_hostname:
path.append(ev.hostname)
path.append(ev.service)
metrics.append(('.'.join(path), ev.metric, int(ev.time)))
await self.push_batch_to_graphite(metrics)