cyberdelia / metrology Goto Github PK
View Code? Open in Web Editor NEWA library to easily measure what's going on in your python.
Home Page: https://metrology.readthedocs.org
License: MIT License
A library to easily measure what's going on in your python.
Home Page: https://metrology.readthedocs.org
License: MIT License
This results in carbon-cache
printing the following line to log:
[listener] invalid line received from client 127.0.0.1:50219, ignoring
When the remote end closes the connection (e.g. carbon-cache restarts), sendall()
throws SIGPIPE:
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib64/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/home/user/.local/lib64/python2.7/site-packages/metrology/utils/periodic.py", line 24, in run
self.task()
File "/home/user/.local/lib64/python2.7/site-packages/metrology/reporter/base.py", line 14, in task
self.write()
File "/home/user/.local/lib64/python2.7/site-packages/metrology/reporter/graphite.py", line 92, in write
self._send()
File "/home/user/.local/lib64/python2.7/site-packages/metrology/reporter/graphite.py", line 133, in _send_plaintext
self.socket.sendall(self.batch_buffer + "\n")
File "/usr/lib64/python2.7/socket.py", line 228, in meth
return getattr(self._sock,name)(*args)
error: [Errno 32] Broken pipe
ECONNREFUSED is thrown when the remote end isn't accepting connections yet:
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib64/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/home/user/.local/lib64/python2.7/site-packages/metrology/utils/periodic.py", line 24, in run
self.task()
File "/home/user/.local/lib64/python2.7/site-packages/metrology/reporter/base.py", line 14, in task
self.write()
File "/home/user/.local/lib64/python2.7/site-packages/metrology/reporter/graphite.py", line 92, in write
self._send()
File "/home/user/.local/lib64/python2.7/site-packages/metrology/reporter/graphite.py", line 133, in _send_plaintext
self.socket.sendall(self.batch_buffer + "\n")
File "/home/user/.local/lib64/python2.7/site-packages/metrology/reporter/graphite.py", line 48, in socket
self._socket.connect((self.host, self.port))
File "/usr/lib64/python2.7/socket.py", line 228, in meth
return getattr(self._sock,name)(*args)
error: [Errno 111] Connection refused
These exceptions cause periodic task (thread) to be terminated with no indication and/or connection retry attempts whatsoever.
I am struggling a bit with the counter. I am aware that I might not be expressing my thoughts as clearly as I thought, but I am trying to think through how I want metrology to work for me here.
I tend to want to have a per second rate in my stats backend for things. The problem with the counter is that it just keeps counting up. The meter is the same: It adds a moving average which is useful, but not the same thing, and the mean_rate, which just keeps going from the start point.
I suppose I want the behaviour I would be getting from a statsd counter. I send it the events, and statsd will calculate the per second rate, and send that to the backend. Basically, I need to call counter.clear()
after sending the current metrology counter value to the backend, to get a new mean_rate for the next flush interval. But that means I lose the total, and moving average values, too.
I had a look at how the metrology statsd reporter handles this, and my guess it is doing the wrong thing. It is just sending the current, continually incrementing value of the counter to statsd, whereas statsd would expect to receive the increment()
calls instead.
I kind of see metrology as a replacement for statsd. Rather than sending UDP to statsd, the metrics are in-process, and gets flushed to, say InfluxDB, once every couple of seconds. If a statsd counter gives me a per second rate for the last flush interval, how do I do this with metrology?
The best I can think of is using the Meter, and clearing it after every flush. If I want to send both the per-second rate for every flush, plus the moving average over the whole process, then I basically need to add a feature to Meter to only clear the counter, but keep the moving averages.
in Gauge class defined in metrology/instruments/gauge.py, the doc provides this example code:
class JobGauge(metrology.instruments.Gauge):
def value(self):
return len(queue)
This example doesn't work if use a Reporter like GraphicReporter that need "value" to be a property, we need to add the @Property annotation to make it work.
Please update the doc of this class with the following:
A gauge is an instantaneous measurement of a value ::
class JobGauge(metrology.instruments.Gauge):
@property
def value(self):
return len(queue)
gauge = Metrology.gauge('pending-jobs', JobGauge())
Thank you
Hello cyberdelia,
i'm having problems getting a gauge to work with librato reporter. Here's my dummy Code:
import time
from metrology import Metrology
from metrology import instruments
from metrology.reporter.librato import LibratoReporter
class JobGauge(instruments.Gauge):
def value(self):
return 10
if __name__ == "__main__":
gauge = Metrology.gauge('pending-jobs', JobGauge())
# Start Librato Reporter
reporter = LibratoReporter("foo", "bar")
reporter.start()
while True:
time.sleep(1)
I get the following exception:
Exception in thread Thread-1:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 551, in __bootstrap_inner
self.run()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/metrology/utils/periodic.py", line 24, in run
self.task()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/metrology/reporter/base.py", line 11, in task
self.write()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/metrology/reporter/librato.py", line 88, in write
data=dumps(metrics),
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 231, in dumps
return _default_encoder.encode(obj)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 201, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 264, in iterencode
return _iterencode(o, 0)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 178, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <bound method JobGauge.value of <__main__.JobGauge object at 0x101b8da90>> is not JSON serializable
seems to me that value() is not called and a method object is sent instead. Did I get the example wrong?
regards
hanso
The following code:
rate = Meter()
for i in range(int(65/0.05)):
rate.mark()
time.sleep(0.05)
print(rate.one_minute_rate)
print(rate.mean_rate)
yields:
12.744700289590714
19.916839105797937
Why does the one-minute moving average differs from the average over the first minute?
The following code causes the Ganglia reporter to crash with a TypeError. Metrology version is 0.9.0. Python ganglia version is 0.2.4 (latest).
from metrology import Metrology
from metrology.reporter.ganglia import GangliaReporter
meter = Metrology.meter('meter')
meter.mark()
reporter = GangliaReporter("Group Name", "localhost", 8649, "udp", interval=1)
reporter.start()
reporter.join()
Exception is:
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "/usr/local/lib/python2.7/dist-packages/metrology/utils/periodic.py", line 24, in run
self.task()
File "/usr/local/lib/python2.7/dist-packages/metrology/reporter/base.py", line 11, in task
self.write()
File "/usr/local/lib/python2.7/dist-packages/metrology/reporter/ganglia.py", line 38, in write
self.send(name, 'Count', metric.count, 'int32', 'count')
File "/usr/local/lib/python2.7/dist-packages/metrology/reporter/ganglia.py", line 56, in send
self.gmetric.send(name=name, value=value, type=kind, units=unit, group=group)
File "/usr/local/lib/python2.7/dist-packages/ganglia/ganglia.py", line 34, in send
meta, data = self.pack(kwargs)
File "/usr/local/lib/python2.7/dist-packages/ganglia/ganglia.py", line 94, in pack
data.pack_string(metric['value'])
File "/usr/lib/python2.7/xdrlib.py", line 92, in pack_string
n = len(s)
TypeError: object of type 'int' has no len()
Finish statsd reporter to send data.
Hello again,
I'm developing Flask extension that collects some metrics from the Flask app.
Flask extension that collects metrics using Metrology and push them to Graphite - https://gist.github.com/diyan/8829149
It's supposed to have some meaningful defaults which could be changes in app settings.
Right now code is alpha quality and works only for my use-cases but I've decided to share it on an early phase.
Would be glad to get any feedback on this (negative is fine).
Also I'm considering split this code into two pieses (but not entirely sure that it's a good idea):
This extension sends following metrics to Graphite:
metrology.<hostname>.<process_name>.flask.http_code_2xx.one_minute_rate
metrology.<hostname>.<process_name>.flask.http_code_3xx.one_minute_rate
metrology.<hostname>.<process_name>.flask.http_code_4xx.one_minute_rate
metrology.<hostname>.<process_name>.flask.http_code_5xx.one_minute_rate
metrology.<hostname>.<process_name>.flask.endpoins.<module_name>__<function_name>.one_minute_rate
metrology.<hostname>.<process_name>.flask.endpoins.<module_name>__<function_name>.percentile_95th
metrology.<hostname>.<process_name>.flask.endpoins.<module_name>__<function_name>.count
Known issues:
Add a TempoDB reporter : http://tempo-db.com/docs/api/
Finish librato reporter, because it doesn't send any data for now.
Thanks for an excellent looking implementation! coming from the Java world, I've been looking for one like this, but for some reason it isn't as visible as scales - though IMO your implementation is much clearer and clean.
I have a Flask app to which I added metrology integration, just added a few simple counters, just to test it out.
When running locally on my machine (using gunicorn and aiohttp worker), everything works just great, metrics get reported to the remote graphite (hosted-graphite), and local logger as well. But our application is deployed to production in a docker, so when I tried running this in our local testing env (using docker-compose), anything connected to metrics just doesn't seem to work anymore.
I connected to the docker and tested the connection using shell and python code, and the metrics came through, so I think it is not an issue with connectivity, but some other thing in the code.
Just for clarification, the code is run exactly the same way (same requirements.txt, same gunicorn and parameters).
No error messages are displayed in the log. Any idea as to how I might debug this?
Thank you!
Fix
@property
def socket(self):
if not hasattr(self, '_socket'):
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._socket.connect((self.host, self.port))
return self._socket
i use the tMetrology.timer('sss')
after i use timer.clear(), the timer.min=0 always, No change
I have a counter and try to decrement it, it raises a TypeError
File "<snip-snip>/lib/python2.7/site-packages/metrology/instruments/timer.py", line 40, in __exit__
self.update(duration)
File "<snip-snip>/lib/python2.7/site-packages/metrology/instruments/timer.py", line 27, in update
self.meter.mark()
File "<snip-snip>/lib/python2.7/site-packages/metrology/instruments/meter.py", line 12, in wrapper
self._tick()
File "<snip-snip>/lib/python2.7/site-packages/metrology/instruments/meter.py", line 41, in _tick
for _ in range(ticks):
exceptions.TypeError: range() integer end argument expected, got float.
Good day.
Sorry for my bad English.
I've installed metrology and next sample script fails:
#!/usr/bin/env python
#coding: utf-8
import time
import logging
from metrology import Metrology
timer = Metrology.timer('do_it_timer')
if __name__ == '__main__':
with timer:
time.sleep(15)
print timer.mean
With an exception:
Traceback (most recent call last):
File "metrology-sample.py", line 16, in <module>
time.sleep(15)
File "/home/vagrant/src/metrology-sample/venv/local/lib/python2.7/site-packages/metrology/instruments/timer.py", line 40, in __exit__
self.update(duration)
File "/home/vagrant/src/metrology-sample/venv/local/lib/python2.7/site-packages/metrology/instruments/timer.py", line 27, in update
self.meter.mark()
File "/home/vagrant/src/metrology-sample/venv/local/lib/python2.7/site-packages/metrology/instruments/meter.py", line 13, in wrapper
self._tick()
File "/home/vagrant/src/metrology-sample/venv/local/lib/python2.7/site-packages/metrology/instruments/meter.py", line 42, in _tick
if ticks and self.last_tick.compare_and_swap(old_tick, new_tick):
File "/home/vagrant/src/metrology-sample/venv/local/lib/python2.7/site-packages/atomic/__init__.py", line 89, in compare_and_swap
return self.compare_and_set(expect_value, new_value)
File "/home/vagrant/src/metrology-sample/venv/local/lib/python2.7/site-packages/atomic/__init__.py", line 86, in compare_and_set
return bool(atomic.long_compare_and_set(self._value, ffi.new('long *', expect_value), new_value))
TypeError: an integer is required
Is it ok?
BTW https://github.com/cyberdelia/metrology/blob/master/tests/instruments/test_timer.py#L18 will fail too if you'll increase sleep time.
@Metrology.timer('test')
def test():
return 'test'
print(test())
Expected output is test
but instead None
is printed.
I believe the relevant code in metrology.instruments.meter.Meter
:
def __call__(self, *args, **kwargs):
if args and hasattr(args[0], '__call__'):
_orig_func = args[0]
def _decorator(*args, **kwargs):
with self:
_orig_func(*args, **kwargs)
return _decorator
It should say return _orig_func(*args, **kwargs)
instead, maybe?
Using metrology 1.2.2
with Python 2.7.13
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.