Compare commits

..

36 Commits

Author SHA1 Message Date
aks07
4dcf9ea488 feat: test 2026-06-10 11:07:38 +05:30
Gaurav Tewari
8f25f2ece7 chore: drop useSaveRecentQuery from gridcard 2026-06-10 01:32:02 +05:30
Gaurav Tewari
3aac04aac2 Merge branch 'main' into feat/show-recent-5-queires-to-user 2026-06-09 22:00:23 +05:30
Gaurav Tewari
a2c6cb680d Merge branch 'main' into feat/show-recent-5-queires-to-user 2026-06-09 18:41:14 +05:30
Gaurav Tewari
3484cbbfdd refactor: getRecentHook and make logic simple 2026-06-09 17:22:38 +05:30
Gaurav Tewari
ebbd430715 refactor: review changes 2026-06-09 16:40:35 +05:30
Gaurav Tewari
d16f2d0d4d fix: minor refactor 2026-06-09 10:49:49 +05:30
Gaurav Tewari
bf74f0680d Merge branch 'main' into feat/show-recent-5-queires-to-user 2026-06-09 03:10:53 +05:30
Gaurav Tewari
6712701f22 refactor: make code much better 2026-06-09 03:02:04 +05:30
Gaurav Tewari
128739f25e fix: more refactor 2026-06-09 02:37:41 +05:30
Gaurav Tewari
cd9fa0cf9c refactor: more changes 2026-06-09 01:32:57 +05:30
Gaurav Tewari
8d7fb6e270 Merge remote-tracking branch 'origin' into feat/show-recent-5-queires-to-user 2026-06-09 01:13:31 +05:30
Gaurav Tewari
cfe7878f94 refactor: self review changes 2026-06-09 01:12:11 +05:30
Gaurav Tewari
e9fae6964d refactor: review changes 2026-06-09 00:03:09 +05:30
Gaurav Tewari
1eeff7283d feat: use source as well in query key 2026-06-08 22:43:00 +05:30
Gaurav Tewari
db6360afaf fix: update query 2026-06-08 10:29:25 +05:30
Gaurav Tewari
13285a5c6a chore: update styling 2026-06-01 15:38:24 +05:30
Gaurav Tewari
908856f73f Merge branch 'main' into feat/show-recent-5-queires-to-user 2026-06-01 15:02:39 +05:30
Gaurav Tewari
26e9f38f94 fix: lint 2026-06-01 14:52:02 +05:30
Gaurav Tewari
66b86a8509 refactor: import issue 2026-06-01 14:28:41 +05:30
Gaurav Tewari
100067d8dc refactor: more changes 2026-06-01 14:24:41 +05:30
Gaurav Tewari
b883a09c78 fix: update types 2026-06-01 14:21:43 +05:30
Gaurav Tewari
96f2160119 refactor: store in local storage 2026-06-01 14:17:28 +05:30
Gaurav Tewari
1824acc860 chore: remove extra commentes 2026-06-01 14:00:02 +05:30
Gaurav Tewari
fd9bc7c42e refactor: more code 2026-06-01 13:53:35 +05:30
Gaurav Tewari
68d17dd164 chore: remove comments 2026-06-01 13:44:11 +05:30
Gaurav Tewari
7568a1a1e1 refactor : more changes 2026-06-01 13:43:39 +05:30
Gaurav Tewari
8c28035e6e feat: add time feature 2026-06-01 13:03:21 +05:30
Gaurav Tewari
3d9dd945f6 refactor: more comments 2026-06-01 12:24:20 +05:30
Gaurav Tewari
3b8bcdecaa refactor: comments 2026-06-01 12:11:15 +05:30
Gaurav Tewari
4b54affb10 refactor: css 2026-06-01 11:41:58 +05:30
Gaurav Tewari
519c5471ba refactor: self review comments 2026-06-01 11:21:40 +05:30
Gaurav Tewari
68c4b6f724 refactor: queries 2026-06-01 10:32:30 +05:30
Gaurav Tewari
e65a1dd1ce refactor: move all components into one 2026-06-01 10:22:19 +05:30
Gaurav Tewari
8d2e024cb2 refactor: recent query 2026-06-01 02:48:57 +05:30
Gaurav Tewari
90cb4e99f9 feat: initial commit 2026-06-01 02:00:50 +05:30
106 changed files with 2877 additions and 7132 deletions

View File

@@ -190,7 +190,7 @@ services:
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
signoz:
!!merge <<: *db-depend
image: signoz/signoz:v0.128.0
image: signoz/signoz:v0.127.1
ports:
- "8080:8080" # signoz port
# - "6060:6060" # pprof port

View File

@@ -117,7 +117,7 @@ services:
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
signoz:
!!merge <<: *db-depend
image: signoz/signoz:v0.128.0
image: signoz/signoz:v0.127.1
ports:
- "8080:8080" # signoz port
volumes:

View File

@@ -181,7 +181,7 @@ services:
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
signoz:
!!merge <<: *db-depend
image: signoz/signoz:${VERSION:-v0.128.0}
image: signoz/signoz:${VERSION:-v0.127.1}
container_name: signoz
ports:
- "8080:8080" # signoz port

View File

@@ -109,7 +109,7 @@ services:
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
signoz:
!!merge <<: *db-depend
image: signoz/signoz:${VERSION:-v0.128.0}
image: signoz/signoz:${VERSION:-v0.127.1}
container_name: signoz
ports:
- "8080:8080" # signoz port

View File

@@ -1364,8 +1364,6 @@ components:
- appservice
- containerapp
- aks
- sqldatabase
- sqldatabasemi
type: string
CloudintegrationtypesServiceMetadata:
properties:
@@ -6728,6 +6726,11 @@ components:
type: object
SpantypesGettableWaterfallTrace:
properties:
aggregations:
items:
$ref: '#/components/schemas/SpantypesSpanAggregationResult'
nullable: true
type: array
endTimestampMillis:
minimum: 0
type: integer
@@ -6815,6 +6818,14 @@ components:
type: object
SpantypesPostableWaterfall:
properties:
aggregations:
items:
$ref: '#/components/schemas/SpantypesSpanAggregation'
nullable: true
type: array
limit:
minimum: 0
type: integer
selectedSpanId:
type: string
uncollapsedSpans:
@@ -20670,6 +20681,76 @@ paths:
summary: Get flamegraph view for a trace
tags:
- tracedetail
/api/v3/traces/{traceID}/waterfall:
post:
deprecated: false
description: Returns the waterfall view of spans for a given trace ID with tree
structure, metadata, and windowed pagination
operationId: GetWaterfall
parameters:
- in: path
name: traceID
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/SpantypesPostableWaterfall'
responses:
"200":
content:
application/json:
schema:
properties:
data:
$ref: '#/components/schemas/SpantypesGettableWaterfallTrace'
status:
type: string
required:
- status
- data
type: object
description: OK
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/RenderErrorResponse'
description: Bad Request
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/RenderErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/RenderErrorResponse'
description: Forbidden
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/RenderErrorResponse'
description: Not Found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/RenderErrorResponse'
description: Internal Server Error
security:
- api_key:
- VIEWER
- tokenizer:
- VIEWER
summary: Get waterfall view for a trace
tags:
- tracedetail
/api/v4/traces/{traceID}/waterfall:
post:
deprecated: false

View File

@@ -5,13 +5,6 @@ import convertObjectIntoParams from 'lib/query/convertObjectIntoParams';
import { ErrorResponse, SuccessResponse } from 'types/api';
import { PayloadProps, Props } from 'types/api/alerts/getTriggered';
/**
* @deprecated Use the generated `useGetAlerts` hook (or `getAlerts` fetcher) from
* `api/generated/services/alerts` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const getTriggered = async (
props: Props,
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadProps, Props } from 'types/api/channels/createEmail';
/**
* @deprecated Use the generated `useCreateChannel` hook (or `createChannel` fetcher) from
* `api/generated/services/channels` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const create = async (
props: Props,
): Promise<SuccessResponseV2<PayloadProps>> => {

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadProps, Props } from 'types/api/channels/createMsTeams';
/**
* @deprecated Use the generated `useCreateChannel` hook (or `createChannel` fetcher) from
* `api/generated/services/channels` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const create = async (
props: Props,
): Promise<SuccessResponseV2<PayloadProps>> => {

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadProps, Props } from 'types/api/channels/createOpsgenie';
/**
* @deprecated Use the generated `useCreateChannel` hook (or `createChannel` fetcher) from
* `api/generated/services/channels` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const create = async (
props: Props,
): Promise<SuccessResponseV2<PayloadProps>> => {

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadProps, Props } from 'types/api/channels/createPager';
/**
* @deprecated Use the generated `useCreateChannel` hook (or `createChannel` fetcher) from
* `api/generated/services/channels` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const create = async (
props: Props,
): Promise<SuccessResponseV2<PayloadProps>> => {

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadProps, Props } from 'types/api/channels/createSlack';
/**
* @deprecated Use the generated `useCreateChannel` hook (or `createChannel` fetcher) from
* `api/generated/services/channels` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const create = async (
props: Props,
): Promise<SuccessResponseV2<PayloadProps>> => {

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadProps, Props } from 'types/api/channels/createWebhook';
/**
* @deprecated Use the generated `useCreateChannel` hook (or `createChannel` fetcher) from
* `api/generated/services/channels` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const create = async (
props: Props,
): Promise<SuccessResponseV2<PayloadProps>> => {

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadProps, Props } from 'types/api/channels/delete';
/**
* @deprecated Use the generated `useDeleteChannelByID` hook (or `deleteChannelByID` fetcher) from
* `api/generated/services/channels` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const deleteChannel = async (
props: Props,
): Promise<SuccessResponseV2<PayloadProps>> => {

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadProps, Props } from 'types/api/channels/editEmail';
/**
* @deprecated Use the generated `useUpdateChannelByID` hook (or `updateChannelByID` fetcher) from
* `api/generated/services/channels` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const editEmail = async (
props: Props,
): Promise<SuccessResponseV2<PayloadProps>> => {

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadProps, Props } from 'types/api/channels/editMsTeams';
/**
* @deprecated Use the generated `useUpdateChannelByID` hook (or `updateChannelByID` fetcher) from
* `api/generated/services/channels` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const editMsTeams = async (
props: Props,
): Promise<SuccessResponseV2<PayloadProps>> => {

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorResponse, ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadProps, Props } from 'types/api/channels/editOpsgenie';
/**
* @deprecated Use the generated `useUpdateChannelByID` hook (or `updateChannelByID` fetcher) from
* `api/generated/services/channels` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const editOpsgenie = async (
props: Props,
): Promise<SuccessResponseV2<PayloadProps> | ErrorResponse> => {

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadProps, Props } from 'types/api/channels/editPager';
/**
* @deprecated Use the generated `useUpdateChannelByID` hook (or `updateChannelByID` fetcher) from
* `api/generated/services/channels` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const editPager = async (
props: Props,
): Promise<SuccessResponseV2<PayloadProps>> => {

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadProps, Props } from 'types/api/channels/editSlack';
/**
* @deprecated Use the generated `useUpdateChannelByID` hook (or `updateChannelByID` fetcher) from
* `api/generated/services/channels` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const editSlack = async (
props: Props,
): Promise<SuccessResponseV2<PayloadProps>> => {

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadProps, Props } from 'types/api/channels/editWebhook';
/**
* @deprecated Use the generated `useUpdateChannelByID` hook (or `updateChannelByID` fetcher) from
* `api/generated/services/channels` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const editWebhook = async (
props: Props,
): Promise<SuccessResponseV2<PayloadProps>> => {

View File

@@ -5,13 +5,6 @@ import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadProps, Props } from 'types/api/channels/get';
import { Channels } from 'types/api/channels/getAll';
/**
* @deprecated Use the generated `useGetChannelByID` hook (or `getChannelByID` fetcher) from
* `api/generated/services/channels` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const get = async (props: Props): Promise<SuccessResponseV2<Channels>> => {
try {
const response = await axios.get<PayloadProps>(`/channels/${props.id}`);

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { Channels, PayloadProps } from 'types/api/channels/getAll';
/**
* @deprecated Use the generated `useListChannels` hook (or `listChannels` fetcher) from
* `api/generated/services/channels` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const getAll = async (): Promise<SuccessResponseV2<Channels[]>> => {
try {
const response = await axios.get<PayloadProps>('/channels');

View File

@@ -5,13 +5,6 @@ import { DEFAULT_TIME_RANGE } from 'container/TopNav/DateTimeSelectionV2/constan
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { CreatePublicDashboardProps } from 'types/api/dashboard/public/create';
/**
* @deprecated Use the generated `useCreatePublicDashboard` hook (or `createPublicDashboard` fetcher) from
* `api/generated/services/dashboard` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const createPublicDashboard = async (
props: CreatePublicDashboardProps,
): Promise<SuccessResponseV2<CreatePublicDashboardProps>> => {

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { GetPublicDashboardDataProps, PayloadProps,PublicDashboardDataProps } from 'types/api/dashboard/public/get';
/**
* @deprecated Use the generated `useGetPublicDashboardData` hook (or `getPublicDashboardData` fetcher) from
* `api/generated/services/dashboard` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const getPublicDashboardData = async (props: GetPublicDashboardDataProps): Promise<SuccessResponseV2<PublicDashboardDataProps>> => {
try {
const response = await axios.get<PayloadProps>(`/public/dashboards/${props.id}`);

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { GetPublicDashboardMetaProps, PayloadProps,PublicDashboardMetaProps } from 'types/api/dashboard/public/getMeta';
/**
* @deprecated Use the generated `useGetPublicDashboard` hook (or `getPublicDashboard` fetcher) from
* `api/generated/services/dashboard` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const getPublicDashboardMeta = async (props: GetPublicDashboardMetaProps): Promise<SuccessResponseV2<PublicDashboardMetaProps>> => {
try {
const response = await axios.get<PayloadProps>(`/dashboards/${props.id}/public`);

View File

@@ -6,13 +6,6 @@ import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { GetPublicDashboardWidgetDataProps } from 'types/api/dashboard/public/getWidgetData';
/**
* @deprecated Use the generated `useGetPublicDashboardWidgetQueryRange` hook (or `getPublicDashboardWidgetQueryRange` fetcher) from
* `api/generated/services/dashboard` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const getPublicDashboardWidgetData = async (props: GetPublicDashboardWidgetDataProps): Promise<SuccessResponseV2<MetricRangePayloadV5>> => {
try {
const response = await axios.get(`/public/dashboards/${props.id}/widgets/${props.index}/query_range`, {

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadProps,RevokePublicDashboardAccessProps } from 'types/api/dashboard/public/delete';
/**
* @deprecated Use the generated `useDeletePublicDashboard` hook (or `deletePublicDashboard` fetcher) from
* `api/generated/services/dashboard` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const revokePublicDashboardAccess = async (
props: RevokePublicDashboardAccessProps,
): Promise<SuccessResponseV2<PayloadProps>> => {

View File

@@ -5,13 +5,6 @@ import { DEFAULT_TIME_RANGE } from 'container/TopNav/DateTimeSelectionV2/constan
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { UpdatePublicDashboardProps } from 'types/api/dashboard/public/update';
/**
* @deprecated Use the generated `useUpdatePublicDashboard` hook (or `updatePublicDashboard` fetcher) from
* `api/generated/services/dashboard` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const updatePublicDashboard = async (
props: UpdatePublicDashboardProps,
): Promise<SuccessResponseV2<UpdatePublicDashboardProps>> => {

View File

@@ -9,13 +9,6 @@ interface ISubstituteVars {
compositeQuery: ICompositeMetricQuery;
}
/**
* @deprecated Use the generated `useReplaceVariables` hook (or `replaceVariables` fetcher) from
* `api/generated/services/querier` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
export const getSubstituteVars = async (
props?: Partial<QueryRangePayloadV5>,
signal?: AbortSignal,

View File

@@ -8,12 +8,6 @@ import { FieldKeyResponse } from 'types/api/dynamicVariables/getFieldKeys';
* Get field keys for a given signal type
* @param signal Type of signal (traces, logs, metrics)
* @param name Optional search text
*
* @deprecated Use the generated `useGetFieldsKeys` hook (or `getFieldsKeys` fetcher) from
* `api/generated/services/fields` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
export const getFieldKeys = async (
signal?: 'traces' | 'logs' | 'metrics',

View File

@@ -11,12 +11,6 @@ import { FieldValueResponse } from 'types/api/dynamicVariables/getFieldValues';
* @param name Name of the attribute for which values are being fetched
* @param value Optional search text
* @param existingQuery Optional existing query - across all present dynamic variables
*
* @deprecated Use the generated `useGetFieldsValues` hook (or `getFieldsValues` fetcher) from
* `api/generated/services/fields` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
export const getFieldValues = async (
signal?: 'traces' | 'logs' | 'metrics',

View File

@@ -2655,8 +2655,6 @@ export enum CloudintegrationtypesServiceIDDTO {
appservice = 'appservice',
containerapp = 'containerapp',
aks = 'aks',
sqldatabase = 'sqldatabase',
sqldatabasemi = 'sqldatabasemi',
}
export type CloudintegrationtypesCloudIntegrationServiceDTOAnyOf = {
/**
@@ -8097,6 +8095,10 @@ export interface SpantypesWaterfallSpanDTO {
}
export interface SpantypesGettableWaterfallTraceDTO {
/**
* @type array,null
*/
aggregations?: SpantypesSpanAggregationResultDTO[] | null;
/**
* @type integer
* @minimum 0
@@ -8216,6 +8218,15 @@ export interface SpantypesPostableTraceAggregationsDTO {
}
export interface SpantypesPostableWaterfallDTO {
/**
* @type array,null
*/
aggregations?: SpantypesSpanAggregationDTO[] | null;
/**
* @type integer
* @minimum 0
*/
limit?: number;
/**
* @type string
*/
@@ -10510,6 +10521,17 @@ export type GetFlamegraph200 = {
status: string;
};
export type GetWaterfallPathParameters = {
traceID: string;
};
export type GetWaterfall200 = {
data: SpantypesGettableWaterfallTraceDTO;
/**
* @type string
*/
status: string;
};
export type GetWaterfallV4PathParameters = {
traceID: string;
};

View File

