コード例 #1
0
def test_finalize_application_settings(server_settings):
    settings = global_settings()

    finalize_application_settings(server_side_config=server_settings,
                                  settings=settings)

    # hostname set in ini_file and not in env vars
    assert settings.utilization.billing_hostname == 'file-hostname'
コード例 #2
0
def test_status_code_exceptions(status_code, expected_exc, log_level, caplog):
    caplog.set_level(logging.INFO)
    HttpClientRecorder.STATUS_CODE = status_code
    settings = finalize_application_settings({
        "license_key": "123LICENSEKEY",
    })
    protocol = AgentProtocol(settings, client_cls=HttpClientRecorder)

    internal_metrics = CustomMetrics()
    with InternalTraceContext(internal_metrics):
        with pytest.raises(expected_exc):
            protocol.send("analytic_event_data")

    internal_metrics = dict(internal_metrics.metrics())
    if status_code == 413:
        assert internal_metrics[
            "Supportability/Python/Collector/MaxPayloadSizeLimit/analytic_event_data"] == [
                1, 0, 0, 0, 0, 0
            ]
    else:
        assert (
            "Supportability/Python/Collector/MaxPayloadSizeLimit/analytic_event_data"
            not in internal_metrics)

    assert len(HttpClientRecorder.SENT) == 1
    request = HttpClientRecorder.SENT[0]
    assert request.params["method"] == "analytic_event_data"

    assert len(caplog.records) == 1
    assert caplog.records[0].levelname == log_level
    message = caplog.records[0].getMessage()
    assert "123LICENSEKEY" not in message
コード例 #3
0
def test_protocol_context_manager():
    protocol = AgentProtocol(finalize_application_settings(),
                             client_cls=HttpClientRecorder)
    with protocol:
        assert HttpClientRecorder.STATE == 1

    assert HttpClientRecorder.STATE == 0
コード例 #4
0
def test_max_payload_size_limit():
    settings = finalize_application_settings(
        {"max_payload_size_in_bytes": 0, "port": -1}
    )
    protocol = AgentProtocol(settings, host="localhost")
    with pytest.raises(DiscardDataForRequest):
        protocol.send("metric_data")
コード例 #5
0
def test_audit_logging():
    with tempfile.NamedTemporaryFile(delete=False) as f:
        f.write(b"*\n")

    settings = finalize_application_settings({"audit_log_file": f.name})
    protocol = AgentProtocol(settings, client_cls=HttpClientRecorder)
    protocol.send("preconnect")

    with open(f.name) as f:
        audit_log_contents = f.read()

    assert audit_log_contents.startswith("*\n")
    assert len(audit_log_contents) > 2
コード例 #6
0
def test_connect_metadata(monkeypatch):
    monkeypatch.setenv("NEW_RELIC_METADATA_FOOBAR", "foobar")
    monkeypatch.setenv("_NEW_RELIC_METADATA_WRONG", "wrong")
    protocol = AgentProtocol.connect(
        APP_NAME,
        LINKED_APPS,
        ENVIRONMENT,
        finalize_application_settings(),
        client_cls=HttpClientRecorder,
    )
    connect = HttpClientRecorder.SENT[1]
    assert connect.params["method"] == "connect"
    connect_payload = json_decode(connect.payload.decode("utf-8"))[0]
    assert connect_payload["metadata"] == {"NEW_RELIC_METADATA_FOOBAR": "foobar"}
コード例 #7
0
def test_ca_bundle_path(monkeypatch, ca_bundle_path):
    # Pretend CA certificates are not available
    class DefaultVerifyPaths(object):
        cafile = None

        def __init__(self, *args, **kwargs):
            pass

    monkeypatch.setattr(ssl, "DefaultVerifyPaths", DefaultVerifyPaths)

    settings = finalize_application_settings({"ca_bundle_path": ca_bundle_path})
    protocol = AgentProtocol(settings)
    expected = ca_bundle_path or certs.where()
    assert protocol.client._connection_kwargs["ca_certs"] == expected
