Files
tyto/docs/development.md
vikingowl 52c10b3d55 docs: add comprehensive documentation
Documentation structure:
- docs/README.md - Documentation index
- docs/getting-started.md - Installation and first run
- docs/usage.md - Dashboard features and usage
- docs/configuration.md - Full configuration reference
- docs/multi-device.md - Agent setup and PKI management
- docs/security.md - Authentication, RBAC, mTLS
- docs/api.md - Complete REST API reference
- docs/deployment.md - Production deployment guide
- docs/troubleshooting.md - Common issues and solutions
- docs/development.md - Contributing and building

Total: ~80KB of documentation covering all features

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 09:23:02 +01:00

9.5 KiB

Development Guide

This guide covers building, testing, and contributing to Tyto.

Prerequisites

  • Go 1.23+
  • Node.js 22+
  • Docker & Docker Compose
  • Make (optional)
  • protoc (for gRPC development)

Getting the Source

git clone https://somegit.dev/vikingowl/tyto.git
cd tyto

Project Structure

tyto/
├── backend/
│   ├── cmd/
│   │   ├── server/          # HTTP/SSE server entry point
│   │   ├── agent/           # Lightweight agent entry point
│   │   └── tyto/            # CLI tool
│   ├── internal/
│   │   ├── api/             # HTTP handlers and routes
│   │   ├── alerts/          # Alert management
│   │   ├── auth/            # Authentication (local, LDAP)
│   │   ├── collectors/      # Metric collectors
│   │   │   ├── gpu/         # Multi-vendor GPU support
│   │   │   └── logs/        # Log collectors
│   │   ├── config/          # Configuration loading
│   │   ├── database/        # SQLite/PostgreSQL
│   │   ├── history/         # Historical data storage
│   │   ├── models/          # Data structures
│   │   ├── pki/             # Certificate management
│   │   ├── server/          # gRPC hub for agents
│   │   └── sse/             # Server-Sent Events broker
│   ├── proto/               # gRPC protocol definitions
│   ├── go.mod
│   └── Dockerfile
├── frontend/
│   ├── src/
│   │   ├── lib/
│   │   │   ├── api/         # API clients
│   │   │   ├── components/  # Svelte components
│   │   │   ├── stores/      # Svelte stores
│   │   │   ├── types/       # TypeScript types
│   │   │   └── utils/       # Utility functions
│   │   └── routes/          # SvelteKit routes
│   ├── package.json
│   └── Dockerfile
├── docs/                    # Documentation
├── scripts/                 # Build and install scripts
├── docker-compose.yml
└── docker-compose.prod.yml

Backend Development

Running Locally

cd backend

# Install dependencies
go mod download

# Run the server
go run ./cmd/server

# Run with specific config
go run ./cmd/server --config ../config.dev.yaml

Building

# Build server binary
go build -o tyto ./cmd/server

# Build agent binary
go build -o tyto-agent ./cmd/agent

# Build CLI
go build -o tyto-cli ./cmd/tyto

# Build with optimizations
CGO_ENABLED=0 go build -ldflags="-s -w" -o tyto ./cmd/server

Cross-Compilation

# Linux AMD64
GOOS=linux GOARCH=amd64 go build -o tyto-linux-amd64 ./cmd/server

# Linux ARM64
GOOS=linux GOARCH=arm64 go build -o tyto-linux-arm64 ./cmd/server

# macOS
GOOS=darwin GOARCH=amd64 go build -o tyto-darwin-amd64 ./cmd/server

Running Tests

# All tests
go test ./...

# With coverage
go test -cover ./...

# Specific package
go test ./internal/collectors/...

# Verbose output
go test -v ./internal/api/...

Linting

# Install golangci-lint
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest

# Run linter
golangci-lint run

gRPC Development

# Install protoc plugins
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

