locust-cloud 1.12.1__py3-none-any.whl → 1.12.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
locust_cloud/cloud.py CHANGED
@@ -401,11 +401,12 @@ def delete(credential_manager):
401
401
  headers=headers,
402
402
  )
403
403
 
404
- if response.status_code != 200:
404
+ if response.status_code == 200:
405
+ logger.debug(response.json()["message"])
406
+ else:
405
407
  logger.info(
406
408
  f"Could not automatically tear down Locust Cloud: HTTP {response.status_code}/{response.reason} - Response: {response.text} - URL: {response.request.url}"
407
409
  )
408
- logger.debug(response.json()["message"])
409
410
  except Exception as e:
410
411
  logger.error(f"Could not automatically tear down Locust Cloud: {e.__class__.__name__}:{e}")
411
412
 
@@ -3,13 +3,13 @@ import logging
3
3
  import os
4
4
  import sys
5
5
  from collections import deque
6
- from contextlib import suppress
7
6
 
8
7
  import flask
9
8
  import gevent
10
9
  import gevent.pywsgi
11
10
  import geventwebsocket.handler
12
11
  import socketio
12
+ import socketio.exceptions
13
13
 
14
14
 
15
15
  def setup_socket_logging():
@@ -23,13 +23,13 @@ def setup_socket_logging():
23
23
  server in addition to the websocket stuff.
24
24
  """
25
25
 
26
- logger = logging.getLogger(__name__)
27
- logger.propagate = False
28
- logger.addHandler(logging.NullHandler())
26
+ quiet_logger = logging.getLogger("be_quiet")
27
+ quiet_logger.propagate = False
28
+ quiet_logger.addHandler(logging.NullHandler())
29
29
 
30
30
  # This app will use a logger with the same name as the application
31
31
  # which means it will pick up the one set up above.
32
- healthcheck_app = flask.Flask(__name__)
32
+ healthcheck_app = flask.Flask("be_quiet")
33
33
 
34
34
  # /login is the health check endpoint currently configured for the
35
35
  # ALB controller in kubernetes.
@@ -38,18 +38,33 @@ def setup_socket_logging():
38
38
  def healthcheck():
39
39
  return ""
40
40
 
41
+ logger = logging.getLogger(__name__)
42
+ socketio_path = f"/{os.environ['CUSTOMER_ID']}/socket-logs"
41
43
  sio = socketio.Server(async_handlers=True, always_connect=True, async_mode="gevent", cors_allowed_origins="*")
42
- sio_app = socketio.WSGIApp(sio, healthcheck_app, socketio_path=f"/{os.environ['CUSTOMER_ID']}/socket-logs")
44
+ sio_app = socketio.WSGIApp(sio, healthcheck_app, socketio_path=socketio_path)
43
45
  message_queue = deque(maxlen=500)
44
46
 
47
+ @sio.event
48
+ def connect(sid, environ, auth): # noqa: ARG001
49
+ logger.debug("Client connected to socketio server")
50
+
51
+ @sio.event
52
+ def disconnect(sid): # noqa: ARG001
53
+ logger.debug("Client disconnected from socketio server")
54
+
45
55
  class QueueCopyStream:
46
56
  def __init__(self, name, original):
47
57
  self.name = name
48
58
  self.original = original
49
59
 
50
60
  def write(self, message):
51
- self.original.write(message)
61
+ """
62
+ Writes to the queue first since when running in gevent the write to
63
+ stdout/stderr can yield and we want to ensure the same ordering in
64
+ the queue as for the written messages.
65
+ """
52
66
  message_queue.append((self.name, message))
67
+ self.original.write(message)
53
68
 
54
69
  def flush(self):
55
70
  self.original.flush()
@@ -65,13 +80,20 @@ def setup_socket_logging():
65
80
  while message_queue and (sid := connected_sid()):
66
81
  name, message = message_queue[0]
67
82
 
68
- with suppress(TimeoutError):
83
+ try:
84
+ if name == "shutdown":
85
+ logger.debug("Sending websocket shutdown event")
86
+
69
87
  sio.call(name, message, to=sid, timeout=5)
70
88
  message_queue.popleft()
71
89
 
72
90
  if name == "shutdown":
91
+ logger.debug("Websocket shutdown event acknowledged by client")
73
92
  return
74
93
 
94
+ except socketio.exceptions.TimeoutError:
95
+ logger.debug("Timed out waiting for client to aknowledge websocket message")
96
+
75
97
  gevent.sleep(1)
76
98
 
77
99
  emitter_greenlet = gevent.spawn(emitter)
@@ -81,6 +103,7 @@ def setup_socket_logging():
81
103
 
82
104
  @atexit.register
83
105
  def notify_shutdown(*args, **kwargs):
106
+ logger.debug("Adding shutdown event to websocket queue")
84
107
  message_queue.append(("shutdown", ""))
85
108
  emitter_greenlet.join(timeout=30)
86
109
 
@@ -92,10 +115,11 @@ def setup_socket_logging():
92
115
 
93
116
  @property
94
117
  def logger(self):
95
- return logger
118
+ return quiet_logger
96
119
 
97
120
  @gevent.spawn
98
121
  def start_websocket_server():
122
+ logger.debug(f"Starting socketio server on port 1095 with path {socketio_path}")
99
123
  server = gevent.pywsgi.WSGIServer(
100
124
  ("", 1095), sio_app, log=None, error_log=None, handler_class=WebSocketHandlerWithoutLogging
101
125
  )
@@ -4,10 +4,8 @@ requests_query = """
4
4
  SELECT
5
5
  name,
6
6
  request_type as method,
7
- SUM(average * count) / SUM(count) as average,
8
7
  SUM(count) as requests,
9
8
  SUM(failed_count) as failed,
10
- MIN(min),
11
9
  MAX(max),
12
10
  SUM(failed_count) / SUM(count) * 100 as "errorPercentage"
13
11
  FROM requests_summary_view
@@ -200,7 +198,6 @@ SELECT
200
198
  fail_ratio as "failRatio",
201
199
  requests,
202
200
  date_trunc('second', end_time - id) AS "runTime",
203
- description,
204
201
  exit_code as "exitCode",
205
202
  username,
206
203
  worker_count as "workerCount",