Skip to content

Commit 763b661

Browse files
committed
memray tracing
1 parent 0365c36 commit 763b661

File tree

10 files changed

+270
-86
lines changed

10 files changed

+270
-86
lines changed

.gcloudignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
test_scripts/
33

44
sample_data/
5+
memray/
56
README.md
67
*.sh
78
TEMP*

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ TEMP*
1717
virtenv*/
1818

1919

20+
memray/

app.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ inbound_services:
88
- warmup
99
env_variables:
1010
GAE_USE_SOCKETS_HTTPLIB: False
11+
PYTHONMALLOC: malloc
1112
app_engine_apis: true
1213

1314

15+

cron.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
cron:
33
- description: "Invoke /schedule which sends out messages triggering do_label per project/plugin."
44
url: /schedule
5-
schedule: every day 14:13
5+
schedule: every day 13:27
66
target: iris3

deploy.sh

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,16 +89,9 @@ echo "Project ID $PROJECT_ID"
8989
gcloud config set project "$PROJECT_ID"
9090

9191
# Must have one of these config (meanwhile, config-dev.yaml is only for local use)
92-
if [[ -f "config-test.yaml" ]]; then
93-
if [[ -f "config.yaml" ]]; then
94-
echo >&2 "Cannot have config.yaml if config-test.yaml exists"
95-
exit 1
96-
fi
97-
else
98-
if [[ ! -f "config.yaml" ]]; then
92+
if [[ ! -f "config-test.yaml" ]] && [[ ! -f "config.yaml" ]]; then
9993
echo >&2 "config.yaml Must have either config.yaml (use config.yaml.original as an example) or config-test.yaml"
10094
exit 1
101-
fi
10295
fi
10396

10497

main.py

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77

88
print("Initializing ", file=sys.stderr)
99
import flask
10-
from util.gcp_utils import increment_invocation_count, invocation_count, memray_filename
10+
from util.gcp_utils import (
11+
increment_invocation_count,
12+
count_invocations_by_path,
13+
memray_filename,
14+
)
1115
from util.detect_gae import detect_gae
1216

1317
app = flask.Flask(__name__)
@@ -66,6 +70,9 @@
6670
logging.info(
6771
"env GAE_USE_SOCKETS_HTTPLIB is %s", os.environ.get("GAE_USE_SOCKETS_HTTPLIB")
6872
)
73+
logging.info(
74+
"env PYTHONMALLOC is %s", os.environ.get("PYTHONMALLOC")
75+
)
6976

7077
PluginHolder.init()
7178

@@ -74,42 +81,43 @@
7481
def list_memray():
7582
s = ""
7683
for f in os.listdir(tmp_dir()):
77-
s += f"<a href='/tmpfile?filename={f}'></a><br>"
78-
return s, 200
84+
s += f"<a href='/memrayfiles/{f}'>{f}</a><br>\n"
85+
if not s:
86+
s = "NONE FOUND"
87+
return Response(s, mimetype="text/html", status=200)
7988

8089

81-
@app.route("/tmpfile")
82-
def tmpfile():
83-
fn = flask.request.args['filename']
84-
with open(f"{tmp_dir()}/{fn}", 'b') as f:
90+
@app.route("/memrayfiles/<filename>")
91+
def memrayfiles(filename):
92+
93+
with open(f"{tmp_dir()}/{filename}", "rb") as f:
8594
content = f.read()
86-
return Response(content, mimetype='application/octet-stream', status=200)
95+
96+
return Response(content, mimetype="application/octet-stream", status=200)
8797

8898

8999
@app.route("/")
90100
def index():
91-
with memray.Tracker(memray_filename()):
101+
with memray.Tracker(memray_filename("index")):
92102
increment_invocation_count("index")
93103
with gae_memory_logging("index"):
94104
msg = iris_homepage_text()
95105
if config_utils.is_test_or_dev_configuration():
96106
msg += "\nI'm running in test or dev mode."
97107

