statsdecor


Namestatsdecor JSON
Version 0.4.2 PyPI version JSON
download
home_pagehttps://github.com/amcintosh/statsdecor
SummaryA set of decorators and helper methods for adding statsd metrics to applications.
upload_time2024-12-10 17:09:36
maintainerAndrew McIntosh
docs_urlNone
authorFreshbooks Dev Team
requires_pythonNone
licenseMIT
keywords statsd stats
VCS
bugtrack_url
requirements statsd datadog
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Statsdecor

[![PyPI](https://img.shields.io/pypi/v/statsdecor)](https://pypi.org/project/statsdecor/)
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/statsdecor)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.txt)
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/amcintosh/statsdecor/run-tests.yml?branch=main)](https://github.com/amcintosh/statsdecor/actions?query=workflow%3A%22Run+Tests%22)

A set of decorators and helper methods for adding statsd metrics to applications.

## Installation

You can use pip to install statsdecor:

```shell
pip install statsdecor
```

## Configuration

You must use `statsdecor.configure` to configure the internal statsd client before
calling other methods:

```python
import statsdecor

statsdecor.configure(host='localhost', prefix='superapp.')
```

Configuration is generally setup during your application's bootstrap. Once
set configuration values are re-used in all clients that `statsdecor` creates.

By default Statsdecor uses the [statsd](https://pypi.org/project/statsd/) client library,
however it can be configured to use the [datadog](https://pypi.org/project/datadog/) client:

```python
import statsdecor

statsdecor.configure(host='localhost', prefix='superapp.', vendor='datadog')
```

The datadog client supports [tagging metrics](https://statsd.readthedocs.io/en/stable/tags.html) (see Usage).

## Usage

You can track metrics with either the module functions, or decorators. Incrementing
and decrementing counters looks like:

### Metric functions

```python
import statsdecor

statsdecor.incr('save.succeeded')
statsdecor.decr('attempts.remaining')
statsdecor.gauge('sessions.active', 9001)
```

When using the datadog client, Statsdecor supports tagging metrics:

```python
statsdecor.incr('save.succeeded', tags=['DogStatsd_does_tags'])
```

Counters and timers can also be set through decorators:

```python
import statsdecor.decorators as stats

@stats.increment('save.succeeded')
def save(self):
    pass

@stats.decrement('attempts.remaining')
def attempt():
    pass

@stats.timed('api_request.duration')
def perform_request(self, req)
    pass
```

When using decorators, metrics are only tracked if the decorated function
does not raise an error.

### Context

When using a [statsd client that supports tagging metrics](https://statsd.readthedocs.io/en/stable/tags.html),
Statsdecor includes a context manager that can help measure latency and volume while using metric tags to
classify their success & failure. For example, suppose you are making a call to a remote service and wish
to write a wrapper that collects latency, volume and failure metrics.

With our knowledge about how the client library indicates errors we can make a context manager
based on StatsContext:

```python
from statsdecor.context import StatsContext

class FoobarClientMetrics(StatsContext):
    def __init__(self, tags=None):
        tags = list(tags or [])
        tags += ['caller:example_1']
        super(ThingyStatsContext, self).__self__('thingy_client', tags=tags)

    def exit_hook(self, exc_type, exc_val, exc_tb):
        if exc_val is not None:
            self.add_tags('result:failure')
        else:
            self.add_tags('result:success')

        # Bonus: since we have the exception, classify the error type
        if isinstance(exc_val, PermissionDenied):
            self.add_tags('error:permissiondenied')
        elif isinstance(exc_val, TimeOut):
            self.add_tags('error:timeout')
        elif exc_val is not None:
            self.add_tags('error:exception')

```

Now writing wrapper functions with metrics is simple:

```python
def foobar_get_clients(**args):
    with FoobarClientMetrics(tags=['method:get_clients']) as stats:
        result = call_foobar_get_client(**args)

        # We know all foo methods return result['status_code'] so let's
        # add a status_code tag!
        stats.add_tags('status_code:{}'.format(result["status_code"]'))
        return result

def foobar_add_client(**args):
    with FoobarClientMetrics(tags=['method:add_client']) as stats:
        result = call_foobar_add_client(**args)
        stats.add_tags('status_code:{}'.format(result["status_code"]'))
        return result
```

Now we can graph:

* volume of calls grouped by the `method` tag
* average response time, excluding errors (timeouts will no longer skew the average)
* volume of errors grouped by method, and/or type

## Development

### Testing

```shell
make lint
make test
```

### Releasing

statsdecor uses [semver](https://semver.org) for version numbers. Before tagging,
check for all changes since the last tag for breaking changes, new features,
and/or bugfixes.

To tag the new version:

```shell
make tag VERSION_PART=major|minor|patch
```

Proceed to github.com/amcintosh/statsdecor/releases and create a new release with the tag.
Github actions should publish to pypi automatically.



            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/amcintosh/statsdecor",
    "name": "statsdecor",
    "maintainer": "Andrew McIntosh",
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": "andrew@amcintosh.net",
    "keywords": "statsd, stats",
    "author": "Freshbooks Dev Team",
    "author_email": "opensource@freshbooks.com",
    "download_url": "https://files.pythonhosted.org/packages/72/be/966deefb39834d8be2879f570a743c1d81ef7fe7bd0ab7dcdc5d6e614bcf/statsdecor-0.4.2.tar.gz",
    "platform": null,
    "description": "# Statsdecor\n\n[![PyPI](https://img.shields.io/pypi/v/statsdecor)](https://pypi.org/project/statsdecor/)\n![PyPI - Python Version](https://img.shields.io/pypi/pyversions/statsdecor)\n[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.txt)\n[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/amcintosh/statsdecor/run-tests.yml?branch=main)](https://github.com/amcintosh/statsdecor/actions?query=workflow%3A%22Run+Tests%22)\n\nA set of decorators and helper methods for adding statsd metrics to applications.\n\n## Installation\n\nYou can use pip to install statsdecor:\n\n```shell\npip install statsdecor\n```\n\n## Configuration\n\nYou must use `statsdecor.configure` to configure the internal statsd client before\ncalling other methods:\n\n```python\nimport statsdecor\n\nstatsdecor.configure(host='localhost', prefix='superapp.')\n```\n\nConfiguration is generally setup during your application's bootstrap. Once\nset configuration values are re-used in all clients that `statsdecor` creates.\n\nBy default Statsdecor uses the [statsd](https://pypi.org/project/statsd/) client library,\nhowever it can be configured to use the [datadog](https://pypi.org/project/datadog/) client:\n\n```python\nimport statsdecor\n\nstatsdecor.configure(host='localhost', prefix='superapp.', vendor='datadog')\n```\n\nThe datadog client supports [tagging metrics](https://statsd.readthedocs.io/en/stable/tags.html) (see Usage).\n\n## Usage\n\nYou can track metrics with either the module functions, or decorators. Incrementing\nand decrementing counters looks like:\n\n### Metric functions\n\n```python\nimport statsdecor\n\nstatsdecor.incr('save.succeeded')\nstatsdecor.decr('attempts.remaining')\nstatsdecor.gauge('sessions.active', 9001)\n```\n\nWhen using the datadog client, Statsdecor supports tagging metrics:\n\n```python\nstatsdecor.incr('save.succeeded', tags=['DogStatsd_does_tags'])\n```\n\nCounters and timers can also be set through decorators:\n\n```python\nimport statsdecor.decorators as stats\n\n@stats.increment('save.succeeded')\ndef save(self):\n    pass\n\n@stats.decrement('attempts.remaining')\ndef attempt():\n    pass\n\n@stats.timed('api_request.duration')\ndef perform_request(self, req)\n    pass\n```\n\nWhen using decorators, metrics are only tracked if the decorated function\ndoes not raise an error.\n\n### Context\n\nWhen using a [statsd client that supports tagging metrics](https://statsd.readthedocs.io/en/stable/tags.html),\nStatsdecor includes a context manager that can help measure latency and volume while using metric tags to\nclassify their success & failure. For example, suppose you are making a call to a remote service and wish\nto write a wrapper that collects latency, volume and failure metrics.\n\nWith our knowledge about how the client library indicates errors we can make a context manager\nbased on StatsContext:\n\n```python\nfrom statsdecor.context import StatsContext\n\nclass FoobarClientMetrics(StatsContext):\n    def __init__(self, tags=None):\n        tags = list(tags or [])\n        tags += ['caller:example_1']\n        super(ThingyStatsContext, self).__self__('thingy_client', tags=tags)\n\n    def exit_hook(self, exc_type, exc_val, exc_tb):\n        if exc_val is not None:\n            self.add_tags('result:failure')\n        else:\n            self.add_tags('result:success')\n\n        # Bonus: since we have the exception, classify the error type\n        if isinstance(exc_val, PermissionDenied):\n            self.add_tags('error:permissiondenied')\n        elif isinstance(exc_val, TimeOut):\n            self.add_tags('error:timeout')\n        elif exc_val is not None:\n            self.add_tags('error:exception')\n\n```\n\nNow writing wrapper functions with metrics is simple:\n\n```python\ndef foobar_get_clients(**args):\n    with FoobarClientMetrics(tags=['method:get_clients']) as stats:\n        result = call_foobar_get_client(**args)\n\n        # We know all foo methods return result['status_code'] so let's\n        # add a status_code tag!\n        stats.add_tags('status_code:{}'.format(result[\"status_code\"]'))\n        return result\n\ndef foobar_add_client(**args):\n    with FoobarClientMetrics(tags=['method:add_client']) as stats:\n        result = call_foobar_add_client(**args)\n        stats.add_tags('status_code:{}'.format(result[\"status_code\"]'))\n        return result\n```\n\nNow we can graph:\n\n* volume of calls grouped by the `method` tag\n* average response time, excluding errors (timeouts will no longer skew the average)\n* volume of errors grouped by method, and/or type\n\n## Development\n\n### Testing\n\n```shell\nmake lint\nmake test\n```\n\n### Releasing\n\nstatsdecor uses [semver](https://semver.org) for version numbers. Before tagging,\ncheck for all changes since the last tag for breaking changes, new features,\nand/or bugfixes.\n\nTo tag the new version:\n\n```shell\nmake tag VERSION_PART=major|minor|patch\n```\n\nProceed to github.com/amcintosh/statsdecor/releases and create a new release with the tag.\nGithub actions should publish to pypi automatically.\n\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A set of decorators and helper methods for adding statsd metrics to applications.",
    "version": "0.4.2",
    "project_urls": {
        "Homepage": "https://github.com/amcintosh/statsdecor"
    },
    "split_keywords": [
        "statsd",
        " stats"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "dd9081e0a8baca8ea91189b839c8b2d922a9894ee2977c80e135ad0a60f4be4b",
                "md5": "c8d110cee49fbc5538e9c67419371edf",
                "sha256": "980cf77dbda83c97556f7a33b37f0eb7eb94c1f83bc815b099adc411115baa0d"
            },
            "downloads": -1,
            "filename": "statsdecor-0.4.2-py2.py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "c8d110cee49fbc5538e9c67419371edf",
            "packagetype": "bdist_wheel",
            "python_version": "py2.py3",
            "requires_python": null,
            "size": 7815,
            "upload_time": "2024-12-10T17:09:35",
            "upload_time_iso_8601": "2024-12-10T17:09:35.336062Z",
            "url": "https://files.pythonhosted.org/packages/dd/90/81e0a8baca8ea91189b839c8b2d922a9894ee2977c80e135ad0a60f4be4b/statsdecor-0.4.2-py2.py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "72be966deefb39834d8be2879f570a743c1d81ef7fe7bd0ab7dcdc5d6e614bcf",
                "md5": "90493b29b12bd6b1c3babbd784d761a6",
                "sha256": "44aa6294793124c798f0c1ff572a1aeafef687b8fa148a5f2dde93086934be9d"
            },
            "downloads": -1,
            "filename": "statsdecor-0.4.2.tar.gz",
            "has_sig": false,
            "md5_digest": "90493b29b12bd6b1c3babbd784d761a6",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 11829,
            "upload_time": "2024-12-10T17:09:36",
            "upload_time_iso_8601": "2024-12-10T17:09:36.309855Z",
            "url": "https://files.pythonhosted.org/packages/72/be/966deefb39834d8be2879f570a743c1d81ef7fe7bd0ab7dcdc5d6e614bcf/statsdecor-0.4.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-12-10 17:09:36",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "amcintosh",
    "github_project": "statsdecor",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [
        {
            "name": "statsd",
            "specs": []
        },
        {
            "name": "datadog",
            "specs": []
        }
    ],
    "lcname": "statsdecor"
}
        
Elapsed time: 0.42092s