Giter Site home page Giter Site logo

graphitesend's Introduction

graphitesend

Build Status Changelog Coverage Status

Easy python bindings to write to Carbon ( Re-write of carbonclient).

Warning

This project is no longer maintained. Lacking rights to publish new versions, a collaborator has forked the project and maintain it there: graphitesender

Read The Docs

graphitesend.rtfd.org

Blog posts

dansysadm.com

Example Scripts

The github repo of graphitesend-examples has lots of examples using graphitesend to grab data from your local linux system.

Installing

pip

$ pip install graphitesend

easy_install

$ easy_install graphitesend

or

source

$ git clone git://github.com/daniellawrence/graphitesend.git
$ cd graphitesend
$ python ./setup.py install

Usage Example

Very basic sending of a metric called metric with a value of 45

>>> import graphitesend
>>> graphitesend.init()
>>> graphitesend.send('metric', 45)
>>> graphitesend.send('metric2', 55)

The above would send the following metric to graphite

system.localhostname.metric 45 epoch-time-stamp
system.localhostname.metric2 55 epoch-time-stamp

Cleaning up the interface and using a group of cpu to alter the metric prefix

>>> import graphitesend
>>> g = graphitesend.init(group='cpu')
>>> g.send('metric', 45)
>>> g.send('metric2', 55)

The above would send the following metric to graphite

system.localhostname.cpu.metric 45 epoch-time-stamp
system.localhostname.cpu.metric2 55 epoch-time-stamp

Using a different prefix (other then system.hostname)

>>> import graphitesend
>>> g = graphitesend.init(prefix='apache.rc')
>>> g.send('404', 4)
>>> g.send('200', 500)

The above would send the following metric to graphite

apache.rc.localhostname.404 4 epoch-time-stamp
apache.rc.localhostname.200 500 epoch-time-stamp

To get rid of localhostname, set another argument โ€” system_name

>>> import graphitesend
>>> g = graphitesend.init(prefix='apache.rc', system_name='')
>>> g.send('404', 4)
>>> g.send('200', 500)

The above would send the following metric to graphite

apache.rc.404 4 epoch-time-stamp
apache.rc.200 500 epoch-time-stamp

Sending a dict()

    >>> import graphitesend
    >>> g = graphitesend.init()
    >>> g.send_dict({'metric': 45, 'metric2': 55})

Sending a list()

    >>> import graphitesend
    >>> g = graphitesend.init()
    >>> g.send_list([('metric', 45), ('metric2', 55)])

Sending a list(), with a custom timestamp for all metric-value pairs

    >>> import graphitesend
    >>> g = graphitesend.init()
    >>> g.send_list([('metric', 45), ('metric2', 55)], timestamp=12345)

Sending a list(), with a custom timestamp for each metric-value pairs

    >>> import graphitesend
    >>> g = graphitesend.init()
    >>> g.send_list([('metric', 45, 1234), ('metric2', 55, 1234)])

Learning? Use dryrun.

With dryrun enabled the data will never get sent to a remote service, it will just print out what would have been sent.

    >>> import graphitesend
    >>> g = graphitesend.init(dryrun=True)
    >>> g.send_list([('metric', 45, 1234), ('metric2', 55, 1234)])

Example: the init()

Set a metric prefix (Default arg)

>>> g = graphitesend.init('prefix')
>>> print g.send('metric', 1)
sent 34 long message: prefix.metric 1.000000 1365068929

set a metric prefix using kwargs

>>> g = graphitesend.init(prefix='prefix')
>>> print g.send('metric', 2)
sent 34 long message: prefix.metric 2.000000 1365068929

Squash any dots in the hostname

>>> g = graphitesend.init(fqdn_squash=True)
>>> print g.send('metric', 3)
sent 56 long message: systems.host_example_com.metric 2.00000 1365069029

view the default prefix, hardset systems. then followed by the name of the host that execute the send().

>>> g = graphitesend.init()
>>> print g.send('metric', 3)
sent 44 long message: systems.<system_name>.metric 3.000000 1365069029

Set a suffix, handy if you have a bunch of timers or percentages

>>> g = graphitesend.init(suffix='_ms')
>>> print g.send('metric', 4)
sent 47 long message: systems.<system_name>.metric_ms 4.000000 1365069100

set a system_name if your submitting results for a different system

>>> g = graphitesend.init(system_name='othersystem')
>>> print g.send('metric', 5)
sent 47 long message: systems.othersystem.metric 5.000000 1365069100