98-
logging.info("index(); invocations of GAE instance : %s", invocation_count())
108+
logging.info(
109+
"index(); invocations of GAE instance : %s", count_invocations_by_path()
110+
)
99111
return Response(msg, mimetype="text/plain", status=200)
100112

101113

102114
@app.route("/_ah/warmup")
103115
def warmup():
104-
with memray.Tracker(memray_filename()):
105-
116+
with memray.Tracker(memray_filename("warmup")):
106117
increment_invocation_count("warmup")
107118
with gae_memory_logging("warmup"):
108119
logging.info("warmup() called")
109-
try:
110-
1 / 0
111-
except Exception:
112-
logging.exception("eeeeee")
120+
113121
return "", 200, {}
114122

115123

@@ -119,7 +127,7 @@ def schedule():
119127
"""
120128
Send out a message per-plugin per-project to label all objects of that type and project.
121129
"""
122-
with memray.Tracker(memray_filename):
130+
with memray.Tracker(memray_filename("schedule")):
123131

124132
increment_invocation_count("schedule")
125133
with gae_memory_logging("schedule"):
@@ -162,9 +170,9 @@ def __get_enabled_projects():
162170
raise Exception("No projects enabled at all")
163171

164172
if (
165-
not detect_gae()
166-
or is_test_or_dev_configuration()
167-
or is_in_test_or_dev_project(current_project_id())
173+
not detect_gae()
174+
or is_test_or_dev_configuration()
175+
or is_in_test_or_dev_project(current_project_id())
168176
):
169177
max_proj_in_dev = 3
170178
if len(enabled_projs) > max_proj_in_dev:
@@ -173,8 +181,8 @@ def __get_enabled_projects():
173181
+ f"to avoid accidentally flooding the system."
174182
+ f"{max_proj_in_dev} projects are available, which exceeds that."
175183
+ f"To avoid this limit, use config.yaml rather than config-dev.yaml or config-test.yaml,"
176-
f"edit test_or_dev_project_markers in the config file,"
177-
f"and run in the cloud rather than locally."
184+
f"edit test_or_dev_project_markers in the config file,"
185+
f"and run in the cloud rather than locally."
178186
)
179187
return enabled_projs
180188

