コード例 #1
0
    def span_event(self, *args, **kwargs):
        attrs = super(DatastoreNodeMixin, self).span_event(*args, **kwargs)
        i_attrs = attrs[0]

        i_attrs['category'] = 'datastore'
        i_attrs['component'] = self.product
        i_attrs['span.kind'] = 'client'

        if self.database_name:
            _, i_attrs['db.instance'] = process_user_attribute(
                'db.instance', self.database_name)
        else:
            i_attrs['db.instance'] = 'Unknown'

        if self.instance_hostname:
            _, i_attrs['peer.hostname'] = process_user_attribute(
                'peer.hostname', self.instance_hostname)
        else:
            i_attrs['peer.hostname'] = 'Unknown'

        peer_address = '%s:%s' % (self.instance_hostname or 'Unknown',
                                  self.port_path_or_id or 'Unknown')

        _, i_attrs['peer.address'] = process_user_attribute(
            'peer.address', peer_address)

        return attrs
コード例 #2
0
    def span_event(self, *args, **kwargs):
        self.agent_attributes['http.url'] = self.http_url
        attrs = super(ExternalNode, self).span_event(*args, **kwargs)
        i_attrs = attrs[0]

        i_attrs['category'] = 'http'
        i_attrs['span.kind'] = 'client'
        _, i_attrs['component'] = attribute.process_user_attribute(
            'component', self.library)

        if self.method:
            _, i_attrs['http.method'] = attribute.process_user_attribute(
                'http.method', self.method)

        return attrs
コード例 #3
0
    def span_event(self, *args, **kwargs):
        attrs = super(ExternalNodeMixin, self).span_event(*args, **kwargs)
        i_attrs = attrs[0]

        i_attrs['category'] = 'http'
        i_attrs['span.kind'] = 'client'
        _, i_attrs['http.url'] = process_user_attribute(
            'http.url', self.url_with_path)
        _, i_attrs['component'] = process_user_attribute(
            'component', self.library)

        if self.method:
            _, i_attrs['http.method'] = process_user_attribute(
                'http.method', self.method)

        return attrs
コード例 #4
0
    def request_parameters_attributes(self):
        # Request parameters are a special case of agent attributes, so they
        # must be added on to agent_attributes separately
        #
        # Filter request parameters through the AttributeFilter, but set the
        # destinations to NONE.
        #
        # That means by default, request parameters won't get included in any
        # destination. But, it will allow user added include/exclude attribute
        # filtering rules to be applied to the request parameters.

        attributes_request = []

        if self._request_params:

            r_attrs = {}

            for k, v in self._request_params.items():
                new_key = 'request.parameters.%s' % k
                new_val = ",".join(v)

                final_key, final_val = process_user_attribute(new_key, new_val)

                if final_key:
                    r_attrs[final_key] = final_val

            attributes_request = create_attributes(
                r_attrs, DST_NONE, self._settings.attribute_filter)

        return attributes_request
コード例 #5
0
    def record_exception(self, exc_info=None, params={}, ignore_errors=[]):

        recorded = self._observe_exception(exc_info, ignore_errors)
        if recorded:
            fullname, message, tb = recorded
            transaction = self.transaction
            settings = transaction and transaction.settings

            # Only add params if High Security Mode is off.

            custom_params = {}

            if settings.high_security:
                if params:
                    _logger.debug('Cannot add custom parameters in '
                                  'High Security Mode.')
            else:
                try:
                    for k, v in params.items():
                        name, val = process_user_attribute(k, v)
                        if name:
                            custom_params[name] = val
                except Exception:
                    _logger.debug(
                        'Parameters failed to validate for unknown '
                        'reason. Dropping parameters for error: %r. Check '
                        'traceback for clues.',
                        fullname,
                        exc_info=True)
                    custom_params = {}

            transaction._create_error_node(settings, fullname, message,
                                           custom_params, self.guid, tb)