Lowercase all the metric names that are send to the graphite server.

>>> g = graphitesend.init(lowercase_metric_names=True)
>>> print g.send('METRIC', 6)
sent 47 long message: systems.<hostname>.metric 6.000000 1365069100

Set a group name, handy if you just parsed iostat and want to prefix all the metrics with iostat, after its already in the <system_name> directory.

>>> g = graphitesend.init(group='groupname')
>>> print g.send('metric', 6)
sent 54 long message: systems.<system_name>.groupname.metric 6.000000 136506924

Connect to a different graphite server

>>> graphitesend.init(graphite_server='graphite.example.com')

Connect to a different graphite server port

>>> graphitesend.init(graphite_port=2003)

Send async messages

>>> graphitesend.init(asynchronous=True)

Change connect timeout (default 2)

>>> graphitesend.init(timeout_in_seconds=5)

CLI

Just added -- A cli script that allows for anything to send metrics over to graphite (not just python).

The usage is very simple you need to give the command a metric and a value.

	$ graphitesend name.of.the.metric 666

Send more* then 1 metric and value

	$ graphitesend name.of.the.metric 666
	$ graphitesend name.of.the.other_metric 2

* Call it 2 times ;)

Porcelain Overview

init

Create the module instance of GraphiteSend.

send

Make sure that we have an instance of the GraphiteClient. Then send the metrics to the graphite server.

send_dict

Make sure that we have an instance of the GraphiteClient. Then send the metrics to the graphite server.

reset

Disconnect from the graphite server and destroy the module instance.

TCP vs UDP

There is a new branch for UDP support called 'udp and tcp'. TCP will continue to be the default with UDP as an option

graphitesend's People

Contributors

complexsplit avatar daniellawrence avatar dwagon avatar e4r7hbug avatar jemmix avatar krislion avatar kubauk avatar saviour123 avatar sergw avatar shir0kamii avatar svetlyak40wt avatar z1nkum 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  avatar

graphitesend's Issues

send_list() appears to only send the first item

Hi,
I am little confused about the way that send_list() works. I am sending a data structure:

[(u'qa.ENV.tppqv1b206.agent.ping', 1.0, 1406298550), (u'qa.ENV.tppqv1b206.kernel.maxfiles', 610162.0, 1406295732), (u'qa.ENV.tppqv1b206.kernel.maxproc', 32768.0, 1406295733), (u'qa.ENV.tppqv1b206.proc.num.run', 3.0, 1406298557), (u'qa.ENV.tppqv1b206.proc.num.', 105.0, 1406298558),
..........]

My data is not showing up on the graphite server as I expect so I did some digging around in graphitesend.py. In the method:
195 def _send(self, message):

I printed out the message that gets passed in and I see this:
1 zabbix_test.qa.ENV.tppqv1b206.agent.ping 1.000000 1406298370
2 zabbix_test.qa.ENV.tppqv1b206.kernel.maxfiles 610162.000000 1406295732
3 zabbix_test.qa.ENV.tppqv1b206.kernel.maxproc 32768.000000 1406295733
4 zabbix_test.qa.ENV.tppqv1b206.proc.num.run 1.000000 1406298377
5 zabbix_test.qa.ENV.tppqv1b206.proc.num. 105.000000 1406298378
6 zabbix_test.qa.ENV.tppqv1b206.system.boottime 1375992896.000000 1406298139
7 zabbix_test.qa.ENV.tppqv1b206.system.cpu.intr 1041.000000 1406298380
8 zabbix_test.qa.ENV.tppqv1b206.system.cpu.load.percpuavg15 0.570000 1406298381

Lastly I printed out the return from:
print self.graphite.send_list(self.metrics)

From which I see:
320 sent 26525 long message: zabbix_test.qa.ENV.tppqv1b206.agent.ping 1.000000 1406298370
321 zabbix_test.qa

It looks like one message and then a partial of the next.

So I am not sure if all my metrics are actually getting sent. It might not be graphitesend, but I'd like to rule it out.

Thanks.

cleanup_metric_name does not handle integers for metric names

For instance, if you want to store and graph values for all your customers using their customer ID, you might write code like this:

sender.init(prefix='customers', postfix='.value')
for customer in customer:
    sender.send(customer.pkey, get_customer_value(customer))

This looks OK code wise, but since pkey is actually from a database and is represented as an int, you get an error:

graphitesend.py", line 217, in clean_metric_name
    metric_name = metric_name.replace('(', '_').replace(')', '')
