Skip to content

Commit 284dc54

Browse files
authored
Fixing support for python2 (#1218)
* Fixing python2 smoke tests * ThreadPool fallback for python2 * ThreadPool fallback for python2 * ThreadPool fallback for python2 * ThreadPool fallback for python2 * Added logging. Removed cancel_fututures param as it was introduced in python 3.9. * Logging enabled * Some logging * Some logging * Git added to the testing image * test * test * agent log logging * fixing python2 test * fixing python2 test * reenabling all tests * reverting unused code * Don't wait on ThreadPoolExecutor * test * test * test * test * test * test * test * Python 2.7 added to the unit tests * Changing version format and grouping apt install packages into one line * python2 not available in ubuntu 20.04 GHA anymore * Changing back the version format
1 parent 194e4d4 commit 284dc54

File tree

13 files changed

+99
-49
lines changed

13 files changed

+99
-49
lines changed

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.2.7
1+
2.2.7.pre8.1

scalyr_agent/builtin_monitors/mysql_monitor.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ def _connect(self):
459459
self._cursor = None
460460
self._logger.error("Database connect failed: %s" % me)
461461
except Exception as ex:
462-
self._logger.error("Exception trying to connect occured: %s" % ex)
462+
self._logger.error("Exception trying to connect occured: %s" % ex, exc_info=ex)
463463
raise Exception("Exception trying to connect: %s" % ex)
464464

465465
def _close(self):
@@ -1314,6 +1314,7 @@ def _connect_to_db(self):
13141314
"Error establishing database connection: %s" % (six.text_type(e)),
13151315
limit_once_per_x_secs=300,
13161316
limit_key="mysql_connect_to_db",
1317+
exc_info=e
13171318
)
13181319

13191320
def gather_sample(self):

scalyr_agent/builtin_monitors/syslog_monitor.py

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@
2626
from __future__ import print_function
2727

2828
import queue
29-
from concurrent.futures import ThreadPoolExecutor, CancelledError
30-
from socketserver import ThreadingMixIn
3129

3230
from scalyr_agent import compat
3331

@@ -56,7 +54,10 @@
5654
from six.moves import range
5755
import six.moves.socketserver
5856

59-
from scalyr_agent.builtin_monitors.thread_pool import ExecutorMixIn
57+
if six.PY2:
58+
from scalyr_agent.builtin_monitors.thread_pool_dummy import ExecutorMixIn
59+
else:
60+
from scalyr_agent.builtin_monitors.thread_pool import ExecutorMixIn
6061

6162
try:
6263
# Only available for python >= 3.6
@@ -591,6 +592,7 @@ def __init__(self, request_processing_executor, request, client_address, server)
591592
else:
592593
six.moves.socketserver.BaseRequestHandler.__init__(self, request, client_address, server)
593594

595+
@staticmethod
594596
def factory_method(request_processing_executor):
595597
def create_handler(request, client_address, server):
596598
return SyslogUDPHandler(request_processing_executor, request, client_address, server)
@@ -606,9 +608,13 @@ def handle(self):
606608
"destport": self.server.server_address[1],
607609
}
608610

609-
self.__request_processing_executor.submit(
610-
self.server.syslog_handler.handle, data, extra
611-
)
611+
if self.__request_processing_executor:
612+
self.__request_processing_executor.submit(
613+
self.server.syslog_handler.handle, data, extra
614+
)
615+
else:
616+
self.server.syslog_handler.handle(data, extra)
617+
612618

613619

614620
class SocketNotReadyException(Exception):
@@ -636,7 +642,9 @@ def read(self):
636642
if not data:
637643
self.is_closed = True
638644
raise SocketClosed()
639-
except (socket.timeout, *NON_BLOCKING_SOCKET_DATA_NOT_READY_EXCEPTIONS) as e:
645+
except socket.timeout as e:
646+
raise SocketNotReadyException(e)
647+
except NON_BLOCKING_SOCKET_DATA_NOT_READY_EXCEPTIONS as e:
640648
raise SocketNotReadyException(e)
641649
except socket.error as e:
642650
if e.errno == errno.EAGAIN:
@@ -980,8 +988,6 @@ class SyslogTCPHandler(six.moves.socketserver.BaseRequestHandler):
980988

981989
def __init__(self, *args, **kwargs):
982990
self.__request_processing_executor = kwargs.pop("request_processing_executor", None)
983-
if not self.__request_processing_executor:
984-
raise ValueError("request_processing_executor is required")
985991

986992
self.request_parser = kwargs.pop("request_parser", "default")
987993
self.incomplete_frame_timeout = kwargs.pop("incomplete_frame_timeout", None)
@@ -1077,25 +1083,30 @@ def handle(self):
10771083
)
10781084

