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
/>
-
Billable egress
++ View your organization's Usage page for billable egress. +
+