コード例 #8
0
 def connect(
     cls,
     app_name,
     linked_applications,
     environment,
     settings,
     client_cls=ServerlessModeClient,
 ):
     aws_lambda_metadata = settings.aws_lambda_metadata
     settings = finalize_application_settings(
         {"cross_application_tracer.enabled": False}, settings)
     # Metadata must come from the original settings object since it
     # can be modified later
     settings.aws_lambda_metadata = aws_lambda_metadata
     return cls(settings, client_cls=client_cls)
コード例 #9
0
    def connect(
        cls,
        app_name,
        linked_applications,
        environment,
        settings,
        client_cls=ApplicationModeClient,
    ):
        with cls(settings, client_cls=client_cls) as preconnect:
            redirect_host = preconnect.send("preconnect")["redirect_host"]

        with cls(settings, host=redirect_host,
                 client_cls=client_cls) as protocol:
            configuration = protocol.send(
                "connect",
                cls._connect_payload(app_name, linked_applications,
                                     environment, settings),
            )

        # Apply High Security Mode to server_config, so the local
        # security settings won't get overwritten when we overlay
        # the server settings on top of them.

        configuration = cls._apply_high_security_mode_fixups(
            configuration, settings)

        # The agent configuration for the application in constructed
        # by taking a snapshot of the locally constructed
        # configuration and overlaying it with that from the server,
        # as well as creating the attribute filter.
        settings = finalize_application_settings(configuration, settings)

        with cls(settings, host=redirect_host,
                 client_cls=client_cls) as protocol:
            protocol.send(
                "agent_settings",
                (global_settings_dump(settings, serializable=True), ))

        if "messages" in configuration:
            for item in configuration["messages"]:
                message = item["message"]
                level = item["level"]
                logger_func = cls.LOGGER_FUNC_MAPPING.get(level, None)
                if logger_func:
                    logger_func("%s", message)

        return protocol
コード例 #10
0
def test_serverless_protocol_finalize(capsys):
    protocol = ServerlessModeProtocol(
        finalize_application_settings(
            {"aws_lambda_metadata": {"foo": "bar", "agent_version": "x"}}
        )
    )
    response = protocol.send("metric_data", (1, 2, 3))
    assert response is None

    payload = protocol.finalize()
    captured = capsys.readouterr()
    assert captured.out.rstrip("\n") == payload

    payload = json_decode(payload)
    assert payload[:2] == [1, "NR_LAMBDA_MONITORING"]

    data = serverless_payload_decode(payload[2])
    assert data["data"] == {"metric_data": [1, 2, 3]}

    assert data["metadata"]["foo"] == "bar"
    assert data["metadata"]["agent_version"] != "x"
コード例 #11
0
def session():
    initialize_agent(app_name='Python Agent Test (test_max_payload_size)',
                     default_settings=_default_settings)

    session = ApplicationSession("https://collector.newrelic.com", None,
                                 finalize_application_settings())

    # patch in application sesssion requests
    original_request = session.requests_session.request
    assert original_request

    def request(*args, **kwargs):
        assert False, "Outbound request made"

    # Disable all requests
    session.requests_session.request = request

    yield session

    # Re-enable requests
    session.requests_session.request = original_request
コード例 #12
0
def test_send(status_code):
    HttpClientRecorder.STATUS_CODE = status_code
    settings = finalize_application_settings({
        "request_headers_map": {
            "custom-header": u"value"
        },
        "agent_run_id": "RUN_TOKEN",
    })
    protocol = AgentProtocol(settings, client_cls=HttpClientRecorder)
    response = protocol.send("metric_data", (1, 2, 3))
    assert response is None

    assert len(HttpClientRecorder.SENT) == 1
    request = HttpClientRecorder.SENT[0]

    assert request.method == "POST"
    assert request.path == "/agent_listener/invoke_raw_method"

    # Verify license key was there, but no way to validate the value
    request.params.pop("license_key")

    assert request.params == {
        "method": "metric_data",
        "marshal_format": "json",
        "protocol_version": AgentProtocol.VERSION,
        "run_id": "RUN_TOKEN",
    }

    assert request.headers == {
        "Content-Type": "application/json",
        "custom-header": u"value",
    }

    assert request.payload == b"[1,2,3]"

    # Verify call to finalize is None
    assert protocol.finalize() is None