10791085
try:
1080-
# Worker is responsible for processing the data read from one request.
1081-
# Using the queue ensures the data is processed in the order it was read.
1082-
DONE = "DONE"
1083-
work_queue = queue.Queue()
1084-
def worker(queue, is_shutdown):
1085-
data = queue.get(block=True)
1086-
while data != DONE:
1087-
if is_shutdown():
1088-
global_log.info("ThreadPool shutting down, skipping further request processing.")
1089-
break
1090-
self.__request_data_process(syslog_parser, data)
1086+
if self.__request_processing_executor:
1087+
# Worker is responsible for processing the data read from one request.
1088+
# Using the queue ensures the data is processed in the order it was read.
1089+
DONE = "DONE"
1090+
work_queue = queue.Queue()
1091+
def worker(queue, is_shutdown):
10911092
data = queue.get(block=True)
1093+
while data != DONE:
1094+
if is_shutdown():
1095+
global_log.info("ThreadPool shutting down, skipping further request processing.")
1096+
break
1097+
self.__request_data_process(syslog_parser, data)
1098+
data = queue.get(block=True)
10921099

1093-
self.__request_processing_executor.submit(worker, work_queue, lambda: self.__request_processing_executor._shutdown)
1100+
self.__request_processing_executor.submit(worker, work_queue, lambda: self.__request_processing_executor._shutdown)
10941101

1095-
for data in self.__request_stream_read(syslog_request, self.server.is_running):
1096-
work_queue.put(data)
1102+
for data in self.__request_stream_read(syslog_request, self.server.is_running):
1103+
work_queue.put(data)
1104+
1105+
work_queue.put(DONE)
1106+
else:
1107+
for data in self.__request_stream_read(syslog_request, self.server.is_running):
1108+
self.__request_data_process(syslog_parser, data)
10971109

1098-
work_queue.put(DONE)
10991110

