Skip to content

Commit

Permalink
feat: auto wire up grafana
Browse files Browse the repository at this point in the history
  • Loading branch information
stuartwdouglas committed Nov 15, 2024
1 parent b02c014 commit e52b793
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 13 deletions.
2 changes: 1 addition & 1 deletion frontend/cli/cmd_schema_import.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ func (s *schemaImportCmd) setup(ctx context.Context) error {
return err
}

err = container.Run(ctx, "ollama/ollama", ollamaContainerName, s.OllamaPort, 11434, optional.Some(ollamaVolume))
err = container.Run(ctx, "ollama/ollama", ollamaContainerName, map[int]int{s.OllamaPort: 11434}, optional.Some(ollamaVolume))
if err != nil {
return err
}
Expand Down
9 changes: 9 additions & 0 deletions frontend/cli/cmd_serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ type serveCmd struct {
ObservabilityConfig observability.Config `embed:"" prefix:"o11y-"`
DatabaseImage string `help:"The container image to start for the database" default:"postgres:15.8" env:"FTL_DATABASE_IMAGE" hidden:""`
RegistryImage string `help:"The container image to start for the image registry" default:"registry:2" env:"FTL_REGISTRY_IMAGE" hidden:""`
GrafanaImage string `help:"The container image to start for the automatic Grafana instance" default:"grafana/otel-lgtm" env:"FTL_GRAFANA_IMAGE" hidden:""`
DisableGrafana bool `help:"Disable the automatic Grafana that is started if no telemetry collector is specified." default:"false"`
controller.CommonConfig
provisioner.CommonProvisionerConfig
}
Expand Down Expand Up @@ -133,6 +135,13 @@ func (s *serveCmd) run(
if err != nil {
return err
}
if !s.DisableGrafana && !bool(s.ObservabilityConfig.ExportOTEL) {
err := dev.SetupGrafana(ctx, s.GrafanaImage)
if err != nil {
return fmt.Errorf("failed to setup grafana image: %w", err)
}
os.Setenv("OTEL_EXPORTER_OTLP_ENDPOINT", "http://localhost:4317")
}

wg, ctx := errgroup.WithContext(ctx)

Expand Down
17 changes: 8 additions & 9 deletions internal/container/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func Pull(ctx context.Context, imageName string) error {
}

// Run starts a new detached container with the given image, name, port map, and (optional) volume mount.
func Run(ctx context.Context, image, name string, hostPort, containerPort int, volume optional.Option[string]) error {
func Run(ctx context.Context, image, name string, hostToContainerPort map[int]int, volume optional.Option[string]) error {
cli, err := dockerClient.Get(ctx)
if err != nil {
return err
Expand All @@ -86,19 +86,17 @@ func Run(ctx context.Context, image, name string, hostPort, containerPort int, v
config := container.Config{
Image: image,
}
bindings := nat.PortMap{}
for k, v := range hostToContainerPort {
containerNatPort := nat.Port(fmt.Sprintf("%d/tcp", v))
bindings[containerNatPort] = []nat.PortBinding{{HostPort: strconv.Itoa(k)}}
}

containerNatPort := nat.Port(fmt.Sprintf("%d/tcp", containerPort))
hostConfig := container.HostConfig{
RestartPolicy: container.RestartPolicy{
Name: container.RestartPolicyAlways,
},
PortBindings: nat.PortMap{
containerNatPort: []nat.PortBinding{
{
HostPort: strconv.Itoa(hostPort),
},
},
},
PortBindings: bindings,
}
if v, ok := volume.Get(); ok {
hostConfig.Binds = []string{v}
Expand All @@ -120,6 +118,7 @@ func Run(ctx context.Context, image, name string, hostPort, containerPort int, v
// RunDB runs a new detached postgres container with the given name and exposed port.
func RunDB(ctx context.Context, name string, port int, image string) error {
cli, err := dockerClient.Get(ctx)

if err != nil {
return err
}
Expand Down
50 changes: 50 additions & 0 deletions internal/dev/grafana.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package dev

import (
"context"
"fmt"

"github.com/alecthomas/types/optional"

"github.com/TBD54566975/ftl/internal/container"
"github.com/TBD54566975/ftl/internal/log"
)

const ftlGrafanaName = "ftl-grafana-1"

func SetupGrafana(ctx context.Context, image string) error {
logger := log.FromContext(ctx)

exists, err := container.DoesExist(ctx, ftlGrafanaName, optional.Some(image))
if err != nil {
return fmt.Errorf("failed to check if container exists: %w", err)
}
// check if port is already in use
ports := []int{3000, 9090, 4317, 4318}

if !exists {
logger.Debugf("Creating docker container '%s' for grafana", ftlGrafanaName)

err = container.Run(ctx, image, ftlGrafanaName, map[int]int{3000: 3000, 9090: 9090, 4317: 4317, 4318: 4318}, optional.None[string]())
if err != nil {
return fmt.Errorf("failed to run grafana container: %w", err)
}

} else {
// Start the existing container
err = container.Start(ctx, ftlGrafanaName)
if err != nil {
return fmt.Errorf("failed to start existing registry container: %w", err)
}

logger.Debugf("Reusing existing docker container %s for grafana", ftlGrafanaName)
}

for _, port := range ports {
err = WaitForPortReady(ctx, port)
if err != nil {
return fmt.Errorf("registry container failed to be healthy: %w", err)
}
}
return nil
}
6 changes: 3 additions & 3 deletions internal/dev/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func SetupRegistry(ctx context.Context, image string, port int) error {
return fmt.Errorf("failed to close listener: %w", err)
}

err = container.Run(ctx, image, ftlRegistryName, port, 5000, optional.None[string]())
err = container.Run(ctx, image, ftlRegistryName, map[int]int{port: 5000}, optional.None[string]())
if err != nil {
return fmt.Errorf("failed to run registry container: %w", err)
}
Expand All @@ -54,15 +54,15 @@ func SetupRegistry(ctx context.Context, image string, port int) error {
logger.Debugf("Reusing existing docker container %s on port %d for image registry", ftlRegistryName, port)
}

err = WaitForRegistryReady(ctx, port)
err = WaitForPortReady(ctx, port)
if err != nil {
return fmt.Errorf("registry container failed to be healthy: %w", err)
}

return nil
}

func WaitForRegistryReady(ctx context.Context, port int) error {
func WaitForPortReady(ctx context.Context, port int) error {

timeout := time.After(10 * time.Minute)
retry := time.NewTicker(5 * time.Millisecond)
Expand Down

0 comments on commit e52b793

Please sign in to comment.