コード例 #13
0
ファイル: data_collector.py プロジェクト: jimmoffet/VoteBot
    def create_session(cls, license_key, app_name, linked_applications,
            environment, settings):

        """Registers the agent for the specified application with the data
        collector and retrieves the server side configuration. Returns a
        session object if successful through which subsequent calls to the
        data collector are made. If unsuccessful then None is returned.

        """

        start = time.time()

        # If no license key provided in the call, fall back to using that
        # from the agent configuration file or environment variables.
        # Flag an error if the result still seems invalid.

        if not license_key:
            license_key = global_settings().license_key

        if not license_key:
            _logger.error('A valid account license key cannot be found. '
                'Has a license key been specified in the agent configuration '
                'file or via the NEW_RELIC_LICENSE_KEY environment variable?')

        try:
            # First need to ask the primary data collector which of the many
            # data collector instances we should use for this agent run.

            _logger.debug('Connecting to data collector to register agent '
                    'with license_key=%r, app_name=%r, '
                    'linked_applications=%r, environment=%r and settings=%r.',
                    license_key, app_name, linked_applications, environment,
                    settings)

            url = collector_url()

            redirect_host = cls.send_request(None, url,
                    'get_redirect_host', license_key)

            # Then we perform a connect to the actual data collector host
            # we need to use. All communications after this point should go
            # to the secondary data collector.
            #
            # We use the global requests session object for now as harvest
            # for different applications are all done in turn. We will need
            # to change this if use multiple threads as currently force
            # session object to maintain only single connection to ensure
            # that keep alive is effective.

            payload = cls._create_connect_payload(app_name,
                    linked_applications, environment, settings)

            url = collector_url(redirect_host)

            server_config = cls.send_request(None, url, 'connect',
                    license_key, None, payload)

            # Apply High Security Mode to server_config, so the local
            # security settings won't get overwritten when we overlay
            # the server settings on top of them.

            server_config = apply_high_security_mode_fixups(settings,
                    server_config)

            # The agent configuration for the application in constructed
            # by taking a snapshot of the locally constructed
            # configuration and overlaying it with that from the server,
            # as well as creating the attribute filter.

            application_config = finalize_application_settings(server_config)

        except NetworkInterfaceException:
            # The reason for errors of this type have already been logged.
            # No matter what the error we just pass back None. The upper
            # layer needs to count how many success times this has failed
            # and escalate things with a more sever error.

            pass

        except Exception:
            # Any other errors are going to be unexpected and likely will
            # indicate an issue with the implementation of the agent.

            _logger.exception('Unexpected exception when attempting to '
                    'register the agent with the data collector. Please '
                    'report this problem to New Relic support for further '
                    'investigation.')

            pass

        else:
            # Everything fine so we create the session object through which
            # subsequent communication with data collector will be done.

            session = cls(url, license_key, application_config)

            duration = time.time() - start

            # Log successful agent registration and any server side messages.

            _logger.info('Successfully registered New Relic Python agent '
                    'where app_name=%r, pid=%r, redirect_host=%r and '
                    'agent_run_id=%r, in %.2f seconds.', app_name,
                    os.getpid(), redirect_host, session.agent_run_id,
                    duration)

            if getattr(application_config, 'high_security', False):
                _logger.info('High Security Mode is being applied to all '
                        'communications between the agent and the data '
                        'collector for this session.')

            logger_func_mapping = {
                'ERROR': _logger.error,
                'WARN': _logger.warning,
                'INFO': _logger.info,
                'VERBOSE': _logger.debug,
            }

            if 'messages' in server_config:
                for item in server_config['messages']:
                    message = item['message']
                    level = item['level']
                    logger_func = logger_func_mapping.get(level, None)
                    if logger_func:
                        logger_func('%s', message)

            return session
