Skip to content
This repository was archived by the owner on Sep 17, 2025. It is now read-only.

Commit 8e4ce16

Browse files
kcoopersteinliyanhui1228
authored andcommitted
[WIP] Implementation of Python Stats API (#149)
1 parent b7ff72d commit 8e4ce16

38 files changed

+2464
-58
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ develop-eggs
1919
lib
2020
lib64
2121
__pycache__
22+
venv/
2223

2324
# Installer logs
2425
pip-log.txt
@@ -53,6 +54,7 @@ docs/_build_doc2dash
5354

5455
# Virtual environment
5556
env/
57+
venv/
5658
coverage.xml
5759

5860
# System test environment variables.

docs/trace/usage.rst

Lines changed: 59 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
OpenCensus Trace for Python
2-
===========================
1+
OpenCensus for Python - A stats collection and distributed tracing framework
2+
============================================================================
33

44
`Census`_ for Python. Census provides a framework to measure a server's resource
55
usage and collect performance stats. This repository contains Python related
@@ -14,7 +14,7 @@ OpenCensus Trace for Python
1414

1515
- `API Documentation`_
1616

17-
.. _API Documentation: http://opencensus.io/opencensus-python/trace/usage.html
17+
.. _API Documentation: https://opencensus.io/api/python/trace/usage.html
1818

1919
Installation & basic usage
2020
--------------------------
@@ -23,14 +23,10 @@ Installation & basic usage
2323

2424
::
2525

26-
pip install opencensus-trace
27-
pipenv install opencensus-trace
26+
pip install opencensus
27+
pipenv install opencensus
2828

29-
# install the Stackdriver exporter by including the extras package
30-
pip install opencensus-trace[stackdriver]
31-
pipenv install opencensus-trace[stackdriver]
32-
33-
2. Initialize a tracer for application:
29+
2. Initialize a tracer for your application:
3430

3531
.. code:: python
3632
@@ -135,7 +131,7 @@ Propagators
135131
~~~~~~~~~~~
136132

137133
You can specify the propagator type for serializing and deserializing the
138-
``SpanContex`` and its headers. There are currently two built in propagators:
134+
``SpanContext`` and its headers. There are currently two built in propagators:
139135
``GoogleCloudFormatPropagator`` and ``TextFormatPropagator``.
140136

141137
This example shows how to use the ``GoogleCloudFormatPropagator``:
@@ -186,8 +182,8 @@ For Django, you can configure the blacklist in the ``OPENCENSUS_PARAMS`` in ``se
186182
Framework Integration
187183
---------------------
188184

189-
Opencensus supports integration with popular web frameworks including
190-
Django, Flask, and Webapp2. When the application receives a HTTP request,
185+
Census supports integration with popular web frameworks including
186+
Django, Flask, Pyramid, and Webapp2. When the application receives a HTTP request,
191187
the tracer will automatically generate a span context using the trace
192188
information extracted from the request headers, and propagated to the
193189
child spans.
@@ -209,41 +205,6 @@ requests will be automatically traced.
209205
# `GoogleCloudFormatPropagator` as propagator.
210206
middleware = FlaskMiddleware(app)
211207
212-
The middleware also supports the factory pattern.
213-
214-
.. code:: python
215-
216-
from opencensus.trace.ext.flask.flask_middleware import FlaskMiddleware
217-
middleware = FlaskMiddleware()
218-
app = flask.Flask(__name__)
219-
middleware.init_app(app)
220-
221-
The Flask application configuration can also be used to specify the sampler,
222-
exporter, propagator in the middleware.
223-
224-
.. code:: python
225-
226-
OPENCENSUS_TRACE = {
227-
'SAMPLER': opencensus.trace.samplers.probability.ProbabilitySampler,
228-
'REPORTER': opencensus.trace.exporters.print_exporter.PrintExporter,
229-
'PROPAGATOR': opencensus.trace.propagation.google_cloud_format.
230-
GoogleCloudFormatPropagator,
231-
}
232-
233-
You can configure the sampling rate and other parameters using the ``OPENCENSUS_TRACE_PARAMS``
234-
key in the app configuration:
235-
236-
.. code:: python
237-
238-
OPENCENSUS_TRACE_PARAMS = {
239-
'BLACKLIST_PATHS': ['/_ah/health'],
240-
'GCP_EXPORTER_PROJECT': None,
241-
'SAMPLING_RATE': 0.5,
242-
'ZIPKIN_EXPORTER_SERVICE_NAME': 'my_service',
243-
'ZIPKIN_EXPORTER_HOST_NAME': 'localhost',
244-
'ZIPKIN_EXPORTER_PORT': 9411,
245-
}
246-
247208
Django
248209
~~~~~~
249210

@@ -266,7 +227,7 @@ And add this line to the ``INSTALLED_APPS`` section:
266227
'opencensus.trace.ext.django',
267228
]
268229
269-
You can configure the the sampler, exporter, propagator using the ``OPENCENSUS_TRACE`` setting in
230+
You can configure the sampler, exporter, propagator using the ``OPENCENSUS_TRACE`` setting in
270231
``settings.py``:
271232