11001111
except Exception as e:
11011112
global_log.warning(

scalyr_agent/builtin_monitors/thread_pool.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,11 @@ def get_singleton(cls, name, max_workers=None):
7676
return cls.__instances[name]
7777

7878
@classmethod
79-
def shutdown(cls, wait=True, cancel_futures=False):
79+
def shutdown(cls, wait=True):
8080
wait_on_futures_str = " and waiting on futures" if wait else ""
8181
for name, executor in cls.__instances.items():
8282
global_log.info("Shutting down ThreadPoolExecutor%s: %s", wait_on_futures_str, name)
8383
try:
84-
executor.shutdown(wait=wait, cancel_futures=cancel_futures)
84+
executor.shutdown(wait=wait)
8585
except Exception as e:
8686
global_log.error("Failed shutting down the ThreadPoolExecutor %s", executor, exc_info=e)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from six.moves.socketserver import ThreadingMixIn
2+
3+
class ExecutorMixIn(ThreadingMixIn):
4+
def __init__(self, global_config):
5+
self._request_reading_executor = None
6+
self._request_processing_executor = None
7+
8+
class ThreadPoolExecutorFactory():
9+
@classmethod
10+
def shutdown(cls, wait=True):
11+
pass

scalyr_agent/monitors_manager.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
from __future__ import unicode_literals
1818
from __future__ import absolute_import
1919

20-
from scalyr_agent.builtin_monitors.thread_pool import ThreadPoolExecutorFactory
21-
2220
if False: # NOSONAR
2321
from typing import List
2422

@@ -41,6 +39,13 @@
4139

4240
import six
4341

42+
if six.PY2:
43+
from scalyr_agent.builtin_monitors.thread_pool_dummy import ThreadPoolExecutorFactory
44+
else:
45+
from scalyr_agent.builtin_monitors.thread_pool import ThreadPoolExecutorFactory
46+
47+
48+
4449
log = scalyr_logging.getLogger(__name__)
4550

4651
# Holds reference to the currently active MonitorsManager instance (singleton). Reference to this
@@ -211,7 +216,7 @@ def stop_manager(self, wait_on_join=True, join_timeout=5):
211216
start_time = time.time()
212217

213218
log.info("Stopping shared thread pools")
214-
ThreadPoolExecutorFactory.shutdown(wait=False, cancel_futures=True)
219+
ThreadPoolExecutorFactory.shutdown(wait=False)
215220

216221

217222
for monitor in self.__running_monitors:
@@ -235,8 +240,6 @@ def stop_manager(self, wait_on_join=True, join_timeout=5):
235240
except Exception:
236241
log.exception("Failed to stop the metric log due to an exception")
237242

238-
ThreadPoolExecutorFactory.shutdown(wait=True, cancel_futures=False)
239-
240243

241244

242245
for monitor in self.__running_monitors:

tests/end_to_end_tests/managed_packages_tests/remote_machine_tests/tools/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ def download_stable_packages(
7373

7474
output_dir.mkdir(parents=True, exist_ok=True)
7575
agent_package_path = output_dir / file_name
76+
if agent_package_path.exists():
77+
raise Exception("While downloading a stable package, found an existing one: " + str(agent_package_path))
7678
with requests.Session() as s:
7779
resp = s.get(url=package_url)
7880
resp.raise_for_status()

tests/image_builder/monitors/base/Dockerfile

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ FROM ubuntu:18.04
22

33
ENV DEBIAN_FRONTEND=noninteractive
44
RUN apt update -y
5-
RUN apt install -y mysql-server
6-
RUN apt install -y postgresql
7-
5+
RUN apt install -y mysql-server postgresql git
86

97
USER postgres
108
RUN service postgresql start && createuser root && createdb root && psql -c "alter user root superuser;" && service postgresql stop

tests/smoke_tests/monitors_test/mysql_test.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,26 +34,33 @@
3434
from tests.utils.log_reader import LogMetricReader, LogReaderError
3535
from tests.utils.log_reader import AgentLogReader
3636

37+
from scalyr_agent import scalyr_logging
38+
3739
import six
3840

3941
HOST = "localhost"
4042
USERNAME = "scalyr_test_user"
4143
PASSWORD = "scalyr_test_password"
4244
DATABASE = "scalyr_test_db"
4345

46+
global_log = scalyr_logging.getLogger(__name__)
4447

4548
@pytest.fixture()
4649
def mysql_client():
4750
# we change owner of the mysql files to workaround the issue which happens with mysql server in docker.
4851
# see: https://serverfault.com/a/872576
4952
os.system("chown -R mysql:mysql /var/lib/mysql /var/run/mysqld")
5053

54+
global_log.info("Starting the mysql server")
5155
exit_code = os.system("service mysql start --ssl")
5256

5357
# On failure include service logs for ease of debugging
5458
if exit_code != 0:
59+
global_log.error("Mysql server start error, dumping logs:")
5560
os.system("cat /var/log/mysql/mysql.log || true")
5661

62+
assert exit_code == 0, "Mysql server start error"
63+
5764
os.system("mysql < /init.sql")
5865

5966
time.sleep(3)
@@ -111,7 +118,6 @@ def _agent_config(self): # type: () -> Dict[six.text_type, Any]
111118
class MySqlLogReader(LogMetricReader):
112119
LINE_PATTERN = r"\s*(?P<timestamp>\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}.\d+Z)\s\[mysql_monitor\((?P<instance_id>[^\]]+)\)\]\s(?P<metric_name>[^\s]+)\s(?P<metric_value>.+)"
113120

114-
115121
def _test(
116122
request,
117123
python_version,
@@ -205,11 +211,14 @@ def _test(
205211

206212
agent_log_reader.go_to_end()
207213
except LogReaderError as e:
208-
if not expected_exception or (
209-
expected_exception not in str(e)
210-
and not re.search(expected_exception, str(e))
211-
):
212-
raise e
214+
if not expected_exception:
215+
msg = "AssertionError, not exception expected, got: " + str(e)
216+
global_log.error(msg, exc_info=e)
217+
raise AssertionError(msg)
218+
if expected_exception not in str(e)and not re.search(expected_exception, str(e)):
219+
msg = "Assertion error, expected: " + str(expected_exception) + "got exception: " + str(e)
220+
global_log.error(msg, exc_info=e)
221+
raise AssertionError(msg)
213222

214223

215224
@pytest.mark.usefixtures("agent_environment")
@@ -283,7 +292,7 @@ def test_mysql_python2_ssl_bad_hostname(request):
283292
use_socket=False,
284293
use_ssl=True,
285294
ca_file="/var/lib/mysql/ca.pem",
286-
expected_exception=r"hostname '127.0.0.1' doesn't match 'MySQL_Server_5.7.\d+_Auto_Generated_Server_Certificate'",
295+
expected_exception=r"hostname u'127.0.0.1' doesn't match u'MySQL_Server_5.7.\d+_Auto_Generated_Server_Certificate'",
287296
)
288297

289298

tests/smoke_tests/monitors_test/syslog_test.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,12 @@ def _test(python_version):
9191
finally:
9292
runner.stop(executable=python_version)
9393

94-
9594
@pytest.mark.usefixtures("agent_environment")
9695
@dockerized_case(CommonMonitorBuilder, __file__)
9796
def test_syslog_python3(request):
9897
_test(python_version="python3")
98+
99+
@pytest.mark.usefixtures("agent_environment")
100+
@dockerized_case(CommonMonitorBuilder, __file__)
101+
def test_syslog_python2(request):
102+
_test(python_version="python2")

0 commit comments

Comments
 (0)