AttributeError: 'int' object has no attribute 'replace'

I can (and have) stuck in a str() to do the right thing for now, but depending on what your opinion is on doing things to make users' code cleaner, perhaps handling this in the library would be a good idea?

Custom timestamp for every value

Feature request: specify timestamp for each value in send_dict() and send_list()
Then data in send_list will be three-tuple:
(metric, value, timestamp)

Allow "-" (Dash) in Metric Names

Thanks for a great little project. We've been using it happily for some time, but it turns out that the metric "cleaning" is getting in our way.

For example, why remove dashes from metric names? Unlike, say, slashes or parens, I can't see why they'd pose a problem. (In fact, in our case, removing them is causing us much grief.)

https://github.com/daniellawrence/graphitesend/blob/master/graphitesend/graphitesend.py#L176

Can we relax the metric name cleaning rules, or make it more user-configurable, or remove them all together?

I'm happy to help code this; just let me know. Thanks!

send_list fails with encoding error on python3

Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/graphitesend/graphitesend.py", line 303, in _send_and_reconnect
    self.socket.sendall(message.encode("ascii"))
AttributeError: 'bytes' object has no attribute 'encode'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/graphitesend/graphitesend.py", line 260, in _dispatch_send
    sending_function(message.encode("ascii"))
  File "/usr/local/lib/python3.5/dist-packages/graphitesend/graphitesend.py", line 308, in _send_and_reconnect
    self.socket.sendall(message.encode("ascii"))
AttributeError: 'bytes' object has no attribute 'encode'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/zerorpc/core.py", line 153, in _async_task
    functor.pattern.process_call(self._context, bufchan, event, functor)
  File "/usr/local/lib/python3.5/dist-packages/zerorpc/patterns.py", line 30, in process_call
    result = functor(*req_event.args)
  File "/usr/local/lib/python3.5/dist-packages/zerorpc/decorators.py", line 44, in __call__
    return self._functor(*args, **kargs)
  File "/media/Storage/Scripts/ReadableWebProxy/FetchAgent/server.py", line 103, in putJob
    self._put_metric("Fetch.Get.{}.count".format(queuename), 1)
  File "/media/Storage/Scripts/ReadableWebProxy/FetchAgent/server.py", line 89, in _put_metric
    self.mon_con.send_list(tosend)
  File "/usr/local/lib/python3.5/dist-packages/graphitesend/graphitesend.py", line 445, in send_list
    return self._dispatch_send(message)
  File "/usr/local/lib/python3.5/dist-packages/graphitesend/graphitesend.py", line 262, in _dispatch_send
    self._handle_send_error(e)
  File "/usr/local/lib/python3.5/dist-packages/graphitesend/graphitesend.py", line 283, in _handle_send_error
    (self.addr, error)
graphitesend.graphitesend.GraphiteSendException: Unknown error while trying to send data down socket to ('10.1.1.56', 2003), error: 'bytes' object has no attribute 'encode'

This is with a GraphitePickleClient() instance.

Instantiation:

		self.mon_con = graphitesend.GraphitePickleClient(
				autoreconnect   = True,
				group           = None,
				prefix          = 'ReadableWebProxy.FetchAgent',
				system_name     = '',
				graphite_server = settings.GRAPHITE_DB_IP,
				graphite_port   = 2003,
				debug           = True,
				clean_metric_name = True,
			)

remove print statements

print statements should be replaced with log statements to enable setting log level to hide or show them

import logging
log = logging.getLogger(name)
log.info('message')

Dry Run

dryrun does not appear to be printing as shown in the examples or I'm doing something wrong.

 16     self.graphite = GraphiteClient(
 17       graphite_server = self.conf.get('Graphite', 'host'),
 18       graphite_port = int(self.conf.get('Graphite', 'port')),
 19       prefix = self.conf.get('Graphite', 'prefix'),
 20       system_name = '',
 21       dryrun = True
 22     )

.....
41 self.graphite.send(m[0], m[1], m[2])

No output at all. Did I miss something?

Thanks.

Importing library breaks any synchronous connection

Not sure why, but probably related to #43. I'm on 0.7.0

See these sequence of commands:

In [1]: import requests; requests.get('https://google.com')
Out[1]: <Response [200]>

In [2]: import graphitesend

In [3]: import requests; requests.get('https://google.com')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/Users/leonsas/Projects/Hypnos/hypnos/sleep_plan/plan_review.pyc in <module>()
----> 1 import requests; requests.get('https://google.com')