272233
.. code:: python
@@ -292,18 +253,56 @@ setting in ``settings.py``:
292253
'ZIPKIN_EXPORTER_PORT': 9411,
293254
}
294255
295-
Webapp2
256+
257+
Pyramid
296258
~~~~~~~
297259

260+
In your application, add the pyramid tween and your requests will be
261+
traced.
262+
298263
.. code:: python
299264
300-
from opencensus.trace.tracers import webapp2_tracer
265+
def main(global_config, **settings):
266+
config = Configurator(settings=settings)
301267
302-
tracer = webapp2_tracer.WebApp2Tracer()
268+
config.add_tween('opencensus.trace.ext.pyramid'
269+
'.pyramid_middleware.OpenCensusTweenFactory')
303270
304-
with tracer.span(name='span1'):
305-
do_something_to_trace()
271+
To configure the sampler, exporter, and propagator, pass the instances
272+
into the pyramid settings
273+
274+
.. code:: python
306275
276+
from opencensus.trace.exporters import print_exporter
277+
from opencensus.trace.propagation import google_cloud_format
278+
from opencensus.trace.samplers import probability
279+
280+
settings = {}
281+
settings['OPENCENSUS_TRACE'] = {
282+
'EXPORTER': print_exporter.PrintExporter(),
283+
'SAMPLER': probability.ProbabilitySampler(rate=0.5),
284+
'PROPAGATOR': google_cloud_format.GoogleCloudFormatPropagator(),
285+
}
286+
287+
config = Configurator(settings=settings)
288+
289+
gRPC Integration
290+
----------------
291+
292+
OpenCensus provides the implementation of interceptors for both the client side
293+
and server side to instrument the gRPC requests and responses. The client
294+
interceptors are used to create a decorated channel that intercepts client
295+
gRPC calls and server interceptors act as decorators over handlers.
296+
297+
gRPC interceptor is a new feature in the grpcio1.8.0 release, please upgrade
298+
your grpcio to the latest version to use this feature.
299+
300+
For sample usage, please refer to the hello world example in the examples
301+
directory.
302+
303+
More information about the gRPC interceptors please see the `proposal`_.
304+
305+
.. _proposal: https://github.com/mehrdada/proposal/blob/python-interceptors/L13-Python-Interceptors.md
307306

308307
Service Integration
309308
-------------------
@@ -345,22 +344,24 @@ to ``trace_integrations`` using ``'postgresql'``.
345344
SQLAlchemy
346345
~~~~~~~~~~
347346

348-
You can trace usage of `sqlalchemy package`_, regardless of the underlying database, by
349-
specifying ``'sqlalchemy'`` to ``trace_integrations``.
347+
You can trace usage of the `sqlalchemy package`_, regardless of the underlying
348+
database, by specifying ``'sqlalchemy'`` to ``trace_integrations``.
350349

351350
.. _SQLAlchemy package: https://pypi.org/project/SQLAlchemy
352351

353-
.. note:: If you enable tracing of SQLAlchemy and the underlying database
352+
.. note:: If you enable tracing of SQLAlchemy as well as the underlying database
354353
driver, you will get duplicate spans. Instead, just trace SQLAlchemy.
355354

356355
Requests
357356
~~~~~~~~
358357