@@ -16,6 +16,8 @@ import type {
GetFlamegraphPathParameters,
GetTraceAggregations200,
GetTraceAggregationsPathParameters,
GetWaterfall200,
GetWaterfallPathParameters,
GetWaterfallV4200,
GetWaterfallV4PathParameters,
RenderErrorResponseDTO,
@@ -226,6 +228,105 @@ export const useGetFlamegraph = <
> => {
return useMutation(getGetFlamegraphMutationOptions(options));
};
/**
* Returns the waterfall view of spans for a given trace ID with tree structure, metadata, and windowed pagination
* @summary Get waterfall view for a trace
*/
export const getWaterfall = (
{ traceID }: GetWaterfallPathParameters,
spantypesPostableWaterfallDTO?: BodyType<SpantypesPostableWaterfallDTO>,
signal?: AbortSignal,
) => {
return GeneratedAPIInstance<GetWaterfall200>({
url: `/api/v3/traces/${traceID}/waterfall`,
method: 'POST',
headers: { 'Content-Type': 'application/json' },
data: spantypesPostableWaterfallDTO,
signal,
});
};
export const getGetWaterfallMutationOptions = <
TError = ErrorType<RenderErrorResponseDTO>,
TContext = unknown,
>(options?: {
mutation?: UseMutationOptions<
Awaited<ReturnType<typeof getWaterfall>>,
TError,
{
pathParams: GetWaterfallPathParameters;
data?: BodyType<SpantypesPostableWaterfallDTO>;
},
TContext
>;
}): UseMutationOptions<
Awaited<ReturnType<typeof getWaterfall>>,
TError,
{
pathParams: GetWaterfallPathParameters;
data?: BodyType<SpantypesPostableWaterfallDTO>;
},
TContext
> => {
const mutationKey = ['getWaterfall'];
const { mutation: mutationOptions } = options
? options.mutation &&
'mutationKey' in options.mutation &&
options.mutation.mutationKey
? options
: { ...options, mutation: { ...options.mutation, mutationKey } }
: { mutation: { mutationKey } };
const mutationFn: MutationFunction<
Awaited<ReturnType<typeof getWaterfall>>,
{
pathParams: GetWaterfallPathParameters;
data?: BodyType<SpantypesPostableWaterfallDTO>;
}
> = (props) => {
const { pathParams, data } = props ?? {};
return getWaterfall(pathParams, data);
};
return { mutationFn, ...mutationOptions };
};
export type GetWaterfallMutationResult = NonNullable<
Awaited<ReturnType<typeof getWaterfall>>
>;
export type GetWaterfallMutationBody =
| BodyType<SpantypesPostableWaterfallDTO>
| undefined;
export type GetWaterfallMutationError = ErrorType<RenderErrorResponseDTO>;
/**
* @summary Get waterfall view for a trace
*/
export const useGetWaterfall = <
TError = ErrorType<RenderErrorResponseDTO>,
TContext = unknown,
>(options?: {
mutation?: UseMutationOptions<
Awaited<ReturnType<typeof getWaterfall>>,
TError,
{
pathParams: GetWaterfallPathParameters;
data?: BodyType<SpantypesPostableWaterfallDTO>;
},
TContext
>;
}): UseMutationResult<
Awaited<ReturnType<typeof getWaterfall>>,
TError,
{
pathParams: GetWaterfallPathParameters;
data?: BodyType<SpantypesPostableWaterfallDTO>;
},
TContext
> => {
return useMutation(getGetWaterfallMutationOptions(options));
};
/**
* Returns the waterfall view of spans including all spans if total spans are under a limit, a max count otherwise. Aggregations are dropped compared to v3
* @summary Get waterfall view for a trace

View File

@@ -5,13 +5,6 @@ import {
QueryKeySuggestionsResponseProps,
} from 'types/api/querySuggestions/types';
/**
* @deprecated Use the generated `useGetFieldsKeys` hook (or `getFieldsKeys` fetcher) from
* `api/generated/services/fields` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
export const getKeySuggestions = (
props: QueryKeyRequestProps,
): Promise<AxiosResponse<QueryKeySuggestionsResponseProps>> => {

View File

@@ -5,13 +5,6 @@ import {
QueryKeyValueSuggestionsResponseProps,
} from 'types/api/querySuggestions/types';
/**
* @deprecated Use the generated `useGetFieldsValues` hook (or `getFieldsValues` fetcher) from
* `api/generated/services/fields` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
export const getValueSuggestions = (
props: QueryKeyValueRequestProps,
): Promise<AxiosResponse<QueryKeyValueSuggestionsResponseProps>> => {

View File

@@ -15,13 +15,6 @@ export interface CreateRoutingPolicyResponse {
message: string;
}
/**
* @deprecated Use the generated `useCreateRoutePolicy` hook (or `createRoutePolicy` fetcher) from
* `api/generated/services/routepolicies` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const createRoutingPolicy = async (
props: CreateRoutingPolicyBody,
): Promise<

View File

@@ -8,13 +8,6 @@ export interface DeleteRoutingPolicyResponse {
message: string;
}
/**
* @deprecated Use the generated `useDeleteRoutePolicyByID` hook (or `deleteRoutePolicyByID` fetcher) from
* `api/generated/services/routepolicies` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const deleteRoutingPolicy = async (
routingPolicyId: string,
): Promise<

View File

@@ -20,13 +20,6 @@ export interface GetRoutingPoliciesResponse {
data?: ApiRoutingPolicy[];
}
/**
* @deprecated Use the generated `useGetAllRoutePolicies` hook (or `getAllRoutePolicies` fetcher) from
* `api/generated/services/routepolicies` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
export const getRoutingPolicies = async (
signal?: AbortSignal,
headers?: Record<string, string>,

View File

@@ -15,13 +15,6 @@ export interface UpdateRoutingPolicyResponse {
message: string;
}
/**
* @deprecated Use the generated `useUpdateRoutePolicy` hook (or `updateRoutePolicy` fetcher) from
* `api/generated/services/routepolicies` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const updateRoutingPolicy = async (
id: string,
props: UpdateRoutingPolicyBody,

View File

@@ -27,6 +27,7 @@ const getTraceV4 = async (
{
selectedSpanId: props.selectedSpanId,
uncollapsedSpans,
limit: 10000,
},
);

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadProps, Props } from 'types/api/user/resetPassword';
/**
* @deprecated Use the generated `useResetPassword` hook (or `resetPassword` fetcher) from
* `api/generated/services/users` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const resetPassword = async (
props: Props,
): Promise<SuccessResponseV2<PayloadProps>> => {

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { UsersProps } from 'types/api/user/inviteUsers';
/**
* @deprecated Use the generated `useCreateBulkInvite` hook (or `createBulkInvite` fetcher) from
* `api/generated/services/users` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const inviteUsers = async (
users: UsersProps,
): Promise<SuccessResponseV2<null>> => {

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadProps, Props } from 'types/api/user/setInvite';
/**
* @deprecated Use the generated `useCreateInvite` hook (or `createInvite` fetcher) from
* `api/generated/services/users` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const sendInvite = async (
props: Props,
): Promise<SuccessResponseV2<PayloadProps>> => {

View File

@@ -5,13 +5,6 @@ import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadProps } from 'types/api/preferences/list';
import { OrgPreference } from 'types/api/preferences/preference';
/**
* @deprecated Use the generated `useListOrgPreferences` hook (or `listOrgPreferences` fetcher) from
* `api/generated/services/preferences` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const listPreference = async (): Promise<
SuccessResponseV2<OrgPreference[]>
> => {

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { Props } from 'types/api/preferences/update';
/**
* @deprecated Use the generated `useUpdateOrgPreference` hook (or `updateOrgPreference` fetcher) from
* `api/generated/services/preferences` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const update = async (props: Props): Promise<SuccessResponseV2<null>> => {
try {
const response = await axios.put(`/org/preferences/${props.name}`, {

View File

@@ -5,13 +5,6 @@ import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadProps } from 'types/api/preferences/list';
import { UserPreference } from 'types/api/preferences/preference';
/**
* @deprecated Use the generated `useListUserPreferences` hook (or `listUserPreferences` fetcher) from
* `api/generated/services/preferences` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const list = async (): Promise<SuccessResponseV2<UserPreference[]>> => {
try {
const response = await axios.get<PayloadProps>(`/user/preferences`);

View File

@@ -5,13 +5,6 @@ import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { PayloadProps, Props } from 'types/api/preferences/get';
import { UserPreference } from 'types/api/preferences/preference';
/**
* @deprecated Use the generated `useGetUserPreference` hook (or `getUserPreference` fetcher) from
* `api/generated/services/preferences` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const get = async (
props: Props,
): Promise<SuccessResponseV2<UserPreference>> => {

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { Props } from 'types/api/preferences/update';
/**
* @deprecated Use the generated `useUpdateUserPreference` hook (or `updateUserPreference` fetcher) from
* `api/generated/services/preferences` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const update = async (props: Props): Promise<SuccessResponseV2<null>> => {
try {
const response = await axios.put(`/user/preferences/${props.name}`, {

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, RawSuccessResponse, SuccessResponseV2 } from 'types/api';
import { Props, SessionsContext } from 'types/api/v2/sessions/context/get';
/**
* @deprecated Use the generated `useGetSessionContext` hook (or `getSessionContext` fetcher) from
* `api/generated/services/sessions` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const get = async (
props: Props,
): Promise<SuccessResponseV2<SessionsContext>> => {

View File

@@ -3,13 +3,6 @@ import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
import { AxiosError } from 'axios';
import { ErrorV2Resp, RawSuccessResponse, SuccessResponseV2 } from 'types/api';
/**
* @deprecated Use the generated `useDeleteSession` hook (or `deleteSession` fetcher) from
* `api/generated/services/sessions` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const deleteSession = async (): Promise<SuccessResponseV2<null>> => {
try {
const response = await axios.delete<RawSuccessResponse<null>>('/sessions');

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, RawSuccessResponse, SuccessResponseV2 } from 'types/api';
import { Props, Token } from 'types/api/v2/sessions/email_password/post';
/**
* @deprecated Use the generated `useCreateSessionByEmailPassword` hook (or `createSessionByEmailPassword` fetcher) from
* `api/generated/services/sessions` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const post = async (props: Props): Promise<SuccessResponseV2<Token>> => {
try {
const response = await axios.post<RawSuccessResponse<Token>>(

View File

@@ -4,13 +4,6 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, RawSuccessResponse, SuccessResponseV2 } from 'types/api';
import { Props, Token } from 'types/api/v2/sessions/rotate/post';
/**
* @deprecated Use the generated `useRotateSession` hook (or `rotateSession` fetcher) from
* `api/generated/services/sessions` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
const post = async (props: Props): Promise<SuccessResponseV2<Token>> => {
try {
const response = await axios.post<RawSuccessResponse<Token>>(

View File

@@ -8,13 +8,6 @@ import {
QueryRangePayloadV5,
} from 'types/api/v5/queryRange';
/**
* @deprecated Use the generated `useQueryRangeV5` hook (or `queryRangeV5` fetcher) from
* `api/generated/services/querier` instead. This hand-written client targets the
* same endpoint and will be removed once call sites migrate.
*
* Part of https://github.com/SigNoz/engineering-pod/issues/5289, add a comment or update when removing this method.
*/
export const getQueryRangeV5 = async (
props: QueryRangePayloadV5,
version: string,

View File

@@ -1,5 +1,11 @@
// TODO: Improve the styling of the query aggregation container and its components. - @YounixM , @H4ad
$dropdown-base-height: 250px;
$recents-header-height: 30px;
$recent-row-height: 36px;
// how many recents are rendered, this caps how tall the dropdown can grow to fit them.
$max-recents-shown: 5;
.code-mirror-where-clause {
width: 100%;
display: flex;
@@ -117,7 +123,23 @@
width: 100% !important;
max-width: 100% !important;
font-family: 'Space Mono', monospace !important;
min-height: 200px !important;
max-height: $dropdown-base-height !important;
overflow-y: auto !important;
// Recents render at the top of the dropdown ahead of regular suggestions.
// At the base max-height, having recents in view would crowd out the
// suggestion list below. This loop grows the dropdown by one row's worth
// of height for every recent present (up to $max-recents-shown), plus the
// section header. `:has(> li:nth-of-type(N) .cm-completionIcon-recent)`
// matches when the Nth child of <ul> is a recent — i.e. there are at
// least N recents visible.
@for $i from 1 through $max-recents-shown {
&:has(> li:nth-of-type(#{$i}) .cm-completionIcon-recent) {
max-height: $dropdown-base-height +
$recents-header-height +
($i * $recent-row-height) !important;
}
}
&::-webkit-scrollbar {
width: 0.3rem;
@@ -133,6 +155,19 @@
background: transparent;
}
completion-section {
display: block;
padding: 10px 12px 6px;
font-size: 10px !important;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--l3-foreground, var(--l2-foreground));
opacity: 0.7;
border-bottom: 0;
background-color: transparent;
}
li {
width: 100% !important;
max-width: 100% !important;
@@ -159,11 +194,78 @@
display: none !important;
}
.cm-completionDetail {
margin-left: auto;
font-style: normal;
font-size: var(--periscope-font-size-small, 11px);
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
opacity: 0.55;
}
&[aria-selected='true'] {
background: var(--l3-background) !important;
font-weight: 600 !important;
}
}
li:has(.cm-completionIcon-recent) {
&:hover .cm-recent-delete,
&[aria-selected='true'] .cm-recent-delete {
opacity: 1;
}
}
li .cm-completionLabel {
flex: 1;
min-width: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.cm-recent-delete {
margin-left: 8px;
display: inline-flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
padding: 0;
border: 0;
border-radius: 4px;
background: transparent;
color: var(--l2-foreground);
font-size: 18px;
line-height: 1;
cursor: pointer;
opacity: 0.5;
transition:
opacity 0.12s ease,
background-color 0.12s ease;
&:hover {
opacity: 1;
background: color-mix(in srgb, var(--l2-foreground) 18%, transparent);
}
}
}
&::after {
content: '↓↑ to navigate · ↵ to apply · esc to dismiss';
display: block;
padding: 8px 12px;
border-top: 1px solid var(--l1-border);
font-family: 'Space Mono', monospace;
font-size: 11px;
font-weight: 500;
letter-spacing: 0.02em;
color: var(--l2-foreground);
opacity: 0.6;
background: color-mix(in srgb, var(--l1-background) 50%, transparent);
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
}

View File

@@ -46,8 +46,15 @@ import {
import { validateQuery } from 'utils/queryValidationUtils';
import { unquote } from 'utils/stringUtils';
import { queryExamples } from './constants';
import { combineInitialAndUserExpression } from './utils';
import { getRecentQueries } from 'lib/recentQueries/getRecentQueries';
import type { SignalType } from 'types/api/v5/queryRange';
import { queryExamples, SUGGESTIONS_SECTION } from './constants';
import {
combineInitialAndUserExpression,
getRecentOptions,
renderRecentDeleteButton,
} from './utils';
import './QuerySearch.styles.scss';
@@ -1250,6 +1257,41 @@ function QuerySearch({
};
}
const signal = dataSource as SignalType;
function combinedSuggestions(
context: CompletionContext,
): CompletionResult | null {
const fullDoc = context.state.doc.toString();
const recentOptions = getRecentOptions(
getRecentQueries(signal, signalSource ?? ''),
fullDoc,
);
const result = autoSuggestions(context);
const suggestionOptions = (result?.options || []).map((opt) => ({
...opt,
section: SUGGESTIONS_SECTION,
}));
if (recentOptions.length === 0 && suggestionOptions.length === 0) {
return result;
}
if (!result) {
return {
from: 0,
to: fullDoc.length,
options: recentOptions,
};
}
return {
...result,
options: [...recentOptions, ...suggestionOptions],
};
}
// Effect to handle focus state and trigger suggestions
useEffect(() => {
const clearTimeout = toggleSuggestions(10);
@@ -1398,11 +1440,12 @@ function QuerySearch({
})}
extensions={[
autocompletion({
override: [autoSuggestions],
override: [combinedSuggestions],
defaultKeymap: true,
closeOnBlur: true,
activateOnTyping: true,
maxRenderedOptions: 50,
addToOptions: [{ render: renderRecentDeleteButton, position: 100 }],
}),
javascript({ jsx: false, typescript: false }),
EditorView.lineWrapping,

View File

@@ -1,3 +1,14 @@
export const RECENTS_SECTION = { name: 'Recent searches', rank: 1 } as const;
export const SUGGESTIONS_SECTION = { name: 'Suggestions', rank: 2 } as const;
// Custom CodeMirror Completion.type for recent-query entries. Used to discriminate
// recents from regular autocomplete completions in renderers and event handlers.
export const RECENT_COMPLETION_TYPE = 'recent';
// Max number of recents rendered in the autocomplete dropdown.
// Do change $max-recents-shown: in QuerySearch.styles.scss if you change this.
export const RECENTS_DISPLAY_CAP = 5;
export const queryExamples = [
{
label: 'Basic Query',

View File

@@ -1,3 +1,19 @@
import { closeCompletion, startCompletion } from '@codemirror/autocomplete';
import type { Completion } from '@codemirror/autocomplete';
import type { EditorView } from '@uiw/react-codemirror';
import dayjs from 'dayjs';
import { normalizeFilterExpression } from 'lib/recentQueries/normalize';
import * as recentQueriesStore from 'lib/recentQueries/recentQueriesStore';
import type { RecentQueryEntry } from 'lib/recentQueries/types';
import type { SignalType } from 'types/api/v5/queryRange';
import 'utils/timeUtils';
import {
RECENT_COMPLETION_TYPE,
RECENTS_DISPLAY_CAP,
RECENTS_SECTION,
} from './constants';
export function combineInitialAndUserExpression(
initial: string,
user: string,
@@ -38,3 +54,106 @@ export function getUserExpressionFromCombined(
}
return c;
}
// Filters and projects a list of recent-query entries into CodeMirror completions.
// Entries are supplied by the caller (typically via the useRecents hook) so this
// function stays pure and React doesn't have to re-subscribe inside CodeMirror's
// autocomplete callback.
export function getRecentOptions(
entries: RecentQueryEntry[],
fullDoc: string,
): Completion[] {
const normalizedDoc = normalizeFilterExpression(fullDoc);
const matches = entries
.filter((e) => {
const normalizedRecent = normalizeFilterExpression(e.filter.expression);
if (normalizedRecent === normalizedDoc) {
return false;
}
if (normalizedDoc === '') {
return true;
}
return normalizedRecent.includes(normalizedDoc);
})
.slice(0, RECENTS_DISPLAY_CAP);
return matches.map((entry, index) => ({
label: entry.filter.expression,
type: RECENT_COMPLETION_TYPE,
// CodeMirror sorts within a section by boost desc, then label asc. The store
// returns entries newest-first, so we mirror that by giving the newest entry
// the highest boost — otherwise CM falls back to alphabetical order and the
// "most recently used" expectation breaks. Stays within the recents section
// because section.rank keeps recents above suggestions regardless of boost.
boost: matches.length - index,
section: RECENTS_SECTION,
detail: dayjs(entry.lastUsedAt).fromNow(),
recentId: entry.id,
recentSignal: entry.signal,
recentSource: entry.source,
apply: (view: EditorView): void => {
view.dispatch({
changes: {
from: 0,
to: view.state.doc.length,
insert: entry.filter.expression,
},
selection: { anchor: entry.filter.expression.length },
});
closeCompletion(view);
},
}));
}
export function renderRecentDeleteButton(
completion: Completion,
_state: unknown,
view: EditorView | null,
): Node | null {
if (completion.type !== RECENT_COMPLETION_TYPE) {
return null;
}
const c = completion as Completion & {
recentId?: string;
recentSignal?: SignalType;
recentSource?: string;
};
const btn = document.createElement('button');
btn.type = 'button';
btn.className = 'cm-recent-delete';
btn.setAttribute('aria-label', 'Remove from recent searches');
btn.title = 'Remove from recent searches';
btn.textContent = '×';
queueMicrotask(() => {
if (btn.parentElement) {
btn.parentElement.title = completion.label;
}
});
const stop = (e: Event): void => {
e.preventDefault();
e.stopPropagation();
};
// CodeMirror's autocomplete closes the popup on pointerdown / mousedown outside
// the editor. The delete button lives inside the popup, so we must stop those
// events early — otherwise clicking × would dismiss the dropdown before the
// click handler fires and the entry wouldn't actually get removed.
btn.addEventListener('pointerdown', stop);
btn.addEventListener('mousedown', stop);
btn.addEventListener('click', (e) => {
stop(e);
if (!c.recentId || !c.recentSignal) {
return;
}
recentQueriesStore.remove(c.recentId, c.recentSignal, c.recentSource ?? '');
if (view) {
view.focus();
startCompletion(view);
}
});
return btn;
}

View File

@@ -62,6 +62,7 @@ function Explorer(): JSX.Element {
handleSetQueryData,
redirectWithQueryBuilderData,
} = useQueryBuilder();
const { safeNavigate } = useSafeNavigate();
const { handleExplorerTabChange } = useHandleExplorerTabChange();
const isAIAssistantEnabled = useIsAIAssistantEnabled();

View File

@@ -0,0 +1,5 @@
export const STORAGE_KEY_PREFIX = 'qb_recent_v1';
export const STORAGE_VERSION = 1;
// Maximum entries kept per (signal, source) bucket. Larger than the UI's
// RECENTS_DISPLAY_CAP so deleting a visible entry surfaces an older one.
export const MAX_ENTRIES = 10;

View File

@@ -0,0 +1,51 @@
import * as store from './recentQueriesStore';
import { getRecentQueries } from './getRecentQueries';
describe('getRecentQueries', () => {
beforeEach(() => {
store.useRecentQueriesStore.setState({ buckets: {} });
localStorage.clear();
});
it('returns the entries for a (signal, source) bucket', () => {
store.save({
signal: 'logs',
filter: { expression: "severity_text = 'ERROR'" },
});
const entries = getRecentQueries('logs', '');
expect(entries).toHaveLength(1);
expect(entries[0].filter.expression).toBe("severity_text = 'ERROR'");
});
it('returns an empty array for a bucket with no entries', () => {
expect(getRecentQueries('logs', '')).toHaveLength(0);
});
it('reads the latest entries on each call (non-subscribing)', () => {
expect(getRecentQueries('logs', '')).toHaveLength(0);
store.save({
signal: 'logs',
filter: { expression: "severity_text = 'ERROR'" },
});
expect(getRecentQueries('logs', '')).toHaveLength(1);
});
it('partitions by signal and source', () => {
store.save({
signal: 'logs',
filter: { expression: "severity_text = 'ERROR'" },
});
store.save({
signal: 'metrics',
source: 'meter',
filter: { expression: 'cpu_usage > 80' },
});
expect(getRecentQueries('logs', '')).toHaveLength(1);
expect(getRecentQueries('metrics', 'meter')).toHaveLength(1);
expect(getRecentQueries('metrics', '')).toHaveLength(0);
});
});

View File

@@ -0,0 +1,14 @@
import type { SignalType } from 'types/api/v5/queryRange';
import * as store from './recentQueriesStore';
import type { RecentQueryEntry } from './types';
// Non-subscribing read of recent searches for a (signal, source) bucket.
// Deliberately not the zustand hook — subscribing would reconfigure CodeMirror
// and close the open completion popup on every store change.
export function getRecentQueries(
signal: SignalType,
source: string,
): RecentQueryEntry[] {
return store.list(signal, source);
}

View File

@@ -0,0 +1,100 @@
import { normalizeFilterExpression } from './normalize';
describe('normalizeFilterExpression', () => {
it('returns empty string for empty input', () => {
expect(normalizeFilterExpression('')).toBe('');
});
it('returns empty string for whitespace-only input', () => {
expect(normalizeFilterExpression(' \t ')).toBe('');
});
it('strips whitespace around operators', () => {
expect(normalizeFilterExpression(' a = 1 ')).toBe('a=1');
expect(normalizeFilterExpression('a = 1')).toBe('a=1');
expect(normalizeFilterExpression('a=1')).toBe('a=1');
});
it('lowercases AND / OR / NOT outside quotes', () => {
expect(normalizeFilterExpression('A AND B OR NOT C')).toBe('AandBornotC');
});
it('lowercases IN / LIKE / ILIKE / CONTAINS', () => {
expect(normalizeFilterExpression('host IN [1, 2] AND name LIKE "foo"')).toBe(
'hostin[1,2]andnamelike"foo"',
);
});
it('lowercases REGEXP', () => {
expect(normalizeFilterExpression('path REGEXP "foo"')).toBe(
'pathregexp"foo"',
);
expect(normalizeFilterExpression('path REGEXP "foo"')).toBe(
normalizeFilterExpression('path regexp "foo"'),
);
});
it('lowercases HAS / HASANY / HASALL / HASTOKEN function names', () => {
expect(normalizeFilterExpression('HAS(tags, "x")')).toBe(
normalizeFilterExpression('has(tags, "x")'),
);
expect(normalizeFilterExpression('HASANY(tags, ["a","b"])')).toBe(
normalizeFilterExpression('hasAny(tags, ["a","b"])'),
);
expect(normalizeFilterExpression('HASALL(tags, ["a","b"])')).toBe(
normalizeFilterExpression('hasAll(tags, ["a","b"])'),
);
expect(normalizeFilterExpression('HASTOKEN(msg, "err")')).toBe(
normalizeFilterExpression('hasToken(msg, "err")'),
);
});
it('lowercases TRUE / FALSE boolean literals', () => {
expect(normalizeFilterExpression('active = TRUE')).toBe(
normalizeFilterExpression('active = true'),
);
expect(normalizeFilterExpression('active = FALSE')).toBe(
normalizeFilterExpression('active = false'),
);
});
it('preserves whitespace and casing inside single-quoted strings', () => {
expect(normalizeFilterExpression("a = 'X Y'")).toBe("a='X Y'");
});
it('preserves whitespace and casing inside double-quoted strings', () => {
expect(normalizeFilterExpression('a = "X Y"')).toBe('a="X Y"');
});
it('does not lowercase keyword-looking substrings inside quotes', () => {
expect(normalizeFilterExpression("msg = 'AND ERROR'")).toBe(
"msg='AND ERROR'",
);
});
it('handles escaped quotes inside strings', () => {
expect(normalizeFilterExpression("msg = 'a\\'b' AND x = 1")).toBe(
"msg='a\\'b'andx=1",
);
});
it('treats two formattings of the same expression as identical', () => {
const a = normalizeFilterExpression(
'service.name = "frontend" AND severity = error',
);
const b = normalizeFilterExpression(
'service.name="frontend" and severity=error',
);
expect(a).toBe(b);
});
it('preserves unquoted value casing (treats them as identifiers)', () => {
expect(normalizeFilterExpression('status = OK')).toBe('status=OK');
});
it('handles mixed quotes in one expression', () => {
expect(normalizeFilterExpression(`a = 'X' AND b = "Y"`)).toBe(
`a='X'andb="Y"`,
);
});
});

View File

@@ -0,0 +1,56 @@
import {
OPERATORS,
QUERY_BUILDER_FUNCTIONS,
TRACE_OPERATOR_OPERATORS,
} from 'constants/antlrQueryConstants';
// Reserved keywords sourced from the ANTLR grammar constants so this list stays
// in sync with the parser. `\b` prevents partial matches inside identifiers
// (e.g. `OR` inside `originator`). `TRUE`/`FALSE` are BOOL literals, included
// so case variants of boolean values also dedup.
const WORD_KEYWORDS = [
...Object.keys(OPERATORS).filter((k) => /^[A-Z]+$/.test(k)),
...Object.keys(TRACE_OPERATOR_OPERATORS).filter((k) => /^[A-Z]+$/.test(k)),
...Object.values(QUERY_BUILDER_FUNCTIONS),
'TRUE',
'FALSE',
];
const KEYWORDS_RE = new RegExp(`\\b(${WORD_KEYWORDS.join('|')})\\b`, 'gi');
// Matches single- or double-quoted string literals, supporting escaped quotes
// (e.g. `'it\'s'` or `"a \" b"`). We preserve quoted spans verbatim during
// normalisation so user-meaningful whitespace and casing inside string values
// stays intact: `name = "Foo Bar"` must not collapse to `name="foobar"`.
const QUOTED_RE = /'(?:\\.|[^'\\])*'|"(?:\\.|[^"\\])*"/g;
// Lowercases reserved keywords and strips ALL whitespace from the unquoted regions
// of the input. Keywords are normalised so casing variants dedup; whitespace is
// dropped so formatting variants (`a=1` vs `a = 1`) dedup too.
function processOutsideQuotes(s: string): string {
return s.replace(KEYWORDS_RE, (m) => m.toLowerCase()).replace(/\s+/g, '');
}
// Produces a canonical form of a filter expression suitable for dedup-key derivation.
// Walks the input alternating between unquoted regions (where we normalise keywords
// and whitespace) and quoted regions (which we copy verbatim).
export function normalizeFilterExpression(input: string): string {
if (!input) {
return '';
}
let result = '';
let lastIndex = 0;
QUOTED_RE.lastIndex = 0;
let match = QUOTED_RE.exec(input);
while (match !== null) {
result += processOutsideQuotes(input.slice(lastIndex, match.index));
result += match[0];
lastIndex = QUOTED_RE.lastIndex;
match = QUOTED_RE.exec(input);
}
result += processOutsideQuotes(input.slice(lastIndex));
return result.trim();
}

View File

@@ -0,0 +1,247 @@
import { MAX_ENTRIES } from './constants';
import * as store from './recentQueriesStore';
import type { RecentQueryInput } from './recentQueriesStore';
import type { RecentQueryEntry } from './types';
const baseInput = (
overrides: Partial<RecentQueryInput> = {},
): RecentQueryInput => ({
signal: 'logs',
filter: { expression: "service.name = 'frontend'" },
...overrides,
});
function saveOrThrow(input: RecentQueryInput): RecentQueryEntry {
const saved = store.save(input);
if (!saved) {
throw new Error('expected save to return an entry');
}
return saved;
}
describe('recentQueries store', () => {
beforeEach(() => {
store.useRecentQueriesStore.setState({ buckets: {} });
localStorage.clear();
});
describe('save + list', () => {
it('saves an entry and lists it', () => {
store.save(baseInput());
const entries = store.list('logs');
expect(entries).toHaveLength(1);
expect(entries[0].filter.expression).toBe("service.name = 'frontend'");
expect(entries[0].id).toBeTruthy();
expect(entries[0].lastUsedAt).toBeGreaterThan(0);
});
it('does not save when the filter expression is empty', () => {
const result = store.save(baseInput({ filter: { expression: '' } }));
expect(result).toBeNull();
expect(store.list('logs')).toHaveLength(0);
});
it('does not save when the filter expression is whitespace only', () => {
const result = store.save(baseInput({ filter: { expression: ' ' } }));
expect(result).toBeNull();
expect(store.list('logs')).toHaveLength(0);
});
});
describe('LRU ordering', () => {
it('places the most recently saved entry at the front', () => {
store.save(baseInput({ filter: { expression: "severity_text = 'ERROR'" } }));
store.save(baseInput({ filter: { expression: 'http.status_code >= 500' } }));
store.save(baseInput({ filter: { expression: 'attempt = 1' } }));
const entries = store.list('logs');
expect(entries.map((e) => e.filter.expression)).toStrictEqual([
'attempt = 1',
'http.status_code >= 500',
"severity_text = 'ERROR'",
]);
});
it('re-saving an existing filter bumps it to the front', () => {
store.save(baseInput({ filter: { expression: "severity_text = 'ERROR'" } }));
store.save(baseInput({ filter: { expression: 'http.status_code >= 500' } }));
store.save(baseInput({ filter: { expression: "severity_text = 'ERROR'" } }));
const entries = store.list('logs');
expect(entries).toHaveLength(2);
expect(entries.map((e) => e.filter.expression)).toStrictEqual([
"severity_text = 'ERROR'",
'http.status_code >= 500',
]);
});
});
describe('dedup', () => {
it('treats formatting variations of the same filter as one entry', () => {
store.save(
baseInput({
filter: { expression: "severity_text = 'ERROR' AND attempt = 1" },
}),
);
store.save(
baseInput({
filter: { expression: "severity_text='ERROR' and attempt=1" },
}),
);
expect(store.list('logs')).toHaveLength(1);
});
});
describe('signal partitioning', () => {
it('saves to the right bucket per signal', () => {
store.save(
baseInput({
signal: 'logs',
filter: { expression: "severity_text = 'ERROR'" },
}),
);
store.save(
baseInput({
signal: 'traces',
filter: { expression: "service.name = 'orders-api'" },
}),
);
store.save(
baseInput({
signal: 'metrics',
filter: { expression: 'cpu_usage > 80' },
}),
);
expect(store.list('logs')).toHaveLength(1);
expect(store.list('traces')).toHaveLength(1);
expect(store.list('metrics')).toHaveLength(1);
expect(store.list('logs')[0].filter.expression).toBe(
"severity_text = 'ERROR'",
);
expect(store.list('traces')[0].filter.expression).toBe(
"service.name = 'orders-api'",
);
expect(store.list('metrics')[0].filter.expression).toBe('cpu_usage > 80');
});
it('does not leak between signals on dedup', () => {
store.save(
baseInput({
signal: 'logs',
filter: { expression: "service.name = 'frontend'" },
}),
);
store.save(
baseInput({
signal: 'traces',
filter: { expression: "service.name = 'frontend'" },
}),
);
expect(store.list('logs')).toHaveLength(1);
expect(store.list('traces')).toHaveLength(1);
});
});
describe('LRU cap', () => {
it('caps the bucket at MAX_ENTRIES and evicts the oldest', () => {
const total = MAX_ENTRIES + 1;
for (let i = 0; i < total; i += 1) {
store.save(baseInput({ filter: { expression: `attempt = ${i}` } }));
}
const entries = store.list('logs');
expect(entries).toHaveLength(MAX_ENTRIES);
expect(entries[0].filter.expression).toBe(`attempt = ${total - 1}`);
expect(entries.some((e) => e.filter.expression === 'attempt = 0')).toBe(
false,
);
});
});
describe('remove', () => {
it('removes an entry by id', () => {
store.save(baseInput({ filter: { expression: "severity_text = 'ERROR'" } }));
const saved = saveOrThrow(
baseInput({ filter: { expression: 'http.status_code >= 500' } }),
);
store.remove(saved.id, 'logs');
const entries = store.list('logs');
expect(entries).toHaveLength(1);
expect(entries[0].filter.expression).toBe("severity_text = 'ERROR'");
});
it('is a no-op when the id does not exist', () => {
store.save(baseInput({ filter: { expression: "severity_text = 'ERROR'" } }));
store.remove('does-not-exist', 'logs');
expect(store.list('logs')).toHaveLength(1);
});
it('does not touch other signals', () => {
const logsEntry = saveOrThrow(
baseInput({
signal: 'logs',
filter: { expression: "service.name = 'frontend'" },
}),
);
store.save(
baseInput({
signal: 'traces',
filter: { expression: "service.name = 'frontend'" },
}),
);
store.remove(logsEntry.id, 'logs');
expect(store.list('logs')).toHaveLength(0);
expect(store.list('traces')).toHaveLength(1);
});
});
describe('persistence', () => {
it('reads back the same entries after the in-memory state is reset', () => {
store.save(baseInput({ filter: { expression: "severity_text = 'ERROR'" } }));
store.save(baseInput({ filter: { expression: 'http.status_code >= 500' } }));
store.useRecentQueriesStore.setState({ buckets: {} });
const entries = store.list('logs');
expect(entries.map((e) => e.filter.expression)).toStrictEqual([
'http.status_code >= 500',
"severity_text = 'ERROR'",
]);
});
});
describe('reactive subscription via zustand', () => {
it('notifies zustand subscribers on save', () => {
const cb = jest.fn();
const unsubscribe = store.useRecentQueriesStore.subscribe(cb);
store.save(baseInput({ filter: { expression: "severity_text = 'ERROR'" } }));
expect(cb).toHaveBeenCalledTimes(1);
unsubscribe();
});
it('notifies zustand subscribers on remove', () => {
const saved = saveOrThrow(
baseInput({ filter: { expression: "severity_text = 'ERROR'" } }),
);
const cb = jest.fn();
const unsubscribe = store.useRecentQueriesStore.subscribe(cb);
store.remove(saved.id, 'logs');
expect(cb).toHaveBeenCalledTimes(1);
unsubscribe();
});
it('stops notifying after unsubscribe', () => {
const cb = jest.fn();
const unsubscribe = store.useRecentQueriesStore.subscribe(cb);
unsubscribe();
store.save(baseInput({ filter: { expression: "severity_text = 'ERROR'" } }));
expect(cb).not.toHaveBeenCalled();
});
});
});

View File

@@ -0,0 +1,144 @@
import get from 'api/browser/localstorage/get';
import set from 'api/browser/localstorage/set';
import type { SignalType } from 'types/api/v5/queryRange';
import { create } from 'zustand';
import { MAX_ENTRIES, STORAGE_VERSION } from './constants';
import { normalizeFilterExpression } from './normalize';
import type { RecentQueriesStoreShape, RecentQueryEntry } from './types';
import { bucketKey, makeId, normalizeSource, storageKeyFor } from './utils';
// Mirrors parsed localStorage so equal raw strings return the same array ref —
// preserves Object.is for zustand selector bail-out.
const persistedBucketCache = new Map<
string,
{ raw: string; parsed: RecentQueryEntry[] }
>();
function loadBucketFromStorage(
signal: SignalType,
source: string,
): RecentQueryEntry[] | null {
const key = bucketKey(signal, source);
try {
const raw = get(storageKeyFor(signal, source));
if (!raw) {
persistedBucketCache.delete(key);
return null;
}
const cached = persistedBucketCache.get(key);
if (cached && cached.raw === raw) {
return cached.parsed;
}
const parsedShape = JSON.parse(raw) as RecentQueriesStoreShape;
if (
parsedShape?.version !== STORAGE_VERSION ||
!Array.isArray(parsedShape.entries)
) {
persistedBucketCache.delete(key);
return null;
}
persistedBucketCache.set(key, { raw, parsed: parsedShape.entries });
return parsedShape.entries;
} catch {
persistedBucketCache.delete(key);
return null;
}
}
function saveBucketToStorage(
signal: SignalType,
source: string,
entries: RecentQueryEntry[],
): void {
try {
const raw = JSON.stringify({ version: STORAGE_VERSION, entries });
if (set(storageKeyFor(signal, source), raw)) {
persistedBucketCache.set(bucketKey(signal, source), {
raw,
parsed: entries,
});
}
} catch {
// Ignore storage errors (e.g. quota exceeded, JSON.stringify failure).
}
}
export type RecentQueryInput = Omit<
RecentQueryEntry,
'id' | 'lastUsedAt' | 'source'
> & {
source?: string;
};
type RecentQueriesState = {
buckets: Record<string, RecentQueryEntry[]>;
save: (entry: RecentQueryInput) => RecentQueryEntry | null;
remove: (id: string, signal: SignalType, source?: string) => void;
};
export const useRecentQueriesStore = create<RecentQueriesState>()(
(set, get) => ({
buckets: {},
save: (entry): RecentQueryEntry | null => {
const normalized = normalizeFilterExpression(entry.filter.expression);
if (!normalized) {
return null;
}
const source = normalizeSource(entry.source);
const key = bucketKey(entry.signal, source);
const current =
get().buckets[key] ?? loadBucketFromStorage(entry.signal, source) ?? [];
const filtered = current.filter(
(e) => normalizeFilterExpression(e.filter.expression) !== normalized,
);
const newEntry: RecentQueryEntry = {
...entry,
source,
id: makeId(entry.signal, source, normalized),
lastUsedAt: Date.now(),
};
const next = [newEntry, ...filtered].slice(0, MAX_ENTRIES);
set({ buckets: { ...get().buckets, [key]: next } });
saveBucketToStorage(entry.signal, source, next);
return newEntry;
},
remove: (id, signal, source = ''): void => {
const key = bucketKey(signal, source);
const current = get().buckets[key] ?? loadBucketFromStorage(signal, source);
if (!current) {
return;
}
const next = current.filter((e) => e.id !== id);
if (next.length === current.length) {
return;
}
set({ buckets: { ...get().buckets, [key]: next } });
saveBucketToStorage(signal, source, next);
},
}),
);
// Plain-function wrappers for non-React callers — same pattern as useColumnStore.ts.
export function save(entry: RecentQueryInput): RecentQueryEntry | null {
return useRecentQueriesStore.getState().save(entry);
}
export function remove(id: string, signal: SignalType, source = ''): void {
useRecentQueriesStore.getState().remove(id, signal, source);
}
// Synchronous bucket read with localStorage fallback for non-React callers.
export function list(signal: SignalType, source = ''): RecentQueryEntry[] {
const key = bucketKey(signal, source);
const state = useRecentQueriesStore.getState();
if (state.buckets[key]) {
return state.buckets[key];
}
return loadBucketFromStorage(signal, source) ?? [];
}

View File

@@ -0,0 +1,126 @@
import { EQueryType } from 'types/common/dashboard';
import { DataSource } from 'types/common/queryBuilder';
import type {
IBuilderQuery,
Query,
} from 'types/api/queryBuilder/queryBuilderData';
import { validateQuery } from 'utils/queryValidationUtils';
import * as store from './recentQueriesStore';
import { saveRecentQuery } from './saveRecentQuery';
jest.mock('utils/queryValidationUtils', () => ({
validateQuery: jest.fn(),
}));
const mockedValidateQuery = validateQuery as jest.MockedFunction<
typeof validateQuery
>;
const buildQuery = (overrides: Partial<IBuilderQuery>[] = [{}]): Query => ({
queryType: EQueryType.QUERY_BUILDER,
promql: [],
clickhouse_sql: [],
id: 'q1',
builder: {
queryFormulas: [],
queryTraceOperator: [],
queryData: overrides.map((o, i) => ({
queryName: `Q${i}`,
dataSource: DataSource.LOGS,
aggregateOperator: 'count',
aggregateAttribute: undefined as never,
functions: [],
filter: { expression: 'service.name = "frontend"' },
groupBy: [],
expression: `Q${i}`,
disabled: false,
having: [],
limit: null,
stepInterval: null,
orderBy: [],
legend: '',
...o,
})) as IBuilderQuery[],
},
});
describe('saveRecentQuery', () => {
beforeEach(() => {
store.useRecentQueriesStore.setState({ buckets: {} });
localStorage.clear();
mockedValidateQuery.mockReturnValue({
isValid: true,
message: '',
errors: [],
});
});
it('saves the query when validation passes', () => {
saveRecentQuery(buildQuery());
const entries = store.list('logs');
expect(entries).toHaveLength(1);
expect(entries[0].filter.expression).toBe('service.name = "frontend"');
});
it('does not save when validateQuery rejects the expression', () => {
mockedValidateQuery.mockReturnValue({
isValid: false,
message: 'bad',
errors: [],
});
saveRecentQuery(buildQuery());
expect(store.list('logs')).toHaveLength(0);
});
it('does not save a builder query with an empty filter expression', () => {
saveRecentQuery(buildQuery([{ filter: { expression: '' } }]));
expect(store.list('logs')).toHaveLength(0);
});
it('saves each builder query in the composite separately', () => {
saveRecentQuery(
buildQuery([
{
dataSource: DataSource.LOGS,
filter: { expression: "service.name = 'frontend'" },
},
{
dataSource: DataSource.TRACES,
filter: { expression: "service.name = 'orders-api'" },
},
]),
);
expect(store.list('logs')).toHaveLength(1);
expect(store.list('traces')).toHaveLength(1);
});
it('keeps a single entry when the same query is run again', () => {
saveRecentQuery(buildQuery());
saveRecentQuery(buildQuery());
expect(store.list('logs')).toHaveLength(1);
});
it('adds a second entry when the filter changes', () => {
saveRecentQuery(
buildQuery([{ filter: { expression: "severity_text = 'ERROR'" } }]),
);
saveRecentQuery(
buildQuery([{ filter: { expression: 'http.status_code >= 500' } }]),
);
expect(store.list('logs')).toHaveLength(2);
});
it('is a no-op when the query is null', () => {
saveRecentQuery(null);
expect(store.list('logs')).toHaveLength(0);
});
});

View File

@@ -0,0 +1,48 @@
import type {
IBuilderQuery,
Query,
QueryState,
} from 'types/api/queryBuilder/queryBuilderData';
import type { SignalType } from 'types/api/v5/queryRange';
import { validateQuery } from 'utils/queryValidationUtils';
import * as store from './recentQueriesStore';
function toSignal(dataSource: IBuilderQuery['dataSource']): SignalType | null {
if (
dataSource === 'logs' ||
dataSource === 'traces' ||
dataSource === 'metrics'
) {
return dataSource;
}
return null;
}
// Persists each builder query's filter expression as a recent search, partitioned
// by signal (and source). Call this on an explicit Stage & Run — not on staged-query
// changes — so page loads, navigation, and correlation redirects don't pollute recents.
// The store dedups by normalized filter, so re-running a query just bumps it to the front.
export function saveRecentQuery(
query: Query | QueryState | null | undefined,
): void {
const queryData = query?.builder?.queryData ?? [];
queryData.forEach((q) => {
const expression = q.filter?.expression?.trim();
if (!expression) {
return;
}
if (!validateQuery(expression).isValid) {
return;
}
const signal = toSignal(q.dataSource);
if (!signal) {
return;
}
store.save({
signal,
source: q.source ?? '',
filter: q.filter ?? { expression: '' },
});
});
}

View File

@@ -0,0 +1,14 @@
import type { Filter, SignalType } from 'types/api/v5/queryRange';
export interface RecentQueryEntry {
id: string;
signal: SignalType;
source: string;
filter: Filter;
lastUsedAt: number;
}
export interface RecentQueriesStoreShape {
version: 1;
entries: RecentQueryEntry[];
}

View File

@@ -0,0 +1,24 @@
import type { SignalType } from 'types/api/v5/queryRange';
import { STORAGE_KEY_PREFIX } from './constants';
export function normalizeSource(source: string | undefined): string {
return source ?? '';
}
export function bucketKey(signal: SignalType, source: string): string {
return `${signal}:${source}`;
}
export function storageKeyFor(signal: SignalType, source: string): string {
return `${STORAGE_KEY_PREFIX}:${bucketKey(signal, source)}`;
}
// Same (signal, source, normalized filter) ⇒ same id ⇒ upsert.
export function makeId(
signal: SignalType,
source: string,
normalizedFilter: string,
): string {
return `${signal}|${source}|${normalizedFilter}`;
}

View File

@@ -39,6 +39,7 @@ import { updateStepInterval } from 'hooks/queryBuilder/useStepInterval';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import useUrlQuery from 'hooks/useUrlQuery';
import { createIdFromObjectFields } from 'lib/createIdFromObjectFields';
import { saveRecentQuery } from 'lib/recentQueries/saveRecentQuery';
import { createNewBuilderItemName } from 'lib/newQueryBuilder/createNewBuilderItemName';
import { getOperatorsBySourceAndPanelType } from 'lib/newQueryBuilder/getOperatorsBySourceAndPanelType';
import { replaceIncorrectObjectFields } from 'lib/replaceIncorrectObjectFields';
@@ -1025,6 +1026,11 @@ export function QueryBuilderProvider({
);
const handleRunQuery = useCallback(() => {
// Save the run query to recent searches. Tied to the explicit Stage & Run
// gesture (not staged-query changes) so navigation and correlation redirects
// don't pollute recents.
saveRecentQuery(currentQuery);
const isExplorer =
location.pathname === ROUTES.LOGS_EXPLORER ||
location.pathname === ROUTES.TRACES_EXPLORER;

View File

@@ -2,6 +2,7 @@ import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
import dayjs from 'dayjs';
import customParseFormat from 'dayjs/plugin/customParseFormat';
import duration from 'dayjs/plugin/duration';
import relativeTime from 'dayjs/plugin/relativeTime';
import timezone from 'dayjs/plugin/timezone';
import utc from 'dayjs/plugin/utc';
@@ -9,6 +10,7 @@ dayjs.extend(utc);
dayjs.extend(customParseFormat);
dayjs.extend(duration);
dayjs.extend(timezone);
dayjs.extend(relativeTime);
export function toUTCEpoch(time: number): number {
const x = new Date();

View File

@@ -10,6 +10,25 @@ import (
)
func (provider *provider) addTraceDetailRoutes(router *mux.Router) error {
if err := router.Handle("/api/v3/traces/{traceID}/waterfall", handler.New(
provider.authzMiddleware.ViewAccess(provider.traceDetailHandler.GetWaterfall),
handler.OpenAPIDef{
ID: "GetWaterfall",
Tags: []string{"tracedetail"},
Summary: "Get waterfall view for a trace",
Description: "Returns the waterfall view of spans for a given trace ID with tree structure, metadata, and windowed pagination",
Request: new(spantypes.PostableWaterfall),
RequestContentType: "application/json",
Response: new(spantypes.GettableWaterfallTrace),
ResponseContentType: "application/json",
SuccessStatusCode: http.StatusOK,
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
},
)).Methods(http.MethodPost).GetError(); err != nil {
return err
}
if err := router.Handle("/api/v4/traces/{traceID}/waterfall", handler.New(
provider.authzMiddleware.ViewAccess(provider.traceDetailHandler.GetWaterfallV4),
handler.OpenAPIDef{

View File

@@ -22,7 +22,7 @@ func newConfig() factory.Config {
Agent: AgentConfig{
// we will maintain the latest version of cloud integration agent from here,
// till we automate it externally or figure out a way to validate it.
Version: "v0.0.11",
Version: "v0.0.10",
},
}
}

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 18"><defs><linearGradient id="f67d1585-6164-4ad0-b2dd-f9cc59b2969f" x1="9.908" y1="15.943" x2="7.516" y2="2.383" gradientUnits="userSpaceOnUse"><stop offset="0.15" stop-color="#0078d4"/><stop offset="0.8" stop-color="#5ea0ef"/><stop offset="1" stop-color="#83b9f9"/></linearGradient></defs><g id="a4fd1868-54fe-4ca6-8ff6-3b01866dc27b"><path d="M14.49,7.15A5.147,5.147,0,0,0,9.24,2.164,5.272,5.272,0,0,0,4.216,5.653,4.869,4.869,0,0,0,0,10.4a4.946,4.946,0,0,0,5.068,4.814H13.82A4.292,4.292,0,0,0,18,11.127,4.105,4.105,0,0,0,14.49,7.15Z" fill="url(#f67d1585-6164-4ad0-b2dd-f9cc59b2969f)"/><path d="M12.9,11.4V8H12v4.13h2.46V11.4ZM5.76,9.73a1.825,1.825,0,0,1-.51-.31.441.441,0,0,1-.12-.32.342.342,0,0,1,.15-.3.683.683,0,0,1,.42-.12,1.62,1.62,0,0,1,1,.29V8.11a2.58,2.58,0,0,0-1-.16,1.641,1.641,0,0,0-1.09.34,1.08,1.08,0,0,0-.42.89c0,.51.32.91,1,1.21a2.907,2.907,0,0,1,.62.36.419.419,0,0,1,.15.32.381.381,0,0,1-.16.31.806.806,0,0,1-.45.11,1.66,1.66,0,0,1-1.09-.42V12a2.173,2.173,0,0,0,1.07.24,1.877,1.877,0,0,0,1.18-.33A1.08,1.08,0,0,0,6.84,11a1.048,1.048,0,0,0-.25-.7A2.425,2.425,0,0,0,5.76,9.73ZM11,11.32A2.191,2.191,0,0,0,11,9a1.808,1.808,0,0,0-.7-.75,2,2,0,0,0-1-.26,2.112,2.112,0,0,0-1.08.27A1.856,1.856,0,0,0,7.49,9a2.465,2.465,0,0,0-.26,1.14,2.256,2.256,0,0,0,.24,1,1.766,1.766,0,0,0,.69.74,2.056,2.056,0,0,0,1,.3l.86,1h1.21L10,12.08A1.79,1.79,0,0,0,11,11.32Zm-1-.25a.941.941,0,0,1-.76.35.916.916,0,0,1-.76-.36,1.523,1.523,0,0,1-.29-1,1.529,1.529,0,0,1,.29-1,1,1,0,0,1,.78-.37.869.869,0,0,1,.75.37,1.619,1.619,0,0,1,.27,1A1.459,1.459,0,0,1,10,11.07Z" fill="#f2f2f2"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -1,565 +0,0 @@
{
"id": "sqldatabase",
"title": "Azure SQL Database",
"icon": "file://icon.svg",
"overview": "file://overview.md",
"supportedSignals": {
"metrics": true,
"logs": true
},
"dataCollected": {
"metrics": [
{
"name": "azure_cpu_percent_average",
"unit": "Percent",
"type": "Gauge",
"description": "Percentage of CPU used by the database workload, relative to its limit."
},
{
"name": "azure_cpu_percent_maximum",
"unit": "Percent",
"type": "Gauge",
"description": "Percentage of CPU used by the database workload, relative to its limit."
},
{
"name": "azure_cpu_percent_minimum",
"unit": "Percent",
"type": "Gauge",
"description": "Percentage of CPU used by the database workload, relative to its limit."
},
{
"name": "azure_sql_instance_cpu_percent_average",
"unit": "Percent",
"type": "Gauge",
"description": "Total CPU usage (user plus system) of the SQL instance, as a percentage."
},
{
"name": "azure_sql_instance_cpu_percent_maximum",
"unit": "Percent",
"type": "Gauge",
"description": "Total CPU usage (user plus system) of the SQL instance, as a percentage."
},
{
"name": "azure_sql_instance_cpu_percent_minimum",
"unit": "Percent",
"type": "Gauge",
"description": "Total CPU usage (user plus system) of the SQL instance, as a percentage."
},
{
"name": "azure_sql_instance_memory_percent_average",
"unit": "Percent",
"type": "Gauge",
"description": "Memory usage of the SQL instance, as a percentage of its limit."
},
{
"name": "azure_sql_instance_memory_percent_maximum",
"unit": "Percent",
"type": "Gauge",
"description": "Memory usage of the SQL instance, as a percentage of its limit."
},
{
"name": "azure_sql_instance_memory_percent_minimum",
"unit": "Percent",
"type": "Gauge",
"description": "Memory usage of the SQL instance, as a percentage of its limit."
},
{
"name": "azure_physical_data_read_percent_average",
"unit": "Percent",
"type": "Gauge",
"description": "Data file IO usage as a percentage of the limit."
},
{
"name": "azure_physical_data_read_percent_maximum",
"unit": "Percent",
"type": "Gauge",
"description": "Data file IO usage as a percentage of the limit."
},
{
"name": "azure_physical_data_read_percent_minimum",
"unit": "Percent",
"type": "Gauge",
"description": "Data file IO usage as a percentage of the limit."
},
{
"name": "azure_log_write_percent_average",
"unit": "Percent",
"type": "Gauge",
"description": "Transaction log write throughput as a percentage of the limit."
},
{
"name": "azure_log_write_percent_maximum",
"unit": "Percent",
"type": "Gauge",
"description": "Transaction log write throughput as a percentage of the limit."
},
{
"name": "azure_log_write_percent_minimum",
"unit": "Percent",
"type": "Gauge",
"description": "Transaction log write throughput as a percentage of the limit."
},
{
"name": "azure_workers_percent_average",
"unit": "Percent",
"type": "Gauge",
"description": "Worker threads in use as a percentage of the limit."
},
{
"name": "azure_workers_percent_maximum",
"unit": "Percent",
"type": "Gauge",
"description": "Worker threads in use as a percentage of the limit."
},
{
"name": "azure_workers_percent_minimum",
"unit": "Percent",
"type": "Gauge",
"description": "Worker threads in use as a percentage of the limit."
},
{
"name": "azure_sessions_percent_average",
"unit": "Percent",
"type": "Gauge",
"description": "Active sessions as a percentage of the limit."
},
{
"name": "azure_sessions_percent_maximum",
"unit": "Percent",
"type": "Gauge",
"description": "Active sessions as a percentage of the limit."
},
{
"name": "azure_sessions_percent_minimum",
"unit": "Percent",
"type": "Gauge",
"description": "Active sessions as a percentage of the limit."
},
{
"name": "azure_sessions_count_average",
"unit": "Count",
"type": "Gauge",
"description": "Number of active sessions."
},
{
"name": "azure_sessions_count_maximum",
"unit": "Count",
"type": "Gauge",
"description": "Number of active sessions."
},
{
"name": "azure_sessions_count_minimum",
"unit": "Count",
"type": "Gauge",
"description": "Number of active sessions."
},
{
"name": "azure_dtu_consumption_percent_average",
"unit": "Percent",
"type": "Gauge",
"description": "DTU consumption as a percentage of the limit (DTU-based purchasing model)."
},
{
"name": "azure_dtu_consumption_percent_maximum",
"unit": "Percent",
"type": "Gauge",
"description": "DTU consumption as a percentage of the limit (DTU-based purchasing model)."
},
{
"name": "azure_dtu_consumption_percent_minimum",
"unit": "Percent",
"type": "Gauge",
"description": "DTU consumption as a percentage of the limit (DTU-based purchasing model)."
},
{
"name": "azure_dtu_used_average",
"unit": "Count",
"type": "Gauge",
"description": "DTUs used (DTU-based purchasing model)."
},
{
"name": "azure_dtu_used_maximum",
"unit": "Count",
"type": "Gauge",
"description": "DTUs used (DTU-based purchasing model)."
},
{
"name": "azure_dtu_used_minimum",
"unit": "Count",
"type": "Gauge",
"description": "DTUs used (DTU-based purchasing model)."
},
{
"name": "azure_dtu_limit_average",
"unit": "Count",
"type": "Gauge",
"description": "DTU limit (DTU-based purchasing model)."
},
{
"name": "azure_dtu_limit_maximum",
"unit": "Count",
"type": "Gauge",
"description": "DTU limit (DTU-based purchasing model)."
},
{
"name": "azure_dtu_limit_minimum",
"unit": "Count",
"type": "Gauge",
"description": "DTU limit (DTU-based purchasing model)."
},
{
"name": "azure_cpu_used_average",
"unit": "Count",
"type": "Gauge",
"description": "vCores used (vCore-based purchasing model)."
},
{
"name": "azure_cpu_used_maximum",
"unit": "Count",
"type": "Gauge",
"description": "vCores used (vCore-based purchasing model)."
},
{
"name": "azure_cpu_used_minimum",
"unit": "Count",
"type": "Gauge",
"description": "vCores used (vCore-based purchasing model)."
},
{
"name": "azure_cpu_limit_average",
"unit": "Count",
"type": "Gauge",
"description": "vCore limit (vCore-based purchasing model)."
},
{
"name": "azure_cpu_limit_maximum",
"unit": "Count",
"type": "Gauge",
"description": "vCore limit (vCore-based purchasing model)."
},
{
"name": "azure_cpu_limit_minimum",
"unit": "Count",
"type": "Gauge",
"description": "vCore limit (vCore-based purchasing model)."
},
{
"name": "azure_storage_average",
"unit": "Bytes",
"type": "Gauge",
"description": "Data space used by the database."
},
{
"name": "azure_storage_maximum",
"unit": "Bytes",
"type": "Gauge",
"description": "Data space used by the database."
},
{
"name": "azure_storage_minimum",
"unit": "Bytes",
"type": "Gauge",
"description": "Data space used by the database."
},
{
"name": "azure_storage_percent_average",
"unit": "Percent",
"type": "Gauge",
"description": "Data space used as a percentage of the maximum data size."
},
{
"name": "azure_storage_percent_maximum",
"unit": "Percent",
"type": "Gauge",
"description": "Data space used as a percentage of the maximum data size."
},
{
"name": "azure_storage_percent_minimum",
"unit": "Percent",
"type": "Gauge",
"description": "Data space used as a percentage of the maximum data size."
},
{
"name": "azure_allocated_data_storage_average",
"unit": "Bytes",
"type": "Gauge",
"description": "Data space allocated to the database (includes unused space)."
},
{
"name": "azure_allocated_data_storage_maximum",
"unit": "Bytes",
"type": "Gauge",
"description": "Data space allocated to the database (includes unused space)."
},
{
"name": "azure_allocated_data_storage_minimum",
"unit": "Bytes",
"type": "Gauge",
"description": "Data space allocated to the database (includes unused space)."
},
{
"name": "azure_xtp_storage_percent_average",
"unit": "Percent",
"type": "Gauge",
"description": "In-Memory OLTP storage used as a percentage of the limit."
},
{
"name": "azure_xtp_storage_percent_maximum",
"unit": "Percent",
"type": "Gauge",
"description": "In-Memory OLTP storage used as a percentage of the limit."
},
{
"name": "azure_xtp_storage_percent_minimum",
"unit": "Percent",
"type": "Gauge",
"description": "In-Memory OLTP storage used as a percentage of the limit."
},
{
"name": "azure_full_backup_size_bytes_average",
"unit": "Bytes",
"type": "Gauge",
"description": "Cumulative full backup storage size."
},
{
"name": "azure_full_backup_size_bytes_maximum",
"unit": "Bytes",
"type": "Gauge",
"description": "Cumulative full backup storage size."
},
{
"name": "azure_full_backup_size_bytes_minimum",
"unit": "Bytes",
"type": "Gauge",
"description": "Cumulative full backup storage size."
},
{
"name": "azure_diff_backup_size_bytes_average",
"unit": "Bytes",
"type": "Gauge",
"description": "Cumulative differential backup storage size."
},
{
"name": "azure_diff_backup_size_bytes_maximum",
"unit": "Bytes",
"type": "Gauge",
"description": "Cumulative differential backup storage size."
},
{
"name": "azure_diff_backup_size_bytes_minimum",
"unit": "Bytes",
"type": "Gauge",
"description": "Cumulative differential backup storage size."
},
{
"name": "azure_log_backup_size_bytes_average",
"unit": "Bytes",
"type": "Gauge",
"description": "Cumulative transaction log backup storage size."
},
{
"name": "azure_log_backup_size_bytes_maximum",
"unit": "Bytes",
"type": "Gauge",
"description": "Cumulative transaction log backup storage size."
},
{
"name": "azure_log_backup_size_bytes_minimum",
"unit": "Bytes",
"type": "Gauge",
"description": "Cumulative transaction log backup storage size."
},
{
"name": "azure_replication_lag_seconds_average",
"unit": "Seconds",
"type": "Gauge",
"description": "Geo-replication lag (RPO) in seconds; reported on the primary database only."
},
{
"name": "azure_replication_lag_seconds_maximum",
"unit": "Seconds",
"type": "Gauge",
"description": "Geo-replication lag (RPO) in seconds; reported on the primary database only."
},
{
"name": "azure_replication_lag_seconds_minimum",
"unit": "Seconds",
"type": "Gauge",
"description": "Geo-replication lag (RPO) in seconds; reported on the primary database only."
},
{
"name": "azure_connection_successful_total",
"unit": "Count",
"type": "Sum",
"description": "Number of successful connections."
},
{
"name": "azure_connection_successful_count",
"unit": "Count",
"type": "Gauge",
"description": "Number of successful connections."
},
{
"name": "azure_connection_failed_total",
"unit": "Count",
"type": "Sum",
"description": "Number of failed connections caused by system errors."
},
{
"name": "azure_connection_failed_count",
"unit": "Count",
"type": "Gauge",
"description": "Number of failed connections caused by system errors."
},
{
"name": "azure_connection_failed_user_error_total",
"unit": "Count",
"type": "Sum",
"description": "Number of failed connections caused by user errors."
},
{
"name": "azure_connection_failed_user_error_count",
"unit": "Count",
"type": "Gauge",
"description": "Number of failed connections caused by user errors."
},
{
"name": "azure_blocked_by_firewall_total",
"unit": "Count",
"type": "Sum",
"description": "Number of connection attempts blocked by the firewall."
},
{
"name": "azure_blocked_by_firewall_count",
"unit": "Count",
"type": "Gauge",
"description": "Number of connection attempts blocked by the firewall."
},
{
"name": "azure_deadlock_total",
"unit": "Count",
"type": "Sum",
"description": "Number of deadlocks."
},
{
"name": "azure_deadlock_count",
"unit": "Count",
"type": "Gauge",
"description": "Number of deadlocks."
},
{
"name": "azure_availability_average",
"unit": "Percent",
"type": "Gauge",
"description": "Database availability percentage (100 if connections succeed, 0 if all fail) per minute."
},
{
"name": "azure_availability_maximum",
"unit": "Percent",
"type": "Gauge",
"description": "Database availability percentage (100 if connections succeed, 0 if all fail) per minute."
},
{
"name": "azure_availability_minimum",
"unit": "Percent",
"type": "Gauge",
"description": "Database availability percentage (100 if connections succeed, 0 if all fail) per minute."
},
{
"name": "azure_availability_count",
"unit": "Percent",
"type": "Gauge",
"description": "Database availability percentage (100 if connections succeed, 0 if all fail) per minute."
},
{
"name": "azure_availability_total",
"unit": "Percent",
"type": "Sum",
"description": "Database availability percentage (100 if connections succeed, 0 if all fail) per minute."
},
{
"name": "azure_tempdb_data_size_average",
"unit": "Count",
"type": "Gauge",
"description": "Space used in tempdb data files, in kilobytes."
},
{
"name": "azure_tempdb_data_size_maximum",
"unit": "Count",
"type": "Gauge",
"description": "Space used in tempdb data files, in kilobytes."
},
{
"name": "azure_tempdb_data_size_minimum",
"unit": "Count",
"type": "Gauge",
"description": "Space used in tempdb data files, in kilobytes."
},
{
"name": "azure_tempdb_log_size_average",
"unit": "Count",
"type": "Gauge",
"description": "Space used in the tempdb transaction log file, in kilobytes."
},
{
"name": "azure_tempdb_log_size_maximum",
"unit": "Count",
"type": "Gauge",
"description": "Space used in the tempdb transaction log file, in kilobytes."
},
{
"name": "azure_tempdb_log_size_minimum",
"unit": "Count",
"type": "Gauge",
"description": "Space used in the tempdb transaction log file, in kilobytes."
},
{
"name": "azure_tempdb_log_used_percent_average",
"unit": "Percent",
"type": "Gauge",
"description": "tempdb transaction log space used as a percentage."
},
{
"name": "azure_tempdb_log_used_percent_maximum",
"unit": "Percent",
"type": "Gauge",
"description": "tempdb transaction log space used as a percentage."
},
{
"name": "azure_tempdb_log_used_percent_minimum",
"unit": "Percent",
"type": "Gauge",
"description": "tempdb transaction log space used as a percentage."
}
],
"logs": [
{
"name": "Resource ID",
"path": "resources.azure.resource.id",
"type": "string"
}
]
},
"telemetryCollectionStrategy": {
"azure": {
"resourceProvider": "Microsoft.Sql",
"resourceType": "servers/databases",
"metrics": {},
"logs": {
"categoryGroups": [
"allLogs"
]
}
}
},
"assets": {
"dashboards": [
{
"id": "overview",
"title": "Azure SQL Database Overview",
"description": "Overview of Azure SQL Database metrics",
"definition": "file://assets/dashboards/overview.json"
}
]
}
}

View File

@@ -1,7 +0,0 @@
### Monitor Azure SQL Database with SigNoz
Collect key Azure SQL Database (single database) metrics and view them with an out of the box dashboard.
This integration collects platform metrics for the `Microsoft.Sql/servers/databases` resource type.
Note: This integration is for Azure SQL Database (the PaaS offering). Azure SQL Managed Instance and SQL Server on Azure VMs expose a different set of metrics and are not covered here.

View File

@@ -1 +0,0 @@
<svg id="a5c93a83-9fd9-4ccb-ba77-53d6c609a7d3" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 18"><defs><linearGradient id="acf2da4b-8aca-4b58-b995-ca6956cf663e" x1="5.41" y1="17.33" x2="5.41" y2="0.61" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#949494"/><stop offset="0.53" stop-color="#a2a2a2"/><stop offset="1" stop-color="#b3b3b3"/></linearGradient><linearGradient id="b152b416-25c2-4a4a-9d7f-a0bb2a13f84a" x1="10.04" y1="17.39" x2="10.04" y2="6.82" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#0078d4"/><stop offset="0.16" stop-color="#1380da"/><stop offset="0.53" stop-color="#3c91e5"/><stop offset="0.82" stop-color="#559cec"/><stop offset="1" stop-color="#5ea0ef"/></linearGradient></defs><title>Icon-databases-136</title><path d="M10.32,16.76a.58.58,0,0,1-.57.57H1.07a.57.57,0,0,1-.57-.57V1.18A.56.56,0,0,1,1.07.61H9.75a.57.57,0,0,1,.57.57Z" fill="url(#acf2da4b-8aca-4b58-b995-ca6956cf663e)"/><path d="M1.94,6.47A1.07,1.07,0,0,1,3,5.41H7.9A1.07,1.07,0,0,1,9,6.47H9A1.07,1.07,0,0,1,7.9,7.54H3A1.07,1.07,0,0,1,1.94,6.47Z" fill="#003067"/><path d="M1.94,3.31A1.07,1.07,0,0,1,3,2.24H7.9A1.07,1.07,0,0,1,9,3.31H9A1.07,1.07,0,0,1,7.9,4.37H3A1.07,1.07,0,0,1,1.94,3.31Z" fill="#003067"/><circle cx="3.06" cy="3.31" r="0.72" fill="#50e6ff"/><circle cx="3.06" cy="6.47" r="0.72" fill="#50e6ff"/><path d="M17.5,14.08a3.36,3.36,0,0,0-2.91-3.22,4.22,4.22,0,0,0-4.35-4A4.32,4.32,0,0,0,6.1,9.64a4,4,0,0,0-3.52,3.85,4.06,4.06,0,0,0,4.2,3.9l.37,0H14l.17,0A3.39,3.39,0,0,0,17.5,14.08Z" fill="url(#b152b416-25c2-4a4a-9d7f-a0bb2a13f84a)"/><path d="M13.61,14.45V11.09h-.93v4.12h2.45v-.76ZM6.51,12.8A2.23,2.23,0,0,1,6,12.49a.44.44,0,0,1-.12-.32.34.34,0,0,1,.15-.3.66.66,0,0,1,.42-.12,1.66,1.66,0,0,1,1,.29v-.86a2.89,2.89,0,0,0-1-.15,1.69,1.69,0,0,0-1.09.33,1.1,1.1,0,0,0-.41.89,1.34,1.34,0,0,0,.94,1.2,2.51,2.51,0,0,1,.61.36.42.42,0,0,1,.15.32.34.34,0,0,1-.15.3.75.75,0,0,1-.45.12,1.63,1.63,0,0,1-1.08-.42v.92A2.25,2.25,0,0,0,6,15.28,1.91,1.91,0,0,0,7.15,15a1.07,1.07,0,0,0,.43-.91,1,1,0,0,0-.25-.7A2.36,2.36,0,0,0,6.51,12.8Zm5.16,1.58A2.37,2.37,0,0,0,12,13.12,2.28,2.28,0,0,0,11.75,12a1.77,1.77,0,0,0-.69-.74A1.94,1.94,0,0,0,10,11,2.21,2.21,0,0,0,9,11.29a1.87,1.87,0,0,0-.73.77A2.52,2.52,0,0,0,8,13.2a2.26,2.26,0,0,0,.24,1.05,1.87,1.87,0,0,0,.68.74,2,2,0,0,0,1,.29l.85,1h1.2l-1.19-1.1A1.82,1.82,0,0,0,11.67,14.38Zm-.93-.25a.92.92,0,0,1-.76.35.91.91,0,0,1-.75-.36,1.5,1.5,0,0,1-.28-1,1.46,1.46,0,0,1,.29-1,.92.92,0,0,1,.77-.37.86.86,0,0,1,.74.37,1.54,1.54,0,0,1,.28,1A1.47,1.47,0,0,1,10.74,14.13Z" fill="#f2f2f2"/></svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -1,167 +0,0 @@
{
"id": "sqldatabasemi",
"title": "Azure SQL Database Managed Instance",
"icon": "file://icon.svg",
"overview": "file://overview.md",
"supportedSignals": {
"metrics": true,
"logs": true
},
"dataCollected": {
"metrics": [
{
"name": "azure_avg_cpu_percent_average",
"unit": "Percent",
"type": "Gauge",
"description": "Average CPU utilization of the managed instance, as a percentage."
},
{
"name": "azure_avg_cpu_percent_maximum",
"unit": "Percent",
"type": "Gauge",
"description": "Maximum CPU utilization of the managed instance, as a percentage."
},
{
"name": "azure_avg_cpu_percent_minimum",
"unit": "Percent",
"type": "Gauge",
"description": "Minimum CPU utilization of the managed instance, as a percentage."
},
{
"name": "azure_io_bytes_read_average",
"unit": "Bytes",
"type": "Gauge",
"description": "Average bytes read from storage by the managed instance."
},
{
"name": "azure_io_bytes_read_maximum",
"unit": "Bytes",
"type": "Gauge",
"description": "Maximum bytes read from storage by the managed instance."
},
{
"name": "azure_io_bytes_read_minimum",
"unit": "Bytes",
"type": "Gauge",
"description": "Minimum bytes read from storage by the managed instance."
},
{
"name": "azure_io_bytes_written_average",
"unit": "Bytes",
"type": "Gauge",
"description": "Average bytes written to storage by the managed instance."
},
{
"name": "azure_io_bytes_written_maximum",
"unit": "Bytes",
"type": "Gauge",
"description": "Maximum bytes written to storage by the managed instance."
},
{
"name": "azure_io_bytes_written_minimum",
"unit": "Bytes",
"type": "Gauge",
"description": "Minimum bytes written to storage by the managed instance."
},
{
"name": "azure_io_requests_average",
"unit": "Count",
"type": "Gauge",
"description": "Average number of storage IO requests made by the managed instance."
},
{
"name": "azure_io_requests_maximum",
"unit": "Count",
"type": "Gauge",
"description": "Maximum number of storage IO requests made by the managed instance."
},
{
"name": "azure_io_requests_minimum",
"unit": "Count",
"type": "Gauge",
"description": "Minimum number of storage IO requests made by the managed instance."
},
{
"name": "azure_reserved_storage_mb_average",
"unit": "Count",
"type": "Gauge",
"description": "Average storage space reserved for the managed instance, in megabytes."
},
{
"name": "azure_reserved_storage_mb_maximum",
"unit": "Count",
"type": "Gauge",
"description": "Maximum storage space reserved for the managed instance, in megabytes."
},
{
"name": "azure_reserved_storage_mb_minimum",
"unit": "Count",
"type": "Gauge",
"description": "Minimum storage space reserved for the managed instance, in megabytes."
},
{
"name": "azure_storage_space_used_mb_average",
"unit": "Count",
"type": "Gauge",
"description": "Average storage space used by the managed instance, in megabytes."
},
{
"name": "azure_storage_space_used_mb_maximum",
"unit": "Count",
"type": "Gauge",
"description": "Maximum storage space used by the managed instance, in megabytes."
},
{
"name": "azure_storage_space_used_mb_minimum",
"unit": "Count",
"type": "Gauge",
"description": "Minimum storage space used by the managed instance, in megabytes."
},
{
"name": "azure_virtual_core_count_average",
"unit": "Count",
"type": "Gauge",
"description": "Average number of virtual cores provisioned for the managed instance."
},
{
"name": "azure_virtual_core_count_maximum",
"unit": "Count",
"type": "Gauge",
"description": "Maximum number of virtual cores provisioned for the managed instance."
},
{
"name": "azure_virtual_core_count_minimum",
"unit": "Count",
"type": "Gauge",
"description": "Minimum number of virtual cores provisioned for the managed instance."
}
],
"logs": [
{
"name": "Resource ID",
"path": "resources.azure.resource.id",
"type": "string"
}
]
},
"telemetryCollectionStrategy": {
"azure": {
"resourceProvider": "Microsoft.Sql",
"resourceType": "managedInstances",
"metrics": {},
"logs": {
"categoryGroups": ["allLogs"]
}
}
},
"assets": {
"dashboards": [
{
"id": "overview",
"title": "Azure SQL Database Managed Instance Overview",
"description": "Overview of Azure SQL Database Managed Instance metrics",
"definition": "file://assets/dashboards/overview.json"
}
]
}
}

View File

@@ -1,5 +0,0 @@
### Monitor Azure SQL Database Managed Instance with SigNoz
Collect key Azure SQL Database Managed Instance metrics and view them with an out of the box dashboard.
This integration collects platform metrics for the `Microsoft.Sql/managedInstances` resource type.

View File

@@ -18,6 +18,27 @@ func NewHandler(module tracedetail.Module) tracedetail.Handler {
return &handler{module: module}
}
func (h *handler) GetWaterfall(rw http.ResponseWriter, r *http.Request) {
req := new(spantypes.PostableWaterfall)
if err := binding.JSON.BindBody(r.Body, req); err != nil {
render.Error(rw, err)
return
}
if err := req.Validate(); err != nil {
render.Error(rw, err)
return
}
result, err := h.module.GetWaterfall(r.Context(), mux.Vars(r)["traceID"], req)
if err != nil {
render.Error(rw, err)
return
}
render.Success(rw, http.StatusOK, result)
}
func (h *handler) GetWaterfallV4(rw http.ResponseWriter, r *http.Request) {
req := new(spantypes.PostableWaterfall)
if err := binding.JSON.BindBody(r.Body, req); err != nil {
@@ -30,7 +51,7 @@ func (h *handler) GetWaterfallV4(rw http.ResponseWriter, r *http.Request) {
return
}
result, err := h.module.GetWaterfallV4(r.Context(), mux.Vars(r)["traceID"], req.SelectedSpanID, req.UncollapsedSpans)
result, err := h.module.GetWaterfallV4(r.Context(), mux.Vars(r)["traceID"], req.SelectedSpanID, req.UncollapsedSpans, req.Limit)
if err != nil {
render.Error(rw, err)
return

View File

@@ -39,16 +39,62 @@ func NewModule(traceStore spantypes.TraceStore, providerSettings factory.Provide
return m
}
// GetWaterfallV4 is the OOM-safe V4 waterfall.
// For large traces (NumSpans > effectiveLimit) it uses a two-step fetch:
// minimal fields for all spans to build the tree, then full fields for the
// visible window only. Aggregations are not returned.
func (m *module) GetWaterfallV4(ctx context.Context, traceID string, selectedSpanID string, uncollapsedSpans []string) (*spantypes.GettableWaterfallTrace, error) {
func (m *module) GetWaterfall(ctx context.Context, traceID string, req *spantypes.PostableWaterfall) (*spantypes.GettableWaterfallTrace, error) {
waterfallTrace, err := m.getTraceData(ctx, traceID)
if err != nil {
return nil, err
}
selectedSpans, uncollapsedSpans, selectedAllSpans := waterfallTrace.GetWaterfallSpans(
req.UncollapsedSpans,
req.SelectedSpanID,
min(req.Limit, m.config.Waterfall.MaxLimitToSelectAllSpans),
m.config.Waterfall.SpanPageSize,
m.config.Waterfall.MaxDepthToAutoExpand,
)
aggregationResults := make([]spantypes.SpanAggregationResult, 0, len(req.Aggregations))
for _, a := range req.Aggregations {
aggregationResults = append(aggregationResults, waterfallTrace.GetSpanAggregation(a.Aggregation, a.Field))
}
return spantypes.NewGettableWaterfallTrace(waterfallTrace, selectedSpans, uncollapsedSpans, selectedAllSpans, aggregationResults), nil
}
// getTraceData fetches all spans for a trace and builds the WaterfallTrace.
func (m *module) getTraceData(ctx context.Context, traceID string) (*spantypes.WaterfallTrace, error) {
summary, err := m.store.GetTraceSummary(ctx, traceID)
if err != nil {
return nil, err
}
if summary.NumSpans > uint64(m.config.Waterfall.MaxLimitToSelectAllSpans) {
spanItems, err := m.store.GetTraceSpans(ctx, traceID, summary)
if err != nil {
return nil, err
}
if len(spanItems) == 0 {
return nil, spantypes.ErrTraceNotFound
}
nodes := make([]*spantypes.WaterfallSpan, len(spanItems))
for i := range spanItems {
nodes[i] = spanItems[i].ToWaterfallSpan(traceID)
}
return spantypes.NewWaterfallTraceFromSpans(nodes), nil
}
// GetWaterfallV4 is the OOM-safe V4 waterfall.
// For large traces (NumSpans > effectiveLimit) it uses a two-step fetch:
// minimal fields for all spans to build the tree, then full fields for the
// visible window only. Aggregations are not returned.
func (m *module) GetWaterfallV4(ctx context.Context, traceID string, selectedSpanID string, uncollapsedSpans []string, selectAllLimit uint) (*spantypes.GettableWaterfallTrace, error) {
summary, err := m.store.GetTraceSummary(ctx, traceID)
if err != nil {
return nil, err
}
effectiveLimit := min(selectAllLimit, m.config.Waterfall.MaxLimitToSelectAllSpans)
if summary.NumSpans > uint64(effectiveLimit) {
attrs := metric.WithAttributes(attrResponseType.String(attrResponseTypeWindowed))
m.metrics.waterfallRequestCount.Add(ctx, 1, attrs)
m.metrics.waterfallSpanCount.Add(ctx, int64(summary.NumSpans), attrs)
@@ -74,7 +120,7 @@ func (m *module) getFullWaterfall(ctx context.Context, traceID string, summary *
waterfallTrace := spantypes.NewWaterfallTraceFromSpans(nodes)
selectedSpans := waterfallTrace.GetAllSpans()
return spantypes.NewGettableWaterfallTrace(waterfallTrace, selectedSpans, nil, true), nil
return spantypes.NewGettableWaterfallTrace(waterfallTrace, selectedSpans, nil, true, nil), nil
}
func (m *module) GetTraceAggregations(ctx context.Context, traceID string, req *spantypes.PostableTraceAggregations) (*spantypes.GettableTraceAggregations, error) {
@@ -169,7 +215,7 @@ func (m *module) getWindowedWaterfall(ctx context.Context, traceID, selectedSpan
spantypes.EnrichSelectedSpans(selectedSpans, fullSpans)
return spantypes.NewGettableWaterfallTrace(
waterfallTrace, selectedSpans, uncollapsedSpans, false,
waterfallTrace, selectedSpans, uncollapsedSpans, false, nil,
), nil
}

View File

@@ -260,7 +260,7 @@ func TestGetSelectedSpans_MultipleRoots(t *testing.T) {
trace := getWaterfallTrace([]*spantypes.WaterfallSpan{root1, root2}, spanMap)
spans, _ := trace.GetSelectedSpans([]string{"root1", "root2"}, "root1", 500, 5)
traceRespnose := spantypes.NewGettableWaterfallTrace(trace, spans, nil, false)
traceRespnose := spantypes.NewGettableWaterfallTrace(trace, spans, nil, false, nil)
assert.Equal(t, []string{"root1", "child1", "root2", "child2"}, spanIDs(spans), "root1 subtree must precede root2 subtree")
assert.Equal(t, "svc-a", traceRespnose.RootServiceName, "metadata comes from first root")
@@ -567,7 +567,7 @@ func TestGetAllSpans(t *testing.T) {
)
trace := getWaterfallTrace([]*spantypes.WaterfallSpan{root}, nil)
spans := trace.GetAllSpans()
traceResponse := spantypes.NewGettableWaterfallTrace(trace, spans, nil, true)
traceResponse := spantypes.NewGettableWaterfallTrace(trace, spans, nil, true, nil)
assert.ElementsMatch(t, spanIDs(spans), []string{"root", "childA", "grandchildA", "leafA", "childB", "grandchildB", "leafB"})
assert.Equal(t, "svc", traceResponse.RootServiceName)
assert.Equal(t, "root-op", traceResponse.RootServiceEntryPoint)

View File

@@ -10,6 +10,7 @@ import (
// Handler exposes HTTP handlers for trace detail APIs.
type Handler interface {
GetWaterfall(http.ResponseWriter, *http.Request)
GetWaterfallV4(http.ResponseWriter, *http.Request)
GetTraceAggregations(http.ResponseWriter, *http.Request)
GetFlamegraph(http.ResponseWriter, *http.Request)
@@ -17,7 +18,8 @@ type Handler interface {
// Module defines the business logic for trace detail operations.
type Module interface {
GetWaterfallV4(ctx context.Context, traceID string, selectedSpanID string, uncollapsedSpans []string) (*spantypes.GettableWaterfallTrace, error)
GetWaterfall(ctx context.Context, traceID string, req *spantypes.PostableWaterfall) (*spantypes.GettableWaterfallTrace, error)
GetWaterfallV4(ctx context.Context, traceID string, selectedSpanID string, uncollapsedSpans []string, selectAllLimit uint) (*spantypes.GettableWaterfallTrace, error)
GetTraceAggregations(ctx context.Context, traceID string, req *spantypes.PostableTraceAggregations) (*spantypes.GettableTraceAggregations, error)
GetFlamegraph(ctx context.Context, traceID string, selectedSpanID string, selectFields []telemetrytypes.TelemetryFieldKey) (*spantypes.GettableFlamegraphTrace, error)
}

View File

@@ -898,6 +898,223 @@ func (r *ClickHouseReader) GetSpansForTrace(ctx context.Context, traceID string,
return searchScanResponses, nil
}
func (r *ClickHouseReader) GetWaterfallSpansForTraceWithMetadataCache(ctx context.Context, orgID valuer.UUID, traceID string) (*model.GetWaterfallSpansForTraceWithMetadataCache, error) {
cachedTraceData := new(model.GetWaterfallSpansForTraceWithMetadataCache)
err := r.cacheForTraceDetail.Get(ctx, orgID, strings.Join([]string{"getWaterfallSpansForTraceWithMetadata", traceID}, "-"), cachedTraceData)
if err != nil {
r.logger.Debug("error in retrieving getWaterfallSpansForTraceWithMetadata cache", errorsV2.Attr(err), "traceID", traceID)
return nil, err
}
if time.Since(time.UnixMilli(int64(cachedTraceData.EndTime))) < r.fluxIntervalForTraceDetail {
r.logger.Info("the trace end time falls under the flux interval, skipping getWaterfallSpansForTraceWithMetadata cache", "traceID", traceID)
return nil, errors.Errorf("the trace end time falls under the flux interval, skipping getWaterfallSpansForTraceWithMetadata cache, traceID: %s", traceID)
}
r.logger.Info("cache is successfully hit, applying cache for getWaterfallSpansForTraceWithMetadata", "traceID", traceID)
return cachedTraceData, nil
}
func (r *ClickHouseReader) GetWaterfallSpansForTraceWithMetadata(ctx context.Context, orgID valuer.UUID, traceID string, req *model.GetWaterfallSpansForTraceWithMetadataParams) (*model.GetWaterfallSpansForTraceWithMetadataResponse, error) {
response := new(model.GetWaterfallSpansForTraceWithMetadataResponse)
var startTime, endTime, durationNano, totalErrorSpans, totalSpans uint64
var spanIdToSpanNodeMap = map[string]*model.Span{}
var traceRoots []*model.Span
var serviceNameToTotalDurationMap = map[string]uint64{}
var serviceNameIntervalMap = map[string][]tracedetail.Interval{}
var hasMissingSpans bool
cachedTraceData, err := r.GetWaterfallSpansForTraceWithMetadataCache(ctx, orgID, traceID)
if err == nil {
startTime = cachedTraceData.StartTime
endTime = cachedTraceData.EndTime
durationNano = cachedTraceData.DurationNano
spanIdToSpanNodeMap = cachedTraceData.SpanIdToSpanNodeMap
serviceNameToTotalDurationMap = cachedTraceData.ServiceNameToTotalDurationMap
traceRoots = cachedTraceData.TraceRoots
totalSpans = cachedTraceData.TotalSpans
totalErrorSpans = cachedTraceData.TotalErrorSpans
hasMissingSpans = cachedTraceData.HasMissingSpans
}
if err != nil {
r.logger.Info("cache miss for getWaterfallSpansForTraceWithMetadata", "traceID", traceID)
searchScanResponses, err := r.GetSpansForTrace(ctx, traceID, fmt.Sprintf("SELECT DISTINCT ON (span_id) timestamp, duration_nano, span_id, trace_id, has_error, kind, resource_string_service$$name, name, links as references, attributes_string, attributes_number, attributes_bool, resources_string, events, status_message, status_code_string, kind_string FROM %s.%s WHERE trace_id=$1 and ts_bucket_start>=$2 and ts_bucket_start<=$3 ORDER BY timestamp ASC, name ASC", r.TraceDB, r.traceTableName))
if err != nil {
return nil, err
}
if len(searchScanResponses) == 0 {
return response, nil
}
totalSpans = uint64(len(searchScanResponses))
for _, item := range searchScanResponses {
ref := []model.OtelSpanRef{}
err := json.Unmarshal([]byte(item.References), &ref)
if err != nil {
r.logger.Error("getWaterfallSpansForTraceWithMetadata: error unmarshalling references", errorsV2.Attr(err), "traceID", traceID)
return nil, errorsV2.Newf(errorsV2.TypeInvalidInput, errorsV2.CodeInvalidInput, "getWaterfallSpansForTraceWithMetadata: error unmarshalling references %s", err.Error())
}
// merge attributes_number and attributes_bool to attributes_string
for k, v := range item.Attributes_bool {
item.Attributes_string[k] = fmt.Sprintf("%v", v)
}
for k, v := range item.Attributes_number {
item.Attributes_string[k] = strconv.FormatFloat(v, 'f', -1, 64)
}
for k, v := range item.Resources_string {
item.Attributes_string[k] = v
}
events := make([]model.Event, 0)
for _, event := range item.Events {
var eventMap model.Event
err = json.Unmarshal([]byte(event), &eventMap)
if err != nil {
r.logger.Error("Error unmarshalling events", errorsV2.Attr(err))
return nil, errorsV2.Newf(errorsV2.TypeInternal, errorsV2.CodeInternal, "getWaterfallSpansForTraceWithMetadata: error in unmarshalling events %s", err.Error())
}
events = append(events, eventMap)
}
startTimeUnixNano := uint64(item.TimeUnixNano.UnixNano())
jsonItem := model.Span{
SpanID: item.SpanID,
TraceID: item.TraceID,
ServiceName: item.ServiceName,
Name: item.Name,
Kind: int32(item.Kind),
DurationNano: item.DurationNano,
HasError: item.HasError,
StatusMessage: item.StatusMessage,
StatusCodeString: item.StatusCodeString,
SpanKind: item.SpanKind,
References: ref,
Events: events,
TagMap: item.Attributes_string,
Children: make([]*model.Span, 0),
TimeUnixNano: startTimeUnixNano, // Store nanoseconds temporarily
}
// metadata calculation
if startTime == 0 || startTimeUnixNano < startTime {
startTime = startTimeUnixNano
}
if endTime == 0 || (startTimeUnixNano+jsonItem.DurationNano) > endTime {
endTime = (startTimeUnixNano + jsonItem.DurationNano)
}
if durationNano == 0 || jsonItem.DurationNano > durationNano {
durationNano = jsonItem.DurationNano
}
if jsonItem.HasError {
totalErrorSpans = totalErrorSpans + 1
}
// collect the intervals for service for execution time calculation
serviceNameIntervalMap[jsonItem.ServiceName] =
append(serviceNameIntervalMap[jsonItem.ServiceName], tracedetail.Interval{StartTime: jsonItem.TimeUnixNano, Duration: jsonItem.DurationNano, Service: jsonItem.ServiceName})
// append to the span node map
spanIdToSpanNodeMap[jsonItem.SpanID] = &jsonItem
}
// traverse through the map and append each node to the children array of the parent node
// and add the missing spans
for _, spanNode := range spanIdToSpanNodeMap {
hasParentSpanNode := false
for _, reference := range spanNode.References {
if reference.RefType == "CHILD_OF" && reference.SpanId != "" {
hasParentSpanNode = true
if parentNode, exists := spanIdToSpanNodeMap[reference.SpanId]; exists {
parentNode.Children = append(parentNode.Children, spanNode)
} else {
// insert the missing span
missingSpan := model.Span{
SpanID: reference.SpanId,
TraceID: spanNode.TraceID,
ServiceName: "",
Name: "Missing Span",
TimeUnixNano: spanNode.TimeUnixNano,
Kind: 0,
DurationNano: spanNode.DurationNano,
HasError: false,
StatusMessage: "",
StatusCodeString: "",
SpanKind: "",
Events: make([]model.Event, 0),
Children: make([]*model.Span, 0),
}
missingSpan.Children = append(missingSpan.Children, spanNode)
spanIdToSpanNodeMap[missingSpan.SpanID] = &missingSpan
traceRoots = append(traceRoots, &missingSpan)
hasMissingSpans = true
}
}
}
if !hasParentSpanNode && !tracedetail.ContainsWaterfallSpan(traceRoots, spanNode) {
traceRoots = append(traceRoots, spanNode)
}
}
// sort the trace roots to add missing spans at the right order
sort.Slice(traceRoots, func(i, j int) bool {
if traceRoots[i].TimeUnixNano == traceRoots[j].TimeUnixNano {
return traceRoots[i].Name < traceRoots[j].Name
}
return traceRoots[i].TimeUnixNano < traceRoots[j].TimeUnixNano
})
serviceNameToTotalDurationMap = tracedetail.CalculateServiceTime(serviceNameIntervalMap)
// TODO: set the span data (model.GetWaterfallSpansForTraceWithMetadataCache) in cache here
// removed existing cache usage since it was not getting used due to this bug https://github.com/SigNoz/engineering-pod/issues/4648
// and was causing out of memory issues https://github.com/SigNoz/engineering-pod/issues/4638
}
processingPostCache := time.Now()
// When req.Limit is 0 (not set by the client), selectAllSpans is set to false
// preserving the old paged behaviour for backward compatibility
limit := min(req.Limit, tracedetail.MaxLimitToSelectAllSpans)
selectAllSpans := totalSpans <= uint64(limit)
var (
selectedSpans []*model.Span
uncollapsedSpans []string
rootServiceName, rootServiceEntryPoint string
)
if selectAllSpans {
selectedSpans, rootServiceName, rootServiceEntryPoint = tracedetail.GetAllSpans(traceRoots)
} else {
selectedSpans, uncollapsedSpans, rootServiceName, rootServiceEntryPoint = tracedetail.GetSelectedSpans(req.UncollapsedSpans, req.SelectedSpanID, traceRoots, spanIdToSpanNodeMap, req.IsSelectedSpanIDUnCollapsed)
}
r.logger.Info("getWaterfallSpansForTraceWithMetadata: processing post cache", "duration", time.Since(processingPostCache), "traceID", traceID)
// convert start timestamp to millis because right now frontend is expecting it in millis
for _, span := range selectedSpans {
span.TimeUnixNano = span.TimeUnixNano / 1000000
}
for serviceName, totalDuration := range serviceNameToTotalDurationMap {
serviceNameToTotalDurationMap[serviceName] = totalDuration / 1000000
}
response.Spans = selectedSpans
response.UncollapsedSpans = uncollapsedSpans // ignoring if all spans are returning
response.StartTimestampMillis = startTime / 1000000
response.EndTimestampMillis = endTime / 1000000
response.TotalSpansCount = totalSpans
response.TotalErrorSpansCount = totalErrorSpans
response.RootServiceName = rootServiceName
response.RootServiceEntryPoint = rootServiceEntryPoint
response.ServiceNameToTotalDurationMap = serviceNameToTotalDurationMap
response.HasMissingSpans = hasMissingSpans
response.HasMore = !selectAllSpans
return response, nil
}
func (r *ClickHouseReader) GetFlamegraphSpansForTraceCache(ctx context.Context, orgID valuer.UUID, traceID string) (*model.GetFlamegraphSpansForTraceCache, error) {
cachedTraceData := new(model.GetFlamegraphSpansForTraceCache)

View File

@@ -535,7 +535,7 @@ func (aH *APIHandler) RegisterRoutes(router *mux.Router, am *middleware.AuthZ) {
router.HandleFunc("/api/v2/traces/fields", am.ViewAccess(aH.traceFields)).Methods(http.MethodGet)
router.HandleFunc("/api/v2/traces/fields", am.EditAccess(aH.updateTraceField)).Methods(http.MethodPost)
router.HandleFunc("/api/v2/traces/flamegraph/{traceId}", am.ViewAccess(aH.GetFlamegraphSpansForTrace)).Methods(http.MethodPost)
router.HandleFunc("/api/v2/traces/waterfall/{traceId}", am.ViewAccess(aH.GetWaterfallSpansForTraceWithMetadata)).Methods(http.MethodPost)
router.HandleFunc("/api/v1/version", am.OpenAccess(aH.getVersion)).Methods(http.MethodGet)
router.HandleFunc("/api/v1/features", am.ViewAccess(aH.getFeatureFlags)).Methods(http.MethodGet)
@@ -1446,6 +1446,39 @@ func (aH *APIHandler) SearchTraces(w http.ResponseWriter, r *http.Request) {
}
func (aH *APIHandler) GetWaterfallSpansForTraceWithMetadata(w http.ResponseWriter, r *http.Request) {
claims, err := authtypes.ClaimsFromContext(r.Context())
if err != nil {
render.Error(w, err)
return
}
orgID, err := valuer.NewUUID(claims.OrgID)
if err != nil {
render.Error(w, err)
return
}
traceID := mux.Vars(r)["traceId"]
if traceID == "" {
render.Error(w, errors.NewInvalidInputf(errors.CodeInvalidInput, "traceID is required"))
return
}
req := new(model.GetWaterfallSpansForTraceWithMetadataParams)
err = json.NewDecoder(r.Body).Decode(&req)
if err != nil {
RespondError(w, model.BadRequest(err), nil)
return
}
result, apiErr := aH.reader.GetWaterfallSpansForTraceWithMetadata(r.Context(), orgID, traceID, req)
if apiErr != nil {
render.Error(w, apiErr)
return
}
aH.WriteJSON(w, r, result)
}
func (aH *APIHandler) GetFlamegraphSpansForTrace(w http.ResponseWriter, r *http.Request) {
claims, err := authtypes.ClaimsFromContext(r.Context())
if err != nil {

View File

@@ -0,0 +1,287 @@
package tracedetail
import (
"maps"
"slices"
"sort"
"github.com/SigNoz/signoz/pkg/query-service/model"
)
var (
SPAN_LIMIT_PER_REQUEST_FOR_WATERFALL float64 = 500
maxDepthForSelectedSpanChildren int = 5
MaxLimitToSelectAllSpans uint = 10_000
)
type Interval struct {
StartTime uint64
Duration uint64
Service string
}
func mergeIntervals(intervals []Interval) []Interval {
if len(intervals) == 0 {
return nil
}
var merged []Interval
current := intervals[0]
for i := 1; i < len(intervals); i++ {
next := intervals[i]
if current.StartTime+current.Duration >= next.StartTime {
endTime := max(current.StartTime+current.Duration, next.StartTime+next.Duration)
current.Duration = endTime - current.StartTime
} else {
merged = append(merged, current)
current = next
}
}
// Add the last interval
merged = append(merged, current)
return merged
}
func ContainsWaterfallSpan(slice []*model.Span, item *model.Span) bool {
for _, v := range slice {
if v.SpanID == item.SpanID {
return true
}
}
return false
}
func findIndexForSelectedSpanFromPreOrder(spans []*model.Span, selectedSpanId string) int {
var selectedSpanIndex = -1
for index, span := range spans {
if span.SpanID == selectedSpanId {
selectedSpanIndex = index
break
}
}
return selectedSpanIndex
}
func getPathFromRootToSelectedSpanId(node *model.Span, selectedSpanId string) (bool, []string) {
spansFromRootToNode := []string{}
spansFromRootToNode = append(spansFromRootToNode, node.SpanID)
if node.SpanID == selectedSpanId {
return true, spansFromRootToNode
}
isPresentInSubtreeForTheNode := false
for _, child := range node.Children {
isPresentInThisSubtree, _spansFromRootToNode := getPathFromRootToSelectedSpanId(child, selectedSpanId)
// if the interested node is present in the given subtree then add the span node to uncollapsed node list
if isPresentInThisSubtree {
isPresentInSubtreeForTheNode = true
spansFromRootToNode = append(spansFromRootToNode, _spansFromRootToNode...)
break
}
}
return isPresentInSubtreeForTheNode, spansFromRootToNode
}
// traverseOpts holds the traversal configuration that remains constant
// throughout the recursion. Per-call state (level, isPartOfPreOrder, etc.)
// is passed as direct arguments.
type traverseOpts struct {
uncollapsedSpans map[string]struct{}
selectedSpanID string
isSelectedSpanUncollapsed bool
selectAll bool
}
func traverseTrace(
span *model.Span,
opts traverseOpts,
level uint64,
isPartOfPreOrder bool,
hasSibling bool,
autoExpandDepth int,
) ([]*model.Span, []string) {
preOrderTraversal := []*model.Span{}
autoExpandedSpans := []string{}
// sort the children to maintain the order across requests
sort.Slice(span.Children, func(i, j int) bool {
if span.Children[i].TimeUnixNano == span.Children[j].TimeUnixNano {
return span.Children[i].Name < span.Children[j].Name
}
return span.Children[i].TimeUnixNano < span.Children[j].TimeUnixNano
})
span.SubTreeNodeCount = 0
nodeWithoutChildren := model.Span{
SpanID: span.SpanID,
TraceID: span.TraceID,
ServiceName: span.ServiceName,
TimeUnixNano: span.TimeUnixNano,
Name: span.Name,
Kind: int32(span.Kind),
DurationNano: span.DurationNano,
HasError: span.HasError,
StatusMessage: span.StatusMessage,
StatusCodeString: span.StatusCodeString,
SpanKind: span.SpanKind,
References: span.References,
Events: span.Events,
TagMap: span.TagMap,
Children: make([]*model.Span, 0),
HasChildren: len(span.Children) > 0,
Level: level,
HasSiblings: hasSibling,
SubTreeNodeCount: 0,
}
if isPartOfPreOrder {
preOrderTraversal = append(preOrderTraversal, &nodeWithoutChildren)
}
remainingAutoExpandDepth := 0
if span.SpanID == opts.selectedSpanID && opts.isSelectedSpanUncollapsed {
remainingAutoExpandDepth = maxDepthForSelectedSpanChildren
} else if autoExpandDepth > 0 {
remainingAutoExpandDepth = autoExpandDepth - 1
}
_, isAlreadyUncollapsed := opts.uncollapsedSpans[span.SpanID]
for index, child := range span.Children {
// A child is included in the pre-order output if its parent is uncollapsed
// OR if the child falls within MAX_DEPTH_FOR_SELECTED_SPAN_CHILDREN levels
// below the selected span.
isChildWithinMaxDepth := remainingAutoExpandDepth > 0
childIsPartOfPreOrder := opts.selectAll || (isPartOfPreOrder && (isAlreadyUncollapsed || isChildWithinMaxDepth))
if isPartOfPreOrder && isChildWithinMaxDepth && !isAlreadyUncollapsed {
if !slices.Contains(autoExpandedSpans, span.SpanID) {
autoExpandedSpans = append(autoExpandedSpans, span.SpanID)
}
}
_childTraversal, _autoExpanded := traverseTrace(child, opts, level+1, childIsPartOfPreOrder, index != (len(span.Children)-1), remainingAutoExpandDepth)
preOrderTraversal = append(preOrderTraversal, _childTraversal...)
autoExpandedSpans = append(autoExpandedSpans, _autoExpanded...)
nodeWithoutChildren.SubTreeNodeCount += child.SubTreeNodeCount + 1
span.SubTreeNodeCount += child.SubTreeNodeCount + 1
}
nodeWithoutChildren.SubTreeNodeCount += 1
return preOrderTraversal, autoExpandedSpans
}
func CalculateServiceTime(serviceIntervals map[string][]Interval) map[string]uint64 {
totalTimes := make(map[string]uint64)
for service, serviceIntervals := range serviceIntervals {
sort.Slice(serviceIntervals, func(i, j int) bool {
return serviceIntervals[i].StartTime < serviceIntervals[j].StartTime
})
mergedIntervals := mergeIntervals(serviceIntervals)
totalTime := uint64(0)
for _, interval := range mergedIntervals {
totalTime += interval.Duration
}
totalTimes[service] = totalTime
}
return totalTimes
}
func GetSelectedSpans(uncollapsedSpans []string, selectedSpanID string, traceRoots []*model.Span, spanIdToSpanNodeMap map[string]*model.Span, isSelectedSpanIDUnCollapsed bool) ([]*model.Span, []string, string, string) {
var preOrderTraversal = make([]*model.Span, 0)
var rootServiceName, rootServiceEntryPoint string
// create a map of uncollapsed spans for quick lookup
uncollapsedSpanMap := make(map[string]struct{})
for _, spanID := range uncollapsedSpans {
uncollapsedSpanMap[spanID] = struct{}{}
}
selectedSpanIndex := -1
for _, rootSpanID := range traceRoots {
if rootNode, exists := spanIdToSpanNodeMap[rootSpanID.SpanID]; exists {
present, spansFromRootToNode := getPathFromRootToSelectedSpanId(rootNode, selectedSpanID)
if present {
for _, spanID := range spansFromRootToNode {
if selectedSpanID == spanID && !isSelectedSpanIDUnCollapsed {
continue
}
uncollapsedSpanMap[spanID] = struct{}{}
}
}
opts := traverseOpts{
uncollapsedSpans: uncollapsedSpanMap,
selectedSpanID: selectedSpanID,
isSelectedSpanUncollapsed: isSelectedSpanIDUnCollapsed,
}
_preOrderTraversal, _autoExpanded := traverseTrace(rootNode, opts, 0, true, false, 0)
// Merge auto-expanded spans into updatedUncollapsedSpans for returning in response
for _, spanID := range _autoExpanded {
uncollapsedSpanMap[spanID] = struct{}{}
}
_selectedSpanIndex := findIndexForSelectedSpanFromPreOrder(_preOrderTraversal, selectedSpanID)
if _selectedSpanIndex != -1 {
selectedSpanIndex = _selectedSpanIndex + len(preOrderTraversal)
}
preOrderTraversal = append(preOrderTraversal, _preOrderTraversal...)
if rootServiceName == "" {
rootServiceName = rootNode.ServiceName
}
if rootServiceEntryPoint == "" {
rootServiceEntryPoint = rootNode.Name
}
}
}
// if we couldn't find the selectedSpan in the trace then defaulting the selected index to 0
if selectedSpanIndex == -1 && selectedSpanID != "" {
selectedSpanIndex = 0
}
// get the 0.4*[span limit] before the interested span index
startIndex := selectedSpanIndex - int(SPAN_LIMIT_PER_REQUEST_FOR_WATERFALL*0.4)
// get the 0.6*[span limit] after the intrested span index
endIndex := selectedSpanIndex + int(SPAN_LIMIT_PER_REQUEST_FOR_WATERFALL*0.6)
// adjust the sliding window according to the available left and right spaces.
if startIndex < 0 {
endIndex = endIndex - startIndex
startIndex = 0
}
if endIndex > len(preOrderTraversal) {
startIndex = startIndex - (endIndex - len(preOrderTraversal))
endIndex = len(preOrderTraversal)
}
if startIndex < 0 {
startIndex = 0
}
return preOrderTraversal[startIndex:endIndex], slices.Collect(maps.Keys(uncollapsedSpanMap)), rootServiceName, rootServiceEntryPoint
}
func GetAllSpans(traceRoots []*model.Span) (spans []*model.Span, rootServiceName, rootEntryPoint string) {
if len(traceRoots) > 0 {
rootServiceName = traceRoots[0].ServiceName
rootEntryPoint = traceRoots[0].Name
}
for _, root := range traceRoots {
childSpans, _ := traverseTrace(root, traverseOpts{selectAll: true}, 0, true, false, 0)
spans = append(spans, childSpans...)
}
return
}

View File

@@ -0,0 +1,446 @@
// Package tracedetail tests — waterfall
//
// # Background
//
// The waterfall view renders a trace as a scrollable list of spans in
// pre-order (parent before children, siblings left-to-right). Because a trace
// can have thousands of spans, only a window of ~500 is returned per request.
// The window is centred on the selected span.
//
// # Key concepts
//
// uncollapsedSpans
//
// The set of span IDs the user has manually expanded in the UI.
// Only the direct children of an uncollapsed span are included in the
// output; grandchildren stay hidden until their parent is also uncollapsed.
// When multiple spans are uncollapsed their children are all visible at once.
//
// selectedSpanID
//
// The span currently focused — set when the user clicks a span in the
// waterfall or selects one from the flamegraph. The output window is always
// centred on this span. The path from the trace root down to the selected
// span is automatically uncollapsed so ancestors are visible even if they are
// not in uncollapsedSpans.
//
// isSelectedSpanIDUnCollapsed
//
// Controls whether the selected span's own children are shown:
// true — user expanded the span (click-to-open in waterfall or flamegraph);
// direct children of the selected span are included.
// false — user selected without expanding;
// the span is visible but its children remain hidden.
//
// traceRoots
//
// Root spans of the trace — spans with no parent in the current dataset.
// Normally one, but multiple roots are common when upstream services are
// not instrumented or their spans were not sampled/exported.
package tracedetail
import (
"fmt"
"testing"
"github.com/SigNoz/signoz/pkg/query-service/model"
"github.com/stretchr/testify/assert"
)
// Pre-order traversal is preserved: parent before children, siblings left-to-right.
func TestGetSelectedSpans_PreOrderTraversal(t *testing.T) {
root := mkSpan("root", "svc",
mkSpan("child1", "svc", mkSpan("grandchild", "svc")),
mkSpan("child2", "svc"),
)
spanMap := buildSpanMap(root)
spans, _, _, _ := GetSelectedSpans([]string{"root", "child1"}, "root", []*model.Span{root}, spanMap, false)
assert.Equal(t, []string{"root", "child1", "grandchild", "child2"}, spanIDs(spans))
}
// Multiple roots: both trees are flattened into a single pre-order list with
// root1's subtree before root2's. Service/entry-point come from the first root.
//
// root1 svc-a ← selected
// └─ child1
// root2 svc-b
// └─ child2
//
// Expected output order: root1 → child1 → root2 → child2
func TestGetSelectedSpans_MultipleRoots(t *testing.T) {
root1 := mkSpan("root1", "svc-a", mkSpan("child1", "svc-a"))
root2 := mkSpan("root2", "svc-b", mkSpan("child2", "svc-b"))
spanMap := buildSpanMap(root1, root2)
spans, _, svcName, entryPoint := GetSelectedSpans([]string{"root1", "root2"}, "root1", []*model.Span{root1, root2}, spanMap, false)
assert.Equal(t, []string{"root1", "child1", "root2", "child2"}, spanIDs(spans), "root1 subtree must precede root2 subtree")
assert.Equal(t, "svc-a", svcName, "metadata comes from first root")
assert.Equal(t, "root1-op", entryPoint, "metadata comes from first root")
}
// Multiple spans uncollapsed simultaneously: children of all uncollapsed spans
// are visible at once.
//
// root
// ├─ childA (uncollapsed) → grandchildA ✓
// └─ childB (uncollapsed) → grandchildB ✓
func TestGetSelectedSpans_MultipleUncollapsed(t *testing.T) {
root := mkSpan("root", "svc",
mkSpan("childA", "svc", mkSpan("grandchildA", "svc")),
mkSpan("childB", "svc", mkSpan("grandchildB", "svc")),
)
spanMap := buildSpanMap(root)
spans, _, _, _ := GetSelectedSpans([]string{"root", "childA", "childB"}, "root", []*model.Span{root}, spanMap, false)
assert.Equal(t, []string{"root", "childA", "grandchildA", "childB", "grandchildB"}, spanIDs(spans))
}
// Collapsing a span with other uncollapsed spans
//
// root
// ├─ childA (previously expanded — in uncollapsedSpans)
// │ ├─ grandchild1 ✓
// │ │ └─ greatGrandchild ✗ (grandchild1 not in uncollapsedSpans)
// │ └─ grandchild2 ✓
// └─ childB ← selected (not expanded)
func TestGetSelectedSpans_ManualUncollapse(t *testing.T) {
root := mkSpan("root", "svc",
mkSpan("childA", "svc",
mkSpan("grandchild1", "svc", mkSpan("greatGrandchild", "svc")),
mkSpan("grandchild2", "svc"),
),
mkSpan("childB", "svc"),
)
spanMap := buildSpanMap(root)
// childA was expanded in a previous interaction; childB is now selected without expanding
spans, _, _, _ := GetSelectedSpans([]string{"childA"}, "childB", []*model.Span{root}, spanMap, false)
// path to childB auto-uncollpases root → childA and childB appear; childA is in
// uncollapsedSpans so its children appear; greatGrandchild stays hidden.
assert.Equal(t, []string{"root", "childA", "grandchild1", "grandchild2", "childB"}, spanIDs(spans))
}
// A collapsed span hides all children.
func TestGetSelectedSpans_CollapsedSpan(t *testing.T) {
root := mkSpan("root", "svc",
mkSpan("child1", "svc"),
mkSpan("child2", "svc"),
)
spanMap := buildSpanMap(root)
spans, _, _, _ := GetSelectedSpans([]string{}, "root", []*model.Span{root}, spanMap, false)
assert.Equal(t, []string{"root"}, spanIDs(spans))
}
// Selecting a span auto-uncollpases the path from root to that span so it is visible.
//
// root → parent → selected
func TestGetSelectedSpans_PathToSelectedIsUncollapsed(t *testing.T) {
root := mkSpan("root", "svc",
mkSpan("parent", "svc",
mkSpan("selected", "svc"),
),
)
spanMap := buildSpanMap(root)
// no manually uncollapsed spans — path should still be opened
spans, _, _, _ := GetSelectedSpans([]string{}, "selected", []*model.Span{root}, spanMap, false)
assert.Equal(t, []string{"root", "parent", "selected"}, spanIDs(spans))
}
// The path-to-selected spans are returned in updatedUncollapsedSpans.
func TestGetSelectedSpans_PathReturnedInUncollapsed(t *testing.T) {
root := mkSpan("root", "svc",
mkSpan("parent", "svc",
mkSpan("selected", "svc"),
),
)
spanMap := buildSpanMap(root)
spans, uncollapsed, _, _ := GetSelectedSpans([]string{}, "selected", []*model.Span{root}, spanMap, false)
assert.ElementsMatch(t, []string{"root", "parent"}, uncollapsed)
assert.Equal(t, []string{"root", "parent", "selected"}, spanIDs(spans))
}
// Siblings of ancestors are rendered as collapsed nodes but their subtrees
// must NOT be expanded.
//
// root
// ├─ unrelated → unrelated-child (✗)
// └─ parent → selected
func TestGetSelectedSpans_SiblingsNotExpanded(t *testing.T) {
root := mkSpan("root", "svc",
mkSpan("unrelated", "svc", mkSpan("unrelated-child", "svc")),
mkSpan("parent", "svc",
mkSpan("selected", "svc"),
),
)
spanMap := buildSpanMap(root)
spans, uncollapsed, _, _ := GetSelectedSpans([]string{}, "selected", []*model.Span{root}, spanMap, false)
// children of root sort alphabetically: parent < unrelated; unrelated-child stays hidden
assert.Equal(t, []string{"root", "parent", "selected", "unrelated"}, spanIDs(spans))
// only the path nodes are tracked as uncollapsed — unrelated is not
assert.ElementsMatch(t, []string{"root", "parent"}, uncollapsed)
}
// An unknown selectedSpanID must not panic; returns a window from index 0.
func TestGetSelectedSpans_UnknownSelectedSpan(t *testing.T) {
root := mkSpan("root", "svc", mkSpan("child", "svc"))
spanMap := buildSpanMap(root)
spans, _, _, _ := GetSelectedSpans([]string{}, "nonexistent", []*model.Span{root}, spanMap, false)
assert.Equal(t, []string{"root"}, spanIDs(spans))
}
// Test to check if Level, HasChildren, HasSiblings, and SubTreeNodeCount are populated correctly.
//
// root level=0, hasChildren=true, hasSiblings=false, subTree=4
// child1 level=1, hasChildren=true, hasSiblings=true, subTree=2
// grandchild level=2, hasChildren=false, hasSiblings=false, subTree=1
// child2 level=1, hasChildren=false, hasSiblings=false, subTree=1
func TestGetSelectedSpans_SpanMetadata(t *testing.T) {
root := mkSpan("root", "svc",
mkSpan("child1", "svc", mkSpan("grandchild", "svc")),
mkSpan("child2", "svc"),
)
spanMap := buildSpanMap(root)
spans, _, _, _ := GetSelectedSpans([]string{"root", "child1"}, "root", []*model.Span{root}, spanMap, false)
byID := map[string]*model.Span{}
for _, s := range spans {
byID[s.SpanID] = s
}
assert.Equal(t, uint64(0), byID["root"].Level)
assert.Equal(t, uint64(1), byID["child1"].Level)
assert.Equal(t, uint64(1), byID["child2"].Level)
assert.Equal(t, uint64(2), byID["grandchild"].Level)
assert.True(t, byID["root"].HasChildren)
assert.True(t, byID["child1"].HasChildren)
assert.False(t, byID["child2"].HasChildren)
assert.False(t, byID["grandchild"].HasChildren)
assert.False(t, byID["root"].HasSiblings, "root has no siblings")
assert.True(t, byID["child1"].HasSiblings, "child1 has sibling child2")
assert.False(t, byID["child2"].HasSiblings, "child2 is the last child")
assert.False(t, byID["grandchild"].HasSiblings, "grandchild has no siblings")
assert.Equal(t, uint64(4), byID["root"].SubTreeNodeCount)
assert.Equal(t, uint64(2), byID["child1"].SubTreeNodeCount)
assert.Equal(t, uint64(1), byID["grandchild"].SubTreeNodeCount)
assert.Equal(t, uint64(1), byID["child2"].SubTreeNodeCount)
}
// If the selected span is already in uncollapsedSpans AND isSelectedSpanIDUnCollapsed=true,
func TestGetSelectedSpans_DuplicateInUncollapsed(t *testing.T) {
root := mkSpan("root", "svc",
mkSpan("selected", "svc", mkSpan("child", "svc")),
)
spanMap := buildSpanMap(root)
_, uncollapsed, _, _ := GetSelectedSpans(
[]string{"selected"}, // already present
"selected",
[]*model.Span{root}, spanMap,
true,
)
count := 0
for _, id := range uncollapsed {
if id == "selected" {
count++
}
}
assert.Equal(t, 1, count, "should appear once")
}
// makeChain builds a linear trace: span0 → span1 → … → span(n-1).
// All span IDs are "span0", "span1", … so the caller can reference them by index.
func makeChain(n int) (*model.Span, map[string]*model.Span, []string) {
spans := make([]*model.Span, n)
for i := n - 1; i >= 0; i-- {
if i == n-1 {
spans[i] = mkSpan(fmt.Sprintf("span%d", i), "svc")
} else {
spans[i] = mkSpan(fmt.Sprintf("span%d", i), "svc", spans[i+1])
}
}
uncollapsed := make([]string, n)
for i := range spans {
uncollapsed[i] = fmt.Sprintf("span%d", i)
}
return spans[0], buildSpanMap(spans[0]), uncollapsed
}
// The selected span is centred: 200 spans before it, 300 after (0.4 / 0.6 split).
func TestGetSelectedSpans_WindowCentredOnSelected(t *testing.T) {
root, spanMap, uncollapsed := makeChain(600)
spans, _, _, _ := GetSelectedSpans(uncollapsed, "span300", []*model.Span{root}, spanMap, false)
assert.Equal(t, 500, len(spans), "window should be 500 spans")
// window is [100, 600): span300 lands at position 200 (300 - 100)
assert.Equal(t, "span100", spans[0].SpanID, "window starts 200 before selected")
assert.Equal(t, "span300", spans[200].SpanID, "selected span at position 200 in window")
assert.Equal(t, "span599", spans[499].SpanID, "window ends 300 after selected")
}
// When the selected span is near the start, the window shifts right so no
// negative index is used — the result is still 500 spans.
func TestGetSelectedSpans_WindowShiftsAtStart(t *testing.T) {
root, spanMap, uncollapsed := makeChain(600)
spans, _, _, _ := GetSelectedSpans(uncollapsed, "span10", []*model.Span{root}, spanMap, false)
assert.Equal(t, 500, len(spans))
assert.Equal(t, "span0", spans[0].SpanID, "window clamped to start of trace")
assert.Equal(t, "span10", spans[10].SpanID, "selected span still in window")
}
// Auto-expanded span IDs from ALL branches are returned in
// updatedUncollapsedSpans. Only internal nodes (spans with children) are
// tracked — leaf spans are never added.
//
// root (selected)
// ├─ childA (internal ✓)
// │ └─ grandchildA (internal ✓)
// │ └─ leafA (leaf ✗)
// └─ childB (internal ✓)
// └─ grandchildB (internal ✓)
// └─ leafB (leaf ✗)
func TestGetSelectedSpans_AutoExpandedSpansReturnedInUncollapsed(t *testing.T) {
root := mkSpan("root", "svc",
mkSpan("childA", "svc",
mkSpan("grandchildA", "svc",
mkSpan("leafA", "svc"),
),
),
mkSpan("childB", "svc",
mkSpan("grandchildB", "svc",
mkSpan("leafB", "svc"),
),
),
)
spanMap := buildSpanMap(root)
_, uncollapsed, _, _ := GetSelectedSpans([]string{}, "root", []*model.Span{root}, spanMap, true)
// all internal nodes across both branches must be tracked
assert.Contains(t, uncollapsed, "root")
assert.Contains(t, uncollapsed, "childA", "internal node depth 1, branch A")
assert.Contains(t, uncollapsed, "childB", "internal node depth 1, branch B")
assert.Contains(t, uncollapsed, "grandchildA", "internal node depth 2, branch A")
assert.Contains(t, uncollapsed, "grandchildB", "internal node depth 2, branch B")
// leaves have no children to show — never added to uncollapsedSpans
assert.NotContains(t, uncollapsed, "leafA", "leaf spans are never added to uncollapsedSpans")
assert.NotContains(t, uncollapsed, "leafB", "leaf spans are never added to uncollapsedSpans")
}
// ─────────────────────────────────────────────────────────────────────────────
// maxDepthForSelectedSpanChildren boundary tests
// ─────────────────────────────────────────────────────────────────────────────
// Depth is measured from the selected span, not the trace root.
// Ancestors appear via the path-to-root logic, not the depth limit.
// Each depth level has two children to confirm the limit is enforced on all
// branches, not just the first.
//
// root
// └─ A ancestor ✓ (path-to-root)
// └─ selected
// ├─ d1a depth 1 ✓
// │ ├─ d2a depth 2 ✓
// │ │ ├─ d3a depth 3 ✓
// │ │ │ ├─ d4a depth 4 ✓
// │ │ │ │ ├─ d5a depth 5 ✓
// │ │ │ │ │ └─ d6a depth 6 ✗
// │ │ │ │ └─ d5b depth 5 ✓
// │ │ │ └─ d4b depth 4 ✓
// │ │ └─ d3b depth 3 ✓
// │ └─ d2b depth 2 ✓
// └─ d1b depth 1 ✓
func TestGetSelectedSpans_DepthCountedFromSelectedSpan(t *testing.T) {
selected := mkSpan("selected", "svc",
mkSpan("d1a", "svc",
mkSpan("d2a", "svc",
mkSpan("d3a", "svc",
mkSpan("d4a", "svc",
mkSpan("d5a", "svc",
mkSpan("d6a", "svc"), // depth 6 — excluded
),
mkSpan("d5b", "svc"), // depth 5 — included
),
mkSpan("d4b", "svc"), // depth 4 — included
),
mkSpan("d3b", "svc"), // depth 3 — included
),
mkSpan("d2b", "svc"), // depth 2 — included
),
mkSpan("d1b", "svc"), // depth 1 — included
)
root := mkSpan("root", "svc", mkSpan("A", "svc", selected))
spanMap := buildSpanMap(root)
spans, _, _, _ := GetSelectedSpans([]string{}, "selected", []*model.Span{root}, spanMap, true)
ids := spanIDs(spans)
assert.Contains(t, ids, "root", "ancestor shown via path-to-root")
assert.Contains(t, ids, "A", "ancestor shown via path-to-root")
for _, id := range []string{"d1a", "d1b", "d2a", "d2b", "d3a", "d3b", "d4a", "d4b", "d5a", "d5b"} {
assert.Contains(t, ids, id, "depth ≤ 5 — must be included")
}
assert.NotContains(t, ids, "d6a", "depth 6 > limit — excluded")
}
func TestGetAllSpans(t *testing.T) {
root := mkSpan("root", "svc",
mkSpan("childA", "svc",
mkSpan("grandchildA", "svc",
mkSpan("leafA", "svc2"),
),
),
mkSpan("childB", "svc3",
mkSpan("grandchildB", "svc",
mkSpan("leafB", "svc2"),
),
),
)
spans, rootServiceName, rootEntryPoint := GetAllSpans([]*model.Span{root})
assert.ElementsMatch(t, spanIDs(spans), []string{"root", "childA", "grandchildA", "leafA", "childB", "grandchildB", "leafB"})
assert.Equal(t, rootServiceName, "svc")
assert.Equal(t, rootEntryPoint, "root-op")
}
func mkSpan(id, service string, children ...*model.Span) *model.Span {
return &model.Span{
SpanID: id,
ServiceName: service,
Name: id + "-op",
Children: children,
}
}
// spanIDs returns SpanIDs in order.
func spanIDs(spans []*model.Span) []string {
ids := make([]string, len(spans))
for i, s := range spans {
ids[i] = s.SpanID
}
return ids
}
// buildSpanMap indexes every span in a set of trees by SpanID.
func buildSpanMap(roots ...*model.Span) map[string]*model.Span {
m := map[string]*model.Span{}
var walk func(*model.Span)
walk = func(s *model.Span) {
m[s.SpanID] = s
for _, c := range s.Children {
walk(c)
}
}
for _, r := range roots {
walk(r)
}
return m
}

View File

@@ -43,6 +43,7 @@ type Reader interface {
// Search Interfaces
SearchTraces(ctx context.Context, params *model.SearchTracesParams) (*[]model.SearchSpansResult, error)
GetWaterfallSpansForTraceWithMetadata(ctx context.Context, orgID valuer.UUID, traceID string, req *model.GetWaterfallSpansForTraceWithMetadataParams) (*model.GetWaterfallSpansForTraceWithMetadataResponse, error)
GetFlamegraphSpansForTrace(ctx context.Context, orgID valuer.UUID, traceID string, req *model.GetFlamegraphSpansForTraceParams) (*model.GetFlamegraphSpansForTraceResponse, error)
// Setter Interfaces

View File

@@ -2,10 +2,57 @@ package model
import (
"encoding/json"
"maps"
"github.com/SigNoz/signoz/pkg/types/cachetypes"
)
type GetWaterfallSpansForTraceWithMetadataCache struct {
StartTime uint64 `json:"startTime"`
EndTime uint64 `json:"endTime"`
DurationNano uint64 `json:"durationNano"`
TotalSpans uint64 `json:"totalSpans"`
TotalErrorSpans uint64 `json:"totalErrorSpans"`
ServiceNameToTotalDurationMap map[string]uint64 `json:"serviceNameToTotalDurationMap"`
SpanIdToSpanNodeMap map[string]*Span `json:"spanIdToSpanNodeMap"`
TraceRoots []*Span `json:"traceRoots"`
HasMissingSpans bool `json:"hasMissingSpans"`
}
func (c *GetWaterfallSpansForTraceWithMetadataCache) Clone() cachetypes.Cacheable {
copyOfServiceNameToTotalDurationMap := make(map[string]uint64)
maps.Copy(copyOfServiceNameToTotalDurationMap, c.ServiceNameToTotalDurationMap)
copyOfSpanIdToSpanNodeMap := make(map[string]*Span)
maps.Copy(copyOfSpanIdToSpanNodeMap, c.SpanIdToSpanNodeMap)
copyOfTraceRoots := make([]*Span, len(c.TraceRoots))
copy(copyOfTraceRoots, c.TraceRoots)
return &GetWaterfallSpansForTraceWithMetadataCache{
StartTime: c.StartTime,
EndTime: c.EndTime,
DurationNano: c.DurationNano,
TotalSpans: c.TotalSpans,
TotalErrorSpans: c.TotalErrorSpans,
ServiceNameToTotalDurationMap: copyOfServiceNameToTotalDurationMap,
SpanIdToSpanNodeMap: copyOfSpanIdToSpanNodeMap,
TraceRoots: copyOfTraceRoots,
HasMissingSpans: c.HasMissingSpans,
}
}
func (c *GetWaterfallSpansForTraceWithMetadataCache) Cost() int64 {
const perSpanBytes = 256
return int64(c.TotalSpans) * perSpanBytes
}
func (c *GetWaterfallSpansForTraceWithMetadataCache) MarshalBinary() (data []byte, err error) {
return json.Marshal(c)
}
func (c *GetWaterfallSpansForTraceWithMetadataCache) UnmarshalBinary(data []byte) error {
return json.Unmarshal(data, c)
}
type GetFlamegraphSpansForTraceCache struct {
StartTime uint64 `json:"startTime"`
EndTime uint64 `json:"endTime"`

View File

@@ -331,6 +331,13 @@ type SearchTracesParams struct {
MaxSpansInTrace int `json:"maxSpansInTrace"`
}
type GetWaterfallSpansForTraceWithMetadataParams struct {
SelectedSpanID string `json:"selectedSpanId"`
IsSelectedSpanIDUnCollapsed bool `json:"isSelectedSpanIDUnCollapsed"`
UncollapsedSpans []string `json:"uncollapsedSpans"`
Limit uint `json:"limit"`
}
type GetFlamegraphSpansForTraceParams struct {
SelectedSpanID string `json:"selectedSpanId"`
Limit uint `json:"limit"`

View File

@@ -332,6 +332,22 @@ func (s *FlamegraphSpan) SetRequestedFields(item SpanItemV2, fields []telemetryt
}
}
type GetWaterfallSpansForTraceWithMetadataResponse struct {
StartTimestampMillis uint64 `json:"startTimestampMillis"`
EndTimestampMillis uint64 `json:"endTimestampMillis"`
DurationNano uint64 `json:"durationNano"`
RootServiceName string `json:"rootServiceName"`
RootServiceEntryPoint string `json:"rootServiceEntryPoint"`
TotalSpansCount uint64 `json:"totalSpansCount"`
TotalErrorSpansCount uint64 `json:"totalErrorSpansCount"`
ServiceNameToTotalDurationMap map[string]uint64 `json:"serviceNameToTotalDurationMap"`
Spans []*Span `json:"spans"`
HasMissingSpans bool `json:"hasMissingSpans"`
// this is needed for frontend and query service sync
UncollapsedSpans []string `json:"uncollapsedSpans"`
HasMore bool `json:"hasMore"`
}
type GetFlamegraphSpansForTraceResponse struct {
StartTimestampMillis uint64 `json:"startTimestampMillis"`
EndTimestampMillis uint64 `json:"endTimestampMillis"`

View File

@@ -25,14 +25,12 @@ var (
AWSServiceSQS = ServiceID{valuer.NewString("sqs")}
// Azure services.
AzureServiceStorageAccountsBlob = ServiceID{valuer.NewString("storageaccountsblob")}
AzureServiceCDNProfile = ServiceID{valuer.NewString("cdnprofile")}
AzureServiceVirtualMachine = ServiceID{valuer.NewString("virtualmachine")}
AzureServiceAppService = ServiceID{valuer.NewString("appservice")}
AzureServiceContainerApp = ServiceID{valuer.NewString("containerapp")}
AzureServiceAKS = ServiceID{valuer.NewString("aks")}
AzureServiceSQLDatabase = ServiceID{valuer.NewString("sqldatabase")}
AzureServiceSQLDatabaseManagedInstance = ServiceID{valuer.NewString("sqldatabasemi")}
AzureServiceStorageAccountsBlob = ServiceID{valuer.NewString("storageaccountsblob")}
AzureServiceCDNProfile = ServiceID{valuer.NewString("cdnprofile")}
AzureServiceVirtualMachine = ServiceID{valuer.NewString("virtualmachine")}
AzureServiceAppService = ServiceID{valuer.NewString("appservice")}
AzureServiceContainerApp = ServiceID{valuer.NewString("containerapp")}
AzureServiceAKS = ServiceID{valuer.NewString("aks")}
)
func (ServiceID) Enum() []any {
@@ -56,8 +54,6 @@ func (ServiceID) Enum() []any {
AzureServiceAppService,
AzureServiceContainerApp,
AzureServiceAKS,
AzureServiceSQLDatabase,
AzureServiceSQLDatabaseManagedInstance,
}
}
@@ -85,8 +81,6 @@ var SupportedServices = map[CloudProviderType][]ServiceID{
AzureServiceAppService,
AzureServiceContainerApp,
AzureServiceAKS,
AzureServiceSQLDatabase,
AzureServiceSQLDatabaseManagedInstance,
},
}

View File

@@ -0,0 +1,251 @@
package spantypes
import (
"testing"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
"github.com/stretchr/testify/assert"
)
// mkASpan builds a WaterfallSpan with timing and field data for analytics tests.
func mkASpan(id string, resource map[string]string, attributes map[string]any, startNs, durationNs uint64) *WaterfallSpan {
return &WaterfallSpan{
SpanID: id,
Resource: resource,
Attributes: attributes,
TimeUnix: startNs,
DurationNano: durationNs,
Children: make([]*WaterfallSpan, 0),
}
}
func buildTraceFromSpans(spans ...*WaterfallSpan) *WaterfallTrace {
spanMap := make(map[string]*WaterfallSpan, len(spans))
var startTime, endTime uint64
initialized := false
for _, s := range spans {
spanMap[s.SpanID] = s
if !initialized || s.TimeUnix < startTime {
startTime = s.TimeUnix
initialized = true
}
if end := s.TimeUnix + s.DurationNano; end > endTime {
endTime = end
}
}
return NewWaterfallTrace(startTime, endTime, uint64(len(spanMap)), 0, spanMap, nil, false)
}
var (
fieldServiceName = telemetrytypes.TelemetryFieldKey{
Name: "service.name",
FieldContext: telemetrytypes.FieldContextResource,
}
fieldHTTPMethod = telemetrytypes.TelemetryFieldKey{
Name: "http.method",
FieldContext: telemetrytypes.FieldContextAttribute,
}
fieldCached = telemetrytypes.TelemetryFieldKey{
Name: "db.cached",
FieldContext: telemetrytypes.FieldContextAttribute,
}
)
func TestGetSpanAggregation_SpanCount(t *testing.T) {
tests := []struct {
name string
trace *WaterfallTrace
field telemetrytypes.TelemetryFieldKey
want map[string]uint64
}{
{
name: "counts by resource field",
trace: buildTraceFromSpans(
mkASpan("s1", map[string]string{"service.name": "frontend"}, nil, 0, 10),
mkASpan("s2", map[string]string{"service.name": "frontend"}, nil, 10, 5),
mkASpan("s3", map[string]string{"service.name": "backend"}, nil, 20, 8),
),
field: fieldServiceName,
want: map[string]uint64{"frontend": 2, "backend": 1},
},
{
name: "counts by string attribute field",
trace: buildTraceFromSpans(
mkASpan("s1", nil, map[string]any{"http.method": "GET"}, 0, 10),
mkASpan("s2", nil, map[string]any{"http.method": "POST"}, 10, 5),
mkASpan("s3", nil, map[string]any{"http.method": "GET"}, 20, 8),
),
field: fieldHTTPMethod,
want: map[string]uint64{"GET": 2, "POST": 1},
},
{
name: "counts by boolean attribute field",
trace: buildTraceFromSpans(
mkASpan("s1", nil, map[string]any{"db.cached": true}, 0, 10),
mkASpan("s2", nil, map[string]any{"db.cached": false}, 10, 5),
mkASpan("s3", nil, map[string]any{"db.cached": true}, 20, 8),
),
field: fieldCached,
want: map[string]uint64{"true": 2, "false": 1},
},
{
name: "spans missing the field are excluded",
trace: buildTraceFromSpans(
mkASpan("s1", map[string]string{"service.name": "frontend"}, nil, 0, 10),
mkASpan("s2", map[string]string{}, nil, 10, 5), // no service.name
mkASpan("s3", map[string]string{"service.name": "backend"}, nil, 20, 8),
),
field: fieldServiceName,
want: map[string]uint64{"frontend": 1, "backend": 1},
},
{
// empty string is a valid field value — counted under the "" key, unlike a missing field
name: "span with empty service.name is counted under empty string key",
trace: buildTraceFromSpans(
mkASpan("s1", map[string]string{"service.name": "frontend"}, nil, 0, 10),
mkASpan("s2", map[string]string{"service.name": ""}, nil, 10, 5),
mkASpan("s3", map[string]string{"service.name": "backend"}, nil, 20, 8),
),
field: fieldServiceName,
want: map[string]uint64{"frontend": 1, "backend": 1, "": 1},
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
result := tc.trace.GetSpanAggregation(SpanAggregationSpanCount, tc.field)
assert.Equal(t, tc.field, result.Field)
assert.Equal(t, SpanAggregationSpanCount, result.Aggregation)
assert.Equal(t, tc.want, result.Value)
})
}
}
func TestGetSpanAggregation_Duration(t *testing.T) {
tests := []struct {
name string
trace *WaterfallTrace
field telemetrytypes.TelemetryFieldKey
want map[string]uint64
}{
{
name: "non-overlapping spans — merged equals sum",
trace: buildTraceFromSpans(
mkASpan("s1", map[string]string{"service.name": "frontend"}, nil, 0, 100),
mkASpan("s2", map[string]string{"service.name": "frontend"}, nil, 100, 50),
mkASpan("s3", map[string]string{"service.name": "backend"}, nil, 0, 80),
),
field: fieldServiceName,
want: map[string]uint64{"frontend": 150, "backend": 80},
},
{
name: "non-overlapping attribute groups — merged equals sum",
trace: buildTraceFromSpans(
mkASpan("s1", nil, map[string]any{"http.method": "GET"}, 0, 30),
mkASpan("s2", nil, map[string]any{"http.method": "GET"}, 50, 20),
mkASpan("s3", nil, map[string]any{"http.method": "POST"}, 0, 70),
),
field: fieldHTTPMethod,
want: map[string]uint64{"GET": 50, "POST": 70},
},
{
name: "overlapping spans — non-overlapping interval merge",
trace: buildTraceFromSpans(
mkASpan("s1", map[string]string{"service.name": "svc"}, nil, 0, 10),
mkASpan("s2", map[string]string{"service.name": "svc"}, nil, 5, 10),
),
field: fieldServiceName,
want: map[string]uint64{"svc": 15}, // [0,10] [5,15] = [0,15]
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
result := tc.trace.GetSpanAggregation(SpanAggregationDuration, tc.field)
assert.Equal(t, tc.field, result.Field)
assert.Equal(t, SpanAggregationDuration, result.Aggregation)
assert.Equal(t, tc.want, result.Value)
})
}
}
func TestGetSpanAggregation_ExecutionTimePercentage(t *testing.T) {
tests := []struct {
name string
trace *WaterfallTrace
field telemetrytypes.TelemetryFieldKey
want map[string]uint64
}{
{
// trace [0,30]: svc occupies [0,10]+[20,30]=20 → 20*100/30 = 66%
name: "non-overlapping spans",
trace: buildTraceFromSpans(
mkASpan("s1", map[string]string{"service.name": "svc"}, nil, 0, 10),
mkASpan("s2", map[string]string{"service.name": "svc"}, nil, 20, 10),
),
field: fieldServiceName,
want: map[string]uint64{"svc": 66},
},
{
// trace [0,15]: svc [0,15]=15 → 100%
name: "partially overlapping spans",
trace: buildTraceFromSpans(
mkASpan("s1", map[string]string{"service.name": "svc"}, nil, 0, 10),
mkASpan("s2", map[string]string{"service.name": "svc"}, nil, 5, 10),
),
field: fieldServiceName,
want: map[string]uint64{"svc": 100},
},
{
// trace [0,20]: outer absorbs inner → 100%
name: "fully contained span",
trace: buildTraceFromSpans(
mkASpan("outer", map[string]string{"service.name": "svc"}, nil, 0, 20),
mkASpan("inner", map[string]string{"service.name": "svc"}, nil, 5, 5),
),
field: fieldServiceName,
want: map[string]uint64{"svc": 100},
},
{
// trace [0,30]: svc [0,15]+[20,30]=25 → 25*100/30 = 83%
name: "three spans with two merges",
trace: buildTraceFromSpans(
mkASpan("s1", map[string]string{"service.name": "svc"}, nil, 0, 10),
mkASpan("s2", map[string]string{"service.name": "svc"}, nil, 5, 10),
mkASpan("s3", map[string]string{"service.name": "svc"}, nil, 20, 10),
),
field: fieldServiceName,
want: map[string]uint64{"svc": 83},
},
{
// trace [0,28]: frontend [0,15]=15 → 53%, backend [0,5]+[20,28]=13 → 46%
name: "independent groups are computed separately",
trace: buildTraceFromSpans(
mkASpan("a1", map[string]string{"service.name": "frontend"}, nil, 0, 10),
mkASpan("a2", map[string]string{"service.name": "frontend"}, nil, 5, 10),
mkASpan("b1", map[string]string{"service.name": "backend"}, nil, 0, 5),
mkASpan("b2", map[string]string{"service.name": "backend"}, nil, 20, 8),
),
field: fieldServiceName,
want: map[string]uint64{"frontend": 53, "backend": 46},
},
{
// trace [100,150]: svc [100,150]=50 → 100%
name: "single span",
trace: buildTraceFromSpans(
mkASpan("s1", map[string]string{"service.name": "svc"}, nil, 100, 50),
),
field: fieldServiceName,
want: map[string]uint64{"svc": 100},
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
result := tc.trace.GetSpanAggregation(SpanAggregationExecutionTimePercentage, tc.field)
assert.Equal(t, tc.field, result.Field)
assert.Equal(t, SpanAggregationExecutionTimePercentage, result.Aggregation)
assert.Equal(t, tc.want, result.Value)
})
}
}

View File

@@ -21,13 +21,28 @@ const (
// ErrTraceNotFound is returned when a trace ID has no matching spans in ClickHouse.
var ErrTraceNotFound = errors.NewNotFoundf(errors.CodeNotFound, "trace not found")
// PostableWaterfall is the request body for the waterfall API.
// PostableWaterfall is the request body for the v3 waterfall API.
type PostableWaterfall struct {
SelectedSpanID string `json:"selectedSpanId"`
UncollapsedSpans []string `json:"uncollapsedSpans"`
SelectedSpanID string `json:"selectedSpanId"`
UncollapsedSpans []string `json:"uncollapsedSpans"`
Limit uint `json:"limit"`
Aggregations []SpanAggregation `json:"aggregations"`
}
func (p *PostableWaterfall) Validate() error {
if len(p.Aggregations) > maxAggregationItems {
return ErrTooManyAggregationItems
}
for _, a := range p.Aggregations {
if !a.Aggregation.isValid() {
return errors.NewInvalidInputf(errors.CodeInvalidInput, "unknown aggregation type: %q", a.Aggregation)
}
fc := a.Field.FieldContext
if fc != telemetrytypes.FieldContextResource && fc != telemetrytypes.FieldContextAttribute {
return errors.NewInvalidInputf(errors.CodeInvalidInput, "aggregation field context must be %q or %q, got %q",
telemetrytypes.FieldContextResource, telemetrytypes.FieldContextAttribute, fc)
}
}
return nil
}

View File

@@ -8,6 +8,7 @@ import (
"time"
"github.com/SigNoz/signoz/pkg/types/cachetypes"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
)
type TraceSummary struct {
@@ -28,18 +29,19 @@ type WaterfallTrace struct {
HasMissingSpans bool `json:"hasMissingSpans"`
}
// GettableWaterfallTrace is the response for the waterfall API.
// GettableWaterfallTrace is the response for the v3 waterfall API.
type GettableWaterfallTrace struct {
StartTimestampMillis uint64 `json:"startTimestampMillis"`
EndTimestampMillis uint64 `json:"endTimestampMillis"`
RootServiceName string `json:"rootServiceName"`
RootServiceEntryPoint string `json:"rootServiceEntryPoint"`
TotalSpansCount uint64 `json:"totalSpansCount"`
TotalErrorSpansCount uint64 `json:"totalErrorSpansCount"`
Spans []*WaterfallSpan `json:"spans"`
HasMissingSpans bool `json:"hasMissingSpans"`
UncollapsedSpans []string `json:"uncollapsedSpans"`
HasMore bool `json:"hasMore"`
StartTimestampMillis uint64 `json:"startTimestampMillis"`
EndTimestampMillis uint64 `json:"endTimestampMillis"`
RootServiceName string `json:"rootServiceName"`
RootServiceEntryPoint string `json:"rootServiceEntryPoint"`
TotalSpansCount uint64 `json:"totalSpansCount"`
TotalErrorSpansCount uint64 `json:"totalErrorSpansCount"`
Spans []*WaterfallSpan `json:"spans"`
HasMissingSpans bool `json:"hasMissingSpans"`
UncollapsedSpans []string `json:"uncollapsedSpans"`
HasMore bool `json:"hasMore"`
Aggregations []SpanAggregationResult `json:"aggregations"`
}
// NewWaterfallTrace constructs a WaterfallTrace from processed span data.
@@ -120,6 +122,23 @@ func NewWaterfallTraceFromSpans(nodes []*WaterfallSpan) *WaterfallTrace {
)
}
func (wt *WaterfallTrace) GetWaterfallSpans(uncollapsedSpanIDs []string, selectedSpanID string, limit uint, spanPageSize float64, maxDepthToAutoExpand int) ([]*WaterfallSpan, []string, bool) {
// Span selection decision: all spans or windowed
selectAllSpans := wt.TotalSpans <= uint64(limit)
var (
selectedSpans []*WaterfallSpan
uncollapsedSpans []string
)
if selectAllSpans {
selectedSpans = wt.GetAllSpans()
} else {
selectedSpans, uncollapsedSpans = wt.GetSelectedSpans(uncollapsedSpanIDs, selectedSpanID, spanPageSize, maxDepthToAutoExpand)
}
return selectedSpans, uncollapsedSpans, selectAllSpans
}
// GetAllSpans returns all spans with pre order traversal.
func (wt *WaterfallTrace) GetAllSpans() []*WaterfallSpan {
var preOrderedSpans []*WaterfallSpan
@@ -218,6 +237,7 @@ func NewGettableWaterfallTrace(
selectedSpans []*WaterfallSpan,
uncollapsedSpans []string,
selectAllSpans bool,
aggregations []SpanAggregationResult,
) *GettableWaterfallTrace {
var rootServiceName, rootServiceEntryPoint string
if len(traceData.TraceRoots) > 0 {
@@ -230,6 +250,15 @@ func NewGettableWaterfallTrace(
span.TimeUnix = span.TimeUnix / 1_000_000
}
// duration values are in nanoseconds; convert in-place to milliseconds.
for i := range aggregations {
if aggregations[i].Aggregation == SpanAggregationDuration {
for k, v := range aggregations[i].Value {
aggregations[i].Value[k] = v / 1_000_000
}
}
}
return &GettableWaterfallTrace{
Spans: selectedSpans,
UncollapsedSpans: uncollapsedSpans,
@@ -241,6 +270,7 @@ func NewGettableWaterfallTrace(
RootServiceEntryPoint: rootServiceEntryPoint,
HasMissingSpans: traceData.HasMissingSpans,
HasMore: !selectAllSpans,
Aggregations: aggregations,
}
}
@@ -262,3 +292,78 @@ func windowAroundIndex(selectedIndex, total int, spanLimitPerRequest float64) (s
start = max(start, 0)
return
}
// mergeSpanIntervals computes non-overlapping execution time for a set of spans.
func mergeSpanIntervals(spans []*WaterfallSpan) uint64 {
if len(spans) == 0 {
return 0
}
sort.Slice(spans, func(i, j int) bool {
return spans[i].TimeUnix < spans[j].TimeUnix
})
currentStart := spans[0].TimeUnix
currentEnd := currentStart + spans[0].DurationNano
total := uint64(0)
for _, span := range spans[1:] {
startNano := span.TimeUnix
endNano := startNano + span.DurationNano
if currentEnd >= startNano {
if endNano > currentEnd {
currentEnd = endNano
}
} else {
total += currentEnd - currentStart
currentStart = startNano
currentEnd = endNano
}
}
return total + (currentEnd - currentStart)
}
// GetSpanAggregation computes one aggregation result over all spans in the trace.
// Duration values are returned in nanoseconds; callers convert to milliseconds as needed.
func (wt *WaterfallTrace) GetSpanAggregation(aggregation SpanAggregationType, field telemetrytypes.TelemetryFieldKey) SpanAggregationResult {
result := SpanAggregationResult{
Field: field,
Aggregation: aggregation,
Value: make(map[string]uint64),
}
switch aggregation {
case SpanAggregationSpanCount:
for _, span := range wt.SpanIDToSpanNodeMap {
if key, ok := span.FieldValue(field); ok {
result.Value[key]++
}
}
case SpanAggregationDuration:
spansByField := make(map[string][]*WaterfallSpan)
for _, span := range wt.SpanIDToSpanNodeMap {
if key, ok := span.FieldValue(field); ok {
spansByField[key] = append(spansByField[key], span)
}
}
for key, spans := range spansByField {
result.Value[key] = mergeSpanIntervals(spans)
}
case SpanAggregationExecutionTimePercentage:
traceDuration := wt.EndTime - wt.StartTime
spansByField := make(map[string][]*WaterfallSpan)
for _, span := range wt.SpanIDToSpanNodeMap {
if key, ok := span.FieldValue(field); ok {
spansByField[key] = append(spansByField[key], span)
}
}
if traceDuration > 0 {
for key, spans := range spansByField {
result.Value[key] = mergeSpanIntervals(spans) * 100 / traceDuration
}
}
}
return result
}

View File

@@ -1,288 +0,0 @@
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n1", "k8s.node.uid": "web-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n1", "k8s.node.uid": "web-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n1", "k8s.node.uid": "web-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n1", "k8s.node.uid": "web-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n1", "k8s.node.uid": "web-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n1", "k8s.node.uid": "web-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n1", "k8s.node.uid": "web-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n1", "k8s.node.uid": "web-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n1", "k8s.node.uid": "web-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n1", "k8s.node.uid": "web-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n1", "k8s.node.uid": "web-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n1", "k8s.node.uid": "web-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n1", "k8s.node.uid": "web-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n1", "k8s.node.uid": "web-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n1", "k8s.node.uid": "web-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-gcp-prod-acc-c1-n1-p-uid", "k8s.pod.name": "web-gcp-prod-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-gcp-prod-acc-c1-n1", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-gcp-prod-acc-c1-n1-p-uid", "k8s.pod.name": "web-gcp-prod-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-gcp-prod-acc-c1-n1", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-gcp-prod-acc-c1-n1-p-uid", "k8s.pod.name": "web-gcp-prod-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-gcp-prod-acc-c1-n1", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n2", "k8s.node.uid": "web-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n2", "k8s.node.uid": "web-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n2", "k8s.node.uid": "web-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n2", "k8s.node.uid": "web-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n2", "k8s.node.uid": "web-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n2", "k8s.node.uid": "web-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n2", "k8s.node.uid": "web-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n2", "k8s.node.uid": "web-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n2", "k8s.node.uid": "web-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n2", "k8s.node.uid": "web-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n2", "k8s.node.uid": "web-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n2", "k8s.node.uid": "web-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n2", "k8s.node.uid": "web-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n2", "k8s.node.uid": "web-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-gcp-prod-acc-c1-n2", "k8s.node.uid": "web-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-gcp-prod-acc-c1-n2-p-uid", "k8s.pod.name": "web-gcp-prod-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-gcp-prod-acc-c1-n2", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-gcp-prod-acc-c1-n2-p-uid", "k8s.pod.name": "web-gcp-prod-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-gcp-prod-acc-c1-n2", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-gcp-prod-acc-c1-n2-p-uid", "k8s.pod.name": "web-gcp-prod-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-gcp-prod-acc-c1-n2", "k8s.cluster.name": "web-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n1", "k8s.node.uid": "web-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n1", "k8s.node.uid": "web-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n1", "k8s.node.uid": "web-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n1", "k8s.node.uid": "web-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n1", "k8s.node.uid": "web-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n1", "k8s.node.uid": "web-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n1", "k8s.node.uid": "web-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n1", "k8s.node.uid": "web-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n1", "k8s.node.uid": "web-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n1", "k8s.node.uid": "web-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n1", "k8s.node.uid": "web-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n1", "k8s.node.uid": "web-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n1", "k8s.node.uid": "web-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n1", "k8s.node.uid": "web-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n1", "k8s.node.uid": "web-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-gcp-dev-acc-c1-n1-p-uid", "k8s.pod.name": "web-gcp-dev-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-gcp-dev-acc-c1-n1", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-gcp-dev-acc-c1-n1-p-uid", "k8s.pod.name": "web-gcp-dev-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-gcp-dev-acc-c1-n1", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-gcp-dev-acc-c1-n1-p-uid", "k8s.pod.name": "web-gcp-dev-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-gcp-dev-acc-c1-n1", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n2", "k8s.node.uid": "web-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n2", "k8s.node.uid": "web-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n2", "k8s.node.uid": "web-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n2", "k8s.node.uid": "web-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n2", "k8s.node.uid": "web-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n2", "k8s.node.uid": "web-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n2", "k8s.node.uid": "web-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n2", "k8s.node.uid": "web-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n2", "k8s.node.uid": "web-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n2", "k8s.node.uid": "web-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n2", "k8s.node.uid": "web-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n2", "k8s.node.uid": "web-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n2", "k8s.node.uid": "web-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n2", "k8s.node.uid": "web-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-gcp-dev-acc-c1-n2", "k8s.node.uid": "web-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-gcp-dev-acc-c1-n2-p-uid", "k8s.pod.name": "web-gcp-dev-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-gcp-dev-acc-c1-n2", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-gcp-dev-acc-c1-n2-p-uid", "k8s.pod.name": "web-gcp-dev-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-gcp-dev-acc-c1-n2", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-gcp-dev-acc-c1-n2-p-uid", "k8s.pod.name": "web-gcp-dev-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-gcp-dev-acc-c1-n2", "k8s.cluster.name": "web-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n1", "k8s.node.uid": "api-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n1", "k8s.node.uid": "api-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n1", "k8s.node.uid": "api-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n1", "k8s.node.uid": "api-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n1", "k8s.node.uid": "api-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n1", "k8s.node.uid": "api-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n1", "k8s.node.uid": "api-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n1", "k8s.node.uid": "api-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n1", "k8s.node.uid": "api-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n1", "k8s.node.uid": "api-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n1", "k8s.node.uid": "api-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n1", "k8s.node.uid": "api-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n1", "k8s.node.uid": "api-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n1", "k8s.node.uid": "api-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n1", "k8s.node.uid": "api-gcp-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-gcp-prod-acc-c1-n1-p-uid", "k8s.pod.name": "api-gcp-prod-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-gcp-prod-acc-c1-n1", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-gcp-prod-acc-c1-n1-p-uid", "k8s.pod.name": "api-gcp-prod-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-gcp-prod-acc-c1-n1", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-gcp-prod-acc-c1-n1-p-uid", "k8s.pod.name": "api-gcp-prod-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-gcp-prod-acc-c1-n1", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n2", "k8s.node.uid": "api-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n2", "k8s.node.uid": "api-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n2", "k8s.node.uid": "api-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n2", "k8s.node.uid": "api-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n2", "k8s.node.uid": "api-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n2", "k8s.node.uid": "api-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n2", "k8s.node.uid": "api-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n2", "k8s.node.uid": "api-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n2", "k8s.node.uid": "api-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n2", "k8s.node.uid": "api-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n2", "k8s.node.uid": "api-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n2", "k8s.node.uid": "api-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n2", "k8s.node.uid": "api-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n2", "k8s.node.uid": "api-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-gcp-prod-acc-c1-n2", "k8s.node.uid": "api-gcp-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-gcp-prod-acc-c1-n2-p-uid", "k8s.pod.name": "api-gcp-prod-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-gcp-prod-acc-c1-n2", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-gcp-prod-acc-c1-n2-p-uid", "k8s.pod.name": "api-gcp-prod-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-gcp-prod-acc-c1-n2", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-gcp-prod-acc-c1-n2-p-uid", "k8s.pod.name": "api-gcp-prod-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-gcp-prod-acc-c1-n2", "k8s.cluster.name": "api-gcp-prod", "cloud.provider": "gcp", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n1", "k8s.node.uid": "api-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n1", "k8s.node.uid": "api-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n1", "k8s.node.uid": "api-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n1", "k8s.node.uid": "api-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n1", "k8s.node.uid": "api-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n1", "k8s.node.uid": "api-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n1", "k8s.node.uid": "api-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n1", "k8s.node.uid": "api-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n1", "k8s.node.uid": "api-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n1", "k8s.node.uid": "api-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n1", "k8s.node.uid": "api-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n1", "k8s.node.uid": "api-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n1", "k8s.node.uid": "api-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n1", "k8s.node.uid": "api-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n1", "k8s.node.uid": "api-gcp-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-gcp-dev-acc-c1-n1-p-uid", "k8s.pod.name": "api-gcp-dev-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-gcp-dev-acc-c1-n1", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-gcp-dev-acc-c1-n1-p-uid", "k8s.pod.name": "api-gcp-dev-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-gcp-dev-acc-c1-n1", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-gcp-dev-acc-c1-n1-p-uid", "k8s.pod.name": "api-gcp-dev-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-gcp-dev-acc-c1-n1", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n2", "k8s.node.uid": "api-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n2", "k8s.node.uid": "api-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n2", "k8s.node.uid": "api-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n2", "k8s.node.uid": "api-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n2", "k8s.node.uid": "api-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n2", "k8s.node.uid": "api-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n2", "k8s.node.uid": "api-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n2", "k8s.node.uid": "api-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n2", "k8s.node.uid": "api-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n2", "k8s.node.uid": "api-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n2", "k8s.node.uid": "api-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n2", "k8s.node.uid": "api-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n2", "k8s.node.uid": "api-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n2", "k8s.node.uid": "api-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-gcp-dev-acc-c1-n2", "k8s.node.uid": "api-gcp-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-gcp-dev-acc-c1-n2-p-uid", "k8s.pod.name": "api-gcp-dev-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-gcp-dev-acc-c1-n2", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-gcp-dev-acc-c1-n2-p-uid", "k8s.pod.name": "api-gcp-dev-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-gcp-dev-acc-c1-n2", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-gcp-dev-acc-c1-n2-p-uid", "k8s.pod.name": "api-gcp-dev-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-gcp-dev-acc-c1-n2", "k8s.cluster.name": "api-gcp-dev", "cloud.provider": "gcp", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n1", "k8s.node.uid": "web-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n1", "k8s.node.uid": "web-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n1", "k8s.node.uid": "web-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n1", "k8s.node.uid": "web-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n1", "k8s.node.uid": "web-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n1", "k8s.node.uid": "web-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n1", "k8s.node.uid": "web-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n1", "k8s.node.uid": "web-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n1", "k8s.node.uid": "web-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n1", "k8s.node.uid": "web-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n1", "k8s.node.uid": "web-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n1", "k8s.node.uid": "web-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n1", "k8s.node.uid": "web-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n1", "k8s.node.uid": "web-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n1", "k8s.node.uid": "web-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-aws-prod-acc-c1-n1-p-uid", "k8s.pod.name": "web-aws-prod-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-aws-prod-acc-c1-n1", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-aws-prod-acc-c1-n1-p-uid", "k8s.pod.name": "web-aws-prod-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-aws-prod-acc-c1-n1", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-aws-prod-acc-c1-n1-p-uid", "k8s.pod.name": "web-aws-prod-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-aws-prod-acc-c1-n1", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n2", "k8s.node.uid": "web-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n2", "k8s.node.uid": "web-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n2", "k8s.node.uid": "web-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n2", "k8s.node.uid": "web-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n2", "k8s.node.uid": "web-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n2", "k8s.node.uid": "web-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n2", "k8s.node.uid": "web-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n2", "k8s.node.uid": "web-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n2", "k8s.node.uid": "web-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n2", "k8s.node.uid": "web-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n2", "k8s.node.uid": "web-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n2", "k8s.node.uid": "web-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n2", "k8s.node.uid": "web-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n2", "k8s.node.uid": "web-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-aws-prod-acc-c1-n2", "k8s.node.uid": "web-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-aws-prod-acc-c1-n2-p-uid", "k8s.pod.name": "web-aws-prod-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-aws-prod-acc-c1-n2", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-aws-prod-acc-c1-n2-p-uid", "k8s.pod.name": "web-aws-prod-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-aws-prod-acc-c1-n2", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-aws-prod-acc-c1-n2-p-uid", "k8s.pod.name": "web-aws-prod-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-aws-prod-acc-c1-n2", "k8s.cluster.name": "web-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n1", "k8s.node.uid": "web-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n1", "k8s.node.uid": "web-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n1", "k8s.node.uid": "web-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n1", "k8s.node.uid": "web-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n1", "k8s.node.uid": "web-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n1", "k8s.node.uid": "web-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n1", "k8s.node.uid": "web-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n1", "k8s.node.uid": "web-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n1", "k8s.node.uid": "web-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n1", "k8s.node.uid": "web-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n1", "k8s.node.uid": "web-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n1", "k8s.node.uid": "web-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n1", "k8s.node.uid": "web-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n1", "k8s.node.uid": "web-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n1", "k8s.node.uid": "web-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-aws-dev-acc-c1-n1-p-uid", "k8s.pod.name": "web-aws-dev-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-aws-dev-acc-c1-n1", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-aws-dev-acc-c1-n1-p-uid", "k8s.pod.name": "web-aws-dev-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-aws-dev-acc-c1-n1", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-aws-dev-acc-c1-n1-p-uid", "k8s.pod.name": "web-aws-dev-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-aws-dev-acc-c1-n1", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n2", "k8s.node.uid": "web-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n2", "k8s.node.uid": "web-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n2", "k8s.node.uid": "web-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n2", "k8s.node.uid": "web-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n2", "k8s.node.uid": "web-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n2", "k8s.node.uid": "web-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n2", "k8s.node.uid": "web-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n2", "k8s.node.uid": "web-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n2", "k8s.node.uid": "web-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n2", "k8s.node.uid": "web-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n2", "k8s.node.uid": "web-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n2", "k8s.node.uid": "web-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n2", "k8s.node.uid": "web-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n2", "k8s.node.uid": "web-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "web-aws-dev-acc-c1-n2", "k8s.node.uid": "web-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-aws-dev-acc-c1-n2-p-uid", "k8s.pod.name": "web-aws-dev-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-aws-dev-acc-c1-n2", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-aws-dev-acc-c1-n2-p-uid", "k8s.pod.name": "web-aws-dev-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-aws-dev-acc-c1-n2", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "web-aws-dev-acc-c1-n2-p-uid", "k8s.pod.name": "web-aws-dev-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "web-aws-dev-acc-c1-n2", "k8s.cluster.name": "web-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n1", "k8s.node.uid": "api-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n1", "k8s.node.uid": "api-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n1", "k8s.node.uid": "api-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n1", "k8s.node.uid": "api-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n1", "k8s.node.uid": "api-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n1", "k8s.node.uid": "api-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n1", "k8s.node.uid": "api-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n1", "k8s.node.uid": "api-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n1", "k8s.node.uid": "api-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n1", "k8s.node.uid": "api-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n1", "k8s.node.uid": "api-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n1", "k8s.node.uid": "api-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n1", "k8s.node.uid": "api-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n1", "k8s.node.uid": "api-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n1", "k8s.node.uid": "api-aws-prod-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-aws-prod-acc-c1-n1-p-uid", "k8s.pod.name": "api-aws-prod-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-aws-prod-acc-c1-n1", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-aws-prod-acc-c1-n1-p-uid", "k8s.pod.name": "api-aws-prod-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-aws-prod-acc-c1-n1", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-aws-prod-acc-c1-n1-p-uid", "k8s.pod.name": "api-aws-prod-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-aws-prod-acc-c1-n1", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n2", "k8s.node.uid": "api-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n2", "k8s.node.uid": "api-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n2", "k8s.node.uid": "api-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n2", "k8s.node.uid": "api-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n2", "k8s.node.uid": "api-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n2", "k8s.node.uid": "api-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n2", "k8s.node.uid": "api-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n2", "k8s.node.uid": "api-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n2", "k8s.node.uid": "api-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n2", "k8s.node.uid": "api-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n2", "k8s.node.uid": "api-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n2", "k8s.node.uid": "api-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n2", "k8s.node.uid": "api-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n2", "k8s.node.uid": "api-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-aws-prod-acc-c1-n2", "k8s.node.uid": "api-aws-prod-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-aws-prod-acc-c1-n2-p-uid", "k8s.pod.name": "api-aws-prod-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-aws-prod-acc-c1-n2", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-aws-prod-acc-c1-n2-p-uid", "k8s.pod.name": "api-aws-prod-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-aws-prod-acc-c1-n2", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-aws-prod-acc-c1-n2-p-uid", "k8s.pod.name": "api-aws-prod-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-aws-prod-acc-c1-n2", "k8s.cluster.name": "api-aws-prod", "cloud.provider": "aws", "env": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n1", "k8s.node.uid": "api-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n1", "k8s.node.uid": "api-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n1", "k8s.node.uid": "api-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n1", "k8s.node.uid": "api-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n1", "k8s.node.uid": "api-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n1", "k8s.node.uid": "api-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n1", "k8s.node.uid": "api-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n1", "k8s.node.uid": "api-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n1", "k8s.node.uid": "api-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n1", "k8s.node.uid": "api-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n1", "k8s.node.uid": "api-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n1", "k8s.node.uid": "api-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n1", "k8s.node.uid": "api-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n1", "k8s.node.uid": "api-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n1", "k8s.node.uid": "api-aws-dev-acc-c1-n1-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-aws-dev-acc-c1-n1-p-uid", "k8s.pod.name": "api-aws-dev-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-aws-dev-acc-c1-n1", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-aws-dev-acc-c1-n1-p-uid", "k8s.pod.name": "api-aws-dev-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-aws-dev-acc-c1-n1", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-aws-dev-acc-c1-n1-p-uid", "k8s.pod.name": "api-aws-dev-acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-aws-dev-acc-c1-n1", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n2", "k8s.node.uid": "api-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n2", "k8s.node.uid": "api-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n2", "k8s.node.uid": "api-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n2", "k8s.node.uid": "api-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n2", "k8s.node.uid": "api-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n2", "k8s.node.uid": "api-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n2", "k8s.node.uid": "api-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n2", "k8s.node.uid": "api-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n2", "k8s.node.uid": "api-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n2", "k8s.node.uid": "api-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n2", "k8s.node.uid": "api-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n2", "k8s.node.uid": "api-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n2", "k8s.node.uid": "api-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n2", "k8s.node.uid": "api-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "api-aws-dev-acc-c1-n2", "k8s.node.uid": "api-aws-dev-acc-c1-n2-uid", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-aws-dev-acc-c1-n2-p-uid", "k8s.pod.name": "api-aws-dev-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-aws-dev-acc-c1-n2", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-aws-dev-acc-c1-n2-p-uid", "k8s.pod.name": "api-aws-dev-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-aws-dev-acc-c1-n2", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "api-aws-dev-acc-c1-n2-p-uid", "k8s.pod.name": "api-aws-dev-acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "api-aws-dev-acc-c1-n2", "k8s.cluster.name": "api-aws-dev", "cloud.provider": "aws", "env": "dev"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}

View File

@@ -1,72 +0,0 @@
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"node-gb-gcp-1","k8s.node.uid":"node-gb-gcp-1-uid","k8s.cluster.name":"gb-gcp-1","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:00:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"node-gb-gcp-1","k8s.node.uid":"node-gb-gcp-1-uid","k8s.cluster.name":"gb-gcp-1","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:02:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"node-gb-gcp-1","k8s.node.uid":"node-gb-gcp-1-uid","k8s.cluster.name":"gb-gcp-1","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:04:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"node-gb-gcp-1","k8s.node.uid":"node-gb-gcp-1-uid","k8s.cluster.name":"gb-gcp-1","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:00:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"node-gb-gcp-1","k8s.node.uid":"node-gb-gcp-1-uid","k8s.cluster.name":"gb-gcp-1","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:02:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"node-gb-gcp-1","k8s.node.uid":"node-gb-gcp-1-uid","k8s.cluster.name":"gb-gcp-1","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:04:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"node-gb-gcp-1","k8s.node.uid":"node-gb-gcp-1-uid","k8s.cluster.name":"gb-gcp-1","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:00:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"node-gb-gcp-1","k8s.node.uid":"node-gb-gcp-1-uid","k8s.cluster.name":"gb-gcp-1","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:02:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"node-gb-gcp-1","k8s.node.uid":"node-gb-gcp-1-uid","k8s.cluster.name":"gb-gcp-1","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:04:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"node-gb-gcp-1","k8s.node.uid":"node-gb-gcp-1-uid","k8s.cluster.name":"gb-gcp-1","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:00:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"node-gb-gcp-1","k8s.node.uid":"node-gb-gcp-1-uid","k8s.cluster.name":"gb-gcp-1","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:02:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"node-gb-gcp-1","k8s.node.uid":"node-gb-gcp-1-uid","k8s.cluster.name":"gb-gcp-1","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:04:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"node-gb-gcp-1","k8s.node.uid":"node-gb-gcp-1-uid","k8s.cluster.name":"gb-gcp-1","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:00:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"node-gb-gcp-1","k8s.node.uid":"node-gb-gcp-1-uid","k8s.cluster.name":"gb-gcp-1","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:02:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"node-gb-gcp-1","k8s.node.uid":"node-gb-gcp-1-uid","k8s.cluster.name":"gb-gcp-1","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:04:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"pod-gb-gcp-1-uid","k8s.pod.name":"pod-gb-gcp-1","k8s.namespace.name":"ns-x","k8s.node.name":"node-gb-gcp-1","k8s.cluster.name":"gb-gcp-1","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:00:00+00:00","value":2,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"pod-gb-gcp-1-uid","k8s.pod.name":"pod-gb-gcp-1","k8s.namespace.name":"ns-x","k8s.node.name":"node-gb-gcp-1","k8s.cluster.name":"gb-gcp-1","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:02:00+00:00","value":2,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"pod-gb-gcp-1-uid","k8s.pod.name":"pod-gb-gcp-1","k8s.namespace.name":"ns-x","k8s.node.name":"node-gb-gcp-1","k8s.cluster.name":"gb-gcp-1","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:04:00+00:00","value":2,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"node-gb-gcp-2","k8s.node.uid":"node-gb-gcp-2-uid","k8s.cluster.name":"gb-gcp-2","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:00:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"node-gb-gcp-2","k8s.node.uid":"node-gb-gcp-2-uid","k8s.cluster.name":"gb-gcp-2","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:02:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"node-gb-gcp-2","k8s.node.uid":"node-gb-gcp-2-uid","k8s.cluster.name":"gb-gcp-2","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:04:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"node-gb-gcp-2","k8s.node.uid":"node-gb-gcp-2-uid","k8s.cluster.name":"gb-gcp-2","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:00:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"node-gb-gcp-2","k8s.node.uid":"node-gb-gcp-2-uid","k8s.cluster.name":"gb-gcp-2","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:02:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"node-gb-gcp-2","k8s.node.uid":"node-gb-gcp-2-uid","k8s.cluster.name":"gb-gcp-2","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:04:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"node-gb-gcp-2","k8s.node.uid":"node-gb-gcp-2-uid","k8s.cluster.name":"gb-gcp-2","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:00:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"node-gb-gcp-2","k8s.node.uid":"node-gb-gcp-2-uid","k8s.cluster.name":"gb-gcp-2","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:02:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"node-gb-gcp-2","k8s.node.uid":"node-gb-gcp-2-uid","k8s.cluster.name":"gb-gcp-2","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:04:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"node-gb-gcp-2","k8s.node.uid":"node-gb-gcp-2-uid","k8s.cluster.name":"gb-gcp-2","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:00:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"node-gb-gcp-2","k8s.node.uid":"node-gb-gcp-2-uid","k8s.cluster.name":"gb-gcp-2","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:02:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"node-gb-gcp-2","k8s.node.uid":"node-gb-gcp-2-uid","k8s.cluster.name":"gb-gcp-2","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:04:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"node-gb-gcp-2","k8s.node.uid":"node-gb-gcp-2-uid","k8s.cluster.name":"gb-gcp-2","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:00:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"node-gb-gcp-2","k8s.node.uid":"node-gb-gcp-2-uid","k8s.cluster.name":"gb-gcp-2","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:02:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"node-gb-gcp-2","k8s.node.uid":"node-gb-gcp-2-uid","k8s.cluster.name":"gb-gcp-2","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:04:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"pod-gb-gcp-2-uid","k8s.pod.name":"pod-gb-gcp-2","k8s.namespace.name":"ns-x","k8s.node.name":"node-gb-gcp-2","k8s.cluster.name":"gb-gcp-2","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:00:00+00:00","value":2,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"pod-gb-gcp-2-uid","k8s.pod.name":"pod-gb-gcp-2","k8s.namespace.name":"ns-x","k8s.node.name":"node-gb-gcp-2","k8s.cluster.name":"gb-gcp-2","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:02:00+00:00","value":2,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"pod-gb-gcp-2-uid","k8s.pod.name":"pod-gb-gcp-2","k8s.namespace.name":"ns-x","k8s.node.name":"node-gb-gcp-2","k8s.cluster.name":"gb-gcp-2","cloud.provider":"gcp"},"timestamp":"2025-01-10T10:04:00+00:00","value":2,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"node-gb-aws-1","k8s.node.uid":"node-gb-aws-1-uid","k8s.cluster.name":"gb-aws-1","cloud.provider":"aws"},"timestamp":"2025-01-10T10:00:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"node-gb-aws-1","k8s.node.uid":"node-gb-aws-1-uid","k8s.cluster.name":"gb-aws-1","cloud.provider":"aws"},"timestamp":"2025-01-10T10:02:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"node-gb-aws-1","k8s.node.uid":"node-gb-aws-1-uid","k8s.cluster.name":"gb-aws-1","cloud.provider":"aws"},"timestamp":"2025-01-10T10:04:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"node-gb-aws-1","k8s.node.uid":"node-gb-aws-1-uid","k8s.cluster.name":"gb-aws-1","cloud.provider":"aws"},"timestamp":"2025-01-10T10:00:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"node-gb-aws-1","k8s.node.uid":"node-gb-aws-1-uid","k8s.cluster.name":"gb-aws-1","cloud.provider":"aws"},"timestamp":"2025-01-10T10:02:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"node-gb-aws-1","k8s.node.uid":"node-gb-aws-1-uid","k8s.cluster.name":"gb-aws-1","cloud.provider":"aws"},"timestamp":"2025-01-10T10:04:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"node-gb-aws-1","k8s.node.uid":"node-gb-aws-1-uid","k8s.cluster.name":"gb-aws-1","cloud.provider":"aws"},"timestamp":"2025-01-10T10:00:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"node-gb-aws-1","k8s.node.uid":"node-gb-aws-1-uid","k8s.cluster.name":"gb-aws-1","cloud.provider":"aws"},"timestamp":"2025-01-10T10:02:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"node-gb-aws-1","k8s.node.uid":"node-gb-aws-1-uid","k8s.cluster.name":"gb-aws-1","cloud.provider":"aws"},"timestamp":"2025-01-10T10:04:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"node-gb-aws-1","k8s.node.uid":"node-gb-aws-1-uid","k8s.cluster.name":"gb-aws-1","cloud.provider":"aws"},"timestamp":"2025-01-10T10:00:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"node-gb-aws-1","k8s.node.uid":"node-gb-aws-1-uid","k8s.cluster.name":"gb-aws-1","cloud.provider":"aws"},"timestamp":"2025-01-10T10:02:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"node-gb-aws-1","k8s.node.uid":"node-gb-aws-1-uid","k8s.cluster.name":"gb-aws-1","cloud.provider":"aws"},"timestamp":"2025-01-10T10:04:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"node-gb-aws-1","k8s.node.uid":"node-gb-aws-1-uid","k8s.cluster.name":"gb-aws-1","cloud.provider":"aws"},"timestamp":"2025-01-10T10:00:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"node-gb-aws-1","k8s.node.uid":"node-gb-aws-1-uid","k8s.cluster.name":"gb-aws-1","cloud.provider":"aws"},"timestamp":"2025-01-10T10:02:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"node-gb-aws-1","k8s.node.uid":"node-gb-aws-1-uid","k8s.cluster.name":"gb-aws-1","cloud.provider":"aws"},"timestamp":"2025-01-10T10:04:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"pod-gb-aws-1-uid","k8s.pod.name":"pod-gb-aws-1","k8s.namespace.name":"ns-x","k8s.node.name":"node-gb-aws-1","k8s.cluster.name":"gb-aws-1","cloud.provider":"aws"},"timestamp":"2025-01-10T10:00:00+00:00","value":2,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"pod-gb-aws-1-uid","k8s.pod.name":"pod-gb-aws-1","k8s.namespace.name":"ns-x","k8s.node.name":"node-gb-aws-1","k8s.cluster.name":"gb-aws-1","cloud.provider":"aws"},"timestamp":"2025-01-10T10:02:00+00:00","value":2,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"pod-gb-aws-1-uid","k8s.pod.name":"pod-gb-aws-1","k8s.namespace.name":"ns-x","k8s.node.name":"node-gb-aws-1","k8s.cluster.name":"gb-aws-1","cloud.provider":"aws"},"timestamp":"2025-01-10T10:04:00+00:00","value":2,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"node-gb-aws-2","k8s.node.uid":"node-gb-aws-2-uid","k8s.cluster.name":"gb-aws-2","cloud.provider":"aws"},"timestamp":"2025-01-10T10:00:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"node-gb-aws-2","k8s.node.uid":"node-gb-aws-2-uid","k8s.cluster.name":"gb-aws-2","cloud.provider":"aws"},"timestamp":"2025-01-10T10:02:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"node-gb-aws-2","k8s.node.uid":"node-gb-aws-2-uid","k8s.cluster.name":"gb-aws-2","cloud.provider":"aws"},"timestamp":"2025-01-10T10:04:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"node-gb-aws-2","k8s.node.uid":"node-gb-aws-2-uid","k8s.cluster.name":"gb-aws-2","cloud.provider":"aws"},"timestamp":"2025-01-10T10:00:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"node-gb-aws-2","k8s.node.uid":"node-gb-aws-2-uid","k8s.cluster.name":"gb-aws-2","cloud.provider":"aws"},"timestamp":"2025-01-10T10:02:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"node-gb-aws-2","k8s.node.uid":"node-gb-aws-2-uid","k8s.cluster.name":"gb-aws-2","cloud.provider":"aws"},"timestamp":"2025-01-10T10:04:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"node-gb-aws-2","k8s.node.uid":"node-gb-aws-2-uid","k8s.cluster.name":"gb-aws-2","cloud.provider":"aws"},"timestamp":"2025-01-10T10:00:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"node-gb-aws-2","k8s.node.uid":"node-gb-aws-2-uid","k8s.cluster.name":"gb-aws-2","cloud.provider":"aws"},"timestamp":"2025-01-10T10:02:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"node-gb-aws-2","k8s.node.uid":"node-gb-aws-2-uid","k8s.cluster.name":"gb-aws-2","cloud.provider":"aws"},"timestamp":"2025-01-10T10:04:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"node-gb-aws-2","k8s.node.uid":"node-gb-aws-2-uid","k8s.cluster.name":"gb-aws-2","cloud.provider":"aws"},"timestamp":"2025-01-10T10:00:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"node-gb-aws-2","k8s.node.uid":"node-gb-aws-2-uid","k8s.cluster.name":"gb-aws-2","cloud.provider":"aws"},"timestamp":"2025-01-10T10:02:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"node-gb-aws-2","k8s.node.uid":"node-gb-aws-2-uid","k8s.cluster.name":"gb-aws-2","cloud.provider":"aws"},"timestamp":"2025-01-10T10:04:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"node-gb-aws-2","k8s.node.uid":"node-gb-aws-2-uid","k8s.cluster.name":"gb-aws-2","cloud.provider":"aws"},"timestamp":"2025-01-10T10:00:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"node-gb-aws-2","k8s.node.uid":"node-gb-aws-2-uid","k8s.cluster.name":"gb-aws-2","cloud.provider":"aws"},"timestamp":"2025-01-10T10:02:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"node-gb-aws-2","k8s.node.uid":"node-gb-aws-2-uid","k8s.cluster.name":"gb-aws-2","cloud.provider":"aws"},"timestamp":"2025-01-10T10:04:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"pod-gb-aws-2-uid","k8s.pod.name":"pod-gb-aws-2","k8s.namespace.name":"ns-x","k8s.node.name":"node-gb-aws-2","k8s.cluster.name":"gb-aws-2","cloud.provider":"aws"},"timestamp":"2025-01-10T10:00:00+00:00","value":2,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"pod-gb-aws-2-uid","k8s.pod.name":"pod-gb-aws-2","k8s.namespace.name":"ns-x","k8s.node.name":"node-gb-aws-2","k8s.cluster.name":"gb-aws-2","cloud.provider":"aws"},"timestamp":"2025-01-10T10:02:00+00:00","value":2,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"pod-gb-aws-2-uid","k8s.pod.name":"pod-gb-aws-2","k8s.namespace.name":"ns-x","k8s.node.name":"node-gb-aws-2","k8s.cluster.name":"gb-aws-2","cloud.provider":"aws"},"timestamp":"2025-01-10T10:04:00+00:00","value":2,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}

View File

@@ -1,3 +0,0 @@
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"miss-n","k8s.node.uid":"miss-n-uid","k8s.cluster.name":"miss-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"miss-n","k8s.node.uid":"miss-n-uid","k8s.cluster.name":"miss-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"miss-n","k8s.node.uid":"miss-n-uid","k8s.cluster.name":"miss-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}

View File

@@ -1,78 +0,0 @@
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"rn-ready-1","k8s.node.uid":"rn-ready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"rn-ready-1","k8s.node.uid":"rn-ready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"rn-ready-1","k8s.node.uid":"rn-ready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"rn-ready-1","k8s.node.uid":"rn-ready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"rn-ready-1","k8s.node.uid":"rn-ready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"rn-ready-1","k8s.node.uid":"rn-ready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"rn-ready-1","k8s.node.uid":"rn-ready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"rn-ready-1","k8s.node.uid":"rn-ready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"rn-ready-1","k8s.node.uid":"rn-ready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"rn-ready-1","k8s.node.uid":"rn-ready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"rn-ready-1","k8s.node.uid":"rn-ready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"rn-ready-1","k8s.node.uid":"rn-ready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"rn-ready-1","k8s.node.uid":"rn-ready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"rn-ready-1","k8s.node.uid":"rn-ready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"rn-ready-1","k8s.node.uid":"rn-ready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"rn-ready-2","k8s.node.uid":"rn-ready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"rn-ready-2","k8s.node.uid":"rn-ready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"rn-ready-2","k8s.node.uid":"rn-ready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"rn-ready-2","k8s.node.uid":"rn-ready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"rn-ready-2","k8s.node.uid":"rn-ready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"rn-ready-2","k8s.node.uid":"rn-ready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"rn-ready-2","k8s.node.uid":"rn-ready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"rn-ready-2","k8s.node.uid":"rn-ready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"rn-ready-2","k8s.node.uid":"rn-ready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"rn-ready-2","k8s.node.uid":"rn-ready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"rn-ready-2","k8s.node.uid":"rn-ready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"rn-ready-2","k8s.node.uid":"rn-ready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"rn-ready-2","k8s.node.uid":"rn-ready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"rn-ready-2","k8s.node.uid":"rn-ready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"rn-ready-2","k8s.node.uid":"rn-ready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"rn-ready-3","k8s.node.uid":"rn-ready-3-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"rn-ready-3","k8s.node.uid":"rn-ready-3-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"rn-ready-3","k8s.node.uid":"rn-ready-3-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"rn-ready-3","k8s.node.uid":"rn-ready-3-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"rn-ready-3","k8s.node.uid":"rn-ready-3-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"rn-ready-3","k8s.node.uid":"rn-ready-3-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"rn-ready-3","k8s.node.uid":"rn-ready-3-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"rn-ready-3","k8s.node.uid":"rn-ready-3-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"rn-ready-3","k8s.node.uid":"rn-ready-3-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"rn-ready-3","k8s.node.uid":"rn-ready-3-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"rn-ready-3","k8s.node.uid":"rn-ready-3-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"rn-ready-3","k8s.node.uid":"rn-ready-3-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"rn-ready-3","k8s.node.uid":"rn-ready-3-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"rn-ready-3","k8s.node.uid":"rn-ready-3-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"rn-ready-3","k8s.node.uid":"rn-ready-3-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"rn-notready-1","k8s.node.uid":"rn-notready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"rn-notready-1","k8s.node.uid":"rn-notready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"rn-notready-1","k8s.node.uid":"rn-notready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"rn-notready-1","k8s.node.uid":"rn-notready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"rn-notready-1","k8s.node.uid":"rn-notready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"rn-notready-1","k8s.node.uid":"rn-notready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"rn-notready-1","k8s.node.uid":"rn-notready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"rn-notready-1","k8s.node.uid":"rn-notready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"rn-notready-1","k8s.node.uid":"rn-notready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"rn-notready-1","k8s.node.uid":"rn-notready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"rn-notready-1","k8s.node.uid":"rn-notready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"rn-notready-1","k8s.node.uid":"rn-notready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"rn-notready-1","k8s.node.uid":"rn-notready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"rn-notready-1","k8s.node.uid":"rn-notready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"rn-notready-1","k8s.node.uid":"rn-notready-1-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"rn-notready-2","k8s.node.uid":"rn-notready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"rn-notready-2","k8s.node.uid":"rn-notready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.cpu.usage","labels":{"k8s.node.name":"rn-notready-2","k8s.node.uid":"rn-notready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":0.5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"rn-notready-2","k8s.node.uid":"rn-notready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"rn-notready-2","k8s.node.uid":"rn-notready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_cpu","labels":{"k8s.node.name":"rn-notready-2","k8s.node.uid":"rn-notready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":4.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"rn-notready-2","k8s.node.uid":"rn-notready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"rn-notready-2","k8s.node.uid":"rn-notready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.memory.working_set","labels":{"k8s.node.name":"rn-notready-2","k8s.node.uid":"rn-notready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":1000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"rn-notready-2","k8s.node.uid":"rn-notready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"rn-notready-2","k8s.node.uid":"rn-notready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.allocatable_memory","labels":{"k8s.node.name":"rn-notready-2","k8s.node.uid":"rn-notready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":8000000000.0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"rn-notready-2","k8s.node.uid":"rn-notready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"rn-notready-2","k8s.node.uid":"rn-notready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.node.condition_ready","labels":{"k8s.node.name":"rn-notready-2","k8s.node.uid":"rn-notready-2-uid","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":0,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"rn-pod-uid","k8s.pod.name":"rn-pod","k8s.namespace.name":"ns-x","k8s.node.name":"rn-ready-1","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":2,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"rn-pod-uid","k8s.pod.name":"rn-pod","k8s.namespace.name":"ns-x","k8s.node.name":"rn-ready-1","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":2,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"rn-pod-uid","k8s.pod.name":"rn-pod","k8s.namespace.name":"ns-x","k8s.node.name":"rn-ready-1","k8s.cluster.name":"rn-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":2,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}

Some files were not shown because too many files have changed in this diff Show More