def time_metrics(self, stats, root, parent):
        """Return a generator yielding the timed metrics for this
        database node as well as all the child nodes.
        """

        field_name = self.field_name or "<unknown>"
        product = self.product

        # Determine the scoped metric

        field_resolver_metric_name = 'GraphQL/resolve/%s/%s' % (product,
                                                                field_name)

        yield TimeMetric(name=field_resolver_metric_name,
                         scope=root.path,
                         duration=self.duration,
                         exclusive=self.exclusive)

        yield TimeMetric(name=field_resolver_metric_name,
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        # Now for the children

        for child in self.children:
            for metric in child.time_metrics(stats, root, self):
                yield metric
Esempio n. 2
0
    def time_metrics(self, stats, root, parent):
        """Return a generator yielding the timed metrics for this
        memcache node as well as all the child nodes.

        """
        yield TimeMetric(name='Solr/all',
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        if root.type == 'WebTransaction':
            yield TimeMetric(name='Solr/allWeb',
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)
        else:
            yield TimeMetric(name='Solr/allOther',
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)

        name = 'Solr/%s' % self.command

        yield TimeMetric(name=name,
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        yield TimeMetric(name=name,
                         scope=root.path,
                         duration=self.duration,
                         exclusive=self.exclusive)
Esempio n. 3
0
    def time_metrics(self, stats, root, parent):
        """Return a generator yielding the timed metrics for this
        external node as well as all the child nodes.

        """

        yield TimeMetric(name='External/all', scope='',
                duration=self.duration, exclusive=self.exclusive)

        if root.type == 'WebTransaction':
            yield TimeMetric(name='External/allWeb', scope='',
                    duration=self.duration, exclusive=self.exclusive)
        else:
            yield TimeMetric(name='External/allOther', scope='',
                    duration=self.duration, exclusive=self.exclusive)

        netloc = self.netloc

        try:

            # Remove cross_process_id from the params dict otherwise it shows
            # up in the UI.

            self.cross_process_id = self.params.pop('cross_process_id')
            self.external_txn_name = self.params.pop('external_txn_name')
        except KeyError:
            self.cross_process_id = None
            self.external_txn_name = None

        name = 'External/%s/all' % netloc

        yield TimeMetric(name=name, scope='', duration=self.duration,
                  exclusive=self.exclusive)

        if self.cross_process_id is None:
            method = self.method or ''

            name = 'External/%s/%s/%s' % (netloc, self.library, method)

            yield TimeMetric(name=name, scope='', duration=self.duration,
                    exclusive=self.exclusive)

            yield TimeMetric(name=name, scope=root.path,
                    duration=self.duration, exclusive=self.exclusive)

        else:
            name = 'ExternalTransaction/%s/%s/%s' % (netloc,
                    self.cross_process_id, self.external_txn_name)

            yield TimeMetric(name=name, scope='', duration=self.duration,
                    exclusive=self.exclusive)

            yield TimeMetric(name=name, scope=root.path,
                    duration=self.duration, exclusive=self.exclusive)

            name = 'ExternalApp/%s/%s/all' % (netloc, self.cross_process_id)

            yield TimeMetric(name=name, scope='', duration=self.duration,
                    exclusive=self.exclusive)
    def time_metrics(self, stats, root, parent):
        """Return a generator yielding the timed metrics for this
        messagebroker node as well as all the child nodes.

        """
        name = 'MessageBroker/%s/%s/%s/Named/%s' % (self.library,
                self.destination_type, self.operation, self.destination_name)

        # Unscoped metric

        yield TimeMetric(name=name, scope='',
                duration=self.duration, exclusive=self.exclusive)

        # Scoped metric

        yield TimeMetric(name=name, scope=root.path,
                duration=self.duration, exclusive=self.exclusive)
Esempio n. 5
0
    def time_metrics(self, stats, root, parent):
        """Return a generator yielding the timed metrics for this
        database node as well as all the child nodes.

        """

        yield TimeMetric(name='Datastore/all',
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        if root.type == 'WebTransaction':
            yield TimeMetric(name='Datastore/allWeb',
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)
        else:
            yield TimeMetric(name='Datastore/allOther',
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)

        # FIXME The follow is what PHP agent was doing, but it may
        # not sync up with what is now actually required. As example,
        # the 'show' operation in PHP agent doesn't generate a full
        # path with a table name, yet get_table() in SQL parser
        # does appear to generate one. Also, the SQL parser has
        # special cases for 'set', 'create' and 'call' as well.

        product = self.product
        target = self.target or '*'
        operation = self.operation

        name = 'Datastore/%s/%s/%s' % (product, target, operation)

        yield TimeMetric(name=name,
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        yield TimeMetric(name=name,
                         scope=root.path,
                         duration=self.duration,
                         exclusive=self.exclusive)

        name = 'Datastore/%s/%s' % (product, operation)

        yield TimeMetric(name=name,
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        name = 'Datastore/%s/all' % product

        yield TimeMetric(name=name,
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)
Esempio n. 6
0
    def time_metrics(self, stats, root, parent):
        """Return a generator yielding the timed metrics for this
        messagebroker node as well as all the child nodes.

        """
        name = self.name

        # Unscoped metric

        yield TimeMetric(name=name,
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        # Scoped metric

        yield TimeMetric(name=name,
                         scope=root.path,
                         duration=self.duration,
                         exclusive=self.exclusive)
Esempio n. 7
0
    def time_metrics(self, stats, root, parent):
        """Return a generator yielding the timed metrics for this
        function node as well as all the child nodes.

        """

        name = '%s/%s' % (self.group, self.name)

        yield TimeMetric(name=name,
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        yield TimeMetric(name=name,
                         scope=root.path,
                         duration=self.duration,
                         exclusive=self.exclusive)

        # Now for the children.

        for child in self.children:
            for metric in child.time_metrics(stats, root, self):
                yield metric
Esempio n. 8
0
    def time_metrics(self, stats, root, parent):
        """Return a generator yielding the timed metrics for this
        function node as well as all the child nodes.

        """

        name = '%s/%s' % (self.group, self.name)

        yield TimeMetric(name=name, scope='', duration=self.duration,
                exclusive=self.exclusive)

        yield TimeMetric(name=name, scope=root.path,
                duration=self.duration, exclusive=self.exclusive)

        # Generate one or more rollup metric if any have been specified.
        # We can actually get a single string value or a list of strings
        # if more than one.
        #
        # We actually implement two cases here. If the rollup name ends
        # with /all, then we implement the old style, which is to
        # generate an unscoped /all metric, plus if a web transaction
        # then /allWeb. For non web transaction also generate /allOther.
        #
        # If not the old style, but new style, the rollup metric
        # has scope corresponding to the transaction type.
        #
        # For the old style it must match one of the existing rollup
        # categories recognised by the UI. For the new, we can add our
        # own rollup categories.

        if self.rollup:
            if isinstance(self.rollup, six.string_types):
                rollups = [self.rollup]
            else:
                rollups = self.rollup

            for rollup in rollups:
                if rollup.endswith('/all'):
                    yield TimeMetric(name=rollup, scope='',
                            duration=self.duration, exclusive=None)

                    if root.type == 'WebTransaction':
                        yield TimeMetric(name=rollup+'Web', scope='',
                                duration=self.duration, exclusive=None)
                    else:
                        yield TimeMetric(name=rollup+'Other', scope='',
                                duration=self.duration, exclusive=None)

                else:
                    yield TimeMetric(name=rollup, scope=root.type,
                            duration=self.duration, exclusive=None)

        # Now for the children.

        for child in self.children:
            for metric in child.time_metrics(stats, root, self):
                yield metric
Esempio n. 9
0
    def time_metrics(self, stats, root, parent):
        """Return a generator yielding the timed metrics for this
        function node as well as all the child nodes.

        """

        name = 'EventLoop/Wait/%s' % self.name

        yield TimeMetric(name=name,
                         scope='',
                         duration=self.duration,
                         exclusive=self.duration)

        yield TimeMetric(name=name,
                         scope=root.path,
                         duration=self.duration,
                         exclusive=self.duration)

        name = 'EventLoop/Wait/all'

        # Create IO loop rollup metrics
        yield TimeMetric(name=name,
                         scope='',
                         duration=self.duration,
                         exclusive=None)

        if root.type == 'WebTransaction':
            yield TimeMetric(name=name + 'Web',
                             scope='',
                             duration=self.duration,
                             exclusive=None)
        else:
            yield TimeMetric(name=name + 'Other',
                             scope='',
                             duration=self.duration,
                             exclusive=None)
    def time_metrics(self, stats):
        """Return a generator yielding the timed metrics for the
        top level web transaction as well as all the child nodes.

        """

        # TODO What to do about a transaction where the name is
        # None. In the PHP agent it replaces it with an
        # underscore for timed metrics and continues. For an
        # apdex metric the PHP agent ignores it however. For now
        # we just ignore it.

        if not self.name:
            return

        if self.type == 'WebTransaction':
            # Report time taken by request dispatcher. We don't
            # know upstream time distinct from actual request
            # time so can't report time exclusively in the
            # dispatcher.

            # TODO Technically could work this out with the
            # modifications in Apache/mod_wsgi to mark start of
            # the request. How though does that differ to queue
            # time. Need to clarify purpose of HttpDispatcher
            # and how the exclusive component would appear in
            # the overview graphs.

            yield TimeMetric(name='HttpDispatcher',
                             scope='',
                             duration=self.duration,
                             exclusive=None)

            # Upstream queue time within any web server front end.

            # TODO How is this different to the exclusive time
            # component for the dispatcher above.

            # TODO Not yet dealing with additional headers for
            # tracking time through multiple front ends.

            if self.queue_start != 0:
                queue_wait = self.start_time - self.queue_start
                if queue_wait < 0:
                    queue_wait = 0

                yield TimeMetric(name='WebFrontend/QueueTime',
                                 scope='',
                                 duration=queue_wait,
                                 exclusive=None)

        # Generate the full transaction metric.

        yield TimeMetric(name=self.path,
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        # Generate the rollup metric.

        if self.type != 'WebTransaction':
            rollup = '%s/all' % self.type
        else:
            rollup = self.type

        yield TimeMetric(name=rollup,
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        if self.errors:
            # Generate overall rollup metric indicating if errors present.
            yield TimeMetric(name='Errors/all',
                             scope='',
                             duration=0.0,
                             exclusive=None)

            # Generate individual error metric for transaction.
            yield TimeMetric(name='Errors/%s' % self.path,
                             scope='',
                             duration=0.0,
                             exclusive=None)

            # Generate rollup metric for WebTransaction errors.
            if self.type == 'WebTransaction':
                yield TimeMetric(name='Errors/allWeb',
                                 scope='',
                                 duration=0.0,
                                 exclusive=None)

            # Generate rollup metric for OtherTransaction errors.
            if self.type != 'WebTransaction':
                yield TimeMetric(name='Errors/allOther',
                                 scope='',
                                 duration=0.0,
                                 exclusive=None)

        # Now for the children.

        for child in self.children:
            for metric in child.time_metrics(stats, self, self):
                yield metric
Esempio n. 11
0
    def time_metrics(self, stats):
        """Return a generator yielding the timed metrics for the
        top level web transaction as well as all the child nodes.

        """

        # TODO What to do about a transaction where the name is
        # None. In the PHP agent it replaces it with an
        # underscore for timed metrics and continues. For an
        # apdex metric the PHP agent ignores it however. For now
        # we just ignore it.

        if not self.base_name:
            return

        if self.type == 'WebTransaction':
            # Report time taken by request dispatcher. We don't
            # know upstream time distinct from actual request
            # time so can't report time exclusively in the
            # dispatcher.

            # TODO Technically could work this out with the
            # modifications in Apache/mod_wsgi to mark start of
            # the request. How though does that differ to queue
            # time. Need to clarify purpose of HttpDispatcher
            # and how the exclusive component would appear in
            # the overview graphs.

            yield TimeMetric(
                    name='HttpDispatcher',
                    scope='',
                    duration=self.response_time,
                    exclusive=None)

            # Upstream queue time within any web server front end.

            # TODO How is this different to the exclusive time
            # component for the dispatcher above.

            # TODO Not yet dealing with additional headers for
            # tracking time through multiple front ends.

            if self.queue_start != 0:
                queue_wait = self.start_time - self.queue_start
                if queue_wait < 0:
                    queue_wait = 0

                yield TimeMetric(
                        name='WebFrontend/QueueTime',
                        scope='',
                        duration=queue_wait,
                        exclusive=None)

        # Generate the full transaction metric.

        yield TimeMetric(
                name=self.path,
                scope='',
                duration=self.response_time,
                exclusive=self.exclusive)

        # Generate the rollup metric.

        if self.type != 'WebTransaction':
            rollup = '%s/all' % self.type
        else:
            rollup = self.type

        yield TimeMetric(
                name=rollup,
                scope='',
                duration=self.response_time,
                exclusive=self.exclusive)

        # Generate Unscoped Total Time metrics.

        if self.type == 'WebTransaction':
            metric_prefix = 'WebTransactionTotalTime'
            metric_suffix = 'Web'
        else:
            metric_prefix = 'OtherTransactionTotalTime'
            metric_suffix = 'Other'

        yield TimeMetric(
                name='%s/%s' % (metric_prefix, self.name_for_metric),
                scope='',
                duration=self.total_time,
                exclusive=self.total_time)

        yield TimeMetric(
                name=metric_prefix,
                scope='',
                duration=self.total_time,
                exclusive=self.total_time)

        # Generate Distributed Tracing metrics

        if self.settings.distributed_tracing.enabled:
            if self.distributed_trace_received:
                dt_tag = "%s/%s/%s/%s/all" % (
                    self.parent_type, self.parent_account,
                    self.parent_app, self.parent_transport_type)
            else:
                dt_tag = "Unknown/Unknown/Unknown/Unknown/all"

            for bonus_tag in ('', metric_suffix):
                yield TimeMetric(
                    name="DurationByCaller/%s%s" % (dt_tag, bonus_tag),
                    scope='',
                    duration=self.duration,
                    exclusive=self.duration)

                if self.distributed_trace_received:
                    yield TimeMetric(
                        name="TransportDuration/%s%s" % (dt_tag, bonus_tag),
                        scope='',
                        duration=self.parent_transport_duration,
                        exclusive=self.parent_transport_duration)

                if self.errors:
                    yield TimeMetric(
                        name='ErrorsByCaller/%s%s' % (dt_tag, bonus_tag),
                        scope='',
                        duration=0.0,
                        exclusive=None)

        # Generate Error metrics

        if self.errors:
            # Generate overall rollup metric indicating if errors present.
            yield TimeMetric(
                    name='Errors/all',
                    scope='',
                    duration=0.0,
                    exclusive=None)

            # Generate individual error metric for transaction.
            yield TimeMetric(
                    name='Errors/%s' % self.path,
                    scope='',
                    duration=0.0,
                    exclusive=None)

            # Generate rollup metric for WebTransaction errors.
            yield TimeMetric(
                    name='Errors/all%s' % metric_suffix,
                    scope='',
                    duration=0.0,
                    exclusive=None)

        # Now for the children.
        for child in self.children:
            for metric in child.time_metrics(stats, self, self):
                yield metric
Esempio n. 12
0
    def time_metrics(self, stats, root, parent):
        """Return a generator yielding the timed metrics for this
        external node as well as all the child nodes.

        """

        yield TimeMetric(name='External/all',
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        if root.type == 'WebTransaction':
            yield TimeMetric(name='External/allWeb',
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)
        else:
            yield TimeMetric(name='External/allOther',
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)

        hostname = self.details.hostname or 'unknown'

        try:
            scheme = self.details.scheme.lower()
            port = self.details.port
        except Exception:
            scheme = None
            port = None

        if (scheme, port) in (('http', 80), ('https', 443)):
            port = None

        netloc = port and ('%s:%s' % (hostname, port)) or hostname

        try:

            # Remove cross_process_id from the params dict otherwise it shows
            # up in the UI.

            self.cross_process_id = self.params.pop('cross_process_id')
            self.external_txn_name = self.params.pop('external_txn_name')
        except KeyError:
            self.cross_process_id = None
            self.external_txn_name = None

        name = 'External/%s/all' % netloc

        yield TimeMetric(name=name,
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        if self.cross_process_id is None:
            method = self.method or ''

            name = 'External/%s/%s/%s' % (netloc, self.library, method)

            yield TimeMetric(name=name,
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)

            yield TimeMetric(name=name,
                             scope=root.path,
                             duration=self.duration,
                             exclusive=self.exclusive)

        else:
            name = 'ExternalTransaction/%s/%s/%s' % (
                netloc, self.cross_process_id, self.external_txn_name)

            yield TimeMetric(name=name,
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)

            yield TimeMetric(name=name,
                             scope=root.path,
                             duration=self.duration,
                             exclusive=self.exclusive)

            name = 'ExternalApp/%s/%s/all' % (netloc, self.cross_process_id)

            yield TimeMetric(name=name,
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)
    def time_metrics(self, stats, root, parent):
        """Return a generator yielding the timed metrics for this
        database node as well as all the child nodes.

        """

        product = self.product
        target = self.target
        operation = self.operation or 'other'

        # Determine the scoped metric

        statement_metric_name = 'Datastore/statement/%s/%s/%s' % (
            product, target, operation)

        operation_metric_name = 'Datastore/operation/%s/%s' % (product,
                                                               operation)

        if target:
            scoped_metric_name = statement_metric_name
        else:
            scoped_metric_name = operation_metric_name

        yield TimeMetric(name=scoped_metric_name,
                         scope=root.path,
                         duration=self.duration,
                         exclusive=self.exclusive)

        # Unscoped rollup metrics

        yield TimeMetric(name='Datastore/all',
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        yield TimeMetric(name='Datastore/%s/all' % product,
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        if root.type == 'WebTransaction':
            yield TimeMetric(name='Datastore/allWeb',
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)

            yield TimeMetric(name='Datastore/%s/allWeb' % product,
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)
        else:
            yield TimeMetric(name='Datastore/allOther',
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)

            yield TimeMetric(name='Datastore/%s/allOther' % product,
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)

        # Unscoped operation metric

        yield TimeMetric(name=operation_metric_name,
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        # Unscoped statement metric

        if target:
            yield TimeMetric(name=statement_metric_name,
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)

        # Unscoped instance Metric

        ds_tracer_settings = stats.settings.datastore_tracer

        if (self.instance_hostname and self.port_path_or_id
                and ds_tracer_settings.instance_reporting.enabled):

            instance_metric_name = 'Datastore/instance/%s/%s/%s' % (
                product, self.instance_hostname, self.port_path_or_id)

            yield TimeMetric(name=instance_metric_name,
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)
Esempio n. 14
0
    def time_metrics(self, stats, root, parent):
        """Return a generator yielding the timed metrics for this
        database node as well as all the child nodes.

        """

        product = self.product
        target = self.target
        operation = self.operation or 'other'

        # Rollup metrics

        yield TimeMetric(name='Datastore/all',
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        yield TimeMetric(name='Datastore/%s/all' % product,
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        if root.type == 'WebTransaction':
            yield TimeMetric(name='Datastore/allWeb',
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)

            yield TimeMetric(name='Datastore/%s/allWeb' % product,
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)

        else:
            yield TimeMetric(name='Datastore/allOther',
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)

            yield TimeMetric(name='Datastore/%s/allOther' % product,
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)

        # Statement metrics.

        if target:
            name = 'Datastore/statement/%s/%s/%s' % (product, target,
                                                     operation)

            yield TimeMetric(name=name,
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)

            yield TimeMetric(name=name,
                             scope=root.path,
                             duration=self.duration,
                             exclusive=self.exclusive)

        # Operation metrics.

        name = 'Datastore/operation/%s/%s' % (product, operation)

        yield TimeMetric(name=name,
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        if not target:
            yield TimeMetric(name=name,
                             scope=root.path,
                             duration=self.duration,
                             exclusive=self.exclusive)
Esempio n. 15
0
    def time_metrics(self, stats, root, parent):
        """
        TODO root是啥?根请求?????
        :param stats:
        :param newrelic.core.transaction_node.TransactionNode root:
        :param parent:
        :return:
        """
        """Return a generator yielding the timed metrics for this
        database node as well as all the child nodes.

        """
        # TODO 时间记录器,root是啥对象??????
        product = self.product
        operation = self.operation or 'other'
        target = self.target

        # Determine the scoped metric

        statement_metric_name = 'Datastore/statement/%s/%s/%s' % (
            product, target, operation)

        operation_metric_name = 'Datastore/operation/%s/%s' % (product,
                                                               operation)

        if target:
            scoped_metric_name = statement_metric_name
        else:
            scoped_metric_name = operation_metric_name

        yield TimeMetric(name=scoped_metric_name,
                         scope=root.path,
                         duration=self.duration,
                         exclusive=self.exclusive)

        # Unscoped rollup metrics

        yield TimeMetric(name='Datastore/all',
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        yield TimeMetric(name='Datastore/%s/all' % product,
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        if root.type == 'WebTransaction':
            yield TimeMetric(name='Datastore/allWeb',
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)

            yield TimeMetric(name='Datastore/%s/allWeb' % product,
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)
        else:
            yield TimeMetric(name='Datastore/allOther',
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)

            yield TimeMetric(name='Datastore/%s/allOther' % product,
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)

        # Unscoped operation metric

        yield TimeMetric(name=operation_metric_name,
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        # Unscoped statement metric

        if target:
            yield TimeMetric(name=statement_metric_name,
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)

        # Unscoped instance Metric

        if self.instance_hostname and self.port_path_or_id:

            instance_metric_name = 'Datastore/instance/%s/%s/%s' % (
                product, self.instance_hostname, self.port_path_or_id)

            yield TimeMetric(name=instance_metric_name,
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)
    def time_metrics(self, stats, root, parent):
        """Return a generator yielding the timed metrics for this
        database node as well as all the child nodes.

        """

        operation_type = self.operation_type
        operation_name = self.operation_name
        deepest_path = self.deepest_path
        product = self.product

        # Determine the scoped metric

        operation_metric_name = 'GraphQL/operation/%s/%s/%s/%s' % (
            product, operation_type, operation_name, deepest_path)

        scoped_metric_name = operation_metric_name

        yield TimeMetric(name=scoped_metric_name,
                         scope=root.path,
                         duration=self.duration,
                         exclusive=self.exclusive)

        # Unscoped rollup metrics

        yield TimeMetric(name='GraphQL/all',
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        yield TimeMetric(name='GraphQL/%s/all' % product,
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        if root.type == 'WebTransaction':
            yield TimeMetric(name='GraphQL/allWeb',
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)

            yield TimeMetric(name='GraphQL/%s/allWeb' % product,
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)
        else:
            yield TimeMetric(name='GraphQL/allOther',
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)

            yield TimeMetric(name='GraphQL/%s/allOther' % product,
                             scope='',
                             duration=self.duration,
                             exclusive=self.exclusive)

        # Unscoped operation metric

        yield TimeMetric(name=operation_metric_name,
                         scope='',
                         duration=self.duration,
                         exclusive=self.exclusive)

        # Now for the children

        for child in self.children:
            for metric in child.time_metrics(stats, root, self):
                yield metric