def test_finish_log_request_info_with_logged_payload( tracked_request, caplog, reset_config ): scout_config.set(log_payload_content=True) tracked_request.is_real_request = True tracked_request.start_span(operation="Something") tracked_request.stop_span() # Find the logged message. actual_message = None for module, level, message in caplog.record_tuples: if module == "scout_apm.core.tracked_request" and level == logging.DEBUG: if message.startswith( "Sending request: {}. Payload: ".format(tracked_request.request_id) ): actual_message = message break assert actual_message # Verify the counts of the spans and the request id. assert actual_message.count("'StartRequest'") == 1 assert actual_message.count("'FinishRequest'") == 1 assert actual_message.count("'TagRequest'") == 1 assert actual_message.count("'StartSpan'") == 1 assert actual_message.count("'StopSpan'") == 1 if objtrace.is_extension: assert actual_message.count("'TagSpan'") == 3 total_requests = 8 else: assert actual_message.count("'TagSpan'") == 0 total_requests = 5 # Verify each request id in the payload is the tracked request's. assert actual_message.count("'request_id'") == total_requests # The actual request id is also included in the log message after Sending request: assert actual_message.count(tracked_request.request_id) == total_requests + 1
def test_log_level(caplog, core_agent_manager): scout_config.set(core_agent_log_level="foo") result = core_agent_manager.log_level() assert result == ["--log-level", "foo"] assert caplog.record_tuples == []
def install(config=None): global shutdown_registered if config is not None: scout_config.set(**config) scout_config.log() if os.name == "nt": logger.info("APM Not Launching on PID: %s - Windows is not supported", os.getpid()) return False if not scout_config.value("monitor"): logger.info( "APM Not Launching on PID: %s - Configuration 'monitor' is not true", os.getpid(), ) return False instruments.ensure_all_installed() objtrace.enable() logger.debug("APM Launching on PID: %s", os.getpid()) launched = CoreAgentManager().launch() report_app_metadata() if launched: # Stop the thread to avoid running threads pre-fork CoreAgentSocketThread.ensure_stopped() if scout_config.value( "shutdown_timeout_seconds") > 0.0 and not shutdown_registered: atexit.register(shutdown) shutdown_registered = True return True
def core_agent_manager(core_agent_dir): scout_config.set(core_agent_dir=core_agent_dir) core_agent_manager = CoreAgentManager() try: yield core_agent_manager finally: assert not core_agent_is_running() scout_config.reset_all()
def test_create_filtered_path_path(path, params): # If config filtered_params is set to "path", expect we always get the path # back scout_config.set(uri_reporting="path") try: assert create_filtered_path(path, params) == path finally: scout_config.reset_all()
def test_socket_path_tcp(self): scout_config.set(core_agent_socket_path="tcp://127.0.0.1:7894") try: result = CoreAgentManager().socket_path() finally: scout_config.reset_all() assert result == ["--tcp", "127.0.0.1:7894"]
def test_config_file_old_name_takes_precedence(self): scout_config.set(config_file="foo", core_agent_config_file="bar") try: result = CoreAgentManager().config_file() finally: scout_config.reset_all() assert result == ["--config-file", "foo"]
def test_config_file(self): scout_config.set(core_agent_config_file="foo") try: result = CoreAgentManager().config_file() finally: scout_config.reset_all() assert result == ["--config-file", "foo"]
def test_ignore(path, expected): scout_config.set(ignore=["/health"]) try: result = ignore_path(path) finally: scout_config.reset_all() assert result == expected
def test_log_level(self): scout_config.set(core_agent_log_level="foo") try: result = CoreAgentManager().log_level() finally: scout_config.reset_all() assert result == ["--log-level", "foo"]
def test_socket_path_path(self): scout_config.set(core_agent_socket_path="/tmp/foo.sock") try: result = CoreAgentManager().socket_path() finally: scout_config.reset_all() assert result == ["--socket", "/tmp/foo.sock"]
def test_log_level_old_name_takes_precedence(self): scout_config.set(log_level="foo", core_agent_log_level="bar") try: result = CoreAgentManager().log_level() finally: scout_config.reset_all() assert result == ["--log-level", "foo"]
def test_ignore_multiple_prefixes(path, expected): scout_config.set(ignore=["/health", "/api"]) try: result = ignore_path(path) finally: scout_config.reset_all() assert result == expected
def set_config_from_bottle(self, app): bottle_configs = {} prefix = "scout." prefix_len = len(prefix) for key, value in app.config.items(): if key.startswith(prefix) and len(key) > prefix_len: scout_key = key[prefix_len:] bottle_configs[scout_key] = value scout_config.set(**bottle_configs)
def test_error_capture_skip(value, error_monitor_errors): scout_config.set(errors_enabled=True) try: Error.capture(value) finally: scout_config.reset_all() assert len(error_monitor_errors) == 0
def test_shutdown_message_disabled(capsys): report_app_metadata() # queued but thread not running try: scout_config.set(shutdown_timeout_seconds=0.1, shutdown_message_enabled=False) shutdown() finally: Config.reset_all() captured = capsys.readouterr() assert not captured.err
def core_agent_manager(core_agent_dir): # Shorten path to socket to prevent core-agent from failing with: # Error opening listener on socket: Custom { kind: InvalidInput, # error: StringError("path must be shorter than SUN_LEN") } socket_path = "{}/test.sock".format(core_agent_dir) scout_config.set(core_agent_dir=core_agent_dir, socket_path=socket_path) core_agent_manager = CoreAgentManager() try: yield core_agent_manager finally: assert not is_running(core_agent_manager) scout_config.reset_all()
def copy_configuration(app): prefix = "scout_" prefix_len = len(prefix) to_set = {} for key, value in app.conf.items(): key_lower = key.lower() if key_lower.startswith(prefix) and len(key_lower) > prefix_len: scout_key = key_lower[prefix_len:] to_set[scout_key] = value scout_config.set(**to_set)
def test_shutdown(capsys): scout_config report_app_metadata() # queued but thread not running try: scout_config.set(shutdown_timeout_seconds=0.1) shutdown() finally: Config.reset_all() captured = capsys.readouterr() assert "Scout draining" in captured.err
def extract_flask_settings(self): """ Copies SCOUT_* settings in the app into Scout's config lookup """ configs = {} configs["application_root"] = self.app.instance_path for name in current_app.config: if name.startswith("SCOUT_"): value = current_app.config[name] clean_name = name.replace("SCOUT_", "").lower() configs[clean_name] = value scout_config.set(**configs)
def includeme(config): configs = {} pyramid_config = config.get_settings() for name in pyramid_config: if name.startswith("SCOUT_"): value = pyramid_config[name] clean_name = name.replace("SCOUT_", "").lower() configs[clean_name] = value scout_config.set(**configs) if scout_apm.core.install(): config.add_tween("scout_apm.pyramid.instruments")
def test_log_level_deprecated(caplog, core_agent_manager): scout_config.set(log_level="foo", core_agent_log_level="bar") result = core_agent_manager.log_level() assert result == ["--log-level", "foo"] assert caplog.record_tuples == [( "scout_apm.core.core_agent_manager", logging.WARNING, ("The config name 'log_level' is deprecated - please use the new name " + "'core_agent_log_level' instead. This might be configured in your " + "environment variables or framework settings as SCOUT_LOG_LEVEL."), )]
def on_setting_changed(self, setting, **kwargs): if setting == "BASE_DIR": scout_name = "application_root" elif setting.startswith("SCOUT_"): scout_name = setting.replace("SCOUT_", "").lower() else: return try: value = getattr(settings, setting) except AttributeError: # It was removed scout_config.unset(scout_name) else: scout_config.set(**{scout_name: value})
def test_no_launch(caplog, core_agent_manager): scout_config.set(core_agent_launch=False) try: result = core_agent_manager.launch() finally: scout_config.set(core_agent_launch=True) assert not result assert not is_running(core_agent_manager) assert caplog.record_tuples == [( "scout_apm.core.core_agent_manager", logging.DEBUG, ("Not attempting to launch Core Agent due to 'core_agent_launch' " + "setting."), )]
def test_no_verify(caplog, core_agent_manager): scout_config.set(core_agent_download=False) try: result = core_agent_manager.launch() finally: scout_config.set(core_agent_download=True) assert not result assert not is_running(core_agent_manager) assert ( "scout_apm.core.core_agent_manager", logging.DEBUG, ("Not attempting to download Core Agent due to " + "'core_agent_download' setting."), ) in caplog.record_tuples
def test_ensure_all_installed_one_disabled(caplog): scout_config.set(disabled_instruments=["jinja2"]) try: ensure_all_installed() finally: scout_config.reset_all() instruments_record_tuples = [ t for t in caplog.record_tuples if t[0] == "scout_apm.instruments" ] assert len(instruments_record_tuples) == 1 assert instruments_record_tuples[0] == ( "scout_apm.instruments", logging.INFO, "jinja2 instrument is disabled. Skipping.", )
def test_error_capture(error_monitor_errors, tracked_request): scout_config.set(errors_enabled=True) tracked_request.tag("spam", "eggs") request_path = "/test/" request_params = {"page": 1} session = {"step": 0} custom_controller = "test-controller" custom_params = {"foo": "bar"} try: try: 1 / 0 except ZeroDivisionError as exc: Error.capture( exc, request_path=request_path, request_params=request_params, session=session, custom_controller=custom_controller, custom_params=custom_params, ) finally: scout_config.reset_all() assert len(error_monitor_errors) == 1 error = error_monitor_errors[0] filepath, line, func_str = error["trace"][0].split(":") assert filepath.endswith("tests/integration/test_api.py") # The line number changes between python versions. Make sure it's not empty. assert line assert func_str == "in test_error_capture" assert error["exception_class"] == "ZeroDivisionError" assert error["message"] == "division by zero" assert error["context"] == { "spam": "eggs", "custom_params": {"foo": "bar"}, } assert error["request_uri"] == request_path assert error["request_params"] == {"page": "1"} assert error["request_session"] == {"step": "0"} assert error["request_components"] == { "module": None, "controller": custom_controller, "action": None, }
def test_download_and_launch(path, core_agent_manager): if path is not None: scout_config.set(core_agent_socket_path=path) try: result = core_agent_manager.launch() assert result is True time.sleep(0.10) # wait for agent to start running for _ in range(10): if core_agent_is_running(): break time.sleep(0.1) else: raise AssertionError("Could not find core agent running") terminate_core_agent_processes() finally: scout_config.reset_all()
def test_send(config, decoded_body, expected_headers, expected_uri, error_service_thread): scout_config.set(**config) try: with httpretty.enabled(allow_net_connect=False): httpretty.register_uri( httpretty.POST, expected_uri, body="Hello World!", ) ErrorServiceThread.send(error={"foo": "BØØM!"}) ErrorServiceThread.wait_until_drained() request = httpretty.last_request() assert (json.loads(gzip_decompress( request.body).decode("utf-8")) == decoded_body) assert request.headers.get("X-Error-Count") == "1" finally: scout_config.reset_all()
def test_config_file_old_name_takes_precedence(core_agent_manager): scout_config.set(config_file="foo", core_agent_config_file="bar") result = core_agent_manager.config_file() assert result == ["--config-file", "foo"]