コード例 #14
0
def test_connect(with_aws, with_pcf, with_gcp, with_azure, with_docker,
                 with_kubernetes, with_ip):
    global AWS, AZURE, GCP, PCF, BOOT_ID, DOCKER, KUBERNETES, IP_ADDRESS
    if not with_aws:
        AWS = Exception
    if not with_pcf:
        PCF = Exception
    if not with_gcp:
        GCP = Exception
    if not with_azure:
        AZURE = Exception
    if not with_docker:
        DOCKER = Exception
    if not with_kubernetes:
        KUBERNETES = Exception
    if not with_ip:
        IP_ADDRESS = None
    settings = finalize_application_settings({
        "browser_monitoring.loader": BROWSER_MONITORING_LOADER,
        "browser_monitoring.debug": BROWSER_MONITORING_DEBUG,
        "capture_params": CAPTURE_PARAMS,
        "process_host.display_name": DISPLAY_NAME,
        "transaction_tracer.record_sql": RECORD_SQL,
        "high_security": HIGH_SECURITY,
        "labels": LABELS,
        "utilization.detect_aws": with_aws,
        "utilization.detect_pcf": with_pcf,
        "utilization.detect_gcp": with_gcp,
        "utilization.detect_azure": with_azure,
        "utilization.detect_docker": with_docker,
        "utilization.detect_kubernetes": with_kubernetes,
        "event_harvest_config": {
            "harvest_limits": {
                "analytic_event_data": ANALYTIC_EVENT_DATA,
                "span_event_data": SPAN_EVENT_DATA,
                "custom_event_data": CUSTOM_EVENT_DATA,
                "error_event_data": ERROR_EVENT_DATA,
            }
        },
    })
    protocol = AgentProtocol.connect(
        APP_NAME,
        LINKED_APPS,
        ENVIRONMENT,
        settings,
        client_cls=HttpClientRecorder,
    )

    # verify there are exactly 3 calls to HttpClientRecorder
    assert len(HttpClientRecorder.SENT) == 3

    # Verify preconnect call
    preconnect = HttpClientRecorder.SENT[0]
    assert preconnect.params["method"] == "preconnect"
    assert preconnect.payload == b"[]"

    # Verify connect call
    connect = HttpClientRecorder.SENT[1]
    assert connect.params["method"] == "connect"
    connect_payload = json_decode(connect.payload.decode("utf-8"))
    connect_payload_asserts(
        connect_payload,
        with_aws=with_aws,
        with_pcf=with_pcf,
        with_gcp=with_gcp,
        with_azure=with_azure,
        with_docker=with_docker,
        with_kubernetes=with_kubernetes,
    )

    # Verify agent_settings call is done with the finalized settings
    agent_settings = HttpClientRecorder.SENT[2]
    assert agent_settings.params["method"] == "agent_settings"
    agent_settings_payload = json_decode(
        agent_settings.payload.decode("utf-8"))
    assert len(agent_settings_payload) == 1
    agent_settings_payload = agent_settings_payload[0]

    # Finalized settings will have a non-None agent_run_id
    assert agent_settings_payload["agent_run_id"] is not None
    assert protocol.configuration.agent_run_id is not None

    # Verify that agent settings sent have converted null, containers, and
    # unserializable types to string
    assert agent_settings_payload["proxy_host"] == "None"
    assert agent_settings_payload["attributes.include"] == "[]"
    assert agent_settings_payload["feature_flag"] == str(set())
    assert isinstance(agent_settings_payload["attribute_filter"],
                      six.string_types)

    # Verify that the connection is closed
    assert HttpClientRecorder.STATE == 0
コード例 #15
0
def test_close_connection():
    protocol = AgentProtocol(finalize_application_settings(),
                             client_cls=HttpClientRecorder)
    protocol.close_connection()
    assert HttpClientRecorder.STATE == -1