# Generate Go code from proto files
protoc --go_out=. --go-grpc_out=. proto/*.proto

Frontend Development

Running Locally

cd frontend

# Install dependencies
npm install

# Start development server
npm run dev

# With specific API URL
VITE_API_URL=http://localhost:8080 npm run dev

Building

# Production build
npm run build

# Preview production build
npm run preview

Running Tests

# Unit tests
npm test

# Watch mode
npm run test:watch

# With coverage
npm run test:coverage

Linting & Formatting

# Lint
npm run lint

# Format
npm run format

# Type check
npm run check

Docker Development

Building Images

# Build all images
docker compose build

# Build specific service
docker compose build backend
docker compose build frontend

# Build without cache
docker compose build --no-cache

Running with Docker

# Start all services
docker compose up

# Start in background
docker compose up -d

# View logs
docker compose logs -f

# Stop services
docker compose down

Development with Hot Reload

# Mount source for hot reload
docker compose -f docker-compose.yml -f docker-compose.dev.yml up

Adding a New Collector

  1. Create collector file in backend/internal/collectors/:
// backend/internal/collectors/example.go
package collectors

import "github.com/vikingowl/tyto/internal/models"

type ExampleCollector struct {
    // collector state
}

func NewExampleCollector() *ExampleCollector {
    return &ExampleCollector{}
}

func (c *ExampleCollector) Collect() (*models.ExampleStats, error) {
    // Collect metrics from system
    return &models.ExampleStats{
        // ...
    }, nil
}
  1. Add model in backend/internal/models/:
// backend/internal/models/example.go
package models

type ExampleStats struct {
    Available bool   `json:"available"`
    Value     int    `json:"value"`
}
  1. Integrate in backend/internal/collectors/all.go:
func (c *AllCollectors) Collect() *models.AllMetrics {
    metrics := &models.AllMetrics{
        // ...existing...
        Example: c.example.Collect(),
    }
    return metrics
}
  1. Add frontend component in frontend/src/lib/components/.

Adding a New API Endpoint

  1. Add handler in backend/internal/api/:
// backend/internal/api/example.go
package api

import (
    "github.com/gin-gonic/gin"
)

func (s *Server) exampleHandler(c *gin.Context) {
    // Handle request
    c.JSON(200, gin.H{"status": "ok"})
}
  1. Register route in backend/internal/api/routes.go:
func (s *Server) setupRoutes() {
    // ...existing routes...

    api := s.router.Group("/api/v1")
    api.GET("/example", s.exampleHandler)
}
  1. Add frontend API client in frontend/src/lib/api/:
// frontend/src/lib/api/example.ts
export async function getExample(): Promise<ExampleResponse> {
    const response = await fetch('/api/v1/example');
    return response.json();
}

Testing

Backend Unit Tests

// backend/internal/collectors/cpu_test.go
package collectors

import (
    "testing"
)

func TestCPUCollector(t *testing.T) {
    collector := NewCPUCollector("/proc")
    stats, err := collector.Collect()

    if err != nil {
        t.Fatalf("Collect() failed: %v", err)
    }

    if len(stats.Cores) == 0 {
        t.Error("Expected at least one CPU core")
    }
}

Frontend Component Tests

// frontend/src/lib/components/CpuCard.test.ts
import { render } from '@testing-library/svelte';
import CpuCard from './CpuCard.svelte';

test('renders CPU usage', () => {
    const { getByText } = render(CpuCard, {
        props: {
            cpu: { totalUsage: 50, cores: [] }
        }
    });

    expect(getByText('50%')).toBeInTheDocument();
});

Integration Tests

# Start test environment
docker compose -f docker-compose.test.yml up -d

# Run integration tests
go test -tags=integration ./tests/...

# Cleanup
docker compose -f docker-compose.test.yml down

Code Style

Go

  • Follow Effective Go
  • Use gofmt for formatting
  • Use meaningful variable names
  • Keep functions small and focused
  • Document exported functions and types

TypeScript/Svelte

  • Use TypeScript strict mode
  • Follow Svelte conventions
  • Use Prettier for formatting
  • Prefer composition over inheritance
  • Keep components focused

Commit Messages

Follow Conventional Commits:

feat: add GPU temperature monitoring
fix: resolve memory leak in SSE broker
docs: update API documentation
refactor: simplify collector interface
test: add integration tests for auth

Pull Request Process

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/my-feature
  3. Make changes and commit
  4. Run tests: go test ./... and npm test
  5. Run linters: golangci-lint run and npm run lint
  6. Push to your fork
  7. Open a Pull Request

PR Checklist

  • Tests pass
  • Linting passes
  • Documentation updated
  • Commit messages follow convention
  • No breaking changes (or documented)

Release Process

  1. Update version in internal/version/version.go
  2. Update CHANGELOG.md
  3. Create git tag: git tag v1.2.3
  4. Push tag: git push origin v1.2.3
  5. CI builds and publishes releases

Debugging

Backend

# Run with debug logging
TYTO_LOG_LEVEL=debug go run ./cmd/server

# Use delve debugger
dlv debug ./cmd/server

Frontend

  • Use browser DevTools
  • React/Svelte DevTools extension
  • console.log for quick debugging

Docker

# Shell into container
docker exec -it tyto-backend /bin/sh

# View container logs
docker logs tyto-backend -f

# Inspect container
docker inspect tyto-backend

Performance Profiling

Go Profiling

import _ "net/http/pprof"

// Access at http://localhost:8080/debug/pprof/
# CPU profile
go tool pprof http://localhost:8080/debug/pprof/profile?seconds=30

# Memory profile
go tool pprof http://localhost:8080/debug/pprof/heap

Frontend Performance

  • Use Lighthouse in Chrome DevTools
  • React Profiler for component performance
  • Network tab for API timing