{"id":49336197,"url":"https://github.com/olegiv/logwatch-ai-go","last_synced_at":"2026-04-27T01:01:45.611Z","repository":{"id":323923313,"uuid":"1095246054","full_name":"olegiv/logwatch-ai-go","owner":"olegiv","description":"Logwatch AI Analyzer - An automated system that analyzes Logwatch and Drupal Watchdog reports using Claude AI and sends summarized insights via Telegram channel.","archived":false,"fork":false,"pushed_at":"2026-04-20T11:32:27.000Z","size":477,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-04-20T13:36:22.536Z","etag":null,"topics":["ai","analysis","analyzer","claude","claude-ai","claude-api","claude-code","drupal","drush","go","golang","jq","llama3","log","logger","logging","logwatch","ollama","telegram","watchdog"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/olegiv.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-11-12T19:41:20.000Z","updated_at":"2026-04-20T11:29:32.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/olegiv/logwatch-ai-go","commit_stats":null,"previous_names":["olegiv/logwatch-ai-go"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/olegiv/logwatch-ai-go","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/olegiv%2Flogwatch-ai-go","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/olegiv%2Flogwatch-ai-go/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/olegiv%2Flogwatch-ai-go/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/olegiv%2Flogwatch-ai-go/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/olegiv","download_url":"https://codeload.github.com/olegiv/logwatch-ai-go/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/olegiv%2Flogwatch-ai-go/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32318417,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T23:26:28.701Z","status":"ssl_error","status_checked_at":"2026-04-26T23:26:25.802Z","response_time":129,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","analysis","analyzer","claude","claude-ai","claude-api","claude-code","drupal","drush","go","golang","jq","llama3","log","logger","logging","logwatch","ollama","telegram","watchdog"],"created_at":"2026-04-27T01:01:44.752Z","updated_at":"2026-04-27T01:01:45.586Z","avatar_url":"https://github.com/olegiv.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Logwatch AI Analyzer (Go)\n\n[![Go](https://github.com/olegiv/logwatch-ai-go/actions/workflows/go.yml/badge.svg)](https://github.com/olegiv/logwatch-ai-go/actions/workflows/go.yml)\n[![CodeQL](https://github.com/olegiv/logwatch-ai-go/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/olegiv/logwatch-ai-go/actions/workflows/github-code-scanning/codeql)\n[![Dependency review](https://github.com/olegiv/logwatch-ai-go/actions/workflows/dependency-review.yml/badge.svg)](https://github.com/olegiv/logwatch-ai-go/actions/workflows/dependency-review.yml)\n\nAn intelligent log analyzer that uses LLM (Large Language Models) to analyze log reports and send actionable insights via Telegram. This is a Go port of the original Node.js [logwatch-ai](https://github.com/olegiv/logwatch-ai) project.\n\n**Supported Log Sources:**\n- **Logwatch** - Linux system log aggregation (syslog, auth, mail, etc.)\n- **Drupal Watchdog** - PHP/Drupal application logs (JSON or drush export)\n\n**Supported LLM Providers:**\n- **Anthropic Claude** - Cloud-based AI (Claude Haiku 4.5 default; Sonnet 4.6 and Opus 4.7 supported)\n- **Ollama** - Local LLM inference for privacy and zero-cost operation\n- **LM Studio** - Local LLM inference with user-friendly GUI\n\n## Features\n\n- **AI-Powered Analysis**: Uses LLM to analyze log reports (Claude AI or local models)\n- **Multiple LLM Providers**: Choose between Anthropic Claude (cloud), Ollama (local), or LM Studio (local)\n- **Multi-Source Support**: Analyze Logwatch reports or Drupal watchdog logs\n- **Smart Notifications**: Dual-channel Telegram notifications (archive + alerts)\n- **Historical Tracking**: SQLite database stores analysis history for trend detection\n- **Intelligent Preprocessing**: Handles large log files (up to 800KB-1MB) with smart content reduction\n- **Cost Optimization**: Implements Claude prompt caching (16-30% cost savings)\n- **Proxy Support**: Full HTTP/HTTPS proxy support for corporate environments\n- **Secure Logging**: Automatic credential sanitization prevents API keys from appearing in logs\n- **Rate Limiting**: Telegram API rate limiting with exponential backoff retry\n- **Prompt Injection Protection**: Input sanitization filters adversarial content from logs\n- **Pure Go**: No CGO dependencies, easy cross-platform deployment\n\n## Quick Start\n\n### Prerequisites\n\n- Go 1.25+ (for building from source)\n- Logwatch installed and configured\n- **LLM Provider** (choose one):\n  - Anthropic API key (for cloud-based Claude AI), OR\n  - Ollama installed locally (for free local inference), OR\n  - LM Studio installed locally (for free local inference with GUI)\n- Telegram bot token and channel IDs\n\n### Installation\n\n1. **Clone the repository**\n```bash\ngit clone --recurse-submodules https://github.com/olegiv/logwatch-ai-go.git\ncd logwatch-ai-go\n\n# If already cloned without --recurse-submodules:\ngit submodule update --init --recursive\n\n# Update submodule to latest version:\ngit submodule update --remote --merge\n```\n\n2. **Build the local/dev binary**\n```bash\nmake build\n```\n\n3. **Configure environment**\n```bash\ncp configs/.env.example .env\n# Edit .env with your credentials\n```\n\n4. **Install system-wide** (optional)\n```bash\nsudo make install\n```\n\n### Configuration\n\nCreate a `.env` file with the following settings:\n\n```bash\n# LLM Provider Selection\n# Options: \"anthropic\" (default), \"ollama\", or \"lmstudio\"\nLLM_PROVIDER=anthropic\n\n# Anthropic/Claude Configuration (used when LLM_PROVIDER=anthropic)\nANTHROPIC_API_KEY=sk-ant-xxxxx\nCLAUDE_MODEL=claude-haiku-4-5-20251001\n\n# Ollama Configuration (used when LLM_PROVIDER=ollama)\n# Requires Ollama running locally: https://ollama.ai\nOLLAMA_BASE_URL=http://localhost:11434\nOLLAMA_MODEL=llama3.3:latest\n\n# LM Studio Configuration (used when LLM_PROVIDER=lmstudio)\n# Requires LM Studio running locally: https://lmstudio.ai\n# See \"LM Studio Setup\" section for recommended models\nLMSTUDIO_BASE_URL=http://localhost:1234\nLMSTUDIO_MODEL=local-model\n\n# AI Settings (applies to all providers)\nAI_TIMEOUT_SECONDS=120\nAI_MAX_TOKENS=8000\n\n# Telegram\nTELEGRAM_BOT_TOKEN=1234567890:ABC-DEF1234ghIkl-zyx57W2v1u123ew11\nTELEGRAM_CHANNEL_ARCHIVE_ID=-1001234567890    # Required\nTELEGRAM_CHANNEL_ALERTS_ID=-1009876543210     # Optional\n\n# Log Source Configuration\n# Options: \"logwatch\" (default), \"drupal_watchdog\", or \"ocms\"\nLOG_SOURCE_TYPE=logwatch\n\n# Logwatch Configuration (used when LOG_SOURCE_TYPE=logwatch)\nLOGWATCH_OUTPUT_PATH=/tmp/logwatch-output.txt\n\n# OCMS Configuration (used when LOG_SOURCE_TYPE=ocms)\n# Single-site mode uses OCMS_LOGS_PATH directly.\n# Multi-site mode uses ocms-sites.json with log kinds: main, error, or all.\nOCMS_LOGS_PATH=/tmp/ocms.log\n\n# Drupal Watchdog Configuration (used when LOG_SOURCE_TYPE=drupal_watchdog)\n# Configure in drupal-sites.json (see configs/drupal-sites.json.example)\n\n# Common Log Settings\nMAX_LOG_SIZE_MB=10\n\n# Application\nLOG_LEVEL=info\nENABLE_DATABASE=true\nDATABASE_PATH=./data/summaries.db\n\n# Preprocessing\nENABLE_PREPROCESSING=true\nMAX_PREPROCESSING_TOKENS=150000\n\n# Proxy (optional)\nHTTP_PROXY=http://proxy.example.com:8080\nHTTPS_PROXY=http://proxy.example.com:8080\n```\n\n### Setting up Telegram\n\n1. **Create a Telegram bot**:\n   - Message [@BotFather](https://t.me/BotFather)\n   - Send `/newbot` and follow the instructions\n   - Save the bot token\n\n2. **Create Telegram channel(s)**:\n   - Create a channel for archives\n   - (Optional) Create a separate channel for alerts\n   - Add your bot as an administrator to both channels\n\n3. **Get channel IDs**:\n   - Forward a message from your channel to [@userinfobot](https://t.me/userinfobot)\n   - The bot will reply with the channel ID (should start with `-100`)\n\n### Ollama Setup (Optional)\n\nFor free local inference without cloud API costs, you can use Ollama:\n\n1. **Install Ollama**:\n```bash\n# macOS\nbrew install ollama\n\n# Linux\ncurl -fsSL https://ollama.ai/install.sh | sh\n```\n\n2. **Pull a model** (recommended for systems with 64GB+ RAM):\n```bash\n# Best quality for log analysis (requires ~40GB RAM)\nollama pull llama3.3:latest\n\n# Alternative for lower-RAM systems\nollama pull llama3.2:8b\n```\n\n3. **Start Ollama server**:\n```bash\nollama serve\n```\n\n4. **Configure in `.env`**:\n```bash\nLLM_PROVIDER=ollama\nOLLAMA_BASE_URL=http://localhost:11434\nOLLAMA_MODEL=llama3.3:latest\n```\n\n**Recommended Models:**\n| Model | RAM Required | Quality | Speed |\n|-------|-------------|---------|-------|\n| `llama3.3:latest` | ~45GB | Excellent | Slower |\n| `qwen2.5:72b` | ~45GB | Excellent | Slower |\n| `deepseek-coder-v2:33b` | ~20GB | Good | Faster |\n| `llama3.2:8b` | ~5GB | Acceptable | Fast |\n\n**Trade-offs vs Claude:**\n- ✅ Zero cost - unlimited analysis\n- ✅ Data privacy - logs never leave your machine\n- ✅ No rate limits or API quotas\n- ⚠️ Slower than cloud (depends on hardware)\n- ⚠️ Quality varies by model (larger models = better)\n- ⚠️ Requires powerful hardware for best results\n\n### LM Studio Setup (Optional)\n\nLM Studio provides a user-friendly desktop application for running local LLMs:\n\n1. **Download and install LM Studio** from https://lmstudio.ai\n\n2. **Load a model** in LM Studio:\n   - Open LM Studio\n   - Browse and download a model (e.g., Llama 3.3, Mistral, Qwen)\n   - Click \"Load\" to load the model into memory\n\n3. **Enable Local Server**:\n   - Click on \"Local Server\" in the left sidebar\n   - Click \"Start Server\" (default port: 1234)\n\n4. **Configure in `.env`**:\n```bash\nLLM_PROVIDER=lmstudio\nLMSTUDIO_BASE_URL=http://localhost:1234\nLMSTUDIO_MODEL=local-model\n```\n\n**Note:** The `local-model` identifier uses whatever model is currently loaded in LM Studio. You can also specify a specific model name if multiple models are loaded.\n\n**Recommended Models:**\n| Model | VRAM Required | Quality | Speed |\n|-------|---------------|---------|-------|\n| Llama-3.3-70B-Instruct | ~40GB | Excellent | Slower |\n| Qwen2.5-32B-Instruct | ~20GB | Excellent | Medium |\n| Mistral-Small-24B-Instruct | ~15GB | Good | Medium |\n| Phi-4-14B | ~9GB | Good | Faster |\n| Llama-3.2-8B-Instruct | ~5GB | Acceptable | Fast |\n\n**Tips for model selection:**\n- Download models from LM Studio's built-in model browser (Search tab)\n- Look for GGUF quantized versions (Q4_K_M or Q5_K_M) for better VRAM efficiency\n- For Apple Silicon Macs, models run on unified memory (RAM = VRAM)\n- Start with a smaller model to test, then upgrade for better quality\n\n**Trade-offs vs Claude:**\n- ✅ Zero cost - unlimited analysis\n- ✅ Data privacy - logs never leave your machine\n- ✅ User-friendly GUI for model management\n- ✅ Easy model switching without CLI commands\n- ✅ OpenAI-compatible API\n- ⚠️ Slower than cloud (depends on hardware)\n- ⚠️ Quality varies by model\n- ⚠️ Requires powerful hardware for large models\n\n### Cron Setup\n\nRun logwatch analysis daily at 2:00 AM:\n\n**Root crontab** (generate logwatch report):\n```bash\n0 2 * * * /opt/logwatch-ai/scripts/generate-logwatch.sh\n```\n\n**User crontab** (run analyzer):\n```bash\n15 2 * * * cd /opt/logwatch-ai \u0026\u0026 ./logwatch-analyzer \u003e\u003e logs/cron.log 2\u003e\u00261\n```\n\nSee [docs/CRON_SETUP.md](docs/CRON_SETUP.md) for detailed setup instructions.\n\n### Drupal Watchdog Setup\n\nTo analyze Drupal watchdog logs instead of logwatch:\n\n**Prerequisites:**\n- `jq` installed (required for multi-site configuration parsing)\n  - Debian/Ubuntu: `apt-get install jq`\n  - macOS: `brew install jq` or `port install jq`\n- drush installed in Drupal project\n\n1. **Configure drupal-sites.json** (see `configs/drupal-sites.json.example`):\n```json\n{\n  \"version\": \"1.0\",\n  \"default_site\": \"production\",\n  \"sites\": {\n    \"production\": {\n      \"name\": \"Production Site\",\n      \"drupal_root\": \"/var/www/html\",\n      \"watchdog_path\": \"/var/log/drupal-watchdog.json\",\n      \"watchdog_format\": \"json\",\n      \"min_severity\": 3,\n      \"watchdog_limit\": 100\n    }\n  }\n}\n```\n\n2. **Set up cron jobs**:\n```bash\n# Export watchdog logs daily at 2:00 AM\n0 2 * * * /opt/logwatch-ai/scripts/generate-drupal-watchdog.sh --site production\n\n# Run analyzer at 2:15 AM\n15 2 * * * cd /opt/logwatch-ai \u0026\u0026 ./logwatch-analyzer -source-type drupal_watchdog -drupal-site production \u003e\u003e logs/cron.log 2\u003e\u00261\n```\n\n**Drupal Watchdog JSON Format:**\n```json\n[\n  {\n    \"wid\": 1234,\n    \"uid\": 1,\n    \"type\": \"php\",\n    \"message\": \"PDOException: SQLSTATE[HY000] [2002] Connection refused\",\n    \"variables\": \"a:0:{}\",\n    \"severity\": 3,\n    \"link\": \"\",\n    \"location\": \"https://example.com/\",\n    \"referer\": \"\",\n    \"hostname\": \"127.0.0.1\",\n    \"timestamp\": 1699900800\n  }\n]\n```\n\n### Multi-Site Drupal Support\n\nFor organizations managing multiple Drupal sites, the analyzer supports a centralized configuration file.\n\n1. **Create `drupal-sites.json`** (search locations: `./`, `./configs/`, `/opt/logwatch-ai/`):\n```json\n{\n  \"version\": \"1.0\",\n  \"default_site\": \"production\",\n  \"sites\": {\n    \"production\": {\n      \"name\": \"Production Site\",\n      \"drupal_root\": \"/var/www/production/drupal\",\n      \"watchdog_path\": \"/var/log/drupal/production-watchdog.json\",\n      \"watchdog_format\": \"json\",\n      \"min_severity\": 3,\n      \"watchdog_limit\": 100\n    },\n    \"staging\": {\n      \"name\": \"Staging Site\",\n      \"drupal_root\": \"/var/www/staging/drupal\",\n      \"watchdog_path\": \"/var/log/drupal/staging-watchdog.json\",\n      \"watchdog_format\": \"json\",\n      \"min_severity\": 4,\n      \"watchdog_limit\": 200\n    }\n  }\n}\n```\n\n2. **List available sites**:\n```bash\n# Analyzer\n./logwatch-analyzer -list-drupal-sites\n\n# Export script\n./scripts/generate-drupal-watchdog.sh --list-sites\n```\n\n3. **Analyze a specific site**:\n```bash\n./logwatch-analyzer -source-type drupal_watchdog -drupal-site production\n```\n\n4. **Export watchdog for a specific site**:\n```bash\n./scripts/generate-drupal-watchdog.sh --site production\n```\n\n5. **Automated multi-site cron** (analyze all sites daily):\n```bash\n# Export watchdog for each site at 2:00 AM\n0 2 * * * /opt/logwatch-ai/scripts/generate-drupal-watchdog.sh --site production\n5 2 * * * /opt/logwatch-ai/scripts/generate-drupal-watchdog.sh --site staging\n\n# Analyze each site at 2:15 AM\n15 2 * * * cd /opt/logwatch-ai \u0026\u0026 ./logwatch-analyzer -drupal-site production \u003e\u003e logs/cron.log 2\u003e\u00261\n20 2 * * * cd /opt/logwatch-ai \u0026\u0026 ./logwatch-analyzer -drupal-site staging \u003e\u003e logs/cron.log 2\u003e\u00261\n```\n\n**Site Configuration Fields:**\n| Field | Required | Description |\n|-------|----------|-------------|\n| `name` | No | Human-readable site name for reports |\n| `drupal_root` | Yes | Path to Drupal installation root |\n| `watchdog_path` | Yes | Path to watchdog export file |\n| `watchdog_format` | No | `json` (default) or `drush` |\n| `min_severity` | No | RFC 5424 severity level 0-7 (default: 3=error) |\n| `watchdog_limit` | No | Max entries in output (default: 100) |\n\n### Multi-Site OCMS Support\n\nFor OCMS multi-site analysis, use `ocms-sites.json` for logwatch-ai site\nselection and `/etc/ocms/sites.conf` as the external OCMS registry. Do not put\nper-site log paths in JSON; the analyzer derives them from the registry\n`INSTANCE_DIR`.\n\n```json\n{\n  \"version\": \"1.0\",\n  \"default_site\": \"example_com\",\n  \"registry_path\": \"/etc/ocms/sites.conf\",\n  \"default_log_kind\": \"main\",\n  \"sites\": {\n    \"example_com\": {\n      \"name\": \"Example Site\"\n    },\n    \"app_example_com\": {\n      \"name\": \"Example App\",\n      \"log_kind\": \"all\"\n    },\n    \"blog_example_com\": {\n      \"name\": \"Example Blog\",\n      \"log_kind\": \"error\"\n    }\n  }\n}\n```\n\nDerived OCMS logs:\n\n- `main`: `\u003cINSTANCE_DIR\u003e/logs/ocms.log`\n- `error`: `\u003cINSTANCE_DIR\u003e/logs/error.log`\n- `all`: both files above, read in that order and analyzed in one report\n\n**OCMS Configuration Fields:**\n\n| Field | Required | Description |\n|-------|----------|-------------|\n| `version` | Yes | Config schema version. Use `\"1.0\"`. |\n| `default_site` | No | Default OCMS site ID from `sites` when `-ocms-site` is not provided. |\n| `registry_path` | No | External OCMS registry path. Defaults to `/etc/ocms/sites.conf`. |\n| `default_log_kind` | No | Default log kind for sites without `sites.\u003cid\u003e.log_kind`. Allowed: `main`, `error`, `all`. Defaults to `main`. |\n| `sites` | Yes | Map keyed by OCMS site ID. IDs must exist in `/etc/ocms/sites.conf`. |\n| `sites.\u003cid\u003e.name` | No | Human-readable site name for reports. |\n| `sites.\u003cid\u003e.log_kind` | No | Per-site log kind override. Allowed: `main`, `error`, `all`. |\n\nLog-kind precedence: CLI `-ocms-log-kind`, then `sites.\u003cid\u003e.log_kind`, then\n`default_log_kind`, then built-in default `main`.\n\n## Usage\n\n### Manual Run\n\n```bash\n# From the project directory\n./bin/logwatch-analyzer\n\n# Or if installed system-wide\nlogwatch-analyzer\n```\n\n### Command-Line Options\n\n```bash\n./logwatch-analyzer [options]\n\nOptions:\n  -source-type string        Log source type: logwatch, drupal_watchdog, ocms\n  -source-path string        Path to log source file (overrides env config)\n  -drupal-site string        Drupal site ID from drupal-sites.json\n  -drupal-sites-config string  Path to drupal-sites.json configuration file\n  -list-drupal-sites         List available Drupal sites and exit\n  -ocms-site string          OCMS site ID from ocms-sites.json\n  -ocms-sites-config string  Path to ocms-sites.json configuration file\n  -ocms-log-kind string      OCMS log kind: main, error, or all\n  -list-ocms-sites           List available OCMS sites and exit\n  -h, -help                  Show usage information\n  -v, -version               Show version information\n```\n\n**Examples:**\n```bash\n# Analyze logwatch with default config\n./logwatch-analyzer\n\n# Override source type\n./logwatch-analyzer -source-type drupal_watchdog\n\n# Analyze OCMS site logs\n./logwatch-analyzer -source-type ocms -ocms-site example_com\n\n# Analyze both OCMS main and error logs in one report\n./logwatch-analyzer -source-type ocms -ocms-site example_com -ocms-log-kind all\n\n# List OCMS sites and derived log paths\n./logwatch-analyzer -list-ocms-sites\n\n# Analyze specific Drupal site\n./logwatch-analyzer -drupal-site production\n\n# Use custom watchdog file\n./logwatch-analyzer -source-type drupal_watchdog -source-path /tmp/custom-watchdog.json\n\n# List available Drupal sites\n./logwatch-analyzer -list-drupal-sites\n```\n\n### Build Options\n\n```bash\nmake build                # Fast local/dev build\nmake build-prod           # Optimized host production build\nmake build-linux-amd64    # Optimized static Linux AMD64 production build\nmake build-darwin-arm64   # Optimized Darwin ARM64 production build\nmake build-all-platforms  # Linux AMD64 + Darwin ARM64 production builds\nmake test                 # Run tests\nmake test-race            # Run tests with race detector\nmake coverage             # Run tests with coverage summary\nmake coverage-html        # Write coverage.out + coverage.html\nmake fmt                  # Format with gofumpt\nmake fmt-check            # Fail if gofumpt would reformat files\nmake vet                  # Run go vet\nmake lint                 # Run all linters\nmake check                # fmt-check + vet + lint + test\nmake deps                 # Download Go module dependencies\nmake tidy                 # Tidy Go modules\nmake install-tools        # Install pinned developer tools\nmake help                 # Show Makefile targets\nmake clean                # Clean build artifacts\nmake install              # Install to /opt/logwatch-ai\n```\n\n### Cross-Platform Builds\n\nGo's built-in cross-compilation makes it easy to build for different platforms:\n\n**Linux AMD64** (Debian 12, Ubuntu 24, most Linux distributions):\n```bash\nmake build-linux-amd64\n# Output: bin/logwatch-analyzer-linux-amd64\n```\n\n**macOS ARM64** (Apple Silicon - M1, M2, M3):\n```bash\nmake build-darwin-arm64\n# Output: bin/logwatch-analyzer-darwin-arm64\n```\n\n**All platforms at once**:\n```bash\nmake build-all-platforms\n# Outputs both binaries and shows file sizes\n```\n\nAll cross-platform builds include production optimizations:\n- `-ldflags=\"-s -w\"` - Strips symbols and debug information\n- `-trimpath` - Removes file system paths from binary\n- Result: Smaller binaries (~20-40% size reduction) and improved security\n\n## Architecture\n\n### Project Structure\n\n```\nlogwatch-ai-go/\n├── cmd/\n│   └── analyzer/           # Main application entry point\n├── internal/\n│   ├── ai/                 # Claude AI client and prompts\n│   ├── analyzer/           # Multi-source abstraction (interfaces)\n│   ├── config/             # Configuration management\n│   ├── drupal/             # Drupal watchdog reader and prompts\n│   ├── errors/             # Error sanitization (credential redaction)\n│   ├── logging/            # Secure logger (credential filtering)\n│   ├── logwatch/           # Logwatch file reading and preprocessing\n│   ├── ocms/               # OCMS log reader, prompt, and preprocessing adapters\n│   ├── notification/       # Telegram notifications\n│   └── storage/            # SQLite database operations\n├── scripts/                # Helper scripts\n├── configs/                # Configuration templates\n├── docs/                   # Documentation\n├── testdata/               # Test fixtures\n└── Makefile               # Build automation\n```\n\n### How It Works\n\n1. **Log Generation**:\n   - *Logwatch*: Root cron runs `generate-logwatch.sh` to create daily report\n   - *OCMS*: Single-site mode reads `OCMS_LOGS_PATH`; multisite mode derives\n     logs from `ocms-sites.json` and `/etc/ocms/sites.conf`\n   - *Drupal*: drush exports watchdog entries to JSON file\n2. **Source Selection**: Application loads appropriate reader based on `LOG_SOURCE_TYPE`\n3. **File Reading**: Source-specific reader validates and parses log content\n4. **Preprocessing**: Large files are intelligently compressed with source-aware priority\n5. **Historical Context**: Retrieves last 7 days of analysis from database\n6. **AI Analysis**: Claude (Haiku 4.5 by default) analyzes with source-specific prompts\n7. **Storage**: Results saved to SQLite database\n8. **Notifications**: Sent to Telegram (archive channel always, alerts channel conditionally)\n9. **Cleanup**: Old database entries (\u003e90 days) are removed\n\n## Cost Estimation\n\n### Anthropic Claude (Cloud)\n\n**Pricing (per 1M tokens):**\n\n| Model                         | Input | Output | Cache write | Cache read |\n|-------------------------------|------:|-------:|------------:|-----------:|\n| claude-haiku-4-5-20251001 (default) | $1  | $5   | $1.25       | $0.10      |\n| claude-sonnet-4-6             | $3    | $15    | $3.75       | $0.30      |\n| claude-opus-4-7               | $5    | $25    | $6.25       | $0.50      |\n\nCanonical pricing table lives in `internal/ai/pricing.go`.\n\n**Typical Costs (Haiku 4.5 default):**\n- **First run**: ~$0.005 (cache creation)\n- **Cached run**: ~$0.003-$0.005 (cache hits)\n- **Monthly (daily)**: ~$0.15/month\n- **Yearly**: ~$1.80/year\n\nSonnet 4.6 multiplies these by ~3; Opus 4.7 by ~5.\n\n### Ollama / LM Studio (Local)\n\n**Cost: $0.00** - Local inference has no monetary cost.\n\nTrade-off: Requires capable hardware (see [Ollama Setup](#ollama-setup-optional) or [LM Studio Setup](#lm-studio-setup-optional) for requirements).\n\n## Telegram Notification Format\n\n```\n🔍 Logwatch Report\n🖥 Host: server01\n📅 Date: 2025-11-12 02:15:00\n🌍 Timezone: Europe/London\n🟢 Status: Good\n\n📋 Execution Stats\n• LLM: claude-haiku-4-5-20251001 (Anthropic)\n• Critical Issues: 0\n• Warnings: 2\n• Recommendations: 3\n• Cost: $0.0154\n• Duration: 12.62s\n• Cache Read: 1234 tokens\n\n📊 Summary\nSystem is operating normally with minor warnings...\n\n⚡ Warnings (2)\n1. Disk usage at 85% on /var partition\n2. 5 failed SSH attempts from 192.168.1.50\n\n💡 Recommendations\n1. Clean up old log files in /var/log\n2. Monitor IP 192.168.1.50 for activity\n\n📈 Key Metrics\n• Failed Logins: 5\n• Disk Usage: 85% on /var\n• Error Count: 0\n```\n\nFor Drupal Watchdog with multi-site, the header shows site name:\n```\n🔍 Drupal Watchdog Report - Production Site\n```\n\n## Differences from Node.js Version\n\nThis Go implementation provides feature parity with the original Node.js version while offering:\n\n### Advantages\n\n- **Pure Go**: No CGO dependencies (using modernc.org/sqlite)\n- **Simpler Deployment**: Single binary, no runtime dependencies\n- **Better Performance**: Faster startup and lower memory usage\n- **Type Safety**: Compile-time type checking\n- **Smaller Binary**: ~10-15MB (vs ~120MB Node.js SEA)\n- **Easier Cross-Compilation**: Build for any platform\n\n### Maintained Features\n\n- ✅ Identical AI prompts and analysis logic\n- ✅ Same database schema (compatible with Node.js version)\n- ✅ Same preprocessing algorithm\n- ✅ Same notification format and dual-channel logic\n- ✅ Same cost tracking and token estimation\n- ✅ Prompt caching support\n- ✅ Proxy configuration\n\n## Development\n\n### Running Tests\n\n```bash\n# Run all tests\nmake test\n\n# Run with coverage\nmake coverage\nmake coverage-html\n\n# Run specific package tests\ngo test -v ./internal/ai\ngo test -v ./internal/logwatch\n```\n\n### Project Dependencies\n\n- **github.com/liushuangls/go-anthropic/v2** - Anthropic Claude SDK\n- **github.com/go-telegram-bot-api/telegram-bot-api/v5** - Telegram Bot API\n- **modernc.org/sqlite** - Pure Go SQLite implementation\n- **github.com/spf13/viper** - Configuration management\n- **github.com/rs/zerolog** - Structured logging\n- **gopkg.in/natefinch/lumberjack.v2** - Log rotation\n\n## Troubleshooting\n\n### Common Issues\n\n**\"Configuration validation failed: ANTHROPIC_API_KEY is required\"**\n- Ensure `.env` file exists and contains valid API key\n\n**\"Logwatch file is too old\"**\n- Check if logwatch cron is running: `sudo crontab -l`\n- Verify logwatch output exists: `ls -lh /tmp/logwatch-output.txt`\n\n**\"Failed to send to archive channel\"**\n- Verify bot is added as admin to the channel\n- Check channel ID starts with `-100`\n- Test bot token: `curl https://api.telegram.org/bot\u003cTOKEN\u003e/getMe`\n\n**Database locked errors**\n- Ensure only one instance is running\n- Check file permissions on `data/` directory\n- Built-in 5-second busy timeout handles temporary lock contention\n\n**Drupal Watchdog: \"Invalid JSON format\"**\n- Ensure watchdog export is valid JSON array format\n- Check for UTF-8 encoding issues in log messages\n- Validate with: `jq . /path/to/watchdog.json`\n\n**Drupal Watchdog: \"Missing entries\"**\n- Check `watchdog_format` in drupal-sites.json matches your file format\n- Verify file permissions and watchdog_path\n- Ensure drush export includes `--count` parameter\n\n**Ollama: \"connection refused\" or \"ollama is not running\"**\n- Ensure Ollama server is running: `ollama serve`\n- Check the base URL in `.env`: `OLLAMA_BASE_URL=http://localhost:11434`\n- Test connection: `curl http://localhost:11434/api/tags`\n\n**Ollama: \"model not found\"**\n- Pull the model first: `ollama pull \u003cmodel-name\u003e`\n- List available models: `ollama list`\n- Verify model name matches `.env`: `OLLAMA_MODEL=llama3.3:latest`\n\n**Ollama: Slow response or timeout**\n- Large models (70B+) require significant RAM and may be slow\n- Consider a smaller model for faster inference\n- Increase timeout: `AI_TIMEOUT_SECONDS=300`\n- Check system resources: `htop` or Activity Monitor\n\n**LM Studio: \"connection refused\" or \"LM Studio is not running\"**\n- Ensure LM Studio is open and the Local Server is started\n- Check the server is running on the correct port (default: 1234)\n- Verify the base URL in `.env`: `LMSTUDIO_BASE_URL=http://localhost:1234`\n- Test connection: `curl http://localhost:1234/v1/models`\n\n**LM Studio: \"no models loaded\"**\n- Load a model in LM Studio before starting the analyzer\n- Click on a model in the Models tab and click \"Load\"\n- Verify model is loaded (shows in the top bar)\n\n**LM Studio: Slow response or timeout**\n- Large models require significant RAM and may be slow\n- Consider loading a smaller/quantized model\n- Increase timeout: `AI_TIMEOUT_SECONDS=300`\n- Check GPU acceleration is enabled in LM Studio settings\n\nSee [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) for more solutions.\n\n## Contributing\n\nContributions are welcome! Please:\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Add tests if applicable\n5. Submit a pull request\n\n## Acknowledgments\n\n- Original [logwatch-ai](https://github.com/olegiv/logwatch-ai) Node.js implementation\n- [Anthropic](https://www.anthropic.com/) for Claude AI\n- The Go community for excellent libraries\n\n## Support\n\n- **Issues**: [GitHub Issues](https://github.com/olegiv/logwatch-ai-go/issues)\n- **Discussions**: [GitHub Discussions](https://github.com/olegiv/logwatch-ai-go/discussions)\n- **Original Project**: [logwatch-ai](https://github.com/olegiv/logwatch-ai)\n\n## License\n\nCopyright (C) 2025-2026 Oleg Ivanchenko\n\nGNU General Public License v3.0 - see [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Folegiv%2Flogwatch-ai-go","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Folegiv%2Flogwatch-ai-go","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Folegiv%2Flogwatch-ai-go/lists"}