From f24df26d7b35c53ecf8eea896568da5409adb9cd Mon Sep 17 00:00:00 2001 From: "Andrey A." <56412611+aantti@users.noreply.github.com> Date: Mon, 16 Feb 2026 13:23:16 +0100 Subject: [PATCH 1/7] fix: do not expose analytics by default --- docker/docker-compose.yml | 4 +-- docker/volumes/api/kong.yml | 46 +++++++++++++++++----------------- docker/volumes/logs/vector.yml | 28 +++++++++++++-------- 3 files changed, 42 insertions(+), 36 deletions(-) diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 6fd37691c2d07..677d5ff63c22e 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -356,8 +356,8 @@ services: container_name: supabase-analytics image: supabase/logflare:1.30.3 restart: unless-stopped - ports: - - 4000:4000 + # ports: + # - 4000:4000 # Uncomment to use Big Query backend for analytics # volumes: # - type: bind diff --git a/docker/volumes/api/kong.yml b/docker/volumes/api/kong.yml index 7441cd31285ab..ae69cec282421 100644 --- a/docker/volumes/api/kong.yml +++ b/docker/volumes/api/kong.yml @@ -197,29 +197,29 @@ services: - name: cors ## Analytics routes - - name: analytics-v1-api - _comment: 'Analytics: /analytics/v1/api/endpoints/* -> http://logflare:4000/api/endpoints/*' - url: http://analytics:4000/api/endpoints - routes: - - name: analytics-v1-api - strip_path: true - paths: - - /analytics/v1/api/endpoints/ - - # auth on analytics dashboard - - name: analytics-v1 - _comment: 'Analytics: /analytics/v1/* -> http://logflare:4000/*' - url: http://analytics:4000/ - routes: - - name: dashboard-v1-all - strip_path: true - paths: - - /analytics/v1 - plugins: - - name: cors - - name: basic-auth - config: - hide_credentials: true + ## Not used - Studio and Vector talk directly to analytics via Docker networking. + ## If external access is needed, add routes with key-auth matching Logflare's x-api-key auth. + # - name: analytics-v1-api + # _comment: 'Analytics: /analytics/v1/api/endpoints/* -> http://logflare:4000/api/endpoints/*' + # url: http://analytics:4000/api/endpoints + # routes: + # - name: analytics-v1-api + # strip_path: true + # paths: + # - /analytics/v1/api/endpoints/ + # - name: analytics-v1 + # _comment: 'Analytics: /analytics/v1/* -> http://logflare:4000/*' + # url: http://analytics:4000/ + # routes: + # - name: dashboard-v1-all + # strip_path: true + # paths: + # - /analytics/v1 + # plugins: + # - name: cors + # - name: basic-auth + # config: + # hide_credentials: true ## Secure Database routes - name: meta diff --git a/docker/volumes/logs/vector.yml b/docker/volumes/logs/vector.yml index e79d7e8268570..989e250f878e3 100644 --- a/docker/volumes/logs/vector.yml +++ b/docker/volumes/logs/vector.yml @@ -177,7 +177,8 @@ sinks: codec: 'json' method: 'post' request: - retry_max_duration_secs: 10 + retry_max_duration_secs: 30 + retry_initial_backoff_secs: 1 headers: x-api-key: ${LOGFLARE_PUBLIC_ACCESS_TOKEN?LOGFLARE_PUBLIC_ACCESS_TOKEN is required} uri: 'http://analytics:4000/api/logs?source_name=gotrue.logs.prod' @@ -189,7 +190,8 @@ sinks: codec: 'json' method: 'post' request: - retry_max_duration_secs: 10 + retry_max_duration_secs: 30 + retry_initial_backoff_secs: 1 headers: x-api-key: ${LOGFLARE_PUBLIC_ACCESS_TOKEN?LOGFLARE_PUBLIC_ACCESS_TOKEN is required} uri: 'http://analytics:4000/api/logs?source_name=realtime.logs.prod' @@ -201,7 +203,8 @@ sinks: codec: 'json' method: 'post' request: - retry_max_duration_secs: 10 + retry_max_duration_secs: 30 + retry_initial_backoff_secs: 1 headers: x-api-key: ${LOGFLARE_PUBLIC_ACCESS_TOKEN?LOGFLARE_PUBLIC_ACCESS_TOKEN is required} uri: 'http://analytics:4000/api/logs?source_name=postgREST.logs.prod' @@ -213,13 +216,13 @@ sinks: codec: 'json' method: 'post' request: - retry_max_duration_secs: 10 + retry_max_duration_secs: 30 + retry_initial_backoff_secs: 1 headers: x-api-key: ${LOGFLARE_PUBLIC_ACCESS_TOKEN?LOGFLARE_PUBLIC_ACCESS_TOKEN is required} - # We must route the sink through kong because ingesting logs before logflare is fully initialised will - # lead to broken queries from studio. This works by the assumption that containers are started in the - # following order: vector > db > logflare > kong - uri: 'http://kong:8000/analytics/v1/api/logs?source_name=postgres.logs' + # Route directly to analytics like other sinks. Retry handles the startup + # race where analytics may not be ready yet when early DB logs arrive. + uri: 'http://analytics:4000/api/logs?source_name=postgres.logs' logflare_functions: type: 'http' inputs: @@ -228,7 +231,8 @@ sinks: codec: 'json' method: 'post' request: - retry_max_duration_secs: 10 + retry_max_duration_secs: 30 + retry_initial_backoff_secs: 1 headers: x-api-key: ${LOGFLARE_PUBLIC_ACCESS_TOKEN?LOGFLARE_PUBLIC_ACCESS_TOKEN is required} uri: 'http://analytics:4000/api/logs?source_name=deno-relay-logs' @@ -240,7 +244,8 @@ sinks: codec: 'json' method: 'post' request: - retry_max_duration_secs: 10 + retry_max_duration_secs: 30 + retry_initial_backoff_secs: 1 headers: x-api-key: ${LOGFLARE_PUBLIC_ACCESS_TOKEN?LOGFLARE_PUBLIC_ACCESS_TOKEN is required} uri: 'http://analytics:4000/api/logs?source_name=storage.logs.prod.2' @@ -253,7 +258,8 @@ sinks: codec: 'json' method: 'post' request: - retry_max_duration_secs: 10 + retry_max_duration_secs: 30 + retry_initial_backoff_secs: 1 headers: x-api-key: ${LOGFLARE_PUBLIC_ACCESS_TOKEN?LOGFLARE_PUBLIC_ACCESS_TOKEN is required} uri: 'http://analytics:4000/api/logs?source_name=cloudflare.logs.prod' From 591d46e491269a9b1d00f5164b62f4262746bca9 Mon Sep 17 00:00:00 2001 From: Jordi Enric <37541088+jordienr@users.noreply.github.com> Date: Mon, 16 Feb 2026 14:17:31 +0100 Subject: [PATCH 2/7] chore: sentry performance monitoring (#42861) - Added tracesSampleRate: 0.1 to all three Sentry configuration files (client, server, edge) - Captures 10% of transactions for performance monitoring - Previously: No performance data was being collected (missing this config) - Now: Sentry will track route performance, error rates per route, and transaction data Why this was needed: - Without tracesSampleRate, Sentry's Performance tab was empty - Error rates per route were not visible - No transaction/route-level metrics were being collected - The SDK was only capturing errors without context about which routes they occurred on Impact: - Enables route-based error tracking (see which endpoints/pages have errors) - Provides performance metrics per route (page load times, API response times) - Allows monitoring of Web Vitals and navigation performance - 10% sample rate balances visibility with Sentry quota usage ## Summary by CodeRabbit * **Bug Fixes** * Fixed date display formatting in logs to ensure accurate timestamp representation. * **Chores** * Enabled performance monitoring to collect transaction data and track application behavior. --- apps/studio/instrumentation-client.ts | 4 ++++ apps/studio/sentry.edge.config.ts | 3 +++ apps/studio/sentry.server.config.ts | 3 +++ 3 files changed, 10 insertions(+) diff --git a/apps/studio/instrumentation-client.ts b/apps/studio/instrumentation-client.ts index 9bd34e8177f0b..5dd543ad6d3fd 100644 --- a/apps/studio/instrumentation-client.ts +++ b/apps/studio/instrumentation-client.ts @@ -57,6 +57,10 @@ Sentry.init({ }), // Setting this option to true will print useful information to the console while you're setting up Sentry. debug: false, + + // Enable performance monitoring - Next.js routes and API calls are automatically instrumented + tracesSampleRate: 0.1, // Capture 10% of transactions for performance monitoring + // [Ali] Filter out browser extensions and user scripts (FE-2094) // Using denyUrls to block known third-party script patterns denyUrls: [/userscript/i], diff --git a/apps/studio/sentry.edge.config.ts b/apps/studio/sentry.edge.config.ts index c5db7e27ad95c..ad17e8b86a208 100644 --- a/apps/studio/sentry.edge.config.ts +++ b/apps/studio/sentry.edge.config.ts @@ -12,4 +12,7 @@ Sentry.init({ }), // Setting this option to true will print useful information to the console while you're setting up Sentry. debug: false, + + // Enable performance monitoring + tracesSampleRate: 0.1, // Capture 10% of transactions for performance monitoring }) diff --git a/apps/studio/sentry.server.config.ts b/apps/studio/sentry.server.config.ts index dba6457bc5f2b..13d62e7bc317e 100644 --- a/apps/studio/sentry.server.config.ts +++ b/apps/studio/sentry.server.config.ts @@ -11,6 +11,9 @@ Sentry.init({ }), // Setting this option to true will print useful information to the console while you're setting up Sentry. debug: false, + + // Enable performance monitoring + tracesSampleRate: 0.1, // Capture 10% of transactions for performance monitoring ignoreErrors: [ // Used exclusively in Monaco Editor. 'ResizeObserver', From 4651480f28f0939b7fad339e91045575e76ad5df Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Mon, 16 Feb 2026 22:06:01 +0800 Subject: [PATCH 3/7] Joshen/fe 2540 fix safari csv drag drop typeerror in table editor (#42852) ## Context Addresses an error when drag and dropping a CSV in the Table Editor when the table is empty, specifically on Safari leading to a `undefined is not an object (evaluating 'n.type')` error For context, Safari obscures the item data from the drag event and only exposes it on the drop event ([ref](https://github.com/mdn/browser-compat-data/issues/24898)) hence why this issue ## Changes involved Am opting to change the UX instead of fixing this browser specific behaviour - Ignore file validity when dragging, let the on drop handle validate the type and reject unsupported files instead - This is better either way as currently our Table Editor shows "CSV files only", when we actually also support TSV files - Also made a slight adjustment to the drag over UI - border around the grid empty area, rather than the whole grid - Before: image - After: image ## Summary by CodeRabbit * **Refactor** * Simplified the empty-table display and CSV import interface for a more consistent user experience. * Import button and drag-and-drop hints now remain visible when the table is empty, removing prior conditional hiding during drag. * Streamlined empty-state styling and messaging for a cleaner, more predictable appearance. * **Tests** * Updated end-to-end test expectations to reflect the persistent empty-state message during drag-over. --- .../components/grid/components/grid/Grid.tsx | 76 ++++++++----------- apps/studio/hooks/ui/useCsvFileDrop.ts | 10 +-- e2e/studio/features/table-editor.spec.ts | 7 +- 3 files changed, 38 insertions(+), 55 deletions(-) diff --git a/apps/studio/components/grid/components/grid/Grid.tsx b/apps/studio/components/grid/components/grid/Grid.tsx index 0b589f5451fb0..2079e3692ea28 100644 --- a/apps/studio/components/grid/components/grid/Grid.tsx +++ b/apps/studio/components/grid/components/grid/Grid.tsx @@ -97,12 +97,7 @@ export const Grid = memo( const { mutate: sendEvent } = useSendEventMutation() - const { - isValidFile: isValidFileDraggedOver, - isDraggedOver, - onDragOver, - onFileDrop, - } = useCsvFileDrop({ + const { isDraggedOver, onDragOver, onFileDrop } = useCsvFileDrop({ enabled: isTableEmpty && !isForeignTable, onFileDropped: (file) => tableEditorSnap.onImportData(valtioRef(file)), onTelemetryEvent: (eventName) => { @@ -241,9 +236,7 @@ export const Grid = memo( {(rows ?? []).length === 0 && (
{isLoading && !isDisabled && ( @@ -272,18 +265,13 @@ export const Grid = memo(
) : (filters ?? []).length === 0 ? ( -
-

- {isDraggedOver ? ( - isValidFileDraggedOver ? ( - 'Drop your CSV file here' - ) : ( - Only CSV files are accepted - ) - ) : ( - 'This table is empty' - )} -

+
+

This table is empty

{tableEntityType === ENTITY_TYPE.FOREIGN_TABLE ? (

@@ -292,30 +280,28 @@ export const Grid = memo(

) : ( - !isDraggedOver && ( -
- -

- or drag and drop a CSV file here -

-
- ) +
+ +

+ or drag and drop a CSV file here +

+
)}
) : ( diff --git a/apps/studio/hooks/ui/useCsvFileDrop.ts b/apps/studio/hooks/ui/useCsvFileDrop.ts index 2f2da36a1889f..26119d2313553 100644 --- a/apps/studio/hooks/ui/useCsvFileDrop.ts +++ b/apps/studio/hooks/ui/useCsvFileDrop.ts @@ -1,7 +1,6 @@ -import { type DragEvent, useCallback, useState } from 'react' - import { type ImportDataFileDroppedEvent } from 'common/telemetry-constants' import { flagInvalidFileImport } from 'components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.utils' +import { useCallback, useState, type DragEvent } from 'react' interface UseCsvFileDropOptions { enabled: boolean @@ -11,7 +10,6 @@ interface UseCsvFileDropOptions { interface UseCsvFileDropReturn { isDraggedOver: boolean - isValidFile: boolean onDragOver: (event: DragEvent) => void onFileDrop: (event: DragEvent) => void } @@ -22,7 +20,6 @@ export function useCsvFileDrop({ onTelemetryEvent, }: UseCsvFileDropOptions): UseCsvFileDropReturn { const [isDraggedOver, setIsDraggedOver] = useState(false) - const [isValidFile, setIsValidFile] = useState(false) const onDragOver = useCallback( (event: DragEvent) => { @@ -35,15 +32,13 @@ export function useCsvFileDrop({ if (event.type === 'dragover' && !isDraggedOver) { setIsDraggedOver(true) - setIsValidFile(item.type === 'text/csv') } else if (event.type === 'dragleave' || event.type === 'drop') { setIsDraggedOver(false) - setIsValidFile(false) } event.stopPropagation() event.preventDefault() }, - [enabled, isDraggedOver, isValidFile] + [enabled, isDraggedOver] ) const onFileDrop = useCallback( @@ -68,7 +63,6 @@ export function useCsvFileDrop({ ) return { - isValidFile: isValidFile && isDraggedOver, isDraggedOver, onDragOver, onFileDrop, diff --git a/e2e/studio/features/table-editor.spec.ts b/e2e/studio/features/table-editor.spec.ts index 7cc237fc4fdcf..e3a4429f71b54 100644 --- a/e2e/studio/features/table-editor.spec.ts +++ b/e2e/studio/features/table-editor.spec.ts @@ -1208,9 +1208,12 @@ testRunner('table editor', () => { const gridContainer = page.getByTestId('table-editor-grid-container') await gridContainer.dispatchEvent('dragover', { dataTransfer }) + + // After the refactor, the empty state text and import button remain visible during drag + // (no more "Drop your CSV file here" overlay), just a dashed border is shown await expect( - page.getByText('Drop your CSV file here'), - 'Drag feedback should show when CSV is dragged over' + page.getByText('This table is empty'), + 'Empty table message should remain visible during drag' ).toBeVisible() await gridContainer.dispatchEvent('drop', { dataTransfer }) From 3aef6f08b8328d669323a8bb4442b723cc09a328 Mon Sep 17 00:00:00 2001 From: Inder Singh <85822513+singh-inder@users.noreply.github.com> Date: Mon, 16 Feb 2026 19:40:47 +0530 Subject: [PATCH 4/7] feat(self-hosted): update vector service and config --- docker/docker-compose.yml | 2 +- docker/volumes/logs/vector.yml | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 677d5ff63c22e..50db1b44ac93c 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -459,7 +459,7 @@ services: vector: container_name: supabase-vector - image: timberio/vector:0.28.1-alpine + image: timberio/vector:0.53.0-alpine restart: unless-stopped volumes: - ./volumes/logs/vector.yml:/etc/vector/vector.yml:ro,z diff --git a/docker/volumes/logs/vector.yml b/docker/volumes/logs/vector.yml index 989e250f878e3..d600bf2867795 100644 --- a/docker/volumes/logs/vector.yml +++ b/docker/volumes/logs/vector.yml @@ -49,10 +49,13 @@ transforms: .metadata.request.headers.referer = req.referer .metadata.request.headers.user_agent = req.agent .metadata.request.headers.cf_connecting_ip = req.client - .metadata.request.method = req.method - .metadata.request.path = req.path - .metadata.request.protocol = req.protocol .metadata.response.status_code = req.status + url, split_err = split(req.request, " ") + if split_err == null { + .metadata.request.method = url[0] + .metadata.request.path = url[1] + .metadata.request.protocol = url[2] + } } if err != null { abort @@ -101,7 +104,7 @@ transforms: parsed, err = parse_regex(.event_message, r'^(?P