/usr/local/lib/python2.7/site-packages/requests/api.pyc in get(url, **kwargs)
     63
     64     kwargs.setdefault('allow_redirects', True)
---> 65     return request('get', url, **kwargs)
     66
     67

/usr/local/lib/python2.7/site-packages/requests/api.pyc in request(method, url, **kwargs)
     47
     48     session = sessions.Session()
---> 49     response = session.request(method=method, url=url, **kwargs)
     50     # By explicitly closing the session, we avoid leaving sockets open which
     51     # can trigger a ResourceWarning in some cases, and look like a memory leak

/usr/local/lib/python2.7/site-packages/opbeat/instrumentation/packages/base.pyc in __call__(self, *args, **kwargs)
     61                                       self._self_method,
     62                                       self.__wrapped__, self._self_instance,
---> 63                                       args, kwargs)
     64
     65         else:

/usr/local/lib/python2.7/site-packages/opbeat/instrumentation/packages/base.pyc in call_if_sampling(self, module, method, wrapped, instance, args, kwargs)
    218     def call_if_sampling(self, module, method, wrapped, instance, args, kwargs):
    219         if not get_transaction():
--> 220             return wrapped(*args, **kwargs)
    221         else:
    222             return self.call(module, method, wrapped, instance, args, kwargs)

/usr/local/lib/python2.7/site-packages/requests/sessions.pyc in request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)
    459         }
    460         send_kwargs.update(settings)
--> 461         resp = self.send(prep, **send_kwargs)
    462
    463         return resp

/usr/local/lib/python2.7/site-packages/requests/sessions.pyc in send(self, request, **kwargs)
    571
    572         # Send the request
--> 573         r = adapter.send(request, **kwargs)
    574
    575         # Total elapsed time of the request (approximately)

/usr/local/lib/python2.7/site-packages/requests/adapters.pyc in send(self, request, stream, timeout, verify, cert, proxies)
    368                     decode_content=False,
    369                     retries=self.max_retries,
--> 370                     timeout=timeout
    371                 )
    372

/usr/local/lib/python2.7/site-packages/requests/packages/urllib3/connectionpool.pyc in urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, **response_kw)
    516             httplib_response = self._make_request(conn, method, url,
    517                                                   timeout=timeout,
--> 518                                                   body=body, headers=headers)
    519
    520             # If we're going to release the connection in ``finally:``, then

/usr/local/lib/python2.7/site-packages/requests/packages/urllib3/connectionpool.pyc in _make_request(self, conn, method, url, timeout, **httplib_request_kw)
    320         # Trigger any extra validation we need to do.
    321         try:
--> 322             self._validate_conn(conn)
    323         except (SocketTimeout, BaseSSLError) as e:
    324             # Py2 raises this as a BaseSSLError, Py3 raises it as socket timeout.

/usr/local/lib/python2.7/site-packages/requests/packages/urllib3/connectionpool.pyc in _validate_conn(self, conn)
    725         # Force connect early to allow us to validate the connection.
    726         if not getattr(conn, 'sock', None):  # AppEngine might not have  `.sock`
--> 727             conn.connect()
    728
    729         if not conn.is_verified:

/usr/local/lib/python2.7/site-packages/requests/packages/urllib3/connection.pyc in connect(self)
    236                                     ca_certs=self.ca_certs,
    237                                     server_hostname=hostname,
--> 238                                     ssl_version=resolved_ssl_version)
    239
    240         if self.assert_fingerprint:

/usr/local/lib/python2.7/site-packages/requests/packages/urllib3/util/ssl_.pyc in ssl_wrap_socket(sock, keyfile, certfile, cert_reqs, ca_certs, server_hostname, ssl_version, ciphers, ssl_context)
    251         context.load_cert_chain(certfile, keyfile)
    252     if HAS_SNI:  # Platform-specific: OpenSSL with enabled SNI
--> 253         return context.wrap_socket(sock, server_hostname=server_hostname)
    254     return context.wrap_socket(sock)

/usr/local/Cellar/python/2.7.12/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.pyc in wrap_socket(self, sock, server_side, do_handshake_on_connect, suppress_ragged_eofs, server_hostname)
    351                          suppress_ragged_eofs=suppress_ragged_eofs,
    352                          server_hostname=server_hostname,
--> 353                          _context=self)
    354
    355     def set_npn_protocols(self, npn_protocols):

