diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..37c813d --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,32 @@ +name: SQLens CI + +on: + push: + branches: [ master, main, develop ] + pull_request: + branches: [ master, main, develop ] + +jobs: + build-and-test: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.23' + cache: true + + - name: Install dependencies + run: go mod tidy + + - name: Run Tests + run: CGO_ENABLED=0 go test -v ./... + + - name: Build Binary + run: | + mkdir -p bin + CGO_ENABLED=0 go build -v -o bin/sqlens ./cmd/sqlens diff --git a/.gitignore b/.gitignore index 5c02dce..486159d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ bin/ -sqlens +/sqlens .DS_Store *.log diff --git a/cmd/sqlens/main.go b/cmd/sqlens/main.go new file mode 100644 index 0000000..a1047e0 --- /dev/null +++ b/cmd/sqlens/main.go @@ -0,0 +1,65 @@ +package main + +import ( + "context" + "log/slog" + "os" + "os/signal" + "syscall" + "time" + + "github.com/sqlens/sqlens/analyzer" + "github.com/sqlens/sqlens/config" + "github.com/sqlens/sqlens/proxy" + "github.com/sqlens/sqlens/store" + "github.com/sqlens/sqlens/web" +) + +func main() { + cfg := config.LoadConfig() + + // Initialize Storage + memStore := store.NewMemoryStore() + + // Initialize Analyzer Pipeline + pipeline := analyzer.NewPipeline( + analyzer.NewFingerprintAnalyzer(), + analyzer.NewN1DetectorAnalyzer( + time.Duration(cfg.N1WindowSecs)*time.Second, + cfg.N1Threshold, + ), + ) + + // Initialize TCP Proxy + proxyServer := proxy.NewServer(cfg.ListenAddr, cfg.TargetAddr, pipeline, memStore) + + // Initialize Web Dashboard + webServer := web.NewServer(":8080", memStore) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Start servers + go func() { + if err := webServer.Start(); err != nil { + slog.Error("Web server failed", "err", err) + } + }() + + go func() { + if err := proxyServer.Start(ctx); err != nil { + slog.Error("Proxy server failed", "err", err) + } + }() + + slog.Info("SQLens started", "web", ":8080", "proxy", cfg.ListenAddr, "target", cfg.TargetAddr) + + // Graceful shutdown + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) + <-sigChan + + slog.Info("Shutting down SQLens...") + cancel() + time.Sleep(time.Second) // wait for cleanup +}