Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reorganize examples and improve ext packages documentation #483

Merged
merged 13 commits into from
Mar 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ flask~=1.0
mysql-connector-python ~= 8.0
wrapt >= 1.0.0, < 2.0.0
psycopg2-binary >= 2.7.3.1
prometheus_client >= 0.5.0, < 1.0.0
42 changes: 42 additions & 0 deletions docs/examples/basic_meter/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
Basic Meter
===========

These examples show how to use OpenTelemetry to capture and report metrics.

There are three different examples:

* basic_metrics: Shows to how create a metric instrument, how to configure an
exporter and a controller and also how to capture data by using the direct
calling convention.

* calling_conventions: Shows how to use the direct, bound and batch calling conventions.

* observer: Shows how to use the observer instrument.

The source files of these examples are available :scm_web:`here <docs/examples/metrics/>`.

Installation
------------

.. code-block:: sh

pip install opentelemetry-api
pip install opentelemetry-sdk
pip install psutil # needed to get ram and cpu usage in the observer example

Run the Example
---------------

.. code-block:: sh

python <example_name>.py

The output will be shown in the console after few seconds.

Useful links
------------

- OpenTelemetry_
- :doc:`../../api/metrics`

.. _OpenTelemetry: https://github.com/open-telemetry/opentelemetry-python/
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
# limitations under the License.
#
"""
This module serves as an example for a simple application using metrics
This module serves as an example for a simple application using metrics.

It shows:
- How to configure a meter passing a sateful or stateless.
- How to configure an exporter and how to create a controller.
Expand All @@ -27,7 +28,7 @@
from opentelemetry.sdk.metrics.export import ConsoleMetricsExporter
from opentelemetry.sdk.metrics.export.controller import PushController

batcher_mode = "stateful"
stateful = True


def usage(argv):
Expand All @@ -42,6 +43,11 @@ def usage(argv):
print("bad mode specified.")
usage(sys.argv)
sys.exit(1)
stateful = batcher_mode == "stateful"

print(
"Starting example, values will be printed to the console every 5 seconds."
)


# The Meter is responsible for creating and recording metrics. Each meter has a
Expand All @@ -57,7 +63,7 @@ def usage(argv):

# A PushController collects metrics created from meter and exports it via the
# exporter every interval
controller = PushController(meter, exporter, 5)
controller = PushController(meter=meter, exporter=exporter, interval=5)

# Metric instruments allow to capture measurements
requests_counter = meter.create_metric(
Expand All @@ -69,15 +75,6 @@ def usage(argv):
label_keys=("environment",),
)

clicks_counter = meter.create_metric(
name="clicks",
description="number of clicks",
unit="1",
value_type=int,
metric_type=Counter,
label_keys=("environment",),
)

requests_size = meter.create_metric(
name="requests_size",
description="size of requests",
Expand All @@ -94,17 +91,14 @@ def usage(argv):
testing_label_set = meter.get_label_set({"environment": "testing"})

# Update the metric instruments using the direct calling convention
requests_size.record(100, staging_label_set)
requests_counter.add(25, staging_label_set)
requests_size.record(100, staging_label_set)
time.sleep(5)

requests_size.record(5000, staging_label_set)
requests_counter.add(50, staging_label_set)
requests_size.record(5000, staging_label_set)
time.sleep(5)

requests_size.record(2, testing_label_set)
requests_counter.add(35, testing_label_set)
time.sleep(5)

clicks_counter.add(5, staging_label_set)
requests_size.record(2, testing_label_set)
time.sleep(5)
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,23 @@
# limitations under the License.
#
"""
This module serves as an example for a simple application using metrics.
It demonstrates the different ways you can record metrics via the meter.
This example shows how to use the different modes to capture metrics.
It shows the usage of the direct, bound and batch calling conventions.
"""
import time

from opentelemetry import metrics
from opentelemetry.sdk.metrics import Counter, MeterProvider
from opentelemetry.sdk.metrics import Counter, Measure, MeterProvider
from opentelemetry.sdk.metrics.export import ConsoleMetricsExporter
from opentelemetry.sdk.metrics.export.controller import PushController

# Use the meter type provided by the SDK package
metrics.set_meter_provider(MeterProvider())
# Meter is responsible for creating and recording metrics
meter = metrics.get_meter(__name__)
# exporter to export metrics to the console
exporter = ConsoleMetricsExporter()
# controller collects metrics created from meter and exports it via the
# exporter every interval
controller = PushController(meter=meter, exporter=exporter, interval=5)

# Example to show how to record using the meter
counter = meter.create_metric(
requests_counter = meter.create_metric(
name="requests",
description="number of requests",
unit="1",
Expand All @@ -43,7 +38,16 @@
label_keys=("environment",),
)

counter2 = meter.create_metric(
requests_size = meter.create_metric(
name="requests_size",
description="size of requests",
unit="1",
value_type=int,
metric_type=Measure,
label_keys=("environment",),
)

clicks_counter = meter.create_metric(
name="clicks",
description="number of clicks",
unit="1",
Expand All @@ -52,36 +56,27 @@
label_keys=("environment",),
)

# Labelsets are used to identify key-values that are associated with a specific
# metric that you want to record. These are useful for pre-aggregation and can
# be used to store custom dimensions pertaining to a metric

# The meter takes a dictionary of key value pairs
label_set = meter.get_label_set({"environment": "staging"})

# Bound instrument usage
print("Updating using direct calling convention...")
# You can record metrics directly using the metric instrument. You pass in a
# labelset that you would like to record for.
requests_counter.add(25, label_set)
time.sleep(5)

print("Updating using a bound instrument...")
# You can record metrics with bound metric instruments. Bound metric
# instruments are created by passing in a labelset. A bound metric instrument
# is essentially metric data that corresponds to a specific set of labels.
# Therefore, getting a bound metric instrument using the same set of labels
# will yield the same bound metric instrument.
bound_counter = counter.bind(label_set)
for i in range(1000):
bound_counter.add(i)

# You can release the bound instrument we you are done
bound_counter.release()

# Direct metric usage
# You can record metrics directly using the metric instrument. You pass in a
# labelset that you would like to record for.
counter.add(25, label_set)
bound_requests_counter = requests_counter.bind(label_set)
bound_requests_counter.add(100)
time.sleep(5)

# Record batch usage
print("Updating using batch calling convention...")
# You can record metrics in a batch by passing in a labelset and a sequence of
# (metric, value) pairs. The value would be recorded for each metric using the
# specified labelset for each.
meter.record_batch(label_set, [(counter, 50), (counter2, 70)])

time.sleep(10)
meter.record_batch(label_set, ((requests_counter, 50), (clicks_counter, 70)))
time.sleep(5)
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,9 @@

# Configure a stateful batcher
batcher = UngroupedBatcher(stateful=True)

metrics.set_meter_provider(MeterProvider())
meter = metrics.get_meter(__name__)

# Exporter to export metrics to the console
exporter = ConsoleMetricsExporter()

# Configure a push controller
controller = PushController(meter=meter, exporter=exporter, interval=2)


Expand Down Expand Up @@ -69,4 +64,4 @@ def get_ram_usage_callback(observer):
label_keys=(),
)

input("Press a key to finish...\n")
input("Metrics will be printed soon. Press a key to finish...\n")
61 changes: 12 additions & 49 deletions docs/examples/basic_tracer/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,25 @@ Basic Tracer
============

This example shows how to use OpenTelemetry to instrument a Python application - e.g. a batch job.
It supports exporting spans either to the console or to Jaeger_.

The source files required to run this example are available :scm_web:`here <docs/examples/basic_tracer/>`.
The source files of this example are available :scm_web:`here <docs/examples/basic_tracer/>`.

Installation
------------

Run the application
-------------------
.. code-block:: sh

Console
*******
pip install opentelemetry-api
pip install opentelemetry-sdk

* Run the sample
Run the Example
---------------

.. code-block:: sh

$ python tracer.py
python tracer.py

The output will be displayed at the console
The output will be displayed in the console:

::

Expand All @@ -29,48 +30,10 @@ The output will be displayed at the console
Span(name="foo", context=SpanContext(trace_id=0xf906f80f64d57c71ea8da4dfbbd2ddf2, span_id=0x1d5d87441ec2f410, trace_state={}), kind=SpanKind.INTERNAL, parent=None, start_time=2019-11-07T21:26:45.934369Z, end_time=2019-11-07T21:26:45.934580Z)


Jaeger
******

Setup `Jaeger Tracing <https://www.jaegertracing.io/docs/latest/getting-started/#all-in-one>`_.

* Run the sample

.. code-block:: sh

$ pip install opentelemetry-ext-jaeger
$ EXPORTER=jaeger python tracer.py


The traces should be available in the Jaeger UI at `<http://localhost:16686>`_


Collector
*********

* Start Collector

.. code-block:: sh

$ pip install docker-compose
$ cd docker
$ docker-compose up

* Run the sample

.. code-block:: sh

$ pip install opentelemetry-ext-otcollector
$ EXPORTER=collector python tracer.py


Collector is configured to export to Jaeger, follow Jaeger UI instructions to find the traces.

Useful links
------------

- For more information on OpenTelemetry, visit OpenTelemetry_.
- For more information on tracing in Python, visit Jaeger_.
- OpenTelemetry_
- :doc:`../../api/trace`

.. _Jaeger: https://www.jaegertracing.io/
.. _OpenTelemetry: https://github.com/open-telemetry/opentelemetry-python/
26 changes: 4 additions & 22 deletions docs/examples/basic_tracer/tracer.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,35 +23,17 @@
ConsoleSpanExporter,
)

if os.getenv("EXPORTER") == "jaeger":
from opentelemetry.ext.jaeger import JaegerSpanExporter

print("Using JaegerSpanExporter")
exporter = JaegerSpanExporter(
service_name="basic-service",
agent_host_name="localhost",
agent_port=6831,
)
elif os.getenv("EXPORTER") == "collector":
from opentelemetry.ext.otcollector.trace_exporter import (
CollectorSpanExporter,
)

print("Using CollectorSpanExporter")
exporter = CollectorSpanExporter(
service_name="basic-service", endpoint="localhost:55678"
)
else:
print("Using ConsoleSpanExporter")
exporter = ConsoleSpanExporter()

# The preferred tracer implementation must be set, as the opentelemetry-api
# defines the interface with a no-op implementation.
trace.set_tracer_provider(TracerProvider())

# We tell OpenTelemetry who it is that is creating spans. In this case, we have
# no real name (no setup.py), so we make one up. If we had a version, we would
# also specify it here.
tracer = trace.get_tracer(__name__)

# SpanExporter receives the spans and send them to the target location.
exporter = ConsoleSpanExporter()
span_processor = BatchExportSpanProcessor(exporter)
trace.get_tracer_provider().add_span_processor(span_processor)

Expand Down
Loading