diff --git a/README.md b/README.md
index c7b9a837c8d..bb199eebd5f 100644
--- a/README.md
+++ b/README.md
@@ -95,11 +95,7 @@ exporter.export([(counter, label_values)])
exporter.shutdown()
```
-See the [API
-documentation](https://open-telemetry.github.io/opentelemetry-python/) for more
-detail, and the
-[opentelemetry-example-app](./examples/opentelemetry-example-app/README.rst)
-for a complete example.
+See the [API documentation](https://open-telemetry.github.io/opentelemetry-python/) for more detail, and the [examples folder](./examples) for a more sample code.
## Contributing
diff --git a/examples/README.md b/examples/README.md
new file mode 100644
index 00000000000..7fcc3f7dc48
--- /dev/null
+++ b/examples/README.md
@@ -0,0 +1,11 @@
+# Examples
+This folder contains various examples to demonstrate using OpenTelemetry.
+
+##### basic_tracer
+This example shows how to use OpenTelemetry to instrument an application - e.g. a batch job.
+
+##### http
+This example shows how to use [OpenTelemetryMiddleware](https://github.com/open-telemetry/opentelemetry-python/tree/master/ext/opentelemetry-ext-wsgi) and [requests](https://github.com/open-telemetry/opentelemetry-python/tree/master/ext/opentelemetry-ext-http-requests) integrations to instrument a client and a server.
+
+##### opentelemetry-example-app
+This package is a complete example of an application instrumented with OpenTelemetry.
\ No newline at end of file
diff --git a/examples/basic_tracer/README.md b/examples/basic_tracer/README.md
new file mode 100644
index 00000000000..4dc0e96bea6
--- /dev/null
+++ b/examples/basic_tracer/README.md
@@ -0,0 +1,62 @@
+# Overview
+
+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](https://www.jaegertracing.io).
+
+## Installation
+
+```sh
+$ pip install opentelemetry-api opentelemetry-sdk
+```
+
+Setup [Jaeger Tracing](https://www.jaegertracing.io/docs/latest/getting-started/#all-in-one)
+
+## Run the Application
+
+### Console
+
+* Run the sample
+
+```bash
+$ # from this directory
+$ python tracer.py
+```
+
+The output will be displayed at the console
+
+```bash
+AsyncRuntimeContext({'current_span': Span(name="baz", context=SpanContext(trace_id=0xf906f80f64d57c71ea8da4dfbbd2ddf2, span_id=0x5611c1407e06e4d7, trace_state={}))})
+Span(name="baz", context=SpanContext(trace_id=0xf906f80f64d57c71ea8da4dfbbd2ddf2, span_id=0x5611c1407e06e4d7, trace_state={}), kind=SpanKind.INTERNAL, parent=Span(name="bar", context=SpanContext(trace_id=0xf906f80f64d57c71ea8da4dfbbd2ddf2, span_id=0x1b9db0e0cc1a3f60, trace_state={})), start_time=2019-11-07T21:26:45.934412Z, end_time=2019-11-07T21:26:45.934567Z)
+Span(name="bar", context=SpanContext(trace_id=0xf906f80f64d57c71ea8da4dfbbd2ddf2, span_id=0x1b9db0e0cc1a3f60, trace_state={}), kind=SpanKind.INTERNAL, parent=Span(name="foo", context=SpanContext(trace_id=0xf906f80f64d57c71ea8da4dfbbd2ddf2, span_id=0x1d5d87441ec2f410, trace_state={})), start_time=2019-11-07T21:26:45.934396Z, end_time=2019-11-07T21:26:45.934576Z)
+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
+
+* Run the sample
+
+```sh
+$ pip install opentelemetry-ext-jaeger
+$ # from this directory
+$ EXPORTER=jaeger python tracer.py
+```
+
+#### Jaeger UI
+
+Open the Jaeger UI in your browser [http://localhost:16686](http://localhost:16686)
+
+
+Select `basic-service` under *Service Name* and click on *Find Traces*.
+
+Click on the trace to view its details.
+
+
+
+## Useful links
+- For more information on OpenTelemetry, visit:
+- For more information on tracing in Python, visit:
+
+## LICENSE
+
+Apache License 2.0
diff --git a/examples/basic_tracer/__init__.py b/examples/basic_tracer/__init__.py
new file mode 100644
index 00000000000..88051cd8bb0
--- /dev/null
+++ b/examples/basic_tracer/__init__.py
@@ -0,0 +1,14 @@
+# pylint: disable=C0103
+# Copyright 2019, OpenTelemetry Authors
+#
+# 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.
diff --git a/examples/basic_tracer/images/jaeger-ui-detail.png b/examples/basic_tracer/images/jaeger-ui-detail.png
new file mode 100644
index 00000000000..63491e132b5
Binary files /dev/null and b/examples/basic_tracer/images/jaeger-ui-detail.png differ
diff --git a/examples/basic_tracer/images/jaeger-ui.png b/examples/basic_tracer/images/jaeger-ui.png
new file mode 100644
index 00000000000..08e6718eef1
Binary files /dev/null and b/examples/basic_tracer/images/jaeger-ui.png differ
diff --git a/examples/basic_tracer/tests/__init__.py b/examples/basic_tracer/tests/__init__.py
new file mode 100644
index 00000000000..d853a7bcf65
--- /dev/null
+++ b/examples/basic_tracer/tests/__init__.py
@@ -0,0 +1,13 @@
+# Copyright 2019, OpenTelemetry Authors
+#
+# 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.
diff --git a/examples/basic_tracer/tests/test_tracer.py b/examples/basic_tracer/tests/test_tracer.py
new file mode 100644
index 00000000000..d5922d6086b
--- /dev/null
+++ b/examples/basic_tracer/tests/test_tracer.py
@@ -0,0 +1,27 @@
+# Copyright 2019, OpenTelemetry Authors
+#
+# 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 os
+import subprocess
+import unittest
+
+
+class TestBasicTracerExample(unittest.TestCase):
+ def test_basic_tracer(self):
+ dirpath = os.path.dirname(os.path.realpath(__file__))
+ test_script = "{}/../tracer.py".format(dirpath)
+ output = subprocess.check_output(test_script).decode()
+
+ self.assertIn('name="foo"', output)
+ self.assertIn('name="bar"', output)
+ self.assertIn('name="baz"', output)
diff --git a/examples/basic_tracer/tracer.py b/examples/basic_tracer/tracer.py
new file mode 100755
index 00000000000..c99141f5aac
--- /dev/null
+++ b/examples/basic_tracer/tracer.py
@@ -0,0 +1,52 @@
+#!/usr/bin/env python3
+#
+# Copyright 2019, OpenTelemetry Authors
+#
+# 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 os
+
+from opentelemetry import trace
+from opentelemetry.context import Context
+from opentelemetry.sdk.trace import Tracer
+from opentelemetry.sdk.trace.export import (
+ BatchExportSpanProcessor,
+ ConsoleSpanExporter,
+)
+
+if os.getenv("EXPORTER") == "jaeger":
+ from opentelemetry.ext.jaeger import JaegerSpanExporter
+
+ exporter = JaegerSpanExporter(
+ service_name="basic-service",
+ agent_host_name="localhost",
+ agent_port=6831,
+ )
+else:
+ exporter = ConsoleSpanExporter()
+
+# The preferred tracer implementation must be set, as the opentelemetry-api
+# defines the interface with a no-op implementation.
+trace.set_preferred_tracer_implementation(lambda T: Tracer())
+tracer = trace.tracer()
+
+# SpanExporter receives the spans and send them to the target location.
+span_processor = BatchExportSpanProcessor(exporter)
+
+tracer.add_span_processor(span_processor)
+with tracer.start_as_current_span("foo"):
+ with tracer.start_as_current_span("bar"):
+ with tracer.start_as_current_span("baz"):
+ print(Context)
+
+span_processor.shutdown()
diff --git a/examples/http/README.md b/examples/http/README.md
new file mode 100644
index 00000000000..5e6f2d7efad
--- /dev/null
+++ b/examples/http/README.md
@@ -0,0 +1,80 @@
+# Overview
+
+This example shows how to use [OpenTelemetryMiddleware](https://github.com/open-telemetry/opentelemetry-python/tree/master/ext/opentelemetry-ext-wsgi) and [requests](https://github.com/open-telemetry/opentelemetry-python/tree/master/ext/opentelemetry-ext-http-requests) integrations to instrument a client and a server in Python.
+It supports exporting spans either to the console or to [Jaeger](https://www.jaegertracing.io).
+
+## Installation
+
+```sh
+$ pip install opentelemetry-api opentelemetry-sdk opentelemetry-ext-wsgi opentelemetry-ext-http-requests
+```
+
+Setup [Jaeger Tracing](https://www.jaegertracing.io/docs/latest/getting-started/#all-in-one)
+
+## Run the Application
+
+### Console
+
+* Run the server
+
+```bash
+$ # from this directory
+$ python server.py
+```
+
+* Run the client from a different terminal
+
+```bash
+$ # from this directory
+$ python tracer_client.py
+```
+
+The output will be displayed at the console on the client side
+
+```bash
+Span(name="/", context=SpanContext(trace_id=0x7c5c0d62031570f00fd106d968139300, span_id=0x3703fd889dcdeb2b, trace_state={}), kind=SpanKind.CLIENT, parent=None, start_time=2019-11-07T21:52:59.591634Z, end_time=2019-11-07T21:53:00.386014Z)
+```
+
+And on the server
+
+```bash
+127.0.0.1 - - [07/Nov/2019 13:53:00] "GET / HTTP/1.1" 200 -
+Span(name="/wiki/Rabbit", context=SpanContext(trace_id=0x7c5c0d62031570f00fd106d968139300, span_id=0x4bf0be462b91d6ef, trace_state={}), kind=SpanKind.CLIENT, parent=Span(name="parent", context=SpanContext(trace_id=0x7c5c0d62031570f00fd106d968139300, span_id=0x68338643ccb2d53b, trace_state={})), start_time=2019-11-07T21:52:59.601597Z, end_time=2019-11-07T21:53:00.380491Z)
+Span(name="parent", context=SpanContext(trace_id=0x7c5c0d62031570f00fd106d968139300, span_id=0x68338643ccb2d53b, trace_state={}), kind=SpanKind.INTERNAL, parent=Span(name="/", context=SpanContext(trace_id=0x7c5c0d62031570f00fd106d968139300, span_id=0x36050ac596949bc1, trace_state={})), start_time=2019-11-07T21:52:59.601233Z, end_time=2019-11-07T21:53:00.384485Z)
+Span(name="/", context=SpanContext(trace_id=0x7c5c0d62031570f00fd106d968139300, span_id=0x36050ac596949bc1, trace_state={}), kind=SpanKind.SERVER, parent=SpanContext(trace_id=0x7c5c0d62031570f00fd106d968139300, span_id=0x3703fd889dcdeb2b, trace_state={}), start_time=2019-11-07T21:52:59.600816Z, end_time=2019-11-07T21:53:00.385322Z)
+```
+
+### Jaeger
+
+* Run the server
+
+```sh
+$ pip install opentelemetry-ext-jaeger
+$ # from this directory
+$ EXPORTER=jaeger python server.py
+```
+
+* Run the client from a different terminal
+
+```bash
+$ EXPORTER=jaeger python tracer_client.py
+```
+
+#### Jaeger UI
+
+Open the Jaeger UI in your browser [http://localhost:16686](http://localhost:16686)
+
+
+Select `http-server` under *Service Name* and click on *Find Traces*.
+
+Click on the trace to view its details.
+
+
+
+## Useful links
+- For more information on OpenTelemetry, visit:
+- For more information on tracing in Python, visit:
+
+## LICENSE
+
+Apache License 2.0
diff --git a/examples/http/__init__.py b/examples/http/__init__.py
new file mode 100644
index 00000000000..d853a7bcf65
--- /dev/null
+++ b/examples/http/__init__.py
@@ -0,0 +1,13 @@
+# Copyright 2019, OpenTelemetry Authors
+#
+# 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.
diff --git a/examples/http/images/jaeger-ui-detail.png b/examples/http/images/jaeger-ui-detail.png
new file mode 100644
index 00000000000..50d1901de6c
Binary files /dev/null and b/examples/http/images/jaeger-ui-detail.png differ
diff --git a/examples/http/images/jaeger-ui.png b/examples/http/images/jaeger-ui.png
new file mode 100644
index 00000000000..02faad1de1e
Binary files /dev/null and b/examples/http/images/jaeger-ui.png differ
diff --git a/examples/http/requirements.txt b/examples/http/requirements.txt
new file mode 100644
index 00000000000..7e1060246fd
--- /dev/null
+++ b/examples/http/requirements.txt
@@ -0,0 +1 @@
+flask
diff --git a/examples/trace/server.py b/examples/http/server.py
similarity index 75%
rename from examples/trace/server.py
rename to examples/http/server.py
index 3632540e213..82cb070c272 100755
--- a/examples/trace/server.py
+++ b/examples/http/server.py
@@ -14,6 +14,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import os
+
import flask
import requests
@@ -22,30 +24,41 @@
from opentelemetry.ext.wsgi import OpenTelemetryMiddleware
from opentelemetry.sdk.trace import Tracer
from opentelemetry.sdk.trace.export import (
+ BatchExportSpanProcessor,
ConsoleSpanExporter,
- SimpleExportSpanProcessor,
)
+if os.getenv("EXPORTER") == "jaeger":
+ from opentelemetry.ext.jaeger import JaegerSpanExporter
+
+ exporter = JaegerSpanExporter(
+ service_name="http-server",
+ agent_host_name="localhost",
+ agent_port=6831,
+ )
+else:
+ exporter = ConsoleSpanExporter()
+
# The preferred tracer implementation must be set, as the opentelemetry-api
# defines the interface with a no-op implementation.
trace.set_preferred_tracer_implementation(lambda T: Tracer())
+tracer = trace.tracer()
+
+# SpanExporter receives the spans and send them to the target location.
+span_processor = BatchExportSpanProcessor(exporter)
+tracer.add_span_processor(span_processor)
# Integrations are the glue that binds the OpenTelemetry API and the
# frameworks and libraries that are used together, automatically creating
# Spans and propagating context as appropriate.
-http_requests.enable(trace.tracer())
-
-# SpanExporter receives the spans and send them to the target location.
-span_processor = SimpleExportSpanProcessor(ConsoleSpanExporter())
-trace.tracer().add_span_processor(span_processor)
-
+http_requests.enable(tracer)
app = flask.Flask(__name__)
app.wsgi_app = OpenTelemetryMiddleware(app.wsgi_app)
@app.route("/")
def hello():
- with trace.tracer().start_as_current_span("parent"):
+ with tracer.start_as_current_span("parent"):
requests.get("https://www.wikipedia.org/wiki/Rabbit")
return "hello"
diff --git a/examples/http/tests/__init__.py b/examples/http/tests/__init__.py
new file mode 100644
index 00000000000..d853a7bcf65
--- /dev/null
+++ b/examples/http/tests/__init__.py
@@ -0,0 +1,13 @@
+# Copyright 2019, OpenTelemetry Authors
+#
+# 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.
diff --git a/examples/http/tests/test_http.py b/examples/http/tests/test_http.py
new file mode 100644
index 00000000000..7aa3f93c153
--- /dev/null
+++ b/examples/http/tests/test_http.py
@@ -0,0 +1,36 @@
+# Copyright 2019, OpenTelemetry Authors
+#
+# 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 os
+import subprocess
+import unittest
+from time import sleep
+
+
+class TestHttpExample(unittest.TestCase):
+ @classmethod
+ def setup_class(cls):
+ dirpath = os.path.dirname(os.path.realpath(__file__))
+ server_script = "{}/../server.py".format(dirpath)
+ cls.server = subprocess.Popen([server_script])
+ sleep(1)
+
+ def test_http(self):
+ dirpath = os.path.dirname(os.path.realpath(__file__))
+ test_script = "{}/../tracer_client.py".format(dirpath)
+ output = subprocess.check_output(test_script).decode()
+ self.assertIn('name="/"', output)
+
+ @classmethod
+ def teardown_class(cls):
+ cls.server.terminate()
diff --git a/examples/trace/client.py b/examples/http/tracer_client.py
similarity index 79%
rename from examples/trace/client.py
rename to examples/http/tracer_client.py
index 662cea8d969..671d1d71f91 100755
--- a/examples/trace/client.py
+++ b/examples/http/tracer_client.py
@@ -14,29 +14,41 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import os
+
import requests
from opentelemetry import trace
from opentelemetry.ext import http_requests
from opentelemetry.sdk.trace import Tracer
from opentelemetry.sdk.trace.export import (
+ BatchExportSpanProcessor,
ConsoleSpanExporter,
- SimpleExportSpanProcessor,
)
+if os.getenv("EXPORTER") == "jaeger":
+ from opentelemetry.ext.jaeger import JaegerSpanExporter
+
+ exporter = JaegerSpanExporter(
+ service_name="http-client",
+ agent_host_name="localhost",
+ agent_port=6831,
+ )
+else:
+ exporter = ConsoleSpanExporter()
+
# The preferred tracer implementation must be set, as the opentelemetry-api
# defines the interface with a no-op implementation.
trace.set_preferred_tracer_implementation(lambda T: Tracer())
tracer = trace.tracer()
+# SpanExporter receives the spans and send them to the target location.
+span_processor = BatchExportSpanProcessor(exporter)
+tracer.add_span_processor(span_processor)
+
# Integrations are the glue that binds the OpenTelemetry API and the
# frameworks and libraries that are used together, automatically creating
# Spans and propagating context as appropriate.
http_requests.enable(tracer)
-
-# SpanExporter receives the spans and send them to the target location.
-span_processor = SimpleExportSpanProcessor(ConsoleSpanExporter())
-tracer.add_span_processor(span_processor)
-
response = requests.get(url="http://127.0.0.1:5000/")
span_processor.shutdown()
diff --git a/tox.ini b/tox.ini
index e0e076fe77d..82512ebd8aa 100644
--- a/tox.ini
+++ b/tox.ini
@@ -2,8 +2,8 @@
skipsdist = True
skip_missing_interpreters = True
envlist =
- py3{4,5,6,7,8}-test-{api,sdk,example-app,ext-wsgi,ext-http-requests,ext-jaeger,ext-pymongo,opentracing-shim}
- pypy3-test-{api,sdk,example-app,ext-wsgi,ext-http-requests,ext-jaeger,ext-pymongo,opentracing-shim}
+ py3{4,5,6,7,8}-test-{api,sdk,example-app,example-basic-tracer,example-http,ext-wsgi,ext-http-requests,ext-jaeger,ext-pymongo,opentracing-shim}
+ pypy3-test-{api,sdk,example-app,example-basic-tracer,example-http,ext-wsgi,ext-http-requests,ext-jaeger,ext-pymongo,opentracing-shim}
py3{4,5,6,7,8}-coverage
; Coverage is temporarily disabled for pypy3 due to the pytest bug.
@@ -35,6 +35,8 @@ changedir =
test-ext-pymongo: ext/opentelemetry-ext-pymongo/tests
test-ext-wsgi: ext/opentelemetry-ext-wsgi/tests
test-example-app: examples/opentelemetry-example-app/tests
+ test-example-basic-tracer: examples/basic_tracer/tests
+ test-example-http: examples/http/tests
test-opentracing-shim: ext/opentelemetry-ext-opentracing-shim/tests
commands_pre =
@@ -46,6 +48,14 @@ commands_pre =
example-app: pip install {toxinidir}/ext/opentelemetry-ext-http-requests
example-app: pip install {toxinidir}/ext/opentelemetry-ext-wsgi
example-app: pip install {toxinidir}/examples/opentelemetry-example-app
+ example-basic-tracer: pip install -e {toxinidir}/opentelemetry-api
+ example-basic-tracer: pip install -e {toxinidir}/opentelemetry-sdk
+ example-http: pip install -e {toxinidir}/opentelemetry-api
+ example-http: pip install -e {toxinidir}/opentelemetry-sdk
+ example-http: pip install -e {toxinidir}/ext/opentelemetry-ext-http-requests
+ example-http: pip install -e {toxinidir}/ext/opentelemetry-ext-wsgi
+ example-http: pip install -r {toxinidir}/examples/http/requirements.txt
+
ext: pip install {toxinidir}/opentelemetry-api
wsgi: pip install {toxinidir}/ext/opentelemetry-ext-wsgi
pymongo: pip install {toxinidir}/ext/opentelemetry-ext-pymongo
@@ -122,7 +132,9 @@ commands =
ext/opentelemetry-ext-pymongo/tests/ \
ext/opentelemetry-ext-wsgi/tests/ \
examples/opentelemetry-example-app/src/opentelemetry_example_app/ \
- examples/opentelemetry-example-app/tests/
+ examples/opentelemetry-example-app/tests/ \
+ examples/basic_tracer/ \
+ examples/http/
flake8 .
isort --check-only --diff --recursive .