Coder Social home page Coder Social logo

metrology's People

Contributors

arturdryomov avatar cyberdelia avatar damiendube avatar diyan avatar jacobian avatar misiek08 avatar quamilek avatar romcheg avatar steven-lai avatar zvin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

metrology's Issues

Non-existent network error handling in GraphiteReporter

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.

Counter, StatsD, per second count

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.

Missing @property annotation on example code in Gauge Instrument

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

creating Gauge causes TypeError

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

Meter.one_minute_rate is wrong and/or badly documented

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?

Ganglia reporter fails with meter

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()

Provide integration with WSGI or Flask

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):

  • Flask extension with functionality tied to Flask framework and some other Flask extensions that I'm using now
  • Generic WSGI middleware with very few meters/counters

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:

  • Only singletone process is supported now (multiple workers under Gunicorn/uWSGI/Circus will screw numbers)

Not sending to graphite/logger when running in docker

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!

Bug in graphite reporter => socket error

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

Timer clear

i use the tMetrology.timer('sss')
after i use timer.clear(), the timer.min=0 always, No change

TypeError when decrementing Counter

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.

Exception when timer measures for too long

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.

Decorators don't allow for return values

@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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.