Skip to content

Add filtering by attributes to metrics list view

Daniele Rossetti requested to merge drosse/metrics-list-filter into master

What does this MR do and why?

Add capability to filter metrics by dimensions/attributes e.g. only show metrics with host.name attribute

Closes https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2538+

Note: This implementation does not address scenarios with long list of suggestions/options for the Attribute filter ( which could happen on system with an elevated number of metrics and dimensions. This will be tackled after Beta as a follow up Metrics list should handle long lists of Attrib... (gitlab-org/opstrace/opstrace#2780) )

MR acceptance checklist

Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Screenshots or screen recordings

image

Screen_Recording_2024-04-15_at_13.45.18

How to set up and validate locally

  • Prerequisites: be logged in and running GDK with Ultimate license
  • Enable :observability_metrics feature flag

Apply patch to load mocks ( copy the patch content below and run in your terminal: pbpaste | git apply )

diff --git a/app/assets/javascripts/observability/client.js b/app/assets/javascripts/observability/client.js
index 16034a37a6d3..f8740454cda5 100644
--- a/app/assets/javascripts/observability/client.js
+++ b/app/assets/javascripts/observability/client.js
@@ -1,22 +1,1638 @@
+/* eslint-disable @gitlab/require-i18n-strings */
 import { isValidDate } from '~/lib/utils/datetime_utility';
 import * as Sentry from '~/sentry/sentry_browser_wrapper';
 import axios from '~/lib/utils/axios_utils';
 import { logError } from '~/lib/logger';
 import { DEFAULT_SORTING_OPTION, SORTING_OPTIONS, CUSTOM_DATE_RANGE_OPTION } from './constants';
 
+const MOCK_METRICS = {
+  metrics: [
+    {
+      name: 'app.ads.ad_requests',
+      description: 'Counts ad requests by request and response type',
+      attributes: ['app.ads.ad_request_type', 'app.ads.ad_response_type'],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'app.frontend.requests',
+      description: '',
+      attributes: ['method', 'status', 'target'],
+      type: 'Sum',
+      last_ingested_at: 1712741683599274800,
+    },
+    {
+      name: 'app.payment.transactions',
+      description: '',
+      attributes: ['app.payment.currency'],
+      type: 'Sum',
+      last_ingested_at: 1712741689160801300,
+    },
+    {
+      name: 'app_recommendations_counter',
+      description: 'Counts the total number of given recommendations',
+      attributes: ['recommendation.type'],
+      type: 'Sum',
+      last_ingested_at: 1712741687141819400,
+    },
+    {
+      name: 'aspnetcore.routing.match_attempts',
+      description: 'Number of requests that were attempted to be matched to an endpoint.',
+      attributes: [
+        'aspnetcore.routing.is_fallback',
+        'aspnetcore.routing.match_status',
+        'http.route',
+      ],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'calls',
+      description: '',
+      attributes: ['service.name', 'span.kind', 'span.name', 'status.code'],
+      type: 'Sum',
+      last_ingested_at: 1712744602707116800,
+    },
+    {
+      name: 'currencyservice_counter',
+      description: '',
+      attributes: ['currency_code'],
+      type: 'Sum',
+      last_ingested_at: 1712741688411283700,
+    },
+    {
+      name: 'duration',
+      description: '',
+      attributes: ['service.name', 'span.kind', 'span.name', 'status.code'],
+      type: 'Histogram',
+      last_ingested_at: 1712744602707116800,
+    },
+    {
+      name: 'http.client.duration',
+      description: 'measures the duration of the outbound HTTP request',
+      attributes: [
+        'http.flavor',
+        'http.host',
+        'http.method',
+        'http.scheme',
+        'http.status_code',
+        'net.peer.name',
+        'net.peer.port',
+      ],
+      type: 'Histogram',
+      last_ingested_at: 1712744602707116800,
+    },
+    {
+      name: 'http.client.request.size',
+      description: 'Measures the size of HTTP request messages.',
+      attributes: ['http.method', 'http.status_code', 'net.peer.name', 'net.peer.port'],
+      type: 'Sum',
+      last_ingested_at: 1712744602707116800,
+    },
+    {
+      name: 'http.client.response.size',
+      description: 'Measures the size of HTTP response messages.',
+      attributes: ['http.method', 'http.status_code', 'net.peer.name', 'net.peer.port'],
+      type: 'Sum',
+      last_ingested_at: 1712744602707116800,
+    },
+    {
+      name: 'http.server.active_requests',
+      description: 'Number of active HTTP server requests.',
+      attributes: ['http.request.method', 'url.scheme'],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'http.server.duration',
+      description: 'Measures the duration of inbound HTTP requests.',
+      attributes: [
+        'http.flavor',
+        'http.method',
+        'http.scheme',
+        'http.status_code',
+        'net.host.name',
+        'net.host.port',
+      ],
+      type: 'Histogram',
+      last_ingested_at: 1712741683599274800,
+    },
+    {
+      name: 'http.server.request.duration',
+      description: 'Duration of HTTP server requests.',
+      attributes: [
+        'http.request.method',
+        'http.response.status_code',
+        'http.route',
+        'network.protocol.version',
+        'url.scheme',
+      ],
+      type: 'Histogram',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'httpcheck.duration',
+      description: 'Measures the duration of the HTTP check.',
+      attributes: ['http.url'],
+      type: 'Gauge',
+      last_ingested_at: 1712739113395153400,
+    },
+    {
+      name: 'httpcheck.error',
+      description: 'Records errors occurring during HTTP check.',
+      attributes: ['error.message', 'http.url'],
+      type: 'Sum',
+      last_ingested_at: 1712739113395153400,
+    },
+    {
+      name: 'httpcheck.status',
+      description: '1 if the check resulted in status_code matching the status_class, otherwise 0.',
+      attributes: ['http.method', 'http.status_class', 'http.status_code', 'http.url'],
+      type: 'Sum',
+      last_ingested_at: 1712739113395153400,
+    },
+    {
+      name: 'jvm.class.count',
+      description: 'Number of classes currently loaded.',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'jvm.class.loaded',
+      description: 'Number of classes loaded since JVM start.',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'jvm.class.unloaded',
+      description: 'Number of classes unloaded since JVM start.',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'jvm.cpu.count',
+      description: 'Number of processors available to the Java virtual machine.',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'jvm.cpu.recent_utilization',
+      description: 'Recent CPU utilization for the process as reported by the JVM.',
+      attributes: [],
+      type: 'Gauge',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'jvm.cpu.time',
+      description: 'CPU time used by the process as reported by the JVM.',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'jvm.gc.duration',
+      description: 'Duration of JVM garbage collection actions.',
+      attributes: ['jvm.gc.action', 'jvm.gc.name'],
+      type: 'Histogram',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'jvm.memory.committed',
+      description: 'Measure of memory committed.',
+      attributes: ['jvm.memory.pool.name', 'jvm.memory.type'],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'jvm.memory.limit',
+      description: 'Measure of max obtainable memory.',
+      attributes: ['jvm.memory.pool.name', 'jvm.memory.type'],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'jvm.memory.used',
+      description: 'Measure of memory used.',
+      attributes: ['jvm.memory.pool.name', 'jvm.memory.type'],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'jvm.memory.used_after_last_gc',
+      description:
+        'Measure of memory used, as measured after the most recent garbage collection event on this pool.',
+      attributes: ['jvm.memory.pool.name', 'jvm.memory.type'],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'jvm.thread.count',
+      description: 'Number of executing platform threads.',
+      attributes: ['jvm.thread.daemon', 'jvm.thread.state'],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'kafka.consumer.assigned_partitions',
+      description: 'The number of partitions currently assigned to this consumer',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.bytes_consumed_rate',
+      description: 'The average number of bytes consumed per second',
+      attributes: ['client-id', 'topic'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.bytes_consumed_total',
+      description: 'The total number of bytes consumed',
+      attributes: ['client-id', 'topic'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.commit_latency_avg',
+      description: 'The average time taken for a commit request',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.commit_latency_max',
+      description: 'The max time taken for a commit request',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.commit_rate',
+      description: 'The number of commit calls per second',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.commit_sync_time_ns_total',
+      description: 'The total time the consumer has spent in commitSync in nanoseconds',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.commit_total',
+      description: 'The total number of commit calls',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.committed_time_ns_total',
+      description: 'The total time the consumer has spent in committed in nanoseconds',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.connection_close_rate',
+      description: 'The number of connections closed per second',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.connection_close_total',
+      description: 'The total number of connections closed',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.connection_count',
+      description: 'The current number of active connections.',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.connection_creation_rate',
+      description: 'The number of new connections established per second',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.connection_creation_total',
+      description: 'The total number of new connections established',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.failed_authentication_rate',
+      description: 'The number of connections with failed authentication per second',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.failed_authentication_total',
+      description: 'The total number of connections with failed authentication',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.failed_reauthentication_rate',
+      description: 'The number of failed re-authentication of connections per second',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.failed_reauthentication_total',
+      description: 'The total number of failed re-authentication of connections',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.failed_rebalance_rate_per_hour',
+      description: 'The number of failed rebalance events per hour',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.failed_rebalance_total',
+      description: 'The total number of failed rebalance events',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.fetch_latency_avg',
+      description: 'The average time taken for a fetch request.',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.fetch_latency_max',
+      description: 'The max time taken for any fetch request.',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.fetch_rate',
+      description: 'The number of fetch requests per second.',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.fetch_size_avg',
+      description: 'The average number of bytes fetched per request',
+      attributes: ['client-id', 'topic'],
+      type: 'Gauge',
+      last_ingested_at: 1712730852272117200,
+    },
+    {
+      name: 'kafka.consumer.fetch_size_max',
+      description: 'The maximum number of bytes fetched per request',
+      attributes: ['client-id', 'topic'],
+      type: 'Gauge',
+      last_ingested_at: 1712730852272117200,
+    },
+    {
+      name: 'kafka.consumer.fetch_throttle_time_avg',
+      description: 'The average throttle time in ms',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.fetch_throttle_time_max',
+      description: 'The maximum throttle time in ms',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.fetch_total',
+      description: 'The total number of fetch requests.',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.heartbeat_rate',
+      description: 'The number of heartbeats per second',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.heartbeat_response_time_max',
+      description: 'The max time taken to receive a response to a heartbeat request',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.heartbeat_total',
+      description: 'The total number of heartbeats',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.incoming_byte_rate',
+      description: 'The number of bytes read off all sockets per second',
+      attributes: ['client-id', 'node-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.incoming_byte_total',
+      description: 'The total number of bytes read off all sockets',
+      attributes: ['client-id', 'node-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.io_ratio',
+      description: '*Deprecated* The fraction of time the I/O thread spent doing I/O',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.io_time_ns_avg',
+      description: 'The average length of time for I/O per select call in nanoseconds.',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.io_time_ns_total',
+      description: 'The total time the I/O thread spent doing I/O',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.io_wait_ratio',
+      description: '*Deprecated* The fraction of time the I/O thread spent waiting',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.io_wait_time_ns_avg',
+      description:
+        'The average length of time the I/O thread spent waiting for a socket ready for reads or writes in nanoseconds.',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.io_wait_time_ns_total',
+      description: 'The total time the I/O thread spent waiting',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.io_waittime_total',
+      description: '*Deprecated* The total time the I/O thread spent waiting',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.iotime_total',
+      description: '*Deprecated* The total time the I/O thread spent doing I/O',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.join_rate',
+      description: 'The number of group joins per second',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.join_time_avg',
+      description: 'The average time taken for a group rejoin',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712153758063543800,
+    },
+    {
+      name: 'kafka.consumer.join_time_max',
+      description: 'The max time taken for a group rejoin',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712153758063543800,
+    },
+    {
+      name: 'kafka.consumer.join_total',
+      description: 'The total number of group joins',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.last_heartbeat_seconds_ago',
+      description: 'The number of seconds since the last coordinator heartbeat was sent',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.last_poll_seconds_ago',
+      description: 'The number of seconds since the last poll() invocation.',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.last_rebalance_seconds_ago',
+      description: 'The number of seconds since the last successful rebalance event',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.network_io_rate',
+      description:
+        'The number of network operations (reads or writes) on all connections per second',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.network_io_total',
+      description: 'The total number of network operations (reads or writes) on all connections',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.outgoing_byte_rate',
+      description: 'The number of outgoing bytes sent to all servers per second',
+      attributes: ['client-id', 'node-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.outgoing_byte_total',
+      description: 'The total number of outgoing bytes sent to all servers',
+      attributes: ['client-id', 'node-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.partition_assigned_latency_avg',
+      description: 'The average time taken for a partition-assigned rebalance listener callback',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712153758063543800,
+    },
+    {
+      name: 'kafka.consumer.partition_assigned_latency_max',
+      description: 'The max time taken for a partition-assigned rebalance listener callback',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712153758063543800,
+    },
+    {
+      name: 'kafka.consumer.poll_idle_ratio_avg',
+      description:
+        "The average fraction of time the consumer's poll() is idle as opposed to waiting for the user code to process records.",
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.rebalance_latency_avg',
+      description:
+        'The average time taken for a group to complete a successful rebalance, which may be composed of several failed re-trials until it succeeded',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712153758063543800,
+    },
+    {
+      name: 'kafka.consumer.rebalance_latency_max',
+      description:
+        'The max time taken for a group to complete a successful rebalance, which may be composed of several failed re-trials until it succeeded',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712153758063543800,
+    },
+    {
+      name: 'kafka.consumer.rebalance_latency_total',
+      description:
+        'The total number of milliseconds this consumer has spent in successful rebalances since creation',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.rebalance_rate_per_hour',
+      description:
+        'The number of successful rebalance events per hour, each event is composed of several failed re-trials until it succeeded',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.rebalance_total',
+      description:
+        'The total number of successful rebalance events, each event is composed of several failed re-trials until it succeeded',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.records_consumed_rate',
+      description: 'The average number of records consumed per second',
+      attributes: ['client-id', 'topic'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.records_consumed_total',
+      description: 'The total number of records consumed',
+      attributes: ['client-id', 'topic'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.records_lag',
+      description: 'The latest lag of the partition',
+      attributes: ['client-id', 'partition', 'topic'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.records_lag_avg',
+      description: 'The average lag of the partition',
+      attributes: ['client-id', 'partition', 'topic'],
+      type: 'Gauge',
+      last_ingested_at: 1712730852272117200,
+    },
+    {
+      name: 'kafka.consumer.records_lag_max',
+      description:
+        'The maximum lag in terms of number of records for any partition in this window. NOTE: This is based on current offset and not committed offset',
+      attributes: ['client-id', 'partition', 'topic'],
+      type: 'Gauge',
+      last_ingested_at: 1712730852272117200,
+    },
+    {
+      name: 'kafka.consumer.records_lead',
+      description: 'The latest lead of the partition',
+      attributes: ['client-id', 'partition', 'topic'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.records_lead_avg',
+      description: 'The average lead of the partition',
+      attributes: ['client-id', 'partition', 'topic'],
+      type: 'Gauge',
+      last_ingested_at: 1712730852272117200,
+    },
+    {
+      name: 'kafka.consumer.records_lead_min',
+      description:
+        'The minimum lead in terms of number of records for any partition in this window',
+      attributes: ['client-id', 'partition', 'topic'],
+      type: 'Gauge',
+      last_ingested_at: 1712730852272117200,
+    },
+    {
+      name: 'kafka.consumer.records_per_request_avg',
+      description: 'The average number of records in each request',
+      attributes: ['client-id', 'topic'],
+      type: 'Gauge',
+      last_ingested_at: 1712730852272117200,
+    },
+    {
+      name: 'kafka.consumer.request_rate',
+      description: 'The number of requests sent per second',
+      attributes: ['client-id', 'node-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.request_size_avg',
+      description: 'The average size of requests sent.',
+      attributes: ['client-id', 'node-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.request_size_max',
+      description: 'The maximum size of any request sent.',
+      attributes: ['client-id', 'node-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.request_total',
+      description: 'The total number of requests sent',
+      attributes: ['client-id', 'node-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.response_rate',
+      description: 'The number of responses received per second',
+      attributes: ['client-id', 'node-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.response_total',
+      description: 'The total number of responses received',
+      attributes: ['client-id', 'node-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.select_rate',
+      description: 'The number of times the I/O layer checked for new I/O to perform per second',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.select_total',
+      description: 'The total number of times the I/O layer checked for new I/O to perform',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.successful_authentication_no_reauth_total',
+      description:
+        'The total number of connections with successful authentication where the client does not support re-authentication',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.successful_authentication_rate',
+      description: 'The number of connections with successful authentication per second',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.successful_authentication_total',
+      description: 'The total number of connections with successful authentication',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.successful_reauthentication_rate',
+      description: 'The number of successful re-authentication of connections per second',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.successful_reauthentication_total',
+      description: 'The total number of successful re-authentication of connections',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.sync_rate',
+      description: 'The number of group syncs per second',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.sync_time_avg',
+      description: 'The average time taken for a group sync',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712153758063543800,
+    },
+    {
+      name: 'kafka.consumer.sync_time_max',
+      description: 'The max time taken for a group sync',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712153758063543800,
+    },
+    {
+      name: 'kafka.consumer.sync_total',
+      description: 'The total number of group syncs',
+      attributes: ['client-id'],
+      type: 'Sum',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.time_between_poll_avg',
+      description: 'The average delay between invocations of poll() in milliseconds.',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.consumer.time_between_poll_max',
+      description: 'The max delay between invocations of poll() in milliseconds.',
+      attributes: ['client-id'],
+      type: 'Gauge',
+      last_ingested_at: 1712740064038286300,
+    },
+    {
+      name: 'kafka.controller.active.count',
+      description: 'The number of controllers active on the broker',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712739111837611000,
+    },
+    {
+      name: 'kafka.isr.operation.count',
+      description: 'The number of in-sync replica shrink and expand operations',
+      attributes: ['operation'],
+      type: 'Sum',
+      last_ingested_at: 1712739111837611000,
+    },
+    {
+      name: 'kafka.lag.max',
+      description: 'The max lag in messages between follower and leader replicas',
+      attributes: [],
+      type: 'Gauge',
+      last_ingested_at: 1712739111837611000,
+    },
+    {
+      name: 'kafka.logs.flush.Count',
+      description: 'Log flush count',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712739111837611000,
+    },
+    {
+      name: 'kafka.logs.flush.time.50p',
+      description: 'Log flush time - 50th percentile',
+      attributes: [],
+      type: 'Gauge',
+      last_ingested_at: 1712739111837611000,
+    },
+    {
+      name: 'kafka.logs.flush.time.99p',
+      description: 'Log flush time - 99th percentile',
+      attributes: [],
+      type: 'Gauge',
+      last_ingested_at: 1712739111837611000,
+    },
+    {
+      name: 'kafka.message.count',
+      description: 'The number of messages received by the broker',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712739111837611000,
+    },
+    {
+      name: 'kafka.network.io',
+      description: 'The bytes received or sent by the broker',
+      attributes: ['direction'],
+      type: 'Sum',
+      last_ingested_at: 1712739111837611000,
+    },
+    {
+      name: 'kafka.partition.count',
+      description: 'The number of partitions on the broker',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712739111837611000,
+    },
+    {
+      name: 'kafka.partition.offline',
+      description: 'The number of partitions offline',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712739111837611000,
+    },
+    {
+      name: 'kafka.partition.underReplicated',
+      description: 'The number of under replicated partitions',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712739111837611000,
+    },
+    {
+      name: 'kafka.purgatory.size',
+      description: 'The number of requests waiting in purgatory',
+      attributes: ['type'],
+      type: 'Sum',
+      last_ingested_at: 1712739111837611000,
+    },
+    {
+      name: 'kafka.request.count',
+      description: 'The number of requests received by the broker',
+      attributes: ['type'],
+      type: 'Sum',
+      last_ingested_at: 1712739111837611000,
+    },
+    {
+      name: 'kafka.request.failed',
+      description: 'The number of requests to the broker resulting in a failure',
+      attributes: ['type'],
+      type: 'Sum',
+      last_ingested_at: 1712739111837611000,
+    },
+    {
+      name: 'kafka.request.queue',
+      description: 'Size of the request queue',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712739111837611000,
+    },
+    {
+      name: 'kafka.request.time.50p',
+      description: 'The 50th percentile time the broker has taken to service requests',
+      attributes: ['type'],
+      type: 'Gauge',
+      last_ingested_at: 1712739111837611000,
+    },
+    {
+      name: 'kafka.request.time.99p',
+      description: 'The 99th percentile time the broker has taken to service requests',
+      attributes: ['type'],
+      type: 'Gauge',
+      last_ingested_at: 1712739111837611000,
+    },
+    {
+      name: 'kafka.request.time.total',
+      description: 'The total time the broker has taken to service requests',
+      attributes: ['type'],
+      type: 'Sum',
+      last_ingested_at: 1712739111837611000,
+    },
+    {
+      name: 'kestrel.active_connections',
+      description: 'Number of connections that are currently active on the server.',
+      attributes: ['network.transport', 'network.type', 'server.address', 'server.port'],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'kestrel.connection.duration',
+      description: 'The duration of connections on the server.',
+      attributes: [
+        'network.protocol.name',
+        'network.protocol.version',
+        'network.transport',
+        'network.type',
+        'server.address',
+        'server.port',
+      ],
+      type: 'Histogram',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'kestrel.queued_connections',
+      description: 'Number of connections that are currently queued and are waiting to start.',
+      attributes: ['network.transport', 'network.type', 'server.address', 'server.port'],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'kestrel.queued_requests',
+      description:
+        'Number of HTTP requests on multiplexed connections (HTTP/2 and HTTP/3) that are currently queued and are waiting to start.',
+      attributes: [
+        'network.protocol.name',
+        'network.protocol.version',
+        'network.transport',
+        'network.type',
+        'server.address',
+        'server.port',
+      ],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'otel.logs.log_processor.logs',
+      description: 'The number of log records received by the processor',
+      attributes: ['processor', 'state'],
+      type: 'Sum',
+      last_ingested_at: 1712741685917173500,
+    },
+    {
+      name: 'otel.logs.log_processor.queue.limit',
+      description: 'The queue size limit',
+      attributes: ['processor'],
+      type: 'Sum',
+      last_ingested_at: 1712741685917173500,
+    },
+    {
+      name: 'otel.logs.log_processor.queue.usage',
+      description: 'The current queue usage',
+      attributes: ['processor', 'state'],
+      type: 'Sum',
+      last_ingested_at: 1712741685917173500,
+    },
+    {
+      name: 'otel.trace.span_processor.queue.limit',
+      description: 'The queue size limit',
+      attributes: ['processor'],
+      type: 'Sum',
+      last_ingested_at: 1712741685917173500,
+    },
+    {
+      name: 'otel.trace.span_processor.queue.usage',
+      description: 'The current queue usage',
+      attributes: ['processor', 'state'],
+      type: 'Sum',
+      last_ingested_at: 1712741685917173500,
+    },
+    {
+      name: 'otel.trace.span_processor.spans',
+      description: 'The number of sampled spans received by the span processor',
+      attributes: ['processor', 'state'],
+      type: 'Sum',
+      last_ingested_at: 1712741685917173500,
+    },
+    {
+      name: 'otlp.exporter.exported',
+      description: '',
+      attributes: ['success', 'type'],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'otlp.exporter.seen',
+      description: '',
+      attributes: ['type'],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'process.cpu.count',
+      description: 'The number of processors (CPU cores) available to the current process.',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'process.cpu.time',
+      description: 'Total CPU seconds broken down by different states.',
+      attributes: ['state'],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'process.memory.usage',
+      description: 'The amount of physical memory allocated for this process.',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'process.memory.virtual',
+      description: 'The amount of committed virtual memory for this process.',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'process.runtime.cpython.context_switches',
+      description: 'Runtime context switches',
+      attributes: ['type'],
+      type: 'Sum',
+      last_ingested_at: 1712741687141819400,
+    },
+    {
+      name: 'process.runtime.cpython.cpu.utilization',
+      description: 'Runtime CPU utilization',
+      attributes: [],
+      type: 'Gauge',
+      last_ingested_at: 1712741687141819400,
+    },
+    {
+      name: 'process.runtime.cpython.cpu_time',
+      description: 'Runtime cpython CPU time',
+      attributes: ['type'],
+      type: 'Sum',
+      last_ingested_at: 1712741687141819400,
+    },
+    {
+      name: 'process.runtime.cpython.gc_count',
+      description: 'Runtime cpython GC count',
+      attributes: ['count'],
+      type: 'Sum',
+      last_ingested_at: 1712741687141819400,
+    },
+    {
+      name: 'process.runtime.cpython.memory',
+      description: 'Runtime cpython memory',
+      attributes: ['type'],
+      type: 'Sum',
+      last_ingested_at: 1712741687141819400,
+    },
+    {
+      name: 'process.runtime.cpython.thread_count',
+      description: 'Runtime active threads count',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712741687141819400,
+    },
+    {
+      name: 'process.runtime.dotnet.assemblies.count',
+      description: 'The number of .NET assemblies that are currently loaded.',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'process.runtime.dotnet.exceptions.count',
+      description:
+        'Count of exceptions that have been thrown in managed code, since the observation started. The value will be unavailable until an exception has been thrown after OpenTelemetry.Instrumentation.Runtime initialization.',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'process.runtime.dotnet.gc.allocations.size',
+      description:
+        'Count of bytes allocated on the managed GC heap since the process start. .NET objects are allocated from this heap. Object allocations from unmanaged languages such as C/C++ do not use this heap.',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'process.runtime.dotnet.gc.collections.count',
+      description: 'Number of garbage collections that have occurred since process start.',
+      attributes: ['generation'],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'process.runtime.dotnet.gc.committed_memory.size',
+      description:
+        'The amount of committed virtual memory for the managed GC heap, as observed during the latest garbage collection. Committed virtual memory may be larger than the heap size because it includes both memory for storing existing objects (the heap size) and some extra memory that is ready to handle newly allocated objects in the future. The value will be unavailable until at least one garbage collection has occurred.',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'process.runtime.dotnet.gc.duration',
+      description: 'The total amount of time paused in GC since the process start.',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'process.runtime.dotnet.gc.heap.fragmentation.size',
+      description:
+        'The heap fragmentation, as observed during the latest garbage collection. The value will be unavailable until at least one garbage collection has occurred.',
+      attributes: ['generation'],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'process.runtime.dotnet.gc.heap.size',
+      description:
+        'The heap size (including fragmentation), as observed during the latest garbage collection. The value will be unavailable until at least one garbage collection has occurred.',
+      attributes: ['generation'],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'process.runtime.dotnet.gc.objects.size',
+      description:
+        "Count of bytes currently in use by objects in the GC heap that haven't been collected yet. Fragmentation and other GC committed memory pools are excluded.",
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'process.runtime.dotnet.jit.compilation_time',
+      description:
+        'The amount of time the JIT compiler has spent compiling methods since the process start.',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'process.runtime.dotnet.jit.il_compiled.size',
+      description:
+        'Count of bytes of intermediate language that have been compiled since the process start.',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'process.runtime.dotnet.jit.methods_compiled.count',
+      description:
+        'The number of times the JIT compiler compiled a method since the process start. The JIT compiler may be invoked multiple times for the same method to compile with different generic parameters, or because tiered compilation requested different optimization settings.',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'process.runtime.dotnet.monitor.lock_contention.count',
+      description:
+        'The number of times there was contention when trying to acquire a monitor lock since the process start. Monitor locks are commonly acquired by using the lock keyword in C#, or by calling Monitor.Enter() and Monitor.TryEnter().',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'process.runtime.dotnet.thread_pool.completed_items.count',
+      description:
+        'The number of work items that have been processed by the thread pool since the process start.',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'process.runtime.dotnet.thread_pool.queue.length',
+      description:
+        'The number of work items that are currently queued to be processed by the thread pool.',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'process.runtime.dotnet.thread_pool.threads.count',
+      description: 'The number of thread pool threads that currently exist.',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'process.runtime.dotnet.timer.count',
+      description:
+        'The number of timer instances that are currently active. Timers can be created by many sources such as System.Threading.Timer, Task.Delay, or the timeout in a CancellationSource. An active timer is registered to tick at some point in the future and has not yet been canceled.',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'process.runtime.go.cgo.calls',
+      description: 'Number of cgo calls made by the current process',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746568665263900,
+    },
+    {
+      name: 'process.runtime.go.gc.count',
+      description: 'Number of completed garbage collection cycles',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746568665263900,
+    },
+    {
+      name: 'process.runtime.go.gc.pause_ns',
+      description: 'Amount of nanoseconds in GC stop-the-world pauses',
+      attributes: [],
+      type: 'Histogram',
+      last_ingested_at: 1712746568665263900,
+    },
+    {
+      name: 'process.runtime.go.gc.pause_total_ns',
+      description: 'Cumulative nanoseconds in GC stop-the-world pauses since the program started',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746568665263900,
+    },
+    {
+      name: 'process.runtime.go.goroutines',
+      description: 'Number of goroutines that currently exist',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746568665263900,
+    },
+    {
+      name: 'process.runtime.go.mem.heap_alloc',
+      description: 'Bytes of allocated heap objects',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746568665263900,
+    },
+    {
+      name: 'process.runtime.go.mem.heap_idle',
+      description: 'Bytes in idle (unused) spans',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746568665263900,
+    },
+    {
+      name: 'process.runtime.go.mem.heap_inuse',
+      description: 'Bytes in in-use spans',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746568665263900,
+    },
+    {
+      name: 'process.runtime.go.mem.heap_objects',
+      description: 'Number of allocated heap objects',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746568665263900,
+    },
+    {
+      name: 'process.runtime.go.mem.heap_released',
+      description: 'Bytes of idle spans whose physical memory has been returned to the OS',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746568665263900,
+    },
+    {
+      name: 'process.runtime.go.mem.heap_sys',
+      description: 'Bytes of heap memory obtained from the OS',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746568665263900,
+    },
+    {
+      name: 'process.runtime.go.mem.live_objects',
+      description: 'Number of live objects is the number of cumulative Mallocs - Frees',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746568665263900,
+    },
+    {
+      name: 'process.runtime.go.mem.lookups',
+      description: 'Number of pointer lookups performed by the runtime',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746568665263900,
+    },
+    {
+      name: 'process.threads',
+      description: 'Process threads count.',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'processedLogs',
+      description:
+        'The number of logs processed by the BatchLogRecordProcessor. [dropped=true if they were dropped due to high throughput]',
+      attributes: ['dropped', 'processorType'],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'processedSpans',
+      description:
+        'The number of spans processed by the BatchSpanProcessor. [dropped=true if they were dropped due to high throughput]',
+      attributes: ['dropped', 'processorType'],
+      type: 'Sum',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'queueSize',
+      description: 'The number of items queued',
+      attributes: ['processorType'],
+      type: 'Gauge',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'rpc.client.duration',
+      description: 'Measures the duration of inbound RPC.',
+      attributes: [
+        'network.type',
+        'rpc.grpc.status_code',
+        'rpc.method',
+        'rpc.service',
+        'rpc.system',
+        'server.address',
+        'server.port',
+      ],
+      type: 'Histogram',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'rpc.client.request.size',
+      description: 'Measures size of RPC request messages (uncompressed).',
+      attributes: ['rpc.method', 'rpc.service', 'rpc.system'],
+      type: 'Histogram',
+      last_ingested_at: 1712744602707116800,
+    },
+    {
+      name: 'rpc.client.requests_per_rpc',
+      description:
+        'Measures the number of messages received per RPC. Should be 1 for all non-streaming RPCs.',
+      attributes: ['rpc.grpc.status_code', 'rpc.method', 'rpc.service', 'rpc.system'],
+      type: 'Histogram',
+      last_ingested_at: 1712744602707116800,
+    },
+    {
+      name: 'rpc.client.response.size',
+      description: 'Measures size of RPC response messages (uncompressed).',
+      attributes: ['rpc.method', 'rpc.service', 'rpc.system'],
+      type: 'Histogram',
+      last_ingested_at: 1712744602707116800,
+    },
+    {
+      name: 'rpc.client.responses_per_rpc',
+      description:
+        'Measures the number of messages received per RPC. Should be 1 for all non-streaming RPCs.',
+      attributes: ['rpc.grpc.status_code', 'rpc.method', 'rpc.service', 'rpc.system'],
+      type: 'Histogram',
+      last_ingested_at: 1712744602707116800,
+    },
+    {
+      name: 'rpc.server.duration',
+      description: 'Measures the duration of inbound RPC.',
+      attributes: [
+        'network.type',
+        'rpc.grpc.status_code',
+        'rpc.method',
+        'rpc.service',
+        'rpc.system',
+        'server.address',
+        'server.port',
+      ],
+      type: 'Histogram',
+      last_ingested_at: 1712746569854326300,
+    },
+    {
+      name: 'rpc.server.request.size',
+      description: 'Measures size of RPC request messages (uncompressed).',
+      attributes: ['rpc.method', 'rpc.service', 'rpc.system'],
+      type: 'Histogram',
+      last_ingested_at: 1712746568665263900,
+    },
+    {
+      name: 'rpc.server.requests_per_rpc',
+      description:
+        'Measures the number of messages received per RPC. Should be 1 for all non-streaming RPCs.',
+      attributes: ['rpc.grpc.status_code', 'rpc.method', 'rpc.service', 'rpc.system'],
+      type: 'Histogram',
+      last_ingested_at: 1712746568665263900,
+    },
+    {
+      name: 'rpc.server.response.size',
+      description: 'Measures size of RPC response messages (uncompressed).',
+      attributes: ['rpc.method', 'rpc.service', 'rpc.system'],
+      type: 'Histogram',
+      last_ingested_at: 1712746568665263900,
+    },
+    {
+      name: 'rpc.server.responses_per_rpc',
+      description:
+        'Measures the number of messages received per RPC. Should be 1 for all non-streaming RPCs.',
+      attributes: ['rpc.grpc.status_code', 'rpc.method', 'rpc.service', 'rpc.system'],
+      type: 'Histogram',
+      last_ingested_at: 1712746568665263900,
+    },
+    {
+      name: 'runtime.uptime',
+      description: 'Milliseconds since application was initialized',
+      attributes: [],
+      type: 'Sum',
+      last_ingested_at: 1712746568665263900,
+    },
+    {
+      name: 'system.cpu.time',
+      description: 'System CPU time',
+      attributes: ['cpu', 'state'],
+      type: 'Sum',
+      last_ingested_at: 1712741687141819400,
+    },
+    {
+      name: 'system.cpu.utilization',
+      description: 'System CPU utilization',
+      attributes: ['cpu', 'state'],
+      type: 'Gauge',
+      last_ingested_at: 1712741687141819400,
+    },
+    {
+      name: 'system.disk.io',
+      description: 'System disk IO',
+      attributes: ['device', 'direction'],
+      type: 'Sum',
+      last_ingested_at: 1712741687141819400,
+    },
+    {
+      name: 'system.disk.operations',
+      description: 'System disk operations',
+      attributes: ['device', 'direction'],
+      type: 'Sum',
+      last_ingested_at: 1712741687141819400,
+    },
+    {
+      name: 'system.disk.time',
+      description: 'System disk time',
+      attributes: ['device', 'direction'],
+      type: 'Sum',
+      last_ingested_at: 1712741687141819400,
+    },
+    {
+      name: 'system.memory.usage',
+      description: 'System memory usage',
+      attributes: ['state'],
+      type: 'Gauge',
+      last_ingested_at: 1712741687141819400,
+    },
+    {
+      name: 'system.memory.utilization',
+      description: 'System memory utilization',
+      attributes: ['state'],
+      type: 'Gauge',
+      last_ingested_at: 1712741687141819400,
+    },
+    {
+      name: 'system.network.connections',
+      description: 'System network connections',
+      attributes: ['family', 'protocol', 'state', 'type'],
+      type: 'Sum',
+      last_ingested_at: 1712741687141819400,
+    },
+    {
+      name: 'system.network.dropped_packets',
+      description: 'System network dropped_packets',
+      attributes: ['device', 'direction'],
+      type: 'Sum',
+      last_ingested_at: 1712741687141819400,
+    },
+    {
+      name: 'system.network.errors',
+      description: 'System network errors',
+      attributes: ['device', 'direction'],
+      type: 'Sum',
+      last_ingested_at: 1712741687141819400,
+    },
+    {
+      name: 'system.network.io',
+      description: 'System network io',
+      attributes: ['device', 'direction'],
+      type: 'Sum',
+      last_ingested_at: 1712741687141819400,
+    },
+    {
+      name: 'system.network.packets',
+      description: 'System network packets',
+      attributes: ['device', 'direction'],
+      type: 'Sum',
+      last_ingested_at: 1712741687141819400,
+    },
+    {
+      name: 'system.swap.usage',
+      description: 'System swap usage',
+      attributes: ['state'],
+      type: 'Gauge',
+      last_ingested_at: 1712741687141819400,
+    },
+    {
+      name: 'system.swap.utilization',
+      description: 'System swap utilization',
+      attributes: ['state'],
+      type: 'Gauge',
+      last_ingested_at: 1712741687141819400,
+    },
+    {
+      name: 'system.thread_count',
+      description: 'System active threads count',
+      attributes: [],
+      type: 'Gauge',
+      last_ingested_at: 1712741687141819400,
+    },
+  ],
+};
+
 function reportErrorAndThrow(e) {
   logError(e);
   Sentry.captureException(e);
   throw e;
 }
+
+function mockReturnDataWithDelay(data) {
+  return new Promise((resolve) => {
+    setTimeout(() => resolve(data), 1000);
+  });
+}
+
 // Provisioning API spec: https://gitlab.com/gitlab-org/opstrace/opstrace/-/blob/main/provisioning-api/pkg/provisioningapi/routes.go#L59
 async function enableObservability(provisioningUrl) {
   try {
-    // Note: axios.put(url, undefined, {withCredentials: true}) does not send cookies properly, so need to use the API below for the correct behaviour
-    return await axios(provisioningUrl, {
-      method: 'put',
-      withCredentials: true,
-    });
+    console.log('[DEBUG] Enabling Observability');
+    return mockReturnDataWithDelay();
   } catch (e) {
     return reportErrorAndThrow(e);
   }
@@ -25,11 +1641,12 @@ async function enableObservability(provisioningUrl) {
 // Provisioning API spec: https://gitlab.com/gitlab-org/opstrace/opstrace/-/blob/main/provisioning-api/pkg/provisioningapi/routes.go#L37
 async function isObservabilityEnabled(provisioningUrl) {
   try {
-    const { data } = await axios.get(provisioningUrl, { withCredentials: true });
+    console.log('[DEBUG] Checking Observability Enabled');
+    const data = { status: 'ready' };
     if (data && data.status) {
       // we currently ignore the 'status' payload and just check if the request was successful
       // We might improve this as part of https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2315
-      return true;
+      return mockReturnDataWithDelay(true);
     }
   } catch (e) {
     if (e.response.status === 404) {
@@ -340,14 +1957,12 @@ async function fetchMetrics(metricsUrl, { filters = {}, limit } = {}) {
       handleMetricsAttributeFilters(filters.attribute, params);
     }
 
-    const { data } = await axios.get(metricsUrl, {
-      withCredentials: true,
-      params,
-    });
+    console.log(`[DEBUG] Fetching metrics with params: ${params.toString()}`);
+    const data = MOCK_METRICS;
     if (!Array.isArray(data.metrics)) {
       throw new Error('metrics are missing/invalid in the response'); // eslint-disable-line @gitlab/require-i18n-strings
     }
-    return data;
+    return mockReturnDataWithDelay(data);
   } catch (e) {
     return reportErrorAndThrow(e);
   }
@@ -432,16 +2047,182 @@ async function fetchMetric(searchUrl, name, type, options = {}) {
       addGroupByFilterToQueryParams(groupBy, params);
     }
 
-    const { data } = await axios.get(searchUrl, {
-      params,
-      signal: options.abortController?.signal,
-      withCredentials: true,
-    });
+    console.log(`[DEBUG] Fetching metric with params: ${params.toString()}`);
+
+    const data = {
+      start_ts: 1705243529862125800,
+      end_ts: 1705329929862125800,
+      results: [
+        {
+          name: 'app.ads.ad_requests',
+          description: 'Counts ad requests by request and response type',
+          unit: '',
+          type: 'Sum',
+          attributes: {
+            'app.ads.ad_request_type': 'NOT_TARGETED',
+            'app.ads.ad_response_type': 'RANDOM',
+          },
+          values: [
+            [1705247947518101200, 2252],
+            [1705253554585113900, 2252],
+            [1705258930136038700, 2252],
+            [1705266254790955000, 2252],
+            [1705274618400971300, 2252],
+            [1705274618400971300, 2252],
+            [1705281863109378800, 2252],
+            [1705288569114644700, 2252],
+            [1705288790896014800, 2252],
+            [1705289034855967500, 2252],
+            [1705289034855967500, 2252],
+            [1705289512918064400, 2252],
+            [1705290250183041800, 2252],
+            [1705290310185114400, 2252],
+            [1705290736882757600, 2252],
+            [1705290796883791400, 2252],
+            [1705290856883483600, 2252],
+            [1705290987064807700, 2252],
+            [1705291047065788400, 2252],
+            [1705291107064986400, 2252],
+            [1705291167065962000, 2252],
+            [1705291227066536200, 2252],
+          ],
+        },
+        {
+          name: 'app.ads.ad_requests',
+          description: 'Counts ad requests by request and response type',
+          unit: '',
+          type: 'Sum',
+          attributes: {
+            'app.ads.ad_request_type': 'TARGETED',
+            'app.ads.ad_response_type': 'RANDOM',
+          },
+          values: [
+            [1705247947518101200, 2278],
+            [1705253554585113900, 2278],
+            [1705258930136038700, 2278],
+            [1705266254790955000, 2278],
+            [1705274618400971300, 2278],
+            [1705274618400971300, 2278],
+            [1705281863109378800, 2278],
+            [1705288569114644700, 2278],
+            [1705288790896014800, 2278],
+            [1705289034855967500, 2278],
+            [1705289034855967500, 2278],
+            [1705289512918064400, 2278],
+            [1705290250183041800, 2278],
+            [1705290310185114400, 2278],
+            [1705290736882757600, 2278],
+            [1705290796883791400, 2278],
+            [1705290856883483600, 2278],
+            [1705290987064807700, 2278],
+            [1705291047065788400, 2278],
+            [1705291107064986400, 2278],
+            [1705291167065962000, 2278],
+            [1705291227066536200, 2278],
+            [1705291633437533400, 2278],
+            [1705291693438488300, 2278],
+            [1705291753436971000, 2278],
+            [1705291813440958500, 2278],
+          ],
+        },
+        {
+          name: 'app.ads.ad_requests',
+          description: 'Counts ad requests by request and response type',
+          unit: '',
+          type: 'Sum',
+          attributes: {
+            'app.ads.ad_request_type': 'TARGETED',
+            'app.ads.ad_response_type': 'TARGETED',
+          },
+          values: [
+            [1705247947518101200, 11436],
+            [1705253554585113900, 11436],
+            [1705258930136038700, 11436],
+            [1705266254790955000, 11436],
+            [1705274618400971300, 11436],
+            [1705274618400971300, 11436],
+            [1705281863109378800, 11436],
+            [1705288569114644700, 11436],
+            [1705288790896014800, 11436],
+            [1705289034855967500, 11436],
+            [1705289034855967500, 11436],
+            [1705289512918064400, 11436],
+            [1705290250183041800, 11436],
+            [1705290310185114400, 11436],
+            [1705290736882757600, 11436],
+            [1705290796883791400, 11436],
+            [1705290856883483600, 11436],
+            [1705290987064807700, 11436],
+            [1705291047065788400, 11436],
+          ],
+        },
+      ],
+    };
 
-    if (!Array.isArray(data.results)) {
-      throw new Error('metrics are missing/invalid in the response'); // eslint-disable-line @gitlab/require-i18n-strings
-    }
-    return data.results;
+    const heatmap = {
+      start_ts: 1707098119807086000,
+      end_ts: 1707098479807086000,
+      results: [
+        {
+          name: 'http_request_duration',
+          description: 'randomDescription',
+          unit: 'randomUnit',
+          type: 'Histogram',
+          data: [
+            {
+              bucketsHash: 123,
+              buckets: ['1.000000', '2.000000', '3.000000', '4.000000', '5.000000', `Inf`], // eslint-disable-line @gitlab/require-i18n-strings
+              distribution: [
+                [
+                  [1707098160000000000, 2],
+                  [1707098220000000000, 6],
+                  [1707098280000000000, 2],
+                  [1707098340000000000, 6],
+                  [1707098400000000000, 6],
+                ],
+                [
+                  [1707098160000000000, 4],
+                  [1707098220000000000, 5],
+                  [1707098280000000000, 2],
+                  [1707098340000000000, 3],
+                  [1707098400000000000, 4],
+                ],
+                [
+                  [1707098160000000000, 2],
+                  [1707098220000000000, 4],
+                  [1707098280000000000, 5],
+                  [1707098340000000000, 1],
+                  [1707098400000000000, 3],
+                ],
+                [
+                  [1707098160000000000, 0],
+                  [1707098220000000000, 1],
+                  [1707098280000000000, 1],
+                  [1707098340000000000, 6],
+                  [1707098400000000000, 2],
+                ],
+                [
+                  [1707098160000000000, 1],
+                  [1707098220000000000, 1],
+                  [1707098280000000000, 1],
+                  [1707098340000000000, 3],
+                  [1707098400000000000, 4],
+                ],
+                [
+                  [1707098160000000000, 6],
+                  [1707098220000000000, 11],
+                  [1707098280000000000, 9],
+                  [1707098340000000000, 7],
+                  [1707098400000000000, 8],
+                ],
+              ],
+            },
+          ],
+        },
+      ],
+    };
+
+    return mockReturnDataWithDelay(options.visual === 'heatmap' ? heatmap.results : data.results);
   } catch (e) {
     return reportErrorAndThrow(e);
   }
@@ -460,11 +2241,20 @@ async function fetchMetricSearchMetadata(searchMetadataUrl, name, type) {
       mname: name,
       mtype: type,
     });
-    const { data } = await axios.get(searchMetadataUrl, {
-      params,
-      withCredentials: true,
+
+    console.log(`[DEBUG] Fetching metrics search metadata with params: ${params.toString()}`);
+
+    return mockReturnDataWithDelay({
+      name: 'app.ads.ad_requests',
+      type: 'Sum',
+      description: 'Counts ad requests by request and response type',
+      attribute_keys: ['app.ads.ad_request_type', 'app.ads.ad_response_type'],
+      last_ingested_at: 1707489287944422100,
+      supported_aggregations: ['1m', '1h', '1d'],
+      supported_functions: ['avg', 'sum', 'min', 'max', 'count'],
+      default_group_by_attributes: ['*'],
+      default_group_by_function: 'sum',
     });
-    return data;
   } catch (e) {
     return reportErrorAndThrow(e);
   }
diff --git a/app/assets/javascripts/observability/components/observability_container.vue b/app/assets/javascripts/observability/components/observability_container.vue
index d0902505ca73..f6cbf7ee771f 100644
--- a/app/assets/javascripts/observability/components/observability_container.vue
+++ b/app/assets/javascripts/observability/components/observability_container.vue
@@ -27,12 +27,12 @@ export default {
 
     // TODO: Improve local GDK dev experience with tracing https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2308
     // Uncomment the lines below to to test this locally
-    // setTimeout(() => {
-    //   this.messageHandler({
-    //     data: { type: 'AUTH_COMPLETION', status: 'success' },
-    //     origin: new URL(this.apiConfig.oauthUrl).origin,
-    //   });
-    // }, 2000);
+    setTimeout(() => {
+      this.messageHandler({
+        data: { type: 'AUTH_COMPLETION', status: 'success' },
+        origin: new URL(this.apiConfig.oauthUrl).origin,
+      });
+    }, 2000);
   },
   destroyed() {
     window.removeEventListener('message', this.messageHandler);
Edited by Daniele Rossetti

Merge request reports