diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 1ce546b..0000000 --- a/.coveragerc +++ /dev/null @@ -1,7 +0,0 @@ -[run] -branch = True -source = monascastatsd -omit = tests/* - -[report] -ignore_errors = True \ No newline at end of file diff --git a/.stestr.conf b/.stestr.conf deleted file mode 100644 index ea359ca..0000000 --- a/.stestr.conf +++ /dev/null @@ -1,3 +0,0 @@ -[DEFAULT] -test_path=./tests -top_dir=./ diff --git a/.zuul.yaml b/.zuul.yaml deleted file mode 100644 index 7621520..0000000 --- a/.zuul.yaml +++ /dev/null @@ -1,9 +0,0 @@ -- project: - templates: - - check-requirements - - openstack-cover-jobs - - openstack-python3-zed-jobs - check: - jobs: - - monasca-tempest-python3-influxdb: - voting: false diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst deleted file mode 100644 index c860b7a..0000000 --- a/CONTRIBUTING.rst +++ /dev/null @@ -1,19 +0,0 @@ -The source repository for this project can be found at: - - https://opendev.org/openstack/monasca-statsd - -Pull requests submitted through GitHub are not monitored. - -To start contributing to OpenStack, follow the steps in the contribution guide -to set up and use Gerrit: - - https://docs.openstack.org/contributors/code-and-documentation/quick-start.html - -Bugs should be filed on Storyboard: - - https://storyboard.openstack.org/#!/project/872 - -For more specific information about contributing to this repository, see the -Monasca contributor guide: - - https://docs.openstack.org/monasca-api/latest/contributor/contributing.html diff --git a/README.rst b/README.rst index 2d6a32c..d4129d3 100644 --- a/README.rst +++ b/README.rst @@ -1,92 +1,9 @@ -Openstack Monasca Statsd -======================== +This project is no longer maintained. -.. image:: https://governance.openstack.org/tc/badges/monasca-statsd.svg - :target: https://governance.openstack.org/tc/reference/tags/index.html +The contents of this repository are still available in the Git +source code management system. To see the contents of this +repository before it reached its end of life, please check out the +previous commit with "git checkout HEAD^1". -A Monasca-Statsd Python Client. -=============================== - -Quick Start Guide ------------------ - -First install the library with ``pip`` or ``easy_install``: - -:: - - # Install in system python ... - sudo pip install monasca-statsd - - # .. or into a virtual env - pip install monasca-statsd - -Then start instrumenting your code: - -:: - - # Import the module. - import monascastatsd as mstatsd - - # Create the connection - conn = mstatsd.Connection(host='localhost', port=8125) - - # Create the client with optional dimensions - client = mstatsd.Client(connection=conn, dimensions={'env': 'test'}) - - NOTE: You can also create a client without specifying the connection and it will create the client - with the default connection information for the monasca-agent statsd processor daemon - which uses host='localhost' and port=8125. - - client = mstatsd.Client(dimensions={'env': 'test'}) - - # Increment and decrement a counter. - counter = client.get_counter(name='page.views') - - counter.increment() - counter += 3 - - counter.decrement() - counter -= 3 - - # Record a gauge 50% of the time. - gauge = client.get_gauge('gauge', dimensions={'env': 'test'}) - - gauge.send('metric', 123.4, sample_rate=0.5) - - # Sample a histogram. - histogram = client.get_histogram('histogram', dimensions={'test': 'True'}) - - histogram.send('metric', 123.4, dimensions={'color': 'red'}) - - # Time a function call. - timer = client.get_timer() - - @timer.timed('page.render') - def render_page(): - # Render things ... - pass - - # Time a block of code. - timer = client.get_timer() - - with timer.time('t'): - # Do stuff - time.sleep(2) - - # Add dimensions to any metric. - histogram = client.get_histogram('my_hist') - histogram.send('query.time', 10, dimensions = {'version': '1.0', 'environment': 'dev'}) - -Feedback --------- - -To suggest a feature, report a bug, or participate in the general -discussion, head over to `StoryBoard`_. - -License -------- - -See LICENSE file. Code was originally forked from Datadog’s -dogstatsd-python, hence the dual license. - -.. _StoryBoard: https://storyboard.openstack.org/#!/project/872 +For any further questions, please email openstack-discuss@lists.openstack.org +or join #openstack-dev on OFTC. diff --git a/Rakefile b/Rakefile deleted file mode 100644 index a12991b..0000000 --- a/Rakefile +++ /dev/null @@ -1,11 +0,0 @@ - -desc "Run tests" -task :test do - sh "nosetests" -end - -task :default => :test - -task :release => :test do - sh "python setup.py sdist upload" -end diff --git a/doc/requirements.txt b/doc/requirements.txt deleted file mode 100644 index fb31f9f..0000000 --- a/doc/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -sphinx!=1.6.6,!=1.6.7,>=1.6.5 # BSD -oslosphinx>=4.7.0 # Apache-2.0 -openstackdocstheme>=1.18.1 # Apache-2.0 diff --git a/doc/source/conf.py b/doc/source/conf.py deleted file mode 100644 index 3e2e53a..0000000 --- a/doc/source/conf.py +++ /dev/null @@ -1,304 +0,0 @@ -# (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP -# Copyright 2017 FUJITSU LIMITED -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Copyright (c) 2012, Datadog -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the Datadog nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL DATADOG BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -*- coding: utf-8 -*- -# -# monasca-statsd documentation build configuration file, created by -# sphinx-quickstart on Thu Jun 14 19:22:15 2012. -# -# This file is execfile()d with the current directory set to its containing dir -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# sys.path.insert(0, os.path.abspath('.')) - -import subprocess -import warnings - -# -- General configuration ---------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.todo', - 'sphinx.ext.coverage', - 'sphinx.ext.viewcode', - 'sphinx.ext.graphviz', - 'oslosphinx' -] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -# source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'monasca-statsd' -author = u'OpenStack' -copyright = u'2014-present, OpenStack Foundatio' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '1.0.0' -# The full version, including alpha/beta/rc tags. -release = '1.0.0' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# today = '' -# Else, today_fmt is used as the format for a strftime call. -# today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = [] - -# The reST default role (used for this markup: `text`) to use for all documents -# default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -# add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -add_module_names = False - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -modindex_common_prefix = ['monasca.'] - - -# -- Options for HTML output -------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# html_theme = 'default' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -# html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -# html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -# html_last_updated_fmt = '%b %d, %Y' -git_cmd = ["git", "log", "--pretty=format:'%ad, commit %h'", "--date=local", - "-n1"] -try: - html_last_updated_fmt = subprocess.check_output(git_cmd).decode('utf-8') -except Exception: - warnings.warn('Cannot get last updated time from git repository. ' - 'Not setting "html_last_updated_fmt".') - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = {} - -# If false, no module index is generated. -# html_domain_indices = True - -# If false, no index is generated. -# html_use_index = True - -# If true, the index is split into individual pages for each letter. -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -# html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'monasca-statsd-pythondoc' - - -# -- Options for LaTeX output ------------------------------------------------- - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # 'papersize': 'letterpaper', - - # The font size ('10pt', '11pt' or '12pt'). - # 'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - # 'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, -# documentclass [howto/manual]). -latex_documents = [ - ('index', - 'monasca-statsd-python.tex', - u'monasca-statsd-python Documentation', - u'OpenStack Foundation', - 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -# latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# latex_use_parts = False - -# If true, show page references after internal links. -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# latex_show_urls = False - -# Documents to append as an appendix to all manuals. -# latex_appendices = [] - -# If false, no module index is generated. -# latex_domain_indices = True - - -# -- Options for manual page output ------------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'monasca-statsd-python', u'monasca-statsd-python Documentation', - [u'OpenStack Foundation'], 1) -] - -# If true, show URL addresses after external links. -# man_show_urls = False - - -# -- Options for Texinfo output ----------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ('index', 'monasca-statsd-python', - u'monasca-statsd-python Documentation', - u'Openstack Foundation', - 'monasca-statsd-python', - 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -# texinfo_appendices = [] - -# If false, no module index is generated. -# texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -# texinfo_show_urls = 'footnote' diff --git a/doc/source/index.rst b/doc/source/index.rst deleted file mode 100644 index 282e71b..0000000 --- a/doc/source/index.rst +++ /dev/null @@ -1,22 +0,0 @@ -Introduction -============ - -A global :class:`~statsd.MonascaStatsd` instance that is easily shared -across an application's modules. Initialize this once in your application's -set-up code and then other modules can import and use it without further -configuration. - - >>> from monascastatsd import monascastatsd - >>> monascastatsd.connect(host='localhost', port=8125) - -Source -====== - -The Monasca-Statsd source is freely available on Github. Check it out `here -`_. - -Get in Touch -============ - -If you'd like to suggest a feature or report a bug, -please add an issue `here `_. diff --git a/mkdocs.yml b/mkdocs.yml deleted file mode 100644 index 9e880ce..0000000 --- a/mkdocs.yml +++ /dev/null @@ -1,2 +0,0 @@ -site_name: monasca-statsd -repo_url: https://github.com/stackforge/monasca-statsd diff --git a/monascastatsd/__init__.py b/monascastatsd/__init__.py deleted file mode 100644 index fef5a04..0000000 --- a/monascastatsd/__init__.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright 2016 FUJITSU LIMITED -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from monascastatsd import client -from monascastatsd import connection -from monascastatsd import counter -from monascastatsd import gauge -from monascastatsd import metricbase -from monascastatsd import timer - -Client = client.Client -Connection = connection.Connection -Counter = counter.Counter -Gauge = gauge.Gauge -MetricBase = metricbase.MetricBase -Timer = timer.Timer - -__all__ = [ - 'Client', - 'Connection', - 'Counter', - 'Gauge', - 'MetricBase', - 'Timer' -] diff --git a/monascastatsd/client.py b/monascastatsd/client.py deleted file mode 100644 index 725a0f7..0000000 --- a/monascastatsd/client.py +++ /dev/null @@ -1,117 +0,0 @@ -# (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Copyright (c) 2012, Datadog -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the Datadog nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL DATADOG BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Monasca-Statsd is a Python client for Statsd that adds dimensions. -""" -from monascastatsd import common -from monascastatsd.connection import Connection -from monascastatsd.counter import Counter -from monascastatsd.gauge import Gauge -from monascastatsd.timer import Timer - - -class Client(object): - - def __init__(self, name=None, host='localhost', port=8125, - connection=None, max_buffer_size=50, dimensions=None): - """Initialize a Client object. - - >>> monascastatsd = MonascaStatsd() - - :name: the name for this client. Everything sent by this client - will be prefixed by name - :param host: the host of the MonascaStatsd server. - :param port: the port of the MonascaStatsd server. - :param max_buffer_size: Maximum number of metric to buffer before - sending to the server if sending metrics in batch - """ - self._max_buffer_size = max_buffer_size - self._set_connection(connection, host, port) - self._dimensions = dimensions - self._client_name = name - - def _set_connection(self, connection, host, port): - if connection is None: - self.connection = Connection(host=host, - port=port, - max_buffer_size=self._max_buffer_size) - else: - self.connection = connection - - def get_counter(self, name, connection=None, dimensions=None): - """Gets a Counter object. - - """ - return self._get_statsd_object_by_type(Counter, name, connection, - dimensions) - - def get_gauge(self, name=None, connection=None, dimensions=None): - """Gets a Gauge object. - - """ - return self._get_statsd_object_by_type(Gauge, name, connection, - dimensions) - - def get_timer(self, name=None, connection=None, dimensions=None): - """Gets a Timer object. - - """ - return self._get_statsd_object_by_type(Timer, name, connection, - dimensions) - - def _get_statsd_object_by_type(self, object_type, name, connection, - dimensions): - return object_type(name=self._update_metric_name(name), - connection=connection or self.connection, - dimensions=self._update_dimensions(dimensions)) - - def _update_metric_name(self, metric_name): - """Update the metric name with the client - - name that was passed in on instantiation. - """ - return common.update_name(self._client_name, metric_name) - - def _update_dimensions(self, dimensions): - """Update the dimensions list with the default - - dimensions that were passed in on instantiation. - """ - return common.update_dimensions(self._dimensions, dimensions) diff --git a/monascastatsd/common.py b/monascastatsd/common.py deleted file mode 100644 index 782cca1..0000000 --- a/monascastatsd/common.py +++ /dev/null @@ -1,25 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -def update_dimensions(dimensions_base=None, dimensions=None): - new_dimensions = (dimensions_base or {}).copy() - new_dimensions.update(dimensions or {}) - - return new_dimensions - - -def update_name(name_base=None, postfix=None): - if name_base and postfix: - return "{}.{}".format(name_base, postfix) - else: - return name_base or postfix diff --git a/monascastatsd/connection.py b/monascastatsd/connection.py deleted file mode 100644 index 800122c..0000000 --- a/monascastatsd/connection.py +++ /dev/null @@ -1,154 +0,0 @@ -# (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP -# Copyright 2016 FUJITSU LIMITED -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Copyright (c) 2012, Datadog -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the Datadog nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL DATADOG BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import six - -import logging -import random -import socket - -logging.basicConfig() -log = logging.getLogger(__name__) - - -class Connection(object): - - def __init__(self, host='localhost', port=8125, max_buffer_size=50): - """Initialize a Connection object. - - >>> monascastatsd = MonascaStatsd() - - :name: the name for this client. Everything sent by this client - will be prefixed by name - :param host: the host of the MonascaStatsd server. - :param port: the port of the MonascaStatsd server. - :param max_buffer_size: Maximum number of metric to buffer before - sending to the server if sending metrics in batch - """ - self.max_buffer_size = max_buffer_size - self._send = self._send_to_server - self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - self.connect(host, port) - self.encoding = 'utf-8' - - def __enter__(self): - self.open_buffer(self.max_buffer_size) - return self - - def __exit__(self, the_type, value, traceback): - self.close_buffer() - - def open_buffer(self, max_buffer_size=50): - """Open a buffer to send a batch of metrics in one packet. - - """ - self.max_buffer_size = max_buffer_size - self.buffer = [] - self._send = self._send_to_buffer - - def close_buffer(self): - """Flush the buffer and switch back to single metric packets. - - """ - self._send = self._send_to_server - self._flush_buffer() - - def connect(self, host, port): - """Connect to the monascastatsd server on the given host and port. - - """ - self.socket.connect((host, int(port))) - - def report(self, metric, metric_type, value, dimensions, sample_rate): - """Use this connection to report metrics. - - """ - if sample_rate == 1 or random.random() <= sample_rate: - self._send_payload(dimensions, metric, - metric_type, sample_rate, - value) - - def _send_payload(self, dimensions, metric, metric_type, - sample_rate, value): - - encoded = self._create_payload(dimensions, metric, - metric_type, sample_rate, - value) - - self._send(encoded) - - def _create_payload(self, dimensions, metric, metric_type, sample_rate, - value): - - payload = [metric, ":", value, "|", metric_type] - payload.extend(self._payload_extension_from_sample_rate(sample_rate)) - payload.extend(self._payload_extension_from_dimensions(dimensions)) - - return "".join(six.moves.map(str, payload)) - - @staticmethod - def _payload_extension_from_sample_rate(sample_rate): - if sample_rate != 1: - return ["|@", sample_rate] - else: - return [] - - @staticmethod - def _payload_extension_from_dimensions(dimensions): - if dimensions: - return ["|#", dimensions] - else: - return [] - - def _send_to_server(self, packet): - try: - self.socket.send(packet.encode(self.encoding)) - except socket.error: - log.exception("Error submitting metric") - - def _send_to_buffer(self, packet): - self.buffer.append(packet) - if len(self.buffer) >= self.max_buffer_size: - self._flush_buffer() - - def _flush_buffer(self): - self._send_to_server("\n".join(self.buffer)) - self.buffer = [] diff --git a/monascastatsd/counter.py b/monascastatsd/counter.py deleted file mode 100644 index 1501670..0000000 --- a/monascastatsd/counter.py +++ /dev/null @@ -1,94 +0,0 @@ -# (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Copyright (c) 2012, Datadog -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the Datadog nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL DATADOG BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -from monascastatsd import metricbase - - -class Counter(metricbase.MetricBase): - - def __init__(self, name, connection, dimensions=None): - super(self.__class__, self).__init__(name=name, - connection=connection, - dimensions=dimensions) - - def increment(self, value=1, dimensions=None, sample_rate=1): - """Increment a counter, optionally setting a value, dimensions - - and a sample rate. - - >>> monascastatsd.increment() - >>> monascastatsd.increment(12) - """ - self._report_change(dimensions, sample_rate, value) - - def decrement(self, value=1, dimensions=None, sample_rate=1): - """Decrement a counter, optionally setting a value, dimensions and a - - sample rate. - - >>> monascastatsd.decrement() - >>> monascastatsd.decrement(2) - """ - self._report_change(dimensions, sample_rate, -value) - - def _report_change(self, dimensions, sample_rate, value): - self._connection.report(metric=self._name, - metric_type='c', - value=value, - dimensions=self.update_dimensions(dimensions), - sample_rate=sample_rate) - - def __add__(self, value): - """Increment the counter with `value` - - :keyword value: The value to add to the counter - :type value: int - """ - self.increment(value=value) - return self - - def __sub__(self, value): - """Decrement the counter with `value` - - :keyword value: The value to remove from the counter - :type value: int - """ - self.decrement(value=value) - return self diff --git a/monascastatsd/gauge.py b/monascastatsd/gauge.py deleted file mode 100644 index 1812549..0000000 --- a/monascastatsd/gauge.py +++ /dev/null @@ -1,64 +0,0 @@ -# (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Copyright (c) 2012, Datadog -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the Datadog nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL DATADOG BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -from monascastatsd import metricbase - - -class Gauge(metricbase.MetricBase): - - def __init__(self, connection, name=None, dimensions=None): - super(self.__class__, self).__init__(name=name, - connection=connection, - dimensions=dimensions) - - def send(self, name, value, dimensions=None, sample_rate=1): - """Record the value of a gauge, optionally setting a list of - - dimensions and a sample rate. - - >>> monascastatsd.gauge('users.online', 123) - >>> monascastatsd.gauge('active.connections', 1001, - >>> dimensions={"protocol": "http"}) - """ - self._connection.report(metric=self.update_name(name), - metric_type='g', - value=value, - dimensions=self.update_dimensions(dimensions), - sample_rate=sample_rate) diff --git a/monascastatsd/metricbase.py b/monascastatsd/metricbase.py deleted file mode 100644 index 55d88e1..0000000 --- a/monascastatsd/metricbase.py +++ /dev/null @@ -1,66 +0,0 @@ -# (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Copyright (c) 2012, Datadog -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the Datadog nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL DATADOG BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -from monascastatsd import common - - -class MetricBase(object): - """Base class for all metric types. - - """ - - def __init__(self, name, connection, dimensions): - self._name = name - self._connection = connection - self._dimensions = dimensions - - def update_dimensions(self, dimensions): - """Update the dimensions list with the default - - dimensions that were passed in on instantiation. - """ - return common.update_dimensions(self._dimensions, dimensions) - - def update_name(self, name): - """Update the metric name with the metric - - base name that was passed in on instantiation. - """ - return common.update_name(self._name, name) diff --git a/monascastatsd/timer.py b/monascastatsd/timer.py deleted file mode 100644 index 78778fd..0000000 --- a/monascastatsd/timer.py +++ /dev/null @@ -1,114 +0,0 @@ -# (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Copyright (c) 2012, Datadog -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the Datadog nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL DATADOG BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import contextlib -import functools -import time - -from monascastatsd import metricbase - - -class Timer(metricbase.MetricBase): - - def __init__(self, connection, name=None, dimensions=None): - super(self.__class__, self).__init__(name=name, - connection=connection, - dimensions=dimensions) - - def timing(self, name, value, dimensions=None, sample_rate=1): - """Record a timing, optionally setting dimensions and a sample rate. - - >>> monascastatsd.timing("query.response.time", 1234) - """ - self._connection.report(metric=self.update_name(name), - metric_type='g', - value=value, - dimensions=self.update_dimensions(dimensions), - sample_rate=sample_rate) - - def timed(self, name, dimensions=None, sample_rate=1): - """A decorator that will measure the distribution of a function's - - run time. Optionally specify a list of tag or a sample rate. - :: - - @monascastatsd.timed('user.query.time', sample_rate=0.5) - def get_user(user_id): - # Do what you need to ... - pass - - # Is equivalent to ... - start = time.time() - try: - get_user(user_id) - finally: - monascastatsd.timing('user.query.time', time.time() - start) - """ - def wrapper(func): - @functools.wraps(func) - def wrapped(*args, **kwargs): - start = time.time() - result = func(*args, **kwargs) - self.timing(name, - time.time() - start, - dimensions=dimensions, - sample_rate=sample_rate) - return result - wrapped.__name__ = func.__name__ - wrapped.__doc__ = func.__doc__ - wrapped.__dict__.update(func.__dict__) - return wrapped - return wrapper - - @contextlib.contextmanager - def time(self, name, dimensions=None, sample_rate=1): - """Time a block of code, optionally setting dimensions and a sample rate. - - try: - with monascastatsd.time("query.response.time"): - Do something... - except Exception: - Log something... - """ - - start_time = time.time() - yield - end_time = time.time() - self.timing(name, end_time - start_time, dimensions, sample_rate) diff --git a/releasenotes/notes/drop-py-2-7-c9e3758f73d5cf29.yaml b/releasenotes/notes/drop-py-2-7-c9e3758f73d5cf29.yaml deleted file mode 100644 index d035349..0000000 --- a/releasenotes/notes/drop-py-2-7-c9e3758f73d5cf29.yaml +++ /dev/null @@ -1,6 +0,0 @@ ---- -upgrade: - - | - Python 2.7 support has been dropped. Last release of monasca-statsd - to support python 2.7 is OpenStack Train. The minimum version of Python now - supported by monasca-statsd is Python 3.6. diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 9f5b247..0000000 --- a/requirements.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Requirements lower bounds listed here are our best effort to keep them up to -# date but we do not test them so no guarantee of having them all correct. If -# you find any incorrect lower bounds, let us know or propose a fix. - -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. -six>=1.12.0 # MIT diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 722f4e5..0000000 --- a/setup.cfg +++ /dev/null @@ -1,43 +0,0 @@ -[metadata] -name = monasca-statsd -maintainer = monasca -maintainer_email = monasca@lists.launchpad.net -description-file = README.rst -summary = Monasca statsd Python client -home-page = https://opendev.org/openstack/monasca-statsd -keywords= - openstack - monitoring - statsd -license = Apache-2 -include_package_data = True -test_suite = nose.collector -python-requires = >=3.6 -classifier = - Development Status :: 5 - Production/Stable - License :: OSI Approved :: Apache Software License - Topic :: System :: Monitoring - Programming Language :: Python - Programming Language :: Python :: Implementation :: CPython - Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.6 - Programming Language :: Python :: 3.7 - Programming Language :: Python :: 3.8 - -[files] -packages = - monascastatsd - -[pbr] -autodoc_index_modules = True - -[egg_info] -tag_build = -tag_date = 0 -tag_svn_revision = 0 - -[build_sphinx] -all_files = 1 -build-dir = doc/build -source-dir = doc/source diff --git a/setup.py b/setup.py deleted file mode 100644 index cd35c3c..0000000 --- a/setup.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import setuptools - -setuptools.setup( - setup_requires=['pbr>=2.0.0'], - pbr=True) diff --git a/test-requirements.txt b/test-requirements.txt deleted file mode 100644 index 9cc0447..0000000 --- a/test-requirements.txt +++ /dev/null @@ -1,9 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. -hacking>=3.0.1,<3.1.0 # Apache-2.0 -bandit>=1.1.0 # Apache-2.0 -coverage!=4.4,>=4.0 # Apache-2.0 -oslotest>=3.2.0 # Apache-2.0 -stestr>=1.0.0 # Apache-2.0 -testrepository>=0.0.18 # Apache-2.0/BSD diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/test_monascastatsd.py b/tests/test_monascastatsd.py deleted file mode 100644 index d8692c8..0000000 --- a/tests/test_monascastatsd.py +++ /dev/null @@ -1,313 +0,0 @@ -# (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Copyright (c) 2012, Datadog -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the Datadog nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL DATADOG BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -*- coding: utf-8 -*- - -"""Tests for monascastatsd.py.""" - -import collections -import socket -import time -import unittest - -import monascastatsd as mstatsd - -from unittest import mock -import six -from six.moves import range - - -class FakeSocket(object): - - """A fake socket for testing.""" - - def __init__(self): - self.payloads = collections.deque() - - def send(self, payload): - self.payloads.append(payload) - - def recv(self): - try: - return self.payloads.popleft() - except IndexError: - return None - - def __repr__(self): - return str(self.payloads) - - -class BrokenSocket(FakeSocket): - - def send(self, payload): - raise socket.error("Socket error") - - -class TestMonascaStatsd(unittest.TestCase): - - def setUp(self): - conn = mstatsd.Connection() - conn.socket = FakeSocket() - self.client = mstatsd.Client(connection=conn, dimensions={'env': 'test'}) - - def recv(self, metric_obj): - return metric_obj._connection.socket.recv() - - @mock.patch('monascastatsd.client.Connection') - def test_client_set_host_port(self, connection_mock): - mstatsd.Client(host='foo.bar', port=5213) - connection_mock.assert_called_once_with(host='foo.bar', - port=5213, - max_buffer_size=50) - - @mock.patch('monascastatsd.client.Connection') - def test_client_default_host_port(self, connection_mock): - mstatsd.Client() - connection_mock.assert_called_once_with(host='localhost', - port=8125, - max_buffer_size=50) - - def test_counter(self): - counter = self.client.get_counter(name='page.views') - - counter.increment() - self.assertEqual(six.b("page.views:1|c|#{'env': 'test'}"), - self.recv(counter)) - - counter += 1 - self.assertEqual(six.b("page.views:1|c|#{'env': 'test'}"), - self.recv(counter)) - - counter.increment(11) - self.assertEqual(six.b("page.views:11|c|#{'env': 'test'}"), - self.recv(counter)) - - counter += 11 - self.assertEqual(six.b("page.views:11|c|#{'env': 'test'}"), - self.recv(counter)) - - counter.decrement() - self.assertEqual(six.b("page.views:-1|c|#{'env': 'test'}"), - self.recv(counter)) - - counter -= 1 - self.assertEqual(six.b("page.views:-1|c|#{'env': 'test'}"), - self.recv(counter)) - - counter.decrement(12) - self.assertEqual(six.b("page.views:-12|c|#{'env': 'test'}"), - self.recv(counter)) - - counter -= 12 - self.assertEqual(six.b("page.views:-12|c|#{'env': 'test'}"), - self.recv(counter)) - - def test_counter_with_dimensions(self): - counter = self.client.get_counter('counter_with_dims', - dimensions={'date': '10/24', 'time': '23:00'}) - - counter.increment(dimensions={'country': 'canada', 'color': 'red'}) - - result = self.recv(counter) - if isinstance(result, bytes): - result = result.decode('utf-8') - - self.assertRegexpMatches(result, "counter_with_dims:1|c|#{") - self.assertRegexpMatches(result, "'country': 'canada'") - self.assertRegexpMatches(result, "'date': '10/24'") - self.assertRegexpMatches(result, "'color': 'red'") - self.assertRegexpMatches(result, "'env': 'test'") - self.assertRegexpMatches(result, "'time': '23:00'") - - counter += 1 - - result = self.recv(counter) - if isinstance(result, bytes): - result = result.decode('utf-8') - - self.assertRegexpMatches(result, "counter_with_dims:1|c|#{") - self.assertRegexpMatches(result, "'date': '10/24'") - self.assertRegexpMatches(result, "'env': 'test'") - self.assertRegexpMatches(result, "'time': '23:00'") - - def test_gauge(self): - gauge = self.client.get_gauge('gauge') - gauge.send('metric', 123.4) - result = self.recv(gauge) - if isinstance(result, bytes): - result = result.decode('utf-8') - - assert result == "gauge.metric:123.4|g|#{'env': 'test'}" - - def test_gauge_with_dimensions(self): - gauge = self.client.get_gauge('gauge') - gauge.send('gt', 123.4, - dimensions={'country': 'china', - 'age': 45, - 'color': 'blue'}) - - result = self.recv(gauge) - if isinstance(result, bytes): - result = result.decode('utf-8') - - self.assertRegexpMatches(result, "gauge.gt:123.4|g|#{") - self.assertRegexpMatches(result, "'country': 'china'") - self.assertRegexpMatches(result, "'age': 45") - self.assertRegexpMatches(result, "'color': 'blue'") - self.assertRegexpMatches(result, "'env': 'test'") - - def test_sample_rate(self): - counter = self.client.get_counter('sampled_counter') - counter.increment(sample_rate=0) - assert not self.recv(counter) - for _ in range(10000): - counter.increment(sample_rate=0.3) - self.assert_almost_equal(3000, - len(self.client.connection.socket.payloads), - 150) - self.assertEqual(six.b("sampled_counter:1|c|@0.3|#{'env': 'test'}"), self.recv(counter)) - - def test_samples_with_dimensions(self): - gauge = self.client.get_gauge() - for _ in range(100): - gauge.send('gst', - 23, - dimensions={'status': 'sampled'}, - sample_rate=0.9) - - def test_timing(self): - timer = self.client.get_timer() - timer.timing('t', 123) - self.assertEqual(six.b("t:123|g|#{'env': 'test'}"), self.recv(timer)) - - def test_time(self): - timer = self.client.get_timer() - with timer.time('t'): - time.sleep(2) - packet = self.recv(timer) - if isinstance(packet, bytes): - packet = packet.decode("utf-8") - - name_value, type_, dimensions = packet.split('|') - name, value = name_value.split(':') - - self.assertEqual('g', type_) - self.assertEqual('t', name) - self.assert_almost_equal(2.0, float(value), 0.1) - self.assertEqual("{'env': 'test'}", dimensions.lstrip('#')) - - def test_timed(self): - timer = self.client.get_timer() - - @timer.timed('timed.test') - def func(a, b, c=1, d=1): - """docstring.""" - time.sleep(0.5) - return (a, b, c, d) - - self.assertEqual('func', func.__name__) - self.assertEqual('docstring.', func.__doc__) - - result = func(1, 2, d=3) - # Assert it handles args and kwargs correctly. - self.assertEqual(result, (1, 2, 1, 3)) - - packet = self.recv(timer) - if isinstance(packet, bytes): - packet = packet.decode("utf-8") - - name_value, type_, dimensions = packet.split('|') - name, value = name_value.split(':') - - self.assertEqual('g', type_) - self.assertEqual('timed.test', name) - self.assert_almost_equal(0.5, float(value), 0.1) - self.assertEqual("{'env': 'test'}", dimensions.lstrip('#')) - - def test_socket_error(self): - self.client.connection.socket = BrokenSocket() - self.client.get_gauge().send('no error', 1) - assert True, 'success' - self.client.connection.socket = FakeSocket() - - def test_batched(self): - self.client.connection.open_buffer() - gauge = self.client.get_gauge('site') - gauge.send('views', 123) - timer = self.client.get_timer('site') - timer.timing('timer', 123) - self.client.connection.close_buffer() - - self.assertEqual(six.b("site.views:123|g|#{'env': 'test'}\n" - "site.timer:123|g|#{'env': 'test'}"), - self.recv(gauge)) - - def test_context_manager(self): - fake_socket = FakeSocket() - with mstatsd.Connection() as conn: - conn.socket = fake_socket - client = mstatsd.Client(name='ContextTester', connection=conn) - client.get_gauge('page').send('views', 123) - client.get_timer('page').timing('timer', 12) - - self.assertEqual(six.b('ContextTester.page.views:123|g\nContextTester.page.timer:12|g'), - fake_socket.recv()) - - def test_batched_buffer_autoflush(self): - fake_socket = FakeSocket() - with mstatsd.Connection() as conn: - conn.socket = fake_socket - client = mstatsd.Client(name='BufferedTester', connection=conn) - counter = client.get_counter('mycounter') - for _ in range(51): - counter.increment() - self.assertEqual(six.b('\n'.join(['BufferedTester.mycounter:1|c' for _ in range(50)])), - fake_socket.recv()) - - self.assertEqual(six.b('BufferedTester.mycounter:1|c'), fake_socket.recv()) - - @staticmethod - def assert_almost_equal(a, b, delta): - assert 0 <= abs(a - b) <= delta, "%s - %s not within %s" % (a, - b, - delta) - - -if __name__ == '__main__': - unittest.main() diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 00214e1..0000000 --- a/tox.ini +++ /dev/null @@ -1,65 +0,0 @@ -[tox] -envlist = py38,pep8,cover -minversion = 2.5 -skipsdist = True - -[testenv] -basepython = python3 -passenv = http_proxy - HTTP_PROXY - https_proxy - HTTPS_PROXY - no_proxy - NO_PROXY -usedevelop = True -install_command = pip install {opts} {packages} -deps = - -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} - -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt -whitelist_externals = bash - find - rm -commands = - find . -type f -name "*.py[c|o]" -delete - stestr run {posargs} - -[testenv:cover] -description = Calculates code coverage -setenv = - PYTHON=coverage run --source monascastatsd --parallel-mode -commands = - stestr run {posargs} - coverage combine - coverage html -d cover - coverage xml -o cover/coverage.xml - -[testenv:debug] -commands = - oslo_debug_helper -t {toxinidir}/tests {posargs} - -[testenv:docs] -deps = -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} - -r{toxinidir}/doc/requirements.txt -commands = - rm -rf doc/build - python setup.py build_sphinx - -[testenv:bandit] -commands = bandit -r monascastatsd -s B311 -n5 -x monascastatsd/tests - -[testenv:flake8] -commands = flake8 monascastatsd - -[testenv:pep8] -commands = - {[testenv:flake8]commands} - {[testenv:bandit]commands} - -[testenv:venv] -commands = {posargs} - -[flake8] -show-source = True -exclude=.venv,.git,.tox,dist,*egg,build,docs,cover -max-line-length = 100