359-
Census can trace HTTP requests made with the `Requests`_ library. The request URL,
358+
Census can trace HTTP requests made with the `Requests package`_. The request URL,
360359
method, and status will be collected.
361360

362361
You can enable Requests integration by specifying ``'requests'`` to ``trace_integrations``.
363362

363+
.. _Requests package: https://pypi.python.org/pypi/requests
364+
364365

365366
Contributing
366367
------------

opencensus/stats/__init__.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright 2018, OpenCensus Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.

opencensus/stats/aggregation.py

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# Copyright 2018, OpenCensus Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from opencensus.stats import bucket_boundaries
16+
from opencensus.stats import aggregation_data
17+
18+
19+
class BaseAggregation(object):
20+
"""Aggregation describes how the data collected is aggregated by type of
21+
aggregation and buckets
22+
23+
:type buckets: list(:class: '~opencensus.stats.bucket_boundaries.
24+
BucketBoundaries')
25+
:param buckets: list of endpoints if the aggregation represents a
26+
distribution
27+
28+
"""
29+
def __init__(self, buckets=None):
30+
self._aggregation_type = "none"
31+
self._buckets = buckets or []
32+
33+
@property
34+
def aggregation_type(self):
35+
"""The aggregation type of the current aggregation"""
36+
return self._aggregation_type
37+
38+
@property
39+
def buckets(self):
40+
"""The buckets of the current aggregation"""
41+
return self._buckets
42+
43+
44+
class SumAggregation(BaseAggregation):
45+
"""Sum Aggregation escribes that data collected and aggregated with this
46+
method will be summed
47+
48+
:type sum: int or float
49+
:param sum: the sum of the data collected and aggregated
50+
51+
"""
52+
def __init__(self, sum=None):
53+
super(SumAggregation, self).__init__()
54+
self._aggregation_type = "sum"
55+
if sum is not None:
56+
self._sum = aggregation_data.SumAggregationDataFloat(sum_data=sum)
57+
else:
58+
self._sum = aggregation_data.SumAggregationDataFloat(sum_data=0)
59+
60+
@property
61+
def aggregation_type(self):
62+
"""The aggregation type of the current aggregation"""
63+
return self._aggregation_type
64+
65+
@property
66+
def sum(self):
67+
"""The sum of the current aggregation"""
68+
return self._sum
69+
70+
71+
class CountAggregation(BaseAggregation):
72+
"""Describes that the data collected and aggregated with this method will
73+
be turned into a count value
74+
75+
:type count: int
76+
:param count: represents the count of this aggregation
77+
78+
"""
79+
def __init__(self, count=0):
80+
super(CountAggregation, self).__init__()
81+
self._aggregation_type = "count"
82+
self._count = aggregation_data.CountAggregationData(count)
83+
84+
@property
85+
def aggregation_type(self):
86+
"""The aggregation type of the current aggregation"""
87+
return self._aggregation_type
88+
89+
@property
90+
def count(self):
91+
"""The count of the current aggregation"""
92+
return self._count
93+
94+
95+
class DistributionAggregation(BaseAggregation):
96+
"""Distribution Aggregation indicates that the desired aggregation is a
97+
histogram distribution
98+
99+
:type boundaries: list(:class:'~opencensus.stats.bucket_boundaries.
100+
BucketBoundaries')
101+
:param boundaries: the bucket endpoints
102+
103+
:type distribution: histogram
104+
:param distribution: histogram of the values of the population
105+
106+
"""
107+
def __init__(self, boundaries=None, distribution=None):
108+
super(DistributionAggregation, self).__init__(boundaries)
109+
self._aggregation_type = "distribution"
110+
self._boundaries = bucket_boundaries.BucketBoundaries(boundaries)
111+
self._distribution = distribution if distribution is not None else {}
112+
113+
@property
114+
def aggregation_type(self):
115+
"""The aggregation type of the current aggregation"""
116+
return self._aggregation_type
117+
118+
@property
119+
def boundaries(self):
120+
"""The boundaries of the current aggregation"""
121+
return self._boundaries
122+
123+
@property
124+
def distribution(self):
125+
"""The distribution of the current aggregation"""
126+
return self._distribution

0 commit comments

Comments
 (0)