コード例 #16
0
            self.harvest_flexible += 1
        else:
            self.harvest_default += 1

        if shutdown:
            self.is_alive = False


class FakeAgent(Agent):
    def __init__(self, *args, **kwargs):
        super(FakeAgent, self).__init__(*args, **kwargs)
        self._applications = {'fake': FakeApplication()}


SETTINGS = finalize_application_settings({
    'enabled': True,
    'debug.disable_harvest_until_shutdown': False,
})


@pytest.fixture
def agent():
    agent = FakeAgent(SETTINGS)
    yield agent
    agent.shutdown_agent(timeout=5)
    assert not agent._harvest_thread.is_alive()


_override_settings = {
    'event_harvest_config.report_period_ms': 80.0 * 1000.0,
}
コード例 #17
0
def transaction_node(request):
    default_capacity = SampledDataSet().capacity
    num_events = default_capacity + 1

    custom_events = SampledDataSet(capacity=num_events)
    for _ in range(num_events):
        event = create_custom_event("Custom", {})
        custom_events.add(event)

    error = ErrorNode(
        timestamp=0,
        type="foo:bar",
        message="oh no! your foo had a bar",
        expected=False,
        span_id=None,
        stack_trace="",
        custom_params={},
        file_name=None,
        line_number=None,
        source=None,
    )

    errors = tuple(error for _ in range(num_events))

    function = FunctionNode(
        group="Function",
        name="foo",
        children=(),
        start_time=0,
        end_time=1,
        duration=1,
        exclusive=1,
        label=None,
        params=None,
        rollup=None,
        guid="GUID",
        agent_attributes={},
        user_attributes={},
    )

    children = tuple(function for _ in range(num_events))

    root = RootNode(
        name="Function/main",
        children=children,
        start_time=1524764430.0,
        end_time=1524764430.1,
        duration=0.1,
        exclusive=0.1,
        guid=None,
        agent_attributes={},
        user_attributes={},
        path="OtherTransaction/Function/main",
        trusted_parent_span=None,
        tracing_vendors=None,
    )

    node = TransactionNode(
        settings=finalize_application_settings({"agent_run_id": "1234567"}),
        path="OtherTransaction/Function/main",
        type="OtherTransaction",
        group="Function",
        base_name="main",
        name_for_metric="Function/main",
        port=None,
        request_uri=None,
        queue_start=0.0,
        start_time=1524764430.0,
        end_time=1524764430.1,
        last_byte_time=0.0,
        total_time=0.1,
        response_time=0.1,
        duration=0.1,
        exclusive=0.1,
        root=root,
        errors=errors,
        slow_sql=(),
        custom_events=custom_events,
        apdex_t=0.5,
        suppress_apdex=False,
        custom_metrics=CustomMetrics(),
        guid="4485b89db608aece",
        cpu_time=0.0,
        suppress_transaction_trace=False,
        client_cross_process_id=None,
        referring_transaction_guid=None,
        record_tt=False,
        synthetics_resource_id=None,
        synthetics_job_id=None,
        synthetics_monitor_id=None,
        synthetics_header=None,
        is_part_of_cat=False,
        trip_id="4485b89db608aece",
        path_hash=None,
        referring_path_hash=None,
        alternate_path_hashes=[],
        trace_intrinsics={},
        distributed_trace_intrinsics={},
        agent_attributes=[],
        user_attributes=[],
        priority=1.0,
        parent_transport_duration=None,
        parent_span=None,
        parent_type=None,
        parent_account=None,
        parent_app=None,
        parent_tx=None,
        parent_transport_type=None,
        sampled=True,
        root_span_guid=None,
        trace_id="4485b89db608aece",
        loop_time=0.0,
    )
    return node
コード例 #18
0
def test_protocol_http_error_causes_retry():
    protocol = AgentProtocol(finalize_application_settings(),
                             client_cls=HttpClientException)
    with pytest.raises(RetryDataForRequest):
        protocol.send("analytic_event_data")
