From 35f2eeefcfef87c2227c28c7e58dea59412ec1bc Mon Sep 17 00:00:00 2001 From: Jordi Enric <37541088+jordienr@users.noreply.github.com> Date: Mon, 14 Sep 2026 15:43:55 +0200 Subject: [PATCH] fix(observability): replace egress chart with usage link FE-4310 (#49850) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem The Network Traffic egress chart is derived from request logs and can substantially undercount billed traffic. Showing it beside diagnostic ingress data left customers with an untrustworthy egress number. ## Fix Remove the log-derived egress chart, retain ingress, and add a Billable egress callout that links to the selected organization’s Usage page. The callout is shown only on hosted Studio, where organization billing data is available. ## How to test - Open API, Storage, Auth, or PostgREST observability. - Confirm Network Traffic shows only the ingress chart. - Confirm the Billable egress callout links to the organization Usage page’s egress section. - Expected result: diagnostic traffic and billable usage are no longer presented as competing egress totals. - Automated checks: git diff --check and final code review passed. Focused lint could not run because missing dependencies require registry access, and DNS for registry.npmjs.org is unavailable. ## Summary by CodeRabbit * **Updates** * Clarified Network Traffic report tooltips to explain that ingress is measured from request logs. * Platform deployment reports now display ingress data only; egress charts are no longer shown. * Added a notice linking to the Usage page for billable egress details. * Applied the updated Network Traffic explanation consistently across API overview, storage, and shared report views. --- .../SharedAPIReport/SharedAPIReport.tsx | 2 +- .../Reports/renderers/ApiRenderers.tsx | 34 ++++++++++--------- .../[ref]/observability/api-overview.tsx | 2 +- .../project/[ref]/observability/storage.tsx | 2 +- 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/apps/studio/components/interfaces/Reports/SharedAPIReport/SharedAPIReport.tsx b/apps/studio/components/interfaces/Reports/SharedAPIReport/SharedAPIReport.tsx index 4227d4cebc1..12b90c40984 100644 --- a/apps/studio/components/interfaces/Reports/SharedAPIReport/SharedAPIReport.tsx +++ b/apps/studio/components/interfaces/Reports/SharedAPIReport/SharedAPIReport.tsx @@ -81,7 +81,7 @@ export function SharedAPIReport({ isLoading={isLoading.networkTraffic || isRefetching} error={error.networkTraffic} title="Network Traffic" - tooltip="Ingress and egress of requests and responses respectively" + tooltip="Ingress is measured from request logs." data={data.networkTraffic || []} renderer={NetworkTrafficRenderer} queryType="logs" diff --git a/apps/studio/components/interfaces/Reports/renderers/ApiRenderers.tsx b/apps/studio/components/interfaces/Reports/renderers/ApiRenderers.tsx index eacfb0f3d27..686f1899c76 100644 --- a/apps/studio/components/interfaces/Reports/renderers/ApiRenderers.tsx +++ b/apps/studio/components/interfaces/Reports/renderers/ApiRenderers.tsx @@ -2,6 +2,7 @@ import { geoCentroid } from 'd3-geo' import sumBy from 'lodash/sumBy' import { ChevronRight } from 'lucide-react' import { useTheme } from 'next-themes' +import Link from 'next/link' import { Fragment, useRef, useState, type ReactNode } from 'react' import { ComposableMap, Geographies, Geography, Marker, ZoomableGroup } from 'react-simple-maps' import { @@ -39,27 +40,27 @@ import { AlertError } from '@/components/ui/AlertError' import BarChart from '@/components/ui/Charts/BarChart' import { DataTableColumnStatusCode } from '@/components/ui/DataTable/DataTableColumn/DataTableColumnStatusCode' import { useFillTimeseriesSorted } from '@/hooks/analytics/useFillTimeseriesSorted' -import { BASE_PATH } from '@/lib/constants' +import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization' +import { BASE_PATH, IS_PLATFORM } from '@/lib/constants' import type { ResponseError } from '@/types' export const NetworkTrafficRenderer = ( props: ReportWidgetProps<{ timestamp: string ingress: number - egress: number }> ) => { + const { data: organization } = useSelectedOrganizationQuery({ enabled: IS_PLATFORM }) const { data, error, isError } = useFillTimeseriesSorted({ data: props.data, timestampKey: 'timestamp', - valueKey: ['ingress_mb', 'egress_mb'], + valueKey: 'ingress_mb', defaultValue: 0, startDate: props.params?.iso_timestamp_start, endDate: props.params?.iso_timestamp_end, }) const totalIngress = sumBy(props.data, 'ingress_mb') - const totalEgress = sumBy(props.data, 'egress_mb') function determinePrecision(valueInMb: number) { return valueInMb < 0.001 ? 7 : totalIngress > 1 ? 2 : 4 @@ -95,18 +96,19 @@ export const NetworkTrafficRenderer = ( displayDateInUtc /> - + {organization && ( +
+
+

Billable egress

+

+ View your organization's Usage page for billable egress. +

+
+ +
+ )} ) } diff --git a/apps/studio/pages/project/[ref]/observability/api-overview.tsx b/apps/studio/pages/project/[ref]/observability/api-overview.tsx index 4f4ef2d7b47..52dad24b796 100644 --- a/apps/studio/pages/project/[ref]/observability/api-overview.tsx +++ b/apps/studio/pages/project/[ref]/observability/api-overview.tsx @@ -179,7 +179,7 @@ export const ApiReport: NextPageWithLayout = () => { params={params.networkTraffic} error={error.networkTraffic} title="Network Traffic" - tooltip="Ingress and egress of requests and responses respectively" + tooltip="Ingress is measured from request logs." data={data.networkTraffic || []} renderer={NetworkTrafficRenderer} /> diff --git a/apps/studio/pages/project/[ref]/observability/storage.tsx b/apps/studio/pages/project/[ref]/observability/storage.tsx index fe4f0790e55..1540c8f807d 100644 --- a/apps/studio/pages/project/[ref]/observability/storage.tsx +++ b/apps/studio/pages/project/[ref]/observability/storage.tsx @@ -184,7 +184,7 @@ export const StorageReport: NextPageWithLayout = () => { params={params.networkTraffic} error={error.networkTraffic} title="Network Traffic" - tooltip="Ingress and egress of requests and responses respectively" + tooltip="Ingress is measured from request logs." data={data.networkTraffic || []} renderer={NetworkTrafficRenderer} />