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
Beispiel #4
0
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()
Beispiel #5
0
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"]
Beispiel #9
0
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"]
Beispiel #13
0
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
Beispiel #14
0
 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)
Beispiel #15
0
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
Beispiel #16
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)
Beispiel #19
0
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
Beispiel #20
0
 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)
Beispiel #21
0
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."),
    )]
Beispiel #23
0
    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.",
    )
Beispiel #27
0
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"]