コード例 #6
0
    def notice_error(self,
                     error=None,
                     attributes=None,
                     expected=None,
                     ignore=None,
                     status_code=None):
        attributes = attributes if attributes is not None else {}

        recorded = self._observe_exception(
            error,
            ignore=ignore,
            expected=expected,
            status_code=status_code,
        )
        if recorded:
            fullname, message, tb, is_expected = recorded
            transaction = self.transaction
            settings = transaction and transaction.settings

            # Only add params if High Security Mode is off.

            custom_params = {}

            if settings.high_security:
                if attributes:
                    _logger.debug(
                        "Cannot add custom parameters in High Security Mode.")
            else:
                try:
                    for k, v in attributes.items():
                        name, val = process_user_attribute(k, v)
                        if name:
                            custom_params[name] = val
                except Exception:
                    _logger.debug(
                        "Parameters failed to validate for unknown "
                        "reason. Dropping parameters for error: %r. Check "
                        "traceback for clues.",
                        fullname,
                        exc_info=True,
                    )
                    custom_params = {}

            if settings and settings.code_level_metrics and settings.code_level_metrics.enabled:
                source = extract_code_from_traceback(tb)
            else:
                source = None

            transaction._create_error_node(
                settings,
                fullname,
                message,
                is_expected,
                custom_params,
                self.guid,
                tb,
                source=source,
            )
コード例 #7
0
    def http_url(self):
        if hasattr(self, '_http_url'):
            return self._http_url

        _, url_attr = attribute.process_user_attribute('http.url',
                                                       self.url_with_path)

        self._http_url = url_attr
        return url_attr
コード例 #8
0
    def request_parameters_attributes(self):
        # Request parameters are a special case of agent attributes, so
        # they must be added on to agent_attributes separately

        # There are 3 cases we need to handle:
        #
        # 1. LEGACY: capture_params = False
        #
        #    Don't add request parameters at all, which means they will not
        #    go through the AttributeFilter.
        #
        # 2. LEGACY: capture_params = True
        #
        #    Filter request parameters through the AttributeFilter, but
        #    set the destinations to `TRANSACTION_TRACER | ERROR_COLLECTOR`.
        #
        #    If the user does not add any additional attribute filtering
        #    rules, this will result in the same outcome as the old
        #    capture_params = True behavior. They will be added to transaction
        #    traces and error traces.
        #
        # 3. CURRENT: capture_params is None
        #
        #    Filter request parameters through the AttributeFilter, but set
        #    the destinations to NONE.
        #
        #    That means by default, request parameters won't get included in
        #    any destination. But, it will allow user added include/exclude
        #    attribute filtering rules to be applied to the request parameters.

        attributes_request = []

        if (self.capture_params is None) or self.capture_params:

            if self._request_params:

                r_attrs = {}

                for k, v in self._request_params.items():
                    new_key = 'request.parameters.%s' % k
                    new_val = ",".join(v)

                    final_key, final_val = process_user_attribute(new_key,
                            new_val)

                    if final_key:
                        r_attrs[final_key] = final_val

                if self.capture_params is None:
                    attributes_request = create_attributes(r_attrs,
                            DST_NONE, self.attribute_filter)
                elif self.capture_params:
                    attributes_request = create_attributes(r_attrs,
                            DST_ERROR_COLLECTOR | DST_TRANSACTION_TRACER,
                            self.attribute_filter)

        return attributes_request
コード例 #9
0
    def processed_user_attributes(self):
        if hasattr(self, '_processed_user_attributes'):
            return self._processed_user_attributes

        self._processed_user_attributes = u_attrs = {}
        for k, v in self.user_attributes.items():
            k, v = attribute.process_user_attribute(k, v)
            u_attrs[k] = v
        return u_attrs
コード例 #10
0
    def span_event(self, *args, **kwargs):
        sql = self.formatted

        if sql:
            # Truncate to 2000 bytes and append ...
            _, sql = attribute.process_user_attribute(
                    'db.statement', sql, max_length=2000, ending='...')

        self.agent_attributes['db.statement'] = sql
        return super(DatabaseNode, self).span_event(*args, **kwargs)
コード例 #11
0
ファイル: node_mixin.py プロジェクト: lxp20201/lxp
    def db_instance(self):
        if hasattr(self, '_db_instance'):
            return self._db_instance

        db_instance_attr = None
        if self.database_name:
            _, db_instance_attr = attribute.process_user_attribute(
                'db.instance', self.database_name)

        self._db_instance = db_instance_attr
        return db_instance_attr