コード例 #19
0
ファイル: data_collector.py プロジェクト: tasnim07/BlackFly
    def create_session(cls, license_key, app_name, linked_applications,
            environment, settings):

        """Registers the agent for the specified application with the data
        collector and retrieves the server side configuration. Returns a
        session object if successful through which subsequent calls to the
        data collector are made. If unsucessful then None is returned.

        """

        start = time.time()

        # If no license key provided in the call, fallback to using that
        # from the agent configuration file or environment variables.
        # Flag an error if the result still seems invalid.

        if not license_key:
            license_key = global_settings().license_key

        if not license_key:
            _logger.error('A valid account license key cannot be found. '
                'Has a license key been specified in the agent configuration '
                'file or via the NEW_RELIC_LICENSE_KEY environment variable?')

        try:
            # First need to ask the primary data collector which of the many
            # data collector instances we should use for this agent run.

            _logger.debug('Connecting to data collector to register agent '
                    'with license_key=%r, app_name=%r, '
                    'linked_applications=%r, environment=%r and settings=%r.',
                    license_key, app_name, linked_applications, environment,
                    settings)

            url = collector_url()

            with InternalTrace('Supportability/Python/Collector/Calls/'
                    'get_redirect_host'):
                redirect_host = cls.send_request(None, url,
                        'get_redirect_host', license_key)

            # Then we perform a connect to the actual data collector host
            # we need to use. All communications after this point should go
            # to the secondary data collector.
            #
            # We use the global requests session object for now as harvest
            # for different applications are all done in turn. We will need
            # to change this if use multiple threads as currently force
            # session object to maintain only single connection to ensure
            # that keep alive is effective.

            payload = cls._create_connect_payload(app_name,
                    linked_applications, environment, settings)

            url = collector_url(redirect_host)

            with InternalTrace('Supportability/Python/Collector/Calls/'
                    'connect'):
                server_config = cls.send_request(None, url, 'connect',
                        license_key, None, payload)

            # Apply High Security Mode to server_config, so the local
            # security settings won't get overwritten when we overlay
            # the server settings on top of them.

            server_config = apply_high_security_mode_fixups(settings,
                    server_config)

            # The agent configuration for the application in constructed
            # by taking a snapshot of the locally constructed
            # configuration and overlaying it with that from the server,
            # as well as creating the attribute filter.

            application_config = finalize_application_settings(server_config)

        except NetworkInterfaceException:
            # The reason for errors of this type have already been logged.
            # No matter what the error we just pass back None. The upper
            # layer needs to count how many success times this has failed
            # and escalate things with a more sever error.

            pass

        except Exception:
            # Any other errors are going to be unexpected and likely will
            # indicate an issue with the implementation of the agent.

            _logger.exception('Unexpected exception when attempting to '
                    'register the agent with the data collector. Please '
                    'report this problem to New Relic support for further '
                    'investigation.')

            pass

        else:
            # Everything fine so we create the session object through which
            # subsequent communication with data collector will be done.

            session = cls(url, license_key, application_config)

            duration = time.time() - start

            # Log successful agent registration and any server side messages.

            _logger.info('Successfully registered New Relic Python agent '
                    'where app_name=%r, pid=%r, redirect_host=%r and '
                    'agent_run_id=%r, in %.2f seconds.', app_name,
                    os.getpid(), redirect_host, session.agent_run_id,
                    duration)

            if getattr(application_config, 'high_security', False):
                _logger.info('High Security Mode is being applied to all '
                        'communications between the agent and the data '
                        'collector for this session.')

            logger_func_mapping = {
                'ERROR': _logger.error,
                'WARN': _logger.warning,
                'INFO': _logger.info,
                'VERBOSE': _logger.debug,
            }

            if 'messages' in server_config:
                for item in server_config['messages']:
                    message = item['message']
                    level = item['level']
                    logger_func = logger_func_mapping.get(level, None)
                    if logger_func:
                        logger_func('%s', message)

            return session