/usr/local/Cellar/python/2.7.12/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.pyc in __init__(self, sock, keyfile, certfile, server_side, cert_reqs, ssl_version, ca_certs, do_handshake_on_connect, family, type, proto, fileno, suppress_ragged_eofs, npn_protocols, ciphers, server_hostname, _context)
    598                     if timeout == 0.0:
    599                         # non-blocking
--> 600                         raise ValueError("do_handshake_on_connect should not be specified for non-blocking sockets")
    601                     self.do_handshake()
    602

ValueError: do_handshake_on_connect should not be specified for non-blocking sockets

In [4]:

Multiple instances of graphitesend objects do not create sockets properly

Python Version:
Python 3.6.4 (default, Mar 14 2018, 14:54:19)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin

GraphiteSend version:
0.10.0

When attempting to instantiate 2 graphitesend objects, only the 2nd graphitesend instance is usable, the 1st becomes broken by creating the second, and when attempting to send data with emitter #1, the below error is raised:

...
  File "/---/py3venv/lib/python3.6/site-packages/graphitesend/graphitesend.py", line 423, in send_list
    return self._dispatch_send(message)
  File "/---/python_venv/py3venv/lib/python3.6/site-packages/graphitesend/graphitesend.py", line 248, in _dispatch_send
    "Socket was not created before send"
graphitesend.graphitesend.GraphiteSendException: Socket was not created before send

As hostname / prefix etc. are fixated on init -- we need to create 2 objects to post data to two differently structured trees, thus we need two graphitesend objects.

asynchronous send caused memory leak

Hello,

I'm load testing a simple 'hello world' API using locust.

It seems that using graphitesend in an asynchronous mode while stressing the API (500 users requesting the same endpoint, ~35 requests per secs), create memory leaks.

Memory leak appears after this error:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/gevent/_socket3.py", line 439, in send
    return _socket.socket.send(self._sock, data, flags)
BlockingIOError: [Errno 11] Resource temporarily unavailable

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "src/gevent/greenlet.py", line 716, in gevent._greenlet.Greenlet.run
  File "/usr/local/lib/python3.6/site-packages/graphitesend/graphitesend.py", line 307, in _send_and_reconnect
    self.socket.sendall(message.encode("ascii"))
  File "/usr/local/lib/python3.6/site-packages/gevent/_socket3.py", line 458, in sendall
    return _socketcommon._sendall(self, data_memory, flags)
  File "/usr/local/lib/python3.6/site-packages/gevent/_socketcommon.py", line 355, in _sendall
    timeleft = __send_chunk(socket, chunk, flags, timeleft, end)
  File "/usr/local/lib/python3.6/site-packages/gevent/_socketcommon.py", line 295, in __send_chunk
    data_sent += socket.send(chunk, flags, timeout=timeleft)
  File "/usr/local/lib/python3.6/site-packages/gevent/_socket3.py", line 443, in send
    self._wait(self._write_event)
  File "src/gevent/_hub_primitives.py", line 265, in gevent.__hub_primitives.wait_on_socket
  File "src/gevent/_hub_primitives.py", line 266, in gevent.__hub_primitives.wait_on_socket
  File "src/gevent/_hub_primitives.py", line 245, in gevent.__hub_primitives._primitive_wait
gevent.exceptions.ConcurrentObjectUseError: This socket is already used by another greenlet: <bound method Waiter.switch of <gevent.__waiter.Waiter object at 0x7f8b1bc67e58>>
2018-11-26T15:44:31Z <Greenlet "Greenlet-0" at 0x7f8b1bc28c48: <bound method GraphiteClient._send_and_reconnect of <graphitesend.graphitesend.GraphiteClient object at 0x7f8b181153c8>> failed with ConcurrentObjectUseError

Using graphitesend without asynchronous mode doesn't create any memory leak.

Code ex:

from flask import Flask
from graphite import GraphiteClient

# we need to patch sockets to make requests async
from gevent import monkey
monkey.patch_all()

app = Flask(__name__)

try:
    config = {
        'graphite_server': '<GRAPHITE_SERV_NAME>',
        'graphite_port': <GRAPHITE_PORT>,
        'prefix': 'graphite',
        'asynchronous': True,
        'autoreconnect': True,
        'dryrun': False
    }
    graphite = GraphiteClient(**config)
    print('Graphite client has been initialized.')
except:
    print('Cannot initialize Graphite client.')