コード例 #12
0
def create_custom_event(event_type, params):
    """Creates a valid custom event.

    Ensures that the custom event has a valid name, and also checks
    the format and number of attributes. No event is created, if the
    name is invalid. An event is created, if any of the attributes are
    invalid, but the invalid attributes are dropped.

    Args:
        event_type (str): The type (name) of the custom event.
        params (dict): Attributes to add to the event.

    Returns:
        Custom event (list of 2 dicts), if successful.
        None, if not successful.

    """
    # TODO 创建一个有效的自定义事件
    # TODO event_type  自定义事件类型
    # TODO params  自定义事件参数

    name = process_event_type(event_type)

    if name is None:
        return None

    attributes = {}

    try:
        for k, v in params.items():
            key, value = process_user_attribute(k, v)
            if key:
                if len(attributes) >= MAX_NUM_USER_ATTRIBUTES:
                    _logger.debug(
                        'Maximum number of attributes already '
                        'added to event %r. Dropping attribute: %r=%r', name,
                        key, value)
                else:
                    attributes[key] = value
    except Exception:
        _logger.debug(
            'Attributes failed to validate for unknown reason. '
            'Check traceback for clues. Dropping event: %r.',
            name,
            exc_info=True)
        return None

    intrinsics = {
        'type': name,  # TODO 自定义事件访问类型
        'timestamp': int(1000.0 * time.time()),  # TODO 访问时间戳
    }

    event = [intrinsics, attributes]
    return event
コード例 #13
0
    def agent_attributes(self):
        # LEGACY: capture_params = True
        #
        #    Filter request parameters as a normal agent attribute.
        #
        #    If the user does not add any additional attribute filtering
        #    rules, this will result in the same outcome as the old
        #    capture_params = True behavior. They will be added to transaction
        #    traces and error traces.
        if self.capture_params is True:
            for k, v in self._request_params.items():
                new_key = 'request.parameters.%s' % k
                new_val = ",".join(v)

                final_key, final_val = process_user_attribute(new_key, new_val)

                if final_key:
                    self._add_agent_attribute(final_key, final_val)

            self._request_params.clear()

        # Add WSGI agent attributes
        if self.read_duration != 0:
            self._add_agent_attribute('wsgi.input.seconds', self.read_duration)
        if self._bytes_read != 0:
            self._add_agent_attribute('wsgi.input.bytes', self._bytes_read)
        if self._calls_read != 0:
            self._add_agent_attribute('wsgi.input.calls.read',
                                      self._calls_read)
        if self._calls_readline != 0:
            self._add_agent_attribute('wsgi.input.calls.readline',
                                      self._calls_readline)
        if self._calls_readlines != 0:
            self._add_agent_attribute('wsgi.input.calls.readlines',
                                      self._calls_readlines)

        if self.sent_duration != 0:
            self._add_agent_attribute('wsgi.output.seconds',
                                      self.sent_duration)
        if self._bytes_sent != 0:
            self._add_agent_attribute('wsgi.output.bytes', self._bytes_sent)
        if self._calls_write != 0:
            self._add_agent_attribute('wsgi.output.calls.write',
                                      self._calls_write)
        if self._calls_yield != 0:
            self._add_agent_attribute('wsgi.output.calls.yield',
                                      self._calls_yield)

        return super(WSGIWebTransaction, self).agent_attributes
コード例 #14
0
    def span_event(self, *args, **kwargs):
        attrs = super(DatabaseNode, self).span_event(*args, **kwargs)
        i_attrs = attrs[0]

        sql = self.formatted

        # Truncate to 2000 bytes and append ...
        _, sql = process_user_attribute('db.statement',
                                        sql,
                                        max_length=2000,
                                        ending='...')

        i_attrs['db.statement'] = sql

        return attrs
コード例 #15
0
def create_custom_event(event_type, params):
    """Creates a valid custom event.

    Ensures that the custom event has a valid name, and also checks
    the format and number of attributes. No event is created, if the
    name is invalid. An event is created, if any of the attributes are
    invalid, but the invalid attributes are dropped.

    Args:
        event_type (str): The type (name) of the custom event.
        params (dict): Attributes to add to the event.

    Returns:
        Custom event (list of 2 dicts), if successful.
        None, if not successful.

    """

    name = process_event_type(event_type)

    if name is None:
        return None

    attributes = {}

    try:
        for k, v in params.items():
            key, value = process_user_attribute(k, v)
            if key:
                if len(attributes) >= MAX_NUM_USER_ATTRIBUTES:
                    _logger.debug('Maximum number of attributes already '
                            'added to event %r. Dropping attribute: %r=%r',
                            name, key, value)
                else:
                    attributes[key] = value
    except Exception:
        _logger.debug('Attributes failed to validate for unknown reason. '
                'Check traceback for clues. Dropping event: %r.', name,
                exc_info=True)
        return None

    intrinsics = {
        'type': name,
        'timestamp': time.time(),
    }

    event = [intrinsics, attributes]
    return event
