Skip to content

Commit 5cfd10a

Browse files
Ziincjordienr
andauthored
feat: self-hosted log drains (supabase#28297)
* feat: initial log drain creation, sans rules creation. * feat: add rules posting * add project settings to self hosted and adapt log drains * feat: log drains crud implementation, env var update * feat: local log drains is working! rules provisioning refined * fix: add filtering * feat: finish implementing CRUD of local log drains. * chore: formatting * only allow navigation to log drains * rm unnecessary checks * rm log * rm logs * rm log * fix type err * turbofix for turboissue --------- Co-authored-by: Jordi Enric <[email protected]>
1 parent 02783c3 commit 5cfd10a

File tree

14 files changed

+344
-98
lines changed

14 files changed

+344
-98
lines changed

apps/docs/spec/analytics_v0_config.yaml

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,7 @@ parameters:
3434
default: ''
3535
type: 'string'
3636
description: |
37-
Allows you to pass in an API key that will used for authentication for ingestion only. This is intended for programmatic usage where an external program sets the API key. A default ingestion API key will be automatically generated.
38-
- id: 'LOGFLARE_PRIVATE_ACCESS_TOKEN' # {string} A unique identifier for this param.
39-
title: 'LOGFLARE_PRIVATE_ACCESS_TOKEN' # {string} Any name.
40-
tags: ['general'] # {string[]} These tags are useful for grouping parameters
41-
links: [] # {string[]} These tags are useful for grouping parameters
42-
required: true
43-
default: ''
44-
type: 'string'
45-
description: |
46-
Allows you to pass in an Management API key that will used for authentication. This is intended for programmatic usage where an external program sets the API key. This key is considered secret.
37+
Allows you to pass in an API key that will used for authentication. This is intended for programmatic usage where an external program sets the API key. If this value is not provided, the default API key will be automatically generated.
4738
- id: 'LOGFLARE_SUPABASE_MODE' # {string} A unique identifier for this param.
4839
title: 'LOGFLARE_SUPABASE_MODE' # {string} Any name.
4940
tags: ['general'] # {string[]} These tags are useful for grouping parameters

apps/docs/spec/functions_v0_config.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,24 @@ info:
1414
- id: general
1515
title: General Settings
1616
description: General server settings.
17+
18+
# This section is an array of public functions which a user might need to execute.
19+
parameters:
20+
- id: 'LOGFLARE_SINGLE_TENANT' # {string} A unique identifier for this param.
21+
title: 'LOGFLARE_SINGLE_TENANT' # {string} Any name.
22+
tags: ['general'] # {string[]} These tags are useful for grouping parameters
23+
links: [] # {string[]} These tags are useful for grouping parameters
24+
required: true
25+
default: 'true'
26+
type: 'boolean'
27+
description: |
28+
This is will seed a singular user into the database, and will disable browser authentication. All browser usage will default to this user. Inviting team users and other team-related functionality is currently not supported for self-hosted. Logflare self-hosted is currently intended for single-user experience only.
29+
- id: 'LOGFLARE_PUBLIC_ACCESS_TOKEN' # {string} A unique identifier for this param.
30+
title: 'LOGFLARE_PUBLIC_ACCESS_TOKEN' # {string} Any name.
31+
tags: ['general'] # {string[]} These tags are useful for grouping parameters
32+
links: [] # {string[]} These tags are useful for grouping parameters
33+
required: true
34+
default: ''
35+
type: 'string'
36+
description: |
37+
Allows you to pass in an API key that will used for authentication. This is intended for programmatic usage where an external program sets the API key. It is advised to use the UI to configure the access tokens instead. If this value is not provided, the default API key will be automatically generated.

apps/studio/components/interfaces/LogDrains/LogDrainDestinationSheetForm.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { useForm } from 'react-hook-form'
55
import { toast } from 'sonner'
66
import { z } from 'zod'
77

8-
import { useFlag, useParams } from 'common'
8+
import { IS_PLATFORM, useFlag, useParams } from 'common'
99
import { DocsButton } from 'components/ui/DocsButton'
1010
import { LogDrainData, useLogDrainsQuery } from 'data/log-drains/log-drains-query'
1111
import { DOCS_URL } from 'lib/constants'
@@ -265,7 +265,8 @@ export function LogDrainDestinationSheetForm({
265265

266266
// Temp check to make sure the name is unique
267267
const logDrainName = form.getValues('name')
268-
const logDrainExists = logDrains?.find((drain) => drain.name === logDrainName)
268+
const logDrainExists =
269+
!!logDrains?.length && logDrains?.find((drain) => drain.name === logDrainName)
269270
if (logDrainExists && mode === 'create') {
270271
toast.error('Log drain name already exists')
271272
return
@@ -569,7 +570,9 @@ export function LogDrainDestinationSheetForm({
569570
</SheetSection>
570571

571572
<div className="mt-auto">
572-
<SheetSection className="border-t bg-background-alternative-200 mt-auto">
573+
<SheetSection
574+
className={`border-t bg-background-alternative-200 mt-auto ${!IS_PLATFORM ? 'hidden' : ''}`}
575+
>
573576
<FormItemLayout
574577
isReactForm={false}
575578
layout="horizontal"

apps/studio/components/interfaces/LogDrains/LogDrains.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export function LogDrains({
5656
}
5757
)
5858
const sentryEnabled = useFlag('SentryLogDrain')
59+
const hasLogDrains = !!logDrains?.length
5960

6061
const { mutate: deleteLogDrain } = useDeleteLogDrainMutation({
6162
onSuccess: () => {
@@ -90,7 +91,7 @@ export function LogDrains({
9091
)
9192
}
9293

93-
if (!isLoading && logDrains?.length === 0) {
94+
if (!isLoading && !hasLogDrains) {
9495
return (
9596
<div className="grid lg:grid-cols-2 gap-3">
9697
{LOG_DRAIN_TYPES.filter((t) => t.value !== 'sentry' || sentryEnabled).map((src) => (

apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.utils.tsx

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -195,16 +195,12 @@ export const generateOtherRoutes = (
195195
export const generateSettingsRoutes = (ref?: string, project?: Project): Route[] => {
196196
const settingsMenu = generateSettingsMenu(ref as string)
197197
return [
198-
...(IS_PLATFORM
199-
? [
200-
{
201-
key: 'settings',
202-
label: 'Project Settings',
203-
icon: <Settings size={ICON_SIZE} strokeWidth={ICON_STROKE_WIDTH} />,
204-
link: ref && `/project/${ref}/settings/general`,
205-
items: settingsMenu,
206-
},
207-
]
208-
: []),
198+
{
199+
key: 'settings',
200+
label: 'Project Settings',
201+
icon: <Settings size={ICON_SIZE} strokeWidth={ICON_STROKE_WIDTH} />,
202+
link: ref && `/project/${ref}/settings/general`,
203+
items: settingsMenu,
204+
},
209205
]
210206
}

apps/studio/components/layouts/ProjectSettingsLayout/SettingsLayout.tsx

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,6 @@ const SettingsLayout = ({ title, children }: PropsWithChildren<SettingsLayoutPro
2121
const { data: project } = useSelectedProjectQuery()
2222
const { data: organization } = useSelectedOrganizationQuery()
2323

24-
useEffect(() => {
25-
if (!IS_PLATFORM) {
26-
router.push('/project/default')
27-
}
28-
}, [router])
29-
3024
// billing pages live under /billing/invoices and /billing/subscription, etc
3125
// so we need to pass the [5]th part of the url to the menu
3226
const page = router.pathname.includes('billing')

apps/studio/components/layouts/ProjectSettingsLayout/SettingsMenu.utils.tsx

Lines changed: 61 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,21 @@ export const generateSettingsMenu = (
2020
billing?: boolean
2121
}
2222
): ProductMenuGroup[] => {
23+
if (!IS_PLATFORM) {
24+
return [
25+
{
26+
title: 'Project Settings',
27+
items: [
28+
{
29+
name: `Log Drains`,
30+
key: `log-drains`,
31+
url: `/project/${ref}/settings/log-drains`,
32+
items: [],
33+
},
34+
],
35+
},
36+
]
37+
}
2338
const isProjectBuilding = project?.status === PROJECT_STATUS.COMING_UP
2439
const buildingUrl = `/project/${ref}`
2540

@@ -28,7 +43,6 @@ export const generateSettingsMenu = (
2843
const edgeFunctionsEnabled = features?.edgeFunctions ?? true
2944
const storageEnabled = features?.storage ?? true
3045
const legacyJwtKeysEnabled = features?.legacyJwtKeys ?? true
31-
const logDrainsEnabled = features?.logDrains ?? true
3246
const billingEnabled = features?.billing ?? true
3347

3448
return [
@@ -41,64 +55,55 @@ export const generateSettingsMenu = (
4155
url: `/project/${ref}/settings/general`,
4256
items: [],
4357
},
44-
...(IS_PLATFORM
45-
? [
46-
{
47-
name: 'Compute and Disk',
48-
key: 'compute-and-disk',
49-
url: `/project/${ref}/settings/compute-and-disk`,
50-
items: [],
51-
},
52-
]
53-
: []),
58+
{
59+
name: 'Compute and Disk',
60+
key: 'compute-and-disk',
61+
url: `/project/${ref}/settings/compute-and-disk`,
62+
items: [],
63+
},
5464
{
5565
name: 'Infrastructure',
5666
key: 'infrastructure',
5767
url: isProjectBuilding ? buildingUrl : `/project/${ref}/settings/infrastructure`,
5868
items: [],
5969
},
60-
...(IS_PLATFORM
61-
? [
62-
{
63-
name: 'Integrations',
64-
key: 'integrations',
65-
url: `/project/${ref}/settings/integrations`,
66-
items: [],
67-
},
68-
...(logDrainsEnabled
69-
? [
70-
{
71-
name: `Log Drains`,
72-
key: `log-drains`,
73-
url: `/project/${ref}/settings/log-drains`,
74-
items: [],
75-
},
76-
]
77-
: []),
78-
{
79-
name: 'Data API',
80-
key: 'api',
81-
url: isProjectBuilding ? buildingUrl : `/project/${ref}/settings/api`,
82-
items: [],
83-
},
84-
{
85-
name: 'API Keys',
86-
key: 'api-keys',
87-
url: `/project/${ref}/settings/api-keys`,
88-
items: [],
89-
label: 'NEW',
90-
},
91-
{
92-
name: 'JWT Keys',
93-
key: 'jwt',
94-
url: legacyJwtKeysEnabled
95-
? `/project/${ref}/settings/jwt`
96-
: `/project/${ref}/settings/jwt/signing-keys`,
97-
items: [],
98-
label: 'NEW',
99-
},
100-
]
101-
: []),
70+
71+
{
72+
name: 'Integrations',
73+
key: 'integrations',
74+
url: `/project/${ref}/settings/integrations`,
75+
items: [],
76+
},
77+
78+
{
79+
name: 'Data API',
80+
key: 'api',
81+
url: isProjectBuilding ? buildingUrl : `/project/${ref}/settings/api`,
82+
items: [],
83+
},
84+
{
85+
name: 'API Keys',
86+
key: 'api-keys',
87+
url: `/project/${ref}/settings/api-keys`,
88+
items: [],
89+
label: 'NEW',
90+
},
91+
{
92+
name: 'JWT Keys',
93+
key: 'jwt',
94+
url: legacyJwtKeysEnabled
95+
? `/project/${ref}/settings/jwt`
96+
: `/project/${ref}/settings/jwt/signing-keys`,
97+
items: [],
98+
label: 'NEW',
99+
},
100+
101+
{
102+
name: `Log Drains`,
103+
key: `log-drains`,
104+
url: `/project/${ref}/settings/log-drains`,
105+
items: [],
106+
},
102107
{
103108
name: 'Add Ons',
104109
key: 'addons',
@@ -125,7 +130,7 @@ export const generateSettingsMenu = (
125130
items: [],
126131
rightIcon: <ArrowUpRight strokeWidth={1} className="h-4 w-4" />,
127132
},
128-
...(IS_PLATFORM && authEnabled
133+
...(authEnabled
129134
? [
130135
{
131136
name: 'Authentication',
@@ -138,7 +143,7 @@ export const generateSettingsMenu = (
138143
},
139144
]
140145
: []),
141-
...(IS_PLATFORM && storageEnabled
146+
...(storageEnabled
142147
? [
143148
{
144149
name: 'Storage',
@@ -149,7 +154,7 @@ export const generateSettingsMenu = (
149154
},
150155
]
151156
: []),
152-
...(IS_PLATFORM && edgeFunctionsEnabled
157+
...(edgeFunctionsEnabled
153158
? [
154159
{
155160
name: 'Edge Functions',

0 commit comments

Comments
 (0)