From 3e019f34ba202ada16bed87d3af3a524a553da1b Mon Sep 17 00:00:00 2001 From: Jianqiao Li Date: Wed, 6 Mar 2019 07:58:34 -0800 Subject: [PATCH] Add Profiler code samples for App Engine (#2028) * Add Profiler code samples for App Engine * Fix comments --- profiler/appengine/flexible/app.yaml | 19 ++++++++ profiler/appengine/flexible/main.py | 45 +++++++++++++++++ profiler/appengine/flexible/main_test.py | 24 ++++++++++ profiler/appengine/flexible/requirements.txt | 3 ++ profiler/appengine/standard_python37/app.yaml | 1 + profiler/appengine/standard_python37/main.py | 48 +++++++++++++++++++ .../appengine/standard_python37/main_test.py | 24 ++++++++++ .../standard_python37/requirements.txt | 2 + profiler/quickstart/main.py | 2 +- 9 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 profiler/appengine/flexible/app.yaml create mode 100644 profiler/appengine/flexible/main.py create mode 100644 profiler/appengine/flexible/main_test.py create mode 100644 profiler/appengine/flexible/requirements.txt create mode 100644 profiler/appengine/standard_python37/app.yaml create mode 100644 profiler/appengine/standard_python37/main.py create mode 100644 profiler/appengine/standard_python37/main_test.py create mode 100644 profiler/appengine/standard_python37/requirements.txt diff --git a/profiler/appengine/flexible/app.yaml b/profiler/appengine/flexible/app.yaml new file mode 100644 index 000000000000..55439a72cf36 --- /dev/null +++ b/profiler/appengine/flexible/app.yaml @@ -0,0 +1,19 @@ +runtime: python +env: flex +entrypoint: gunicorn -b :$PORT main:app + +# App Engine flexible Python 3 runtime uses Python 3.7.x, which supports both +# CPU and Wall profiling. +runtime_config: + python_version: 3 + +# This sample incurs costs to run on the App Engine flexible environment. +# The settings below are to reduce costs during testing and are not appropriate +# for production use. For more information, see: +# https://cloud.google.com/appengine/docs/flexible/python/configuring-your-app-with-app-yaml +manual_scaling: + instances: 1 +resources: + cpu: 1 + memory_gb: 0.5 + disk_size_gb: 10 diff --git a/profiler/appengine/flexible/main.py b/profiler/appengine/flexible/main.py new file mode 100644 index 000000000000..03feabad277a --- /dev/null +++ b/profiler/appengine/flexible/main.py @@ -0,0 +1,45 @@ +# Copyright 2019 Google Inc. All Rights Reserved. +# +# 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. +"""An example of using https://cloud.google.com/profiler on GAE flex.""" + +from flask import Flask +# [START profiler_python_appengine_flex] +import googlecloudprofiler + +# Profiler initialization. It starts a daemon thread which continuously +# collects and uploads profiles. Best done as early as possible. +try: + # service and service_version can be automatically inferred when + # running on App Engine. project_id must be set if not running + # on GCP. + googlecloudprofiler.start(verbose=3) +except (ValueError, NotImplementedError) as exc: + print(exc) # Handle errors here + +# [END profiler_python_appengine_flex] + + +app = Flask(__name__) + + +@app.route('/') +def hello(): + """Return a friendly HTTP greeting.""" + return 'Hello World!' + + +if __name__ == '__main__': + # This is used when running locally. Gunicorn is used to run the + # application on Google App Engine. See entrypoint in app.yaml. + app.run(host='127.0.0.1', port=8080, debug=True) diff --git a/profiler/appengine/flexible/main_test.py b/profiler/appengine/flexible/main_test.py new file mode 100644 index 000000000000..6df63eacbc36 --- /dev/null +++ b/profiler/appengine/flexible/main_test.py @@ -0,0 +1,24 @@ +# Copyright 2019 Google Inc. All Rights Reserved. +# +# 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 main + + +def test_index(): + main.app.testing = True + client = main.app.test_client() + + r = client.get('/') + assert r.status_code == 200 + assert 'Hello World' in r.data.decode('utf-8') diff --git a/profiler/appengine/flexible/requirements.txt b/profiler/appengine/flexible/requirements.txt new file mode 100644 index 000000000000..306c4ffd8141 --- /dev/null +++ b/profiler/appengine/flexible/requirements.txt @@ -0,0 +1,3 @@ +Flask==1.0.2 +gunicorn==19.9.0 +google-cloud-profiler diff --git a/profiler/appengine/standard_python37/app.yaml b/profiler/appengine/standard_python37/app.yaml new file mode 100644 index 000000000000..a0b719d6dd41 --- /dev/null +++ b/profiler/appengine/standard_python37/app.yaml @@ -0,0 +1 @@ +runtime: python37 diff --git a/profiler/appengine/standard_python37/main.py b/profiler/appengine/standard_python37/main.py new file mode 100644 index 000000000000..ce41cc9e4046 --- /dev/null +++ b/profiler/appengine/standard_python37/main.py @@ -0,0 +1,48 @@ +# Copyright 2019 Google LLC +# +# 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. +"""An example of using https://cloud.google.com/profiler on GAE standard.""" + +from flask import Flask +# [START profiler_python_appengine_standard_python37] +import googlecloudprofiler + +# Profiler initialization. It starts a daemon thread which continuously +# collects and uploads profiles. Best done as early as possible. +try: + # service and service_version can be automatically inferred when + # running on App Engine. project_id must be set if not running + # on GCP. + googlecloudprofiler.start(verbose=3) +except (ValueError, NotImplementedError) as exc: + print(exc) # Handle errors here + +# [END profiler_python_appengine_standard_python37] + + +# If `entrypoint` is not defined in app.yaml, App Engine will look for an app +# called `app` in `main.py`. +app = Flask(__name__) + + +@app.route('/') +def hello(): + """Return a friendly HTTP greeting.""" + return 'Hello World!' + + +if __name__ == '__main__': + # This is used when running locally only. When deploying to Google App + # Engine, a webserver process such as Gunicorn will serve the app. This + # can be configured by adding an `entrypoint` to app.yaml. + app.run(host='127.0.0.1', port=8080, debug=True) diff --git a/profiler/appengine/standard_python37/main_test.py b/profiler/appengine/standard_python37/main_test.py new file mode 100644 index 000000000000..6df63eacbc36 --- /dev/null +++ b/profiler/appengine/standard_python37/main_test.py @@ -0,0 +1,24 @@ +# Copyright 2019 Google Inc. All Rights Reserved. +# +# 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 main + + +def test_index(): + main.app.testing = True + client = main.app.test_client() + + r = client.get('/') + assert r.status_code == 200 + assert 'Hello World' in r.data.decode('utf-8') diff --git a/profiler/appengine/standard_python37/requirements.txt b/profiler/appengine/standard_python37/requirements.txt new file mode 100644 index 000000000000..94e54c91bf28 --- /dev/null +++ b/profiler/appengine/standard_python37/requirements.txt @@ -0,0 +1,2 @@ +Flask==1.0.2 +google-cloud-profiler diff --git a/profiler/quickstart/main.py b/profiler/quickstart/main.py index b121bdbbc4d0..98206a39674e 100644 --- a/profiler/quickstart/main.py +++ b/profiler/quickstart/main.py @@ -33,7 +33,7 @@ def main(): # project_id='my-project-id', ) except (ValueError, NotImplementedError) as exc: - print(exc) # Handles errors here + print(exc) # Handle errors here # [END profiler_python_quickstart] busyloop()