コード例 #16
0
    def add_custom_parameter(self, name, value):
        if not self._settings:
            return False

        if self._settings.high_security:
            _logger.debug('Cannot add custom parameter in High Security Mode.')
            return False

        if len(self._custom_params) >= MAX_NUM_USER_ATTRIBUTES:
            _logger.debug('Maximum number of custom attributes already '
                    'added. Dropping attribute: %r=%r', name, value)
            return False

        key, val = process_user_attribute(name, value)

        if key is None:
            return False
        else:
            self._custom_params[key] = val
            return True
コード例 #17
0
    def record_exception(self, exc=None, value=None, tb=None,
                         params={}, ignore_errors=[]):

        # Bail out if the transaction is not active or
        # collection of errors not enabled.

        if not self._settings:
            return

        settings = self._settings
        error_collector = settings.error_collector

        if not error_collector.enabled:
            return

        if not settings.collect_errors and not settings.collect_error_events:
            return

        # If no exception details provided, use current exception.

        if exc is None and value is None and tb is None:
            exc, value, tb = sys.exc_info()

        # Has to be an error to be logged.

        if exc is None or value is None or tb is None:
            return

        # Where ignore_errors is a callable it should return a
        # tri-state variable with the following behavior.
        #
        #   True - Ignore the error.
        #   False- Record the error.
        #   None - Use the default ignore rules.

        should_ignore = None

        if callable(ignore_errors):
            should_ignore = ignore_errors(exc, value, tb)
            if should_ignore:
                return

        module = value.__class__.__module__
        name = value.__class__.__name__

        if should_ignore is None:
            # We need to check for module.name and module:name.
            # Originally we used module.class but that was
            # inconsistent with everything else which used
            # module:name. So changed to use ':' as separator, but
            # for backward compatibility need to support '.' as
            # separator for time being. Check that with the ':'
            # last as we will use that name as the exception type.

            if module:
                fullname = '%s.%s' % (module, name)
            else:
                fullname = name

            if not callable(ignore_errors) and fullname in ignore_errors:
                return

            if fullname in error_collector.ignore_errors:
                return

            if module:
                fullname = '%s:%s' % (module, name)
            else:
                fullname = name

            if not callable(ignore_errors) and fullname in ignore_errors:
                return

            if fullname in error_collector.ignore_errors:
                return

        else:
            if module:
                fullname = '%s:%s' % (module, name)
            else:
                fullname = name

        # Only remember up to limit of what can be caught for a
        # single transaction. This could be trimmed further
        # later if there are already recorded errors and would
        # go over the harvest limit.

        if len(self._errors) >= settings.agent_limits.errors_per_transaction:
            return

        # Only add params if High Security Mode is off.

        custom_params = {}

        if settings.high_security:
            if params:
                _logger.debug('Cannot add custom parameters in '
                        'High Security Mode.')
        else:
            try:
                for k, v in params.items():
                    name, val = process_user_attribute(k, v)
                    if name:
                        custom_params[name] = val
            except Exception:
                _logger.debug('Parameters failed to validate for unknown '
                        'reason. Dropping parameters for error: %r. Check '
                        'traceback for clues.', fullname, exc_info=True)
                custom_params = {}

        # Check to see if we need to strip the message before recording it.

        if (settings.strip_exception_messages.enabled and
                fullname not in settings.strip_exception_messages.whitelist):
            message = STRIP_EXCEPTION_MESSAGE
        else:
            try:

                # Favor unicode in exception messages.

                message = six.text_type(value)

            except Exception:
                try:

                    # If exception cannot be represented in unicode, this means
                    # that it is a byte string encoded with an encoding
                    # that is not compatible with the default system encoding.
                    # So, just pass this byte string along.

                    message = str(value)

                except Exception:
                    message = '<unprintable %s object>' % type(value).__name__

        # Check that we have not recorded this exception
        # previously for this transaction due to multiple
        # error traces triggering. This is not going to be
        # exact but the UI hides exceptions of same type
        # anyway. Better that we under count exceptions of
        # same type and message rather than count same one
        # multiple times.

        for error in self._errors:
            if error.type == fullname and error.message == message:
                return

        node = newrelic.core.error_node.ErrorNode(
                timestamp=time.time(),
                type=fullname,
                message=message,
                stack_trace=exception_stack(tb),
                custom_params=custom_params,
                file_name=None,
                line_number=None,
                source=None)

        # TODO Errors are recorded in time order. If
        # there are two exceptions of same type and
        # different message, the UI displays the first
        # one. In the PHP agent it was recording the
        # errors in reverse time order and so the UI
        # displayed the last one. What is the the
        # official order in which they should be sent.

        self._errors.append(node)