@app.route("/")
def hello():
    tmp = ['test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test']
    print(tmp)
    graphite.send('metric1', 2)
    return "Hello World!"


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8083)

The API is running using uWSGI (2.0.17.1), graphitesend (0.10.0), gevent (1.2.1) Flask (0.12) and python 3.6.4

import syntax problem

Greetings,

In both python 2.6.6 on a centos 6 box and in Portal Python 2.7.6 on a Windows computer, I need to do:

from graphitesend import graphitesend
gs = graphitesend.init()
gs.send("foo", 5)

in order for graphitesend to work. If I just do an import, as per your documentation, I get the following:

import graphitesend
gs = graphitesend.init()
gs.send("foo", 5)

results in:

$ python t.py 
Traceback (most recent call last):
  File "t.py", line 2, in <module>
    gs = graphitesend.init()
AttributeError: 'module' object has no attribute 'init'

New release?

Are there any plans to have a new release (maybe 0.7.1) that includes the latest python3 fixes?

Thanks.

Please make string escaping optional (i.e. clean_metric_name() should be optional)

Thank you for the good work on graphitesend!

I have a small project which sends stats to graphite via send_list(stats_list), where stats_list is a list of tuples. The problem is that I'm trying to replace an existing collectd Write_Graphite plugin, and that plugin escapes stats slightly differently than graphitesend does.

Of course, I could always just open a tcp socket and dump into graphite, but I'm hoping to use graphitesend instead.

I'd like a configurable auto_escape option, like this...

    gs = graphitesend.init(graphite_server=self.server,
        graphite_port=self.port,
        prefix=self.prefix,
        system_name=self.host.name,
        group='snmp',
        auto_escape=False)
      #^^^^^^^^^^^^^^^^^^^^^^^^^

The default for auto_escape should be True for backwards compatibility. If auto_escape is False, clean_metric_name() should never be called on metrics. That leaves me responsible for escaping characters, which is just fine by me.

I can submit a PR if you like.

ValueError: zero length field name in format

I am getting below valueerror anyone else has similar error

Traceback (most recent call last):
File "/usr/bin/graphitesend", line 9, in
load_entry_point('graphitesend==0.6.0', 'console_scripts', 'graphitesend')()
File "/usr/lib/python2.6/site-packages/graphitesend/graphitesend.py", line 609, in cli
graphitesend_instance.send(metric, value)
File "/usr/lib/python2.6/site-packages/graphitesend/graphitesend.py", line 346, in send
return self._dispatch_send(message)
File "/usr/lib/python2.6/site-packages/graphitesend/graphitesend.py", line 259, in _dispatch_send
len(message), message)
ValueError: zero length field name in format

AttributeError: 'module' object has no attribute 'init'

Trying to use this module on Windows with Python 3.4 and CentOS with Python 3.3:

Python 3.3.3 (default, Mar 9 2016, 14:47:56)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-11)] on linux
Type "help", "copyright", "credits" or "license" for more information.

import graphitesend as gr
g = gr.init()
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'module' object has no attribute 'init'

Module's dictionary:

print(gr.dict)
{'doc': None, 'cached': '/usr/local/lib/python3.3/site-packages/graphitesend/pycache/init.cpython-33.pyc', 'loader': <_frozen_importlib.SourceFileLoader object at 0x7fb398ce5550>, 'path': ['/usr/local/lib/python3.3/site-packages/graphitesend'], 'file': '/usr/local/lib/python3.3/site-packages/graphitesend/init.py', 'name': 'graphitesend', 'builtins': {'exec': , 'MemoryError': <class 'MemoryError'>, 'id': , 'callable': , 'RuntimeWarning': <class 'RuntimeWarning'>, 'PermissionError': <class 'PermissionError'>, 'ConnectionAbortedError': <class 'ConnectionAbortedError'>, 'Warning': <class 'Warning'>, 'ZeroDivisionError': <class 'ZeroDivisionError'>, 'hasattr': , 'copyright': Copyright (c) 2001-2013 Python Software Foundation.
All Rights Reserved.

Copyright (c) 2000 BeOpen.com.
All Rights Reserved.

Copyright (c) 1995-2001 Corporation for National Research Initiatives.
All Rights Reserved.

Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam.
All Rights Reserved., 'int': <class 'int'>, 'ord': , 'slice': <class 'slice'>, 'dict': <class 'dict'>, 'SystemError': <class 'SystemError'>, 'min': , 'TypeError': <class 'TypeError'>, 'AttributeError': <class 'AttributeError'>, 'SyntaxError': <class 'SyntaxError'>, 'BrokenPipeError': <class 'BrokenPipeError'>, 'bytearray': <class 'bytearray'>, 'IOError': <class 'OSError'>, 'ConnectionRefusedError': <class 'ConnectionRefusedError'>, 'name': 'builtins', 'exit': Use exit() or Ctrl-D (i.e. EOF) to exit, 'complex': <class 'complex'>, 'UnicodeTranslateError': <class 'UnicodeTranslateError'>, 'super': <class 'super'>, 'NotADirectoryError': <class 'NotADirectoryError'>, 'locals': , 'help': Type help() for interactive help, or help(object) for help about object., 'next': , 'all': , 'SyntaxWarning': <class 'SyntaxWarning'>, 'hex': , 'enumerate': <class 'enumerate'>, 'license': Type license() to see the full license text, 'classmethod': <class 'classmethod'>, 'NotImplemented': NotImplemented, 'import': , 'zip': <class 'zip'>, 'input': , 'BytesWarning': <class 'BytesWarning'>, 'TimeoutError': <class 'TimeoutError'>, 'delattr': , 'KeyError': <class 'KeyError'>, 'UnboundLocalError': <class 'UnboundLocalError'>, 'bytes': <class 'bytes'>, 'ProcessLookupError': <class 'ProcessLookupError'>, 'doc': "Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is the nil' object; Ellipsis represents...' in slices.", 'build_class': , 'KeyboardInterrupt': <class 'KeyboardInterrupt'>, 'NameError': <class 'NameError'>, 'property': <class 'property'>, 'memoryview': <class 'memoryview'>, 'len': , 'FutureWarning': <class 'FutureWarning'>, 'EOFError': <class 'EOFError'>, 'chr': , 'debug': True, 'BufferError': <class 'BufferError'>, 'ConnectionResetError': <class 'ConnectionResetError'>, 'frozenset': <class 'frozenset'>, 'sum': , 'pow': , 'compile': , 'FloatingPointError': <class 'FloatingPointError'>, 'False': False, 'SystemExit': <class 'SystemExit'>, 'PendingDeprecationWarning': <class 'PendingDeprecationWarning'>, 'package': None, 'RuntimeError': <class 'RuntimeError'>, 'ascii': , 'object': <class 'object'>, 'UnicodeError': <class 'UnicodeError'>, 'ImportError': <class 'ImportError'>, 'format': , 'quit': Use quit() or Ctrl-D (i.e. EOF) to exit, 'loader': <class '_frozen_importlib.BuiltinImporter'>, 'dir': , 'ArithmeticError': <class 'ArithmeticError'>, 'bin': , 'float': <class 'float'>, 'BlockingIOError': <class 'BlockingIOError'>, 'ChildProcessError': <class 'ChildProcessError'>, 'tuple': <class 'tuple'>, 'TabError': <class 'TabError'>, 'list': <class 'list'>, 'isinstance': , 'IsADirectoryError': <class 'IsADirectoryError'>, 'staticmethod': <class 'staticmethod'>, 'AssertionError': <class 'AssertionError'>, 'IndentationError': <class 'IndentationError'>, 'IndexError': <class 'IndexError'>, 'UnicodeDecodeError': <class 'UnicodeDecodeError'>, 'FileNotFoundError': <class 'FileNotFoundError'>, 'ConnectionError': <class 'ConnectionError'>, 'True': True, 'hash': , 'print': , 'range': <class 'range'>, 'ResourceWarning': <class 'ResourceWarning'>, 'EnvironmentError': <class 'OSError'>, 'DeprecationWarning': <class 'DeprecationWarning'>, 'oct': , 'getattr': , 'globals': , 'setattr': , 'UnicodeWarning': <class 'UnicodeWarning'>, 'filter': <class 'filter'>, 'reversed': <class 'reversed'>, 'sorted': , 'UserWarning': <class 'UserWarning'>, 'InterruptedError': <class 'InterruptedError'>, 'open': , 'FileExistsError': <class 'FileExistsError'>, 'any': , 'bool': <class 'bool'>, 'ReferenceError': <class 'ReferenceError'>, 'map': <class 'map'>, 'BaseException': <class 'BaseException'>, 'NotImplementedError': <class 'NotImplementedError'>, 'repr': , 'OverflowError': <class 'OverflowError'>, 'vars': , 'max': , 'ImportWarning': <class 'ImportWarning'>, 'LookupError': <class 'LookupError'>, 'round': , 'type': <class 'type'>, 'Exception': <class 'Exception'>, 'Ellipsis': Ellipsis, 'str': <class 'str'>, 'GeneratorExit': <class 'GeneratorExit'>, 'StopIteration': <class 'StopIteration'>, 'None': None, 'ValueError': <class 'ValueError'>, 'abs': , 'eval': , 'divmod': , 'set': <class 'set'>, 'credits': Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
for supporting Python development. See www.python.org for more information., 'UnicodeEncodeError': <class 'UnicodeEncodeError'>, 'OSError': <class 'OSError'>, 'iter': , 'issubclass': }, 'package': 'graphitesend', 'initializing': False}