@@ -184,9 +192,9 @@ def __send_pubsub_per_projectplugin(configured_projects):
184192
for project_id in configured_projects:
185193
for plugin_cls in PluginHolder.plugins:
186194
if (
187-
not plugin_cls.is_labeled_on_creation()
188-
or plugin_cls.relabel_on_cron()
189-
or config_utils.label_all_on_cron()
195+
not plugin_cls.is_labeled_on_creation()
196+
or plugin_cls.relabel_on_cron()
197+
or config_utils.label_all_on_cron()
190198
):
191199
pubsub_utils.publish(
192200
msg=json.dumps(
@@ -210,7 +218,7 @@ def __send_pubsub_per_projectplugin(configured_projects):
210218

211219
@app.route("/label_one", methods=["POST"])
212220
def label_one():
213-
with memray.Tracker(memray_filename()):
221+
with memray.Tracker(memray_filename("label_one")):
214222

215223
increment_invocation_count("label_one")
216224
with gae_memory_logging("label_one"):
@@ -261,7 +269,9 @@ def label_one():
261269
# since most errors are unrecoverable.
262270
return "OK", 200
263271
except Exception:
264-
project_id = data.get("resource", {}).get("labels", {}).get("project_id")
272+
project_id = (
273+
data.get("resource", {}).get("labels", {}).get("project_id")
274+
)
265275
logging.exception("Error on label_one %s %s", plugins_found, project_id)
266276
return "Error", 500
267277

@@ -320,14 +330,16 @@ def __extract_pubsub_content() -> Dict:
320330

321331
@app.route("/do_label", methods=["POST"])
322332
def do_label():
323-
with memray.Tracker(memray_filename()):
333+
with memray.Tracker(memray_filename("do_label")):
324334
increment_invocation_count("do_label")
325335
with gae_memory_logging("do_label"):
326336

327337
"""Receive a push message from PubSub, sent from schedule() above,
328338
with instructions to label all objects of a given plugin and project_id.
329339
"""
330-
project_id = "" # set up variables to allow logging in Exception block at end
340+
project_id = (
341+
"" # set up variables to allow logging in Exception block at end
342+
)
331343
plugin_class_name = ""
332344
try:
333345
data = __extract_pubsub_content()
@@ -344,7 +356,9 @@ def do_label():
344356
project_id = data["project_id"]
345357
with timing(f"do_label {plugin_class_name} {project_id}"):
346358
logging.info(
347-
"do_label() for %s in %s", plugin.__class__.__name__, project_id
359+
"do_label() for %s in %s",
360+
plugin.__class__.__name__,
361+
project_id,
348362
)
349363
plugin.label_all(project_id)
350364
logging.info("OK on do_label %s %s", plugin_class_name, project_id)
@@ -354,7 +368,9 @@ def do_label():
354368

355369
return "OK", 200
356370
except Exception:
357-
logging.exception("Error on do_label %s %s", plugin_class_name, project_id)
371+
logging.exception(
372+
"Error on do_label %s %s", plugin_class_name, project_id
373+
)
358374
return "Error", 500
359375

360376

test_scripts/integration_test.py

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from concurrent.futures import ThreadPoolExecutor
99
from subprocess import CalledProcessError
1010
from typing import Union, List
11+
from urllib.error import HTTPError
1112

1213
from test_scripts.utils_for_tests import assert_root_path
1314
from util.config_utils import iris_prefix, iris_homepage_text
@@ -169,26 +170,39 @@ def wait_for_traffic_shift(deployment_project):
169170

170171
url = f"https://iris3-dot-{deployment_project}.uc.r.appspot.com/"
171172
while time.time() - start_wait_for_trafficshift < 180: # break after 180 sec
172-
with urllib.request.urlopen(url) as response:
173-
txt_b = response.read()
174-
txt = str(txt_b, "UTF-8")
175-
if iris_homepage_text() in txt:
176-
print(
177-
"Wait for traffic shift took",
178-
int(1000 * (time.time() - start_wait_for_trafficshift)),
179-
"msec",
180-
)
181-
return # Could alternatively check for the iris_prefix, which is meant to be here unique.
182-
print(
183-
'Site now has "',
184-
txt[:100],
185-
'"not including the expected ',
186-
iris_prefix(),
187-
)
173+
try:
174+
found_it = __check_for_new_v(start_wait_for_trafficshift, url)
175+
if found_it:
176+
return
177+
else:
178+
time.sleep(3)
179+
continue
180+
except HTTPError as e:
181+
logging.error(e) # Keep trying despite exception
188182

189183
raise TimeoutError(time.time() - start_wait_for_trafficshift)
190184

191185

186+
def __check_for_new_v(start_wait_for_trafficshift, url) -> bool:
187+
with urllib.request.urlopen(url) as response:
188+
txt_b = response.read()
189+
txt = str(txt_b, "UTF-8")
190+
if iris_homepage_text() in txt:
191+
print(
192+
"Wait for traffic shift took",
193+
int(1000 * (time.time() - start_wait_for_trafficshift)),
194+
"msec",
195+
)
196+
return True
197+
print(
198+
'Site now has "',
199+
txt[:100],
200+
'"not including the expected ',
201+
iris_prefix(),
202+
)
203+
return False
204+
205+
192206
def fill_in_config_template(
193207
run_id, deployment_project, test_project, pubsub_test_token
194208
):
@@ -265,6 +279,7 @@ def get_run_id():
265279
else:
266280
# Random value to distinguish this test runs from others
267281
run_id = random_str(4)
282+
print("run_id is", run_id, file=sys.stderr)
268283
return run_id
269284

270285

@@ -337,5 +352,5 @@ def create_resources(test_project, run_id, gce_zone):
337352
assert_root_path()
338353

339354
main()
340-
print("Exiting with ", "failure" if exit_code else "success")
355+
print("Exiting with", "failure" if exit_code else "success")
341356
sys.exit(exit_code)

0 commit comments

Comments
 (0)