コード例 #18
0
ファイル: time_trace.py プロジェクト: Liu3420175/Python-Agent
    def record_exception(self, exc_info=None, params={}, ignore_errors=[]):

        # Bail out if the transaction is not active or
        # collection of errors not enabled.
        # 记录异常,调用的是事务对象Transaction的接口,很好理解
        transaction = self.transaction
        settings = transaction and transaction.settings

        if not settings:
            return

        # If no exception details provided, use current exception.

        if exc_info and None not in exc_info:
            exc, value, tb = exc_info
        else:
            exc, value, tb = sys.exc_info()

        # Has to be an error to be logged.

        if exc is None or value is None or tb is None:
            return

        # Where ignore_errors is a callable it should return a
        # tri-state variable with the following behavior.
        #
        #   True - Ignore the error.
        #   False- Record the error.
        #   None - Use the default ignore rules.

        should_ignore = None

        if hasattr(transaction, '_ignore_errors'):
            should_ignore = transaction._ignore_errors(exc, value, tb)
            if should_ignore:
                return

        if callable(ignore_errors):
            should_ignore = ignore_errors(exc, value, tb)
            if should_ignore:
                return

        module = value.__class__.__module__
        name = value.__class__.__name__

        if should_ignore is None:
            # We need to check for module.name and module:name.
            # Originally we used module.class but that was
            # inconsistent with everything else which used
            # module:name. So changed to use ':' as separator, but
            # for backward compatibility need to support '.' as
            # separator for time being. Check that with the ':'
            # last as we will use that name as the exception type.
            # 组装异常错误信息名称
            if module:
                names = ('%s:%s' % (module, name), '%s.%s' % (module, name))
            else:
                names = (name)

            for fullname in names:
                if not callable(ignore_errors) and fullname in ignore_errors:
                    return

                if fullname in settings.error_collector.ignore_errors:
                    return

            fullname = names[0]

        else:
            if module:
                fullname = '%s:%s' % (module, name)
            else:
                fullname = name

        # Only add params if High Security Mode is off.

        custom_params = {}

        if settings.high_security:
            if params:
                _logger.debug('Cannot add custom parameters in '
                              'High Security Mode.')
        else:
            try:
                for k, v in params.items():
                    name, val = process_user_attribute(k, v)
                    if name:
                        custom_params[name] = val
            except Exception:
                _logger.debug(
                    'Parameters failed to validate for unknown '
                    'reason. Dropping parameters for error: %r. Check '
                    'traceback for clues.',
                    fullname,
                    exc_info=True)
                custom_params = {}

        # Check to see if we need to strip the message before recording it.

        if (settings.strip_exception_messages.enabled and fullname
                not in settings.strip_exception_messages.whitelist):
            message = STRIP_EXCEPTION_MESSAGE
        else:
            try:

                # Favor unicode in exception messages.

                message = six.text_type(value)

            except Exception:
                try:

                    # If exception cannot be represented in unicode, this means
                    # that it is a byte string encoded with an encoding
                    # that is not compatible with the default system encoding.
                    # So, just pass this byte string along.

                    message = str(value)

                except Exception:
                    message = '<unprintable %s object>' % type(value).__name__

        # Record a supportability metric if error attributes are being
        # overiden.
        if 'error.class' in self.agent_attributes:
            transaction._record_supportability('Supportability/'
                                               'SpanEvent/Errors/Dropped')
        # Add error details as agent attributes to span event.
        # 添加一些代理的参数
        self._add_agent_attribute('error.class', fullname)
        self._add_agent_attribute('error.message', message)

        transaction._create_error_node(settings, fullname, message,
                                       custom_params, self.guid, tb)