No print on dryrun

Related to #14 .

Apparently the docs were not updated four years ago?

Although this issue is aged I second the latter comment. It is confusing when the docs say that stuff is printed on a dry run where it is not.

GraphiteSendException: Socket closed before able to send data to ('x.x.x.x', 2003), with error: [Errno 32] Broken pipe

Hey Guys,

I'm getting a lot of exceptions at random..

The graphite listener is on the same server so network issues seem unlikely. Any idea where i should start to look?

  File "./travel/services/payments.py", line 59, in charge
    m_client.send('latency', time_taken)
  File "/usr/local/lib/python2.7/dist-packages/graphitesend/graphitesend.py", line 360, in send
    return self._dispatch_send(message)
  File "/usr/local/lib/python2.7/dist-packages/graphitesend/graphitesend.py", line 262, in _dispatch_send
    self._handle_send_error(e)
  File "/usr/local/lib/python2.7/dist-packages/graphitesend/graphitesend.py", line 276, in _handle_send_error
    (self.addr, error)

graphitesend 0.5.0 is not on Pypi

Hi,

I saw you bumped a version to release recent features, but it seems you didn't upload the new version to Pypi. Could you please do it so that everyone can use graphitesend in its latest version ?

Thank you for your work

how to send as pickle format?

I am trying to figure out how to send as pickle, I don't see anything in the documentation, but seems like it is supported looking over the source code. I tried a couple ways:

g = graphitesend.init(init_type='pickle')
g.send_list([('metric', 45), ('metric2', 55)])

Result: sends to port 2003 (not 2004) as large packets containing multiple metrics. Suppose metrics are separated by newlines. I see the metrics in Graphite.

g = graphitesend.init(init_type='pickle', graphite_port=2004)
g.send_list([('metric', 45), ('metric2', 55)])

Result: sends to port 2004 but not as pickle format? I do not see the metrics in Graphite.

How do you specify you want to send metrics using the pickle format?

pickle_tcp/pickle not functional

I think you want to use GraphitePickleClient here:

    if init_type in ['pickle_tcp', 'pickle']:
        _module_instance = GraphiteClient(*args, **kwargs)

windows python 3.x issues

Here are some issues on windows

D:\python\Scripts>python
Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:43:06) [MSC v.1600 32 bit (In
tel)] on win32
Type "help", "copyright", "credits" or "license" for more information.

import graphitesend
graphitesend.init()
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'module' object has no attribute 'init'

D:\python>graphitesend test2 44
Traceback (most recent call last):
File "D:\python\lib\site-packages\graphitesend\graphitesend.py", line 260, in
_dispatch_send
sending_function(message.encode("ascii"))
File "D:\python\lib\site-packages\graphitesend\graphitesend.py", line 291, in
_send
self.socket.sendall(message.encode("ascii"))
AttributeError: 'bytes' object has no attribute 'encode'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "D:\python\Scripts\graphitesend-script.py", line 9, in
load_entry_point('graphitesend==0.7.0', 'console_scripts', 'graphitesend')()

File "D:\python\lib\site-packages\graphitesend\graphitesend.py", line 623, in
cli
graphitesend_instance.send(metric, value)
File "D:\python\lib\site-packages\graphitesend\graphitesend.py", line 360, in
send
return self._dispatch_send(message)
File "D:\python\lib\site-packages\graphitesend\graphitesend.py", line 262, in
_dispatch_send
self._handle_send_error(e)
File "D:\python\lib\site-packages\graphitesend\graphitesend.py", line 283, in
_handle_send_error
(self.addr, error)
graphitesend.graphitesend.GraphiteSendException: Unknown error while trying to s
end data down socket to ('ai-graphiteprd1', 2003), error: 'bytes' object has no

attribute 'encode'

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.