Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyformance/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "1.0.7"
__version__ = "2.0.0"
2 changes: 1 addition & 1 deletion pyformance/meters/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

@dataclass
class EventPoint:
time: int
time: float
values: Dict[str, Any]


Expand Down
54 changes: 50 additions & 4 deletions pyformance/reporters/influx.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import base64
import logging
import re
from enum import Enum

from six import iteritems

Expand All @@ -26,6 +27,14 @@
DEFAULT_INFLUX_PASSWORD = None
DEFAULT_INFLUX_PROTOCOL = "http"

class ReportingPrecision(Enum):
HOURS = "h"
MINUTES = "m"
SECONDS = "s"
MILLISECONDS = "ms"
MICROSECONDS = "u"
NANOSECONDS = "ns"


class InfluxReporter(Reporter):
"""
Expand All @@ -47,7 +56,13 @@ def __init__(
autocreate_database=False,
clock=None,
global_tags=None,
reporting_precision = ReportingPrecision.SECONDS
):
"""
:param reporting_precision: The precision in which the reporter reports to influx.
The default is seconds. This is a tradeoff between precision and performance. More
coarse precision may result in significant improvements in compression and vice versa.
"""
super(InfluxReporter, self).__init__(registry, reporting_interval, clock)
self.prefix = prefix
self.database = database
Expand All @@ -64,6 +79,8 @@ def __init__(
else:
self.global_tags = global_tags

self.reporting_precision = reporting_precision

def _create_database(self):
url = "%s://%s:%s/query" % (self.protocol, self.server, self.port)
q = quote("CREATE DATABASE %s" % self.database)
Expand All @@ -87,10 +104,14 @@ def _create_database(self):
def report_now(self, registry=None, timestamp=None):
if self.autocreate_database and not self._did_create_database:
self._create_database()
timestamp = timestamp or int(round(self.clock.time()))
Copy link
Author

@Asaf-m Asaf-m Dec 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that the old code was rounding the time (same for events time at line 127). I thought this is an unexpected behavior so I removed the rounding part. In other words, for "seconds" precision for example, the code drops the milliseconds data.

timestamp = timestamp or self.clock.time()
timestamp_in_reporting_precision = _to_timestamp_in_precision(
timestamp=timestamp,
precision=self.reporting_precision
)
metrics = (registry or self.registry).dump_metrics(key_is_metric=True)

influx_lines = self._get_influx_protocol_lines(metrics, timestamp)
influx_lines = self._get_influx_protocol_lines(metrics, timestamp_in_reporting_precision)
# If you don't have anything nice to say than don't say nothing
if influx_lines:
post_data = "\n".join(influx_lines)
Expand Down Expand Up @@ -120,11 +141,15 @@ def _get_influx_protocol_lines(self, metrics, timestamp):
for event in metric_values.get("events", []):
values = InfluxReporter._stringify_values(event.values)

event_timestamp = _to_timestamp_in_precision(
timestamp=event.time,
precision=self.reporting_precision
)
line = "%s%s %s %s" % (
table,
tags,
values,
int(round(event.time))
event_timestamp
)

lines.append(line)
Expand Down Expand Up @@ -160,7 +185,7 @@ def _stringify_tags(self, metric):
return ""

def _get_url(self):
path = "/write?db=%s&precision=s" % self.database
path = "/write?db=%s&precision=%s" % (self.database, self.reporting_precision.value)
return "%s://%s:%s%s" % (self.protocol, self.server, self.port, path)

def _add_auth_data(self, request):
Expand All @@ -186,6 +211,27 @@ def _try_send(self, url, data):
response
)

def _to_timestamp_in_precision(timestamp: float, precision: ReportingPrecision) -> int:
if precision == ReportingPrecision.HOURS:
return int(timestamp / 60 / 60)

if precision == ReportingPrecision.MINUTES:
return int(timestamp / 60)

if precision == ReportingPrecision.SECONDS:
return int(timestamp)

if precision == ReportingPrecision.MILLISECONDS:
return int(timestamp * 1e3)

if precision == ReportingPrecision.MICROSECONDS:
return int(timestamp * 1e6)

if precision == ReportingPrecision.NANOSECONDS:
return int(timestamp * 1e9)

raise Exception("Unsupported ReportingPrecision")


def _format_field_value(value):
if isinstance(value, MarkInt):
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tox]
envlist = py27,py34,py35,py36
envlist = py37

[testenv]
commands=
Expand Down