@@ -135,13 +135,17 @@ type vectorConfig struct {
135135 ApiKey string
136136 VectorId string
137137 LogflareId string
138+ LogflareHost string
138139 KongId string
139140 GotrueId string
140141 RestId string
141142 RealtimeId string
142143 StorageId string
143144 EdgeRuntimeId string
144145 DbId string
146+ SourceName string
147+ SourceType string
148+ SourceInclude []string
145149}
146150
147151var (
@@ -169,6 +173,18 @@ var (
169173
170174var serviceTimeout = 30 * time .Second
171175
176+ var (
177+ startAppleAnalyticsForwarders = utils .StartAppleAnalyticsForwarders
178+ stopAppleAnalyticsForwarders = utils .StopAppleAnalyticsForwarders
179+ )
180+
181+ const (
182+ vectorSourceDockerLogs = "docker_logs"
183+ vectorSourceFile = "file"
184+ appleVectorLogDir = "/var/log/supabase"
185+ appleVectorLogGlob = appleVectorLogDir + "/*.jsonl"
186+ )
187+
172188var resolveContainerIP = utils .GetContainerIP
173189var listProjectContainers = utils .ListProjectContainers
174190var removeProjectContainer = utils .RemoveContainer
@@ -287,6 +303,35 @@ func buildKongConfig(ctx context.Context, deps KongDependencies) (kongConfig, er
287303 }, nil
288304}
289305
306+ func buildVectorConfig (ctx context.Context ) (vectorConfig , error ) {
307+ cfg := vectorConfig {
308+ ApiKey : utils .Config .Analytics .ApiKey ,
309+ VectorId : utils .VectorId ,
310+ LogflareId : utils .LogflareId ,
311+ LogflareHost : utils .LogflareId ,
312+ KongId : utils .KongId ,
313+ GotrueId : utils .GotrueId ,
314+ RestId : utils .RestId ,
315+ RealtimeId : utils .RealtimeId ,
316+ StorageId : utils .StorageId ,
317+ EdgeRuntimeId : utils .EdgeRuntimeId ,
318+ DbId : utils .DbId ,
319+ SourceName : "docker_host" ,
320+ SourceType : vectorSourceDockerLogs ,
321+ }
322+ if utils .UsesAppleContainerRuntime () {
323+ logflareHost , err := runtimeContainerHost (ctx , utils .LogflareId , true )
324+ if err != nil {
325+ return vectorConfig {}, err
326+ }
327+ cfg .LogflareHost = logflareHost
328+ cfg .SourceName = "apple_logs"
329+ cfg .SourceType = vectorSourceFile
330+ cfg .SourceInclude = []string {appleVectorLogGlob }
331+ }
332+ return cfg , nil
333+ }
334+
290335func startKong (ctx context.Context , deps KongDependencies ) error {
291336 var kongConfigBuf bytes.Buffer
292337 kongConfig , err := buildKongConfig (ctx , deps )
@@ -478,17 +523,13 @@ func run(ctx context.Context, fsys afero.Fs, excludedContainers []string, dbConf
478523 for _ , name := range excludedContainers {
479524 excluded [name ] = true
480525 }
481- if utils .UsesAppleContainerRuntime () {
482- if ! excluded [utils .ShortContainerImageName (utils .Config .Analytics .Image )] || ! excluded [utils .ShortContainerImageName (utils .Config .Analytics .VectorImage )] {
483- fmt .Fprintln (os .Stderr , utils .Yellow ("WARNING:" ), "apple-container runtime does not support analytics yet; skipping logflare and vector." )
484- excluded [utils .ShortContainerImageName (utils .Config .Analytics .Image )] = true
485- excluded [utils .ShortContainerImageName (utils .Config .Analytics .VectorImage )] = true
486- }
487- }
488526 notExcluded := func (sc types.ServiceConfig ) bool {
489527 val , ok := excluded [sc .Name ]
490528 return ! val || ! ok
491529 }
530+ if utils .UsesAppleContainerRuntime () && ! excluded [utils .ShortContainerImageName (utils .Config .Analytics .VectorImage )] {
531+ _ = stopAppleAnalyticsForwarders (afero .NewOsFs ())
532+ }
492533
493534 jwks , err := utils .Config .Auth .ResolveJWKS (ctx )
494535 if err != nil {
@@ -626,49 +667,54 @@ EOF
626667
627668 // Start vector
628669 if isVectorEnabled {
670+ cfg , err := buildVectorConfig (ctx )
671+ if err != nil {
672+ return err
673+ }
629674 var vectorConfigBuf bytes.Buffer
630- if err := vectorConfigTemplate .Option ("missingkey=error" ).Execute (& vectorConfigBuf , vectorConfig {
631- ApiKey : utils .Config .Analytics .ApiKey ,
632- VectorId : utils .VectorId ,
633- LogflareId : utils .LogflareId ,
634- KongId : utils .KongId ,
635- GotrueId : utils .GotrueId ,
636- RestId : utils .RestId ,
637- RealtimeId : utils .RealtimeId ,
638- StorageId : utils .StorageId ,
639- EdgeRuntimeId : utils .EdgeRuntimeId ,
640- DbId : utils .DbId ,
641- }); err != nil {
675+ if err := vectorConfigTemplate .Option ("missingkey=error" ).Execute (& vectorConfigBuf , cfg ); err != nil {
642676 return errors .Errorf ("failed to exec template: %w" , err )
643677 }
644678 var binds , env , securityOpts []string
679+ if utils .UsesAppleContainerRuntime () {
680+ hostLogDir , err := utils .AppleAnalyticsLogsDirPath ()
681+ if err != nil {
682+ return errors .Errorf ("failed to resolve apple analytics log dir: %w" , err )
683+ }
684+ if err := os .MkdirAll (hostLogDir , 0755 ); err != nil {
685+ return errors .Errorf ("failed to create apple analytics log dir: %w" , err )
686+ }
687+ binds = append (binds , hostLogDir + ":" + appleVectorLogDir + ":rw" )
688+ }
645689 // Special case for GitLab pipeline
646690 parsed , err := client .ParseHostURL (utils .Docker .DaemonHost ())
647691 if err != nil {
648692 return errors .Errorf ("failed to parse docker host: %w" , err )
649693 }
650694 // Ref: https://vector.dev/docs/reference/configuration/sources/docker_logs/#docker_host
651- dindHost := & url.URL {Scheme : "http" , Host : net .JoinHostPort (utils .DinDHost , "2375" )}
652- switch parsed .Scheme {
653- case "tcp" :
654- if _ , port , err := net .SplitHostPort (parsed .Host ); err == nil {
655- dindHost .Host = net .JoinHostPort (utils .DinDHost , port )
656- }
657- env = append (env , "DOCKER_HOST=" + dindHost .String ())
658- case "npipe" :
659- const dockerDaemonNeededErr = "Analytics on Windows requires Docker daemon exposed on tcp://localhost:2375.\n See https://supabase.com/docs/guides/local-development/cli/getting-started?queryGroups=platform&platform=windows#running-supabase-locally for more details."
660- fmt .Fprintln (os .Stderr , utils .Yellow ("WARNING:" ), dockerDaemonNeededErr )
661- env = append (env , "DOCKER_HOST=" + dindHost .String ())
662- case "unix" :
663- if dindHost , err = client .ParseHostURL (client .DefaultDockerHost ); err != nil {
664- return errors .Errorf ("failed to parse default host: %w" , err )
665- } else if strings .HasSuffix (parsed .Host , "/.docker/run/docker.sock" ) {
666- fmt .Fprintln (os .Stderr , utils .Yellow ("WARNING:" ), "analytics requires mounting default docker socket:" , dindHost .Host )
667- binds = append (binds , fmt .Sprintf ("%[1]s:%[1]s:ro" , dindHost .Host ))
668- } else {
669- // Podman and OrbStack can mount root-less socket without issue
670- binds = append (binds , fmt .Sprintf ("%s:%s:ro" , parsed .Host , dindHost .Host ))
671- securityOpts = append (securityOpts , "label:disable" )
695+ if ! utils .UsesAppleContainerRuntime () {
696+ dindHost := & url.URL {Scheme : "http" , Host : net .JoinHostPort (utils .DinDHost , "2375" )}
697+ switch parsed .Scheme {
698+ case "tcp" :
699+ if _ , port , err := net .SplitHostPort (parsed .Host ); err == nil {
700+ dindHost .Host = net .JoinHostPort (utils .DinDHost , port )
701+ }
702+ env = append (env , "DOCKER_HOST=" + dindHost .String ())
703+ case "npipe" :
704+ const dockerDaemonNeededErr = "Analytics on Windows requires Docker daemon exposed on tcp://localhost:2375.\n See https://supabase.com/docs/guides/local-development/cli/getting-started?queryGroups=platform&platform=windows#running-supabase-locally for more details."
705+ fmt .Fprintln (os .Stderr , utils .Yellow ("WARNING:" ), dockerDaemonNeededErr )
706+ env = append (env , "DOCKER_HOST=" + dindHost .String ())
707+ case "unix" :
708+ if dindHost , err = client .ParseHostURL (client .DefaultDockerHost ); err != nil {
709+ return errors .Errorf ("failed to parse default host: %w" , err )
710+ } else if strings .HasSuffix (parsed .Host , "/.docker/run/docker.sock" ) {
711+ fmt .Fprintln (os .Stderr , utils .Yellow ("WARNING:" ), "analytics requires mounting default docker socket:" , dindHost .Host )
712+ binds = append (binds , fmt .Sprintf ("%[1]s:%[1]s:ro" , dindHost .Host ))
713+ } else {
714+ // Podman and OrbStack can mount root-less socket without issue
715+ binds = append (binds , fmt .Sprintf ("%s:%s:ro" , parsed .Host , dindHost .Host ))
716+ securityOpts = append (securityOpts , "label:disable" )
717+ }
672718 }
673719 }
674720 if _ , err := utils .DockerStart (
@@ -1399,6 +1445,12 @@ EOF
13991445 started = append (started , utils .KongId )
14001446 }
14011447
1448+ if utils .UsesAppleContainerRuntime () && isVectorEnabled {
1449+ if err := startAppleAnalyticsForwarders (utils .AppleAnalyticsSourceContainers ()); err != nil {
1450+ return err
1451+ }
1452+ }
1453+
14021454 // Start Studio.
14031455 if isStudioEnabled {
14041456 binds , _ , err := serve .PopulatePerFunctionConfigs (workdir , "" , nil , fsys )
0 commit comments