Skip to content

Commit 912ccc3

Browse files
authored
feat: make trace demo application use OpenTelemetry (GoogleCloudPlatform#8428)
removes trace demo application that using OpenCensus from the repo. makes the removed demo's README file to reference to the active demo. modifies the OpenTelemetry based demo so it has functional parity with the removed demo. removes manual span creation that with OT leads to orphan span ingestion. adds comment explaining needlessness of manual trace context creation. updates README to refresh the instructions for OT version of the demo app. refactors `setup.sh` to include building image into the script. removes container building to improve deployment time and instead uses predeployed (in gcr.io/google_samples) image. fixes distinct traces by adding request instrumentation.
1 parent b04113a commit 912ccc3

21 files changed

+340
-635
lines changed

trace/cloud-trace-demo-app-opentelemetry/README.md

Lines changed: 106 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,73 +2,120 @@
22

33
Open this demo app in [Google Cloud Shell](https://cloud.google.com/shell/docs/). This includes necessary tools.
44

5-
65
[![Open Cloud Trace Demo APP in Cloud Shell](http://gstatic.com/cloudssh/images/open-btn.svg)](https://console.cloud.google.com/cloudshell/open?cloudshell_git_repo=https://github.com/GoogleCloudPlatform/python-docs-samples&page=editor&open_in_editor=trace/cloud-trace-demo-app/README.md&cloudshell_tutorial=trace/cloud-trace-demo-app/README.md)
76

8-
#### Demo Requirements
7+
## Demo Requirements
8+
99
If you are using Cloud Shell, skip to the next section.
1010

1111
1. Install gcloud <https://cloud.google.com/sdk/install>
1212
2. Install kubectl <https://kubernetes.io/docs/tasks/tools/install-kubectl/>
1313
3. Install docker <https://docs.docker.com/install/>
1414

15-
16-
#### Create a GKE cluster
17-
18-
4. Enable Google Cloud and set up region and zone.
19-
20-
`gcloud init`
21-
5. Enable the GKE API & billing:
22-
23-
`gcloud services enable container.googleapis.com`
24-
6. Create a GKE cluster named "cloud-trace-demo", replacing `your-gcp-zone` below
25-
with the
26-
[GCP Zone](https://cloud.google.com/compute/docs/regions-zones) closest in proximity to you:
27-
28-
```
29-
gcloud container clusters create cloud-trace-demo\`
30-
--num-nodes 1 \
31-
--enable-basic-auth \
32-
--issue-client-certificate \
33-
--zone your-gcp-zone
34-
```
35-
7. Verify that you have access to the cluster:
36-
37-
`kubectl get nodes`
38-
39-
#### Deploy The Cloud Trace Demo App
40-
41-
8. Build and tag the docker image for demo app:
42-
43-
`docker build -t gcr.io/${PROJECT_ID}/cloud-trace-demo:v1 .`
44-
9. Deploy resource to the cluster:
45-
46-
`kubectl apply -f deployment.yaml`
47-
10. Track the status of the deployment:
48-
49-
`kubectl get deployments`
50-
51-
Deployment is complete when all of the available deployments are ready.
52-
11. Run the following command to see the pods the deployment created:
53-
54-
`kubectl get pods`
55-
56-
#### Deploy The Cloud Trace Demo Service
57-
58-
12. Create the cloud trace demo service:
59-
60-
`kubectl apply -f service.yaml`
61-
13. Get the services IP address by running the following command:
62-
63-
`kubectl get services`
64-
14. Send a curl request to the EXTERNAL_IP, replacing `EXTERNAL_IP` with the external IP address found
65-
in step 13:
66-
67-
`curl EXTERNAL_IP`
68-
15. Visit [Trace List](https://console.cloud.google.com/traces/list) to check traces generated.
15+
## Deploy and run the demo application
16+
17+
1. Enable Google Cloud and set up region and zone.
18+
19+
```bash
20+
gcloud init
21+
```
22+
23+
1. Enable the GKE API:
24+
25+
```bash
26+
gcloud services enable container.googleapis.com
27+
```
28+
29+
1. Setup GCP project to `YOUR_PROJECT_ID`. Replace `YOUR_PROJECT_ID` with your GCP project id.
30+
31+
```bash
32+
gcloud config set project YOUR_PROJECT_ID
33+
```
34+
35+
1. Setup the location of GKE cluster and create a new cluster named
36+
`cloud-trace-demo`.
37+
The example below sets the cluster's location to the "us-central1-c" zone.
38+
You can replace the zone with one which you like. See [zones][] for the full
39+
list.
40+
41+
```bash
42+
ZONE=us-central1-c
43+
gcloud container clusters create cloud-trace-demo \
44+
--zone $ZONE
45+
```
46+
47+
1. Update GKE cluster credentials and verify the access to the cluster:
48+
49+
```bash
50+
gcloud container clusters get-credentials cloud-trace-demo --zone $ZONE
51+
kubectl get nodes
52+
```
53+
54+
The output is similar to the following:
55+
56+
```bash
57+
NAME STATUS ROLES AGE VERSION
58+
gke-cloud-trace-demo-default-pool-43f3fe97-dnk1 Ready <none> 5m v1.23.8-gke.1900
59+
gke-cloud-trace-demo-default-pool-43f3fe97-j2b8 Ready <none> 5m v1.23.8-gke.1900
60+
gke-cloud-trace-demo-default-pool-43f3fe97-znvv Ready <none> 5m v1.23.8-gke.1900
61+
```
62+
63+
1. Download the demo application:
64+
65+
```bash
66+
git clone https://github.com/GoogleCloudPlatform/python-docs-samples
67+
cd python-docs-samples/trace/cloud-trace-demo-app-opentelemetry/
68+
```
69+
70+
1. Setup the application:
71+
72+
```bash
73+
./setup.sh
74+
```
75+
76+
The setup deployes 3 services of the demo application using a pre-built
77+
image. If you like, you can build your own container image using
78+
[`app/Dockerfile`][dockerfile].
79+
80+
1. Track the status of the deployment:
81+
82+
```bash
83+
kubectl get deployments
84+
```
85+
86+
The output is similar to the following:
87+
88+
```bash
89+
NAME READY UP-TO-DATE AVAILABLE AGE
90+
cloud-trace-demo-a 1/1 1 1 3m
91+
cloud-trace-demo-b 1/1 1 1 3m
92+
cloud-trace-demo-c 1/1 1 1 3m
93+
```
94+
95+
1. Send a curl request to the cloud-trace-demo-a:
96+
97+
```bash
98+
curl $(kubectl get svc -o=jsonpath='{.items[?(@.metadata.name=="cloud-trace-demo-a")].status.loadBalancer.ingress[0].ip}')
99+
```
100+
101+
The output is similar to the following:
102+
103+
```bash
104+
Hello, I am service A
105+
And I am service B
106+
Hello, I am service C
107+
```
108+
109+
1. Visit [Trace List](https://console.cloud.google.com/traces/list) to check traces generated.
69110
Click on any trace in the graph to see the Waterfall View.
70-
111+
71112
![Screenshot](example-trace.png)
72-
16. Clean up GKE cluster/pods/services:
73113

74-
`gcloud container clusters delete cloud-trace-demo`
114+
1. To clean up the provisioned resources:
115+
116+
```bash
117+
gcloud container clusters delete cloud-trace-demo --zone $ZONE
118+
```
119+
120+
[zones]: https://cloud.google.com/compute/docs/regions-zones#zones_and_clusters
121+
[dockerfile]: https://github.com/GoogleCloudPlatform/python-docs-samples/blob/main/trace/cloud-trace-demo-app-opentelemetry/app/Dockerfile

trace/cloud-trace-demo-app-opentelemetry/app/Dockerfile

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616
# https://hub.docker.com/_/python
1717
FROM python:3.10-slim
1818

19-
# Copy local code to the container image.
19+
RUN pip3 install --upgrade pip
20+
2021
ENV APP_HOME /app
2122
WORKDIR $APP_HOME
22-
COPY . ./
23-
COPY requirements.txt /app/
24-
RUN pip install Flask gunicorn
23+
24+
# Copy local code to the container image.
25+
COPY *.py *.txt ./
26+
2527
RUN pip install -r requirements.txt
2628

2729
CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 app:app

trace/cloud-trace-demo-app-opentelemetry/app/app.py

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,49 +11,71 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14+
1415
"""
1516
A sample app demonstrating CloudTraceSpanExporter
1617
"""
18+
19+
import os
1720
import random
1821
import time
1922

20-
# [START trace_demo_imports]
2123
import flask
22-
from opentelemetry import propagate, trace
24+
# [START trace_demo_imports]
25+
from opentelemetry import trace
2326
from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
2427
from opentelemetry.instrumentation.flask import FlaskInstrumentor
28+
from opentelemetry.instrumentation.requests import RequestsInstrumentor
29+
from opentelemetry.propagate import set_global_textmap
2530
from opentelemetry.propagators.cloud_trace_propagator import CloudTraceFormatPropagator
2631
from opentelemetry.sdk.trace import TracerProvider
27-
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
28-
32+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
2933
# [END trace_demo_imports]
30-
31-
app = flask.Flask(__name__)
32-
FlaskInstrumentor().instrument_app(app)
34+
import requests
3335

3436

37+
# [START trace_demo_create_exporter]
3538
def configure_exporter(exporter):
36-
trace.set_tracer_provider(TracerProvider())
37-
trace.get_tracer_provider().add_span_processor(SimpleSpanProcessor(exporter))
38-
propagate.set_global_textmap(CloudTraceFormatPropagator())
39+
set_global_textmap(CloudTraceFormatPropagator())
40+
tracer_provider = TracerProvider()
41+
tracer_provider.add_span_processor(BatchSpanProcessor(exporter))
42+
trace.set_tracer_provider(tracer_provider)
3943

4044

4145
configure_exporter(CloudTraceSpanExporter())
4246
tracer = trace.get_tracer(__name__)
47+
# [END trace_demo_create_exporter]
48+
49+
50+
# [START trace_demo_middleware]
51+
app = flask.Flask(__name__)
52+
FlaskInstrumentor().instrument_app(app)
53+
RequestsInstrumentor().instrument()
54+
# [END trace_demo_middleware]
4355

4456

4557
@app.route("/")
4658
def template_test():
4759
# Sleep for a random time to imitate a random processing time
4860
time.sleep(random.uniform(0, 0.5))
4961

50-
with tracer.start_as_current_span("span1"):
51-
with tracer.start_as_current_span("span2"):
52-
with tracer.start_as_current_span("span3"):
53-
print("Hello world from Cloud Trace Exporter!")
54-
55-
return "Hello World"
62+
# If there is an endpoint, send keyword to next service.
63+
# Return received input with the keyword
64+
keyword = os.getenv("KEYWORD")
65+
endpoint = os.getenv("ENDPOINT")
66+
# [START trace_context_header]
67+
if endpoint is not None and endpoint != "":
68+
data = {'body': keyword}
69+
response = requests.get(
70+
endpoint,
71+
params=data,
72+
)
73+
return keyword + "\n" + response.text
74+
else:
75+
return keyword, 200
76+
# [END trace_context_header]
5677

5778

5879
if __name__ == "__main__":
59-
app.run(debug=True, host="0.0.0.0", port=8080)
80+
port = os.getenv("PORT")
81+
app.run(debug=True, host="0.0.0.0", port=port)

trace/cloud-trace-demo-app-opentelemetry/app/app_test.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,20 @@
1414
"""
1515
A sample app demonstrating Google Cloud Trace
1616
"""
17+
import os
18+
1719
import mock
1820

1921
import app
2022

2123

2224
def test_traces():
25+
expected = "Lorem ipsum dolor sit amet"
26+
os.environ["KEYWORD"] = expected
27+
app.app.testing = True
2328
exporter = mock.Mock()
2429
app.configure_exporter(exporter)
2530
client = app.app.test_client()
2631
resp = client.get("/")
2732
assert resp.status_code == 200
33+
assert expected in resp.data.decode('utf-8')

0 commit comments

Comments
 (0)