Miscellaneous
Timestamps
- class metricq.Timestamp(nanoseconds)
A MetricQ Timestamp
- Parameters:
- nanoseconds
int number of nanoseconds elapsed since the UNIX epoch
- nanoseconds
- __add__(delta)
Return the timestamp delta in the future (or in the past, if delta is negative), relative to a
Timestampinstance.>>> epoch = Timestamp(0) >>> a_week_later = epoch + Timedelta.from_string("7 days") >>> str(a_week_later) '[604800000000000] 1970-01-08 01:00:00+01:00'
- __eq__(other)
Check whether two
Timestampsrefer to the same instance of time:>>> now = Timestamp.now() >>> later = now + Timedelta.from_s(10) >>> now == later False
- __lt__(other)
Compare whether this timestamp describes a time before another timestamp.
>>> now = Timestamp.now() >>> later = now + Timedelta.from_s(10) >>> now < later True
Together with
__eq__(), all relational operations (<=,>,!=, etc.) are supported. Timestamps are totally ordered (as supplied byfunctools.total_ordering()).
- __str__()
Yield a human-readable date-time string in the local timezone:
- Return type:
>>> # in UTC+01:00, it was already 1 in the night when the UNIX epoch happened >>> str(Timestamp(0)) '[0] 1970-01-01 01:00:00+01:00'
- classmethod ago(delta)
Return a timestamp delta in the past.
This is equivalent to:
Timestamp.now() - delta
- property datetime: datetime
Create an aware UTC datetime object
All MetricQ timestamps are POSIX timestamps, hence UTC.
- classmethod from_datetime(dt)
Create a Timestamp from an aware datetime object. If you have a naive datetime object, consider using
from_local_datetime()instead.- Return type:
- classmethod from_iso8601(iso_string)
Create a Timestamp from a ISO 8601 date-time string.
>>> Timestamp.from_iso8601("1970-01-01T00:00:00.0Z") == Timestamp(0) True
This is a convenience method that parses the date-time string into a
datetime.datetimeusingdateutil.parser.isoparse(), and then callsfrom_datetime()to create aTimestampfrom that.The provided iso_string must include timezone information. To parse local time strings, you must convert them yourself and use
from_local_datetime(). Or better yet, somehow create an awaredatetime.datetimeand usefrom_datetime().Note
The parser only supports up to 6 sub-second digits, further digits are simply dropped. If you need to parse timestamps with higher precision, you need to convert the string to nanoseconds yourself.
- classmethod from_local_datetime(dt)
Create a timestamp from a naive
datetimeobject that uses the local timezone. If you have a proper aware object, usefrom_datetime()instead.This function uses dateutil.tz.gettz() which uses /etc/localtime. Using naive datetime object can be error-prone. Naive local times are ambiguous during daylight savings time adjustments. If you have to use this function, your workflow is probably broken.
- Return type:
- classmethod from_now(delta)
Return a timestamp delta in the future.
This is equivalent to:
Timestamp.now() + delta
- classmethod from_posix_seconds(seconds)
Create a Timestamp from a POSIX timestamp
- classmethod now()
Return a Timestamp corresponding to “now”
Timedeltas (Durations)
- class metricq.Timedelta(nanoseconds)
A (possibly negative) duration of time
- Parameters:
- nanoseconds
int duration in nanoseconds
- nanoseconds
- Supported operations:
Operation
Types
Result
d1 + d2d1,d2:Timedelta
the sum of the duration of
d1andd2as aTimedeltaobjectd + dtd:Timedelta
the combined duration of
dandTimedelta.from_timedelta(dt)as aTimedeltaobjectd + ta
Timestampoffset by durationd(the same ast + d, seeTimestamp.__add__)d1 == d2d1,d2:Timedelta
Trueifd1andd2describe the same duration of timed == dtd:Timedelta
Trueifd.datetime == dt(seedatetime.timedelta)d1 < d2d1,d2:Timedelta
Trueifd1is shorter thand2d < dtd:Timedelta
Trueifd.datetime < dt(seedatetime.timedelta)d * cThe duration scaled by the factor
c, truncated to nanosecond precision See__mul__().d / cThe duration divided by
c, truncated to nanosecond precision. See__truediv__().d // nThe duration divided by an integer factor
n, truncated to nanosecond precision. See__floordiv__().In addition to
<and=, all other relational operations are supported and behave as you would expect. The type is hashable.
- __floordiv__(other)
Divide a duration by an integer or another
Timedelta.>>> td = Timedelta.from_s(10) // 3 >>> td.s 3.333333333 >>> td.precise_string '3333333333ns'
This divides the number of nanoseconds in this duration by factor using Floor Division, i.e. for some
n: intandtd: Timedeltawe have>>> assert (td // n).ns == td.ns // n
Division by another
Timedeltayields an integral result:>>> assert Timedelta.from_s(10) // Timedelta.from_s(3) == 3
Note
Floor Division produces surprising results for
floatarguments and is therefore not supported here (i.e.3 // 0.2 == 14.0). Use__truediv__()if you want to scale a duration by a non-integer factor.
- __str__()
A string containing the number of seconds of this duration
- Return type:
>>> "One day has {} seconds".format(Timedelta.from_string("1 day")) 'One day has 86400.0s seconds'
- __truediv__(other)
Divide a duration by a floating point or
Timedelta.>>> (Timedelta.from_s(10) / 2.5).precise_string '4s'
This divides the number of nanoseconds in this duration by factor using True Division, but truncates the result to an
int:>>> assert (td / x).ns == int(td.ns / x)
where
td: Timedeltaandx: float.Division by another
Timedeltainstead yields afloatresult.Note
Use
__floordiv__()if you know that the divisor is an integer, this will prevent rounding errors.
- staticmethod from_ms(milliseconds)
Create a duration from a number of milliseconds
- staticmethod from_s(seconds)
Create a duration from a number of seconds
- staticmethod from_string(duration_str)
Parse a human-readable string representation of a duration.
>>> "One day has {} seconds".format(Timedelta.from_string("1 day")) 'One day has 86400.0s seconds'
- Parameters:
- duration_str
str A duration string in the form of “<number> <unit>”. Accepted units are:
Name
short
long
Seconds
"s""second","seconds"Milliseconds
"ms""millisecond","milliseconds"Microseconds
"us""microsecond","microseconds"Nanoseconds
"ns""nanosecond","nanoseconds"Minutes
"min""minute","minutes"Hours
"h""hour","hours"Days
"d""day","days"
- duration_str
- Return type:
- Returns:
The parsed
Timedeltaobject- Raises:
ValueError – if the string is not of the correct format or an invalid unit was specified
- staticmethod from_timedelta(delta)
Convert from a standard
timedeltaobject.- Parameters:
- delta
timedelta a standard
datetime.timedeltaobject
- delta
- Return type:
- Returns:
A
Timedeltaobject
- staticmethod from_us(microseconds)
Create a duration from a number of microseconds
- property precise_string: str
An exact string representation of the duration preserving all nanosecond digits. If possible, a human-readable string is returned, e.g.
100ms. The result of this can be parsed byfrom_string()without losing precision.
- property timedelta: timedelta
This duration as a standard
datetime.timedeltaobject
Time-value pairs and aggregates
- class metricq.TimeValue(timestamp, value)
A timestamp-value pair.
Unpack it like so:
>>> tv = TimeValue(Timestamp.now(), 42.0) >>> (timestamp, value) = tv
- dict()
returns a dict representing the TimeValue instance. Keys are timestamp and value
Deprecated since version 5.0.0: Use the individual properties instead and select an appropriate timestamp type.
- class metricq.TimeAggregate(timestamp, minimum, maximum, sum, count, integral_ns, active_time)
Summary of a metric’s values within a certain period of time.
- staticmethod from_proto(timestamp, proto)
- Return type:
- staticmethod from_value(timestamp, value)
- Return type:
- staticmethod from_value_pair(timestamp_before, timestamp, value)
Create a TimeAggregate from a pair of timestamps (class:Timestamp) and one value
- Raises:
NonMonotonicTimestamps – if the two timestamps are not strictly monotonic
- Return type:
- property integral_s: float
Integral of values in this aggregate over its active time, seconds-based
- property mean: float
Mean value of this aggregate. This is the general way to access the mean value if nothing specific is known about the underlying raw data.
It may involve a heuristic to decide between
mean_integralandmean_sum. Currently, it defaults tomean_integral.
- property mean_integral: float
Mean value of this aggregate, calculated from the integral. Use this if you want to explicitly force this property.
In the HTA context, this should only be NaN if the aggregate interval is outside the of the interval from the earliest to the latest measurement point.
- property mean_sum: float
Mean value of this aggregate, calculated from the sum. This can be useful when the underlying metric should be at regular intervals, but there are gaps in the data. Otherwise,
mean_integralor justmeanare more appropriate.This value will be NaN if there are no raw data points in the aggregate interval.
Helper types
RPC handling
- @metricq.rpc_handler(*function_tags)
A Decorator to mark an
asyncmethod as an RPC handler- Parameters:
- function_tags
str The names of the RPCs that this method should handle
- function_tags
- Return type:
Callable[[Callable[...,Optional[Any]]],Callable[...,Optional[Any]]]
Example
from metricq import Source, rpc_handler class MySource(Source): ... @rpc_handler("config") async def on_config(self, **config): print(f"Received configuration: {config}") ...
Note
This only has an effect on methods of classes implementing MetricQ clients (see
Client), i.e.Sink,Source,IntervalSource,HistoryClient, etc.