Cài đặt SigNoz Self-hosted với Docker: APM mã nguồn mở thay thế Datadog

Monitoring tutorial - IT technology blog
Monitoring tutorial - IT technology blog

Vấn đề: Ba công cụ, ba dashboard, một mớ hỗn độn

Hệ thống monitoring của mình gồm Prometheus + Grafana theo dõi 15 server. Setup này giúp phát hiện sự cố trước khi user báo — nhưng chỉ giải quyết được một phần bài toán. Cụ thể, khi một API endpoint bắt đầu chậm bất thường, quy trình debug trông như thế này:

  • Mở Grafana xem CPU/RAM có vấn đề không
  • Mở Jaeger tìm distributed traces xem request đi đâu
  • SSH vào server grep log tìm error

Ba bước, ba cửa sổ, ba công cụ không liên kết nhau. Mình đã mất 30–40 phút debug không ít lần — không phải vì vấn đề phức tạp, mà vì mất thời gian ghép bức tranh tổng thể từ các mảnh rời.

Thêm vào đó, có người trong team đề xuất Datadog. Nhìn vào pricing — $23/host/tháng × 15 server = $345/tháng — câu trả lời là không.

Gốc rễ: Thiếu observability, không phải thiếu monitoring

Monitoringobservability khác nhau hoàn toàn. Monitoring cho bạn biết cái gì đang xảy ra (CPU 90%). Observability cho bạn biết tại sao — request nào gây ra, từ service nào, log error tương ứng là gì.

Ba trụ cột của observability:

  • Metrics — số liệu thống kê theo thời gian (Prometheus làm tốt điều này)
  • Traces — hành trình của một request qua các service (Jaeger, Zipkin)
  • Logs — chi tiết sự kiện (Graylog, ELK)

Khi ba thứ này nằm trong ba hệ thống riêng lẻ, việc liên kết chúng là công việc thủ công — và thường mất thời gian hơn cả việc fix bug. SigNoz xử lý đúng chỗ ngứa này: gộp cả ba vào một platform, cho phép click từ một trace sang log tương ứng trong vài giây.

Các lựa chọn thay thế và tại sao SigNoz thắng

Trước khi chọn SigNoz, mình cũng cân nhắc:

  • Grafana + Tempo + Loki: Mạnh, nhưng cấu hình phức tạp, phải integrate thủ công từng phần
  • Jaeger standalone: Chỉ traces, không có metrics và logs
  • Elastic APM: Nặng, RAM đói, license phức tạp cho production
  • SigNoz: OpenTelemetry native, single Docker Compose, UI tích hợp sẵn, mã nguồn mở (AGPL)

Yếu tố quyết định: SigNoz dùng ClickHouse làm backend storage thay vì Elasticsearch. ClickHouse được tối ưu cho time-series data — query aggregation trên hàng triệu dòng trace chạy nhanh hơn vài lần, RAM tiêu thụ thấp hơn khoảng 3–5x so với Elastic stack tương đương.

Cách tốt nhất: Cài SigNoz Self-hosted với Docker Compose

Yêu cầu hệ thống

  • RAM: tối thiểu 4GB, khuyến nghị 8GB
  • CPU: 2 cores trở lên
  • Disk: 20GB+ (ClickHouse lưu data traces/logs)
  • Docker + Docker Compose đã cài sẵn

Bước 1: Clone repo và chạy

# Clone SigNoz
git clone -b main https://github.com/SigNoz/signoz.git
cd signoz/deploy

# Chạy toàn bộ stack
docker compose -f docker/clickhouse-setup/docker-compose.yaml up -d

Lần đầu chạy sẽ pull khoảng 2–3GB image. Sau khi xong, kiểm tra các container:

docker compose -f docker/clickhouse-setup/docker-compose.yaml ps

# Kết quả mong đợi (tất cả phải "Up"):
# signoz-frontend         Up
# signoz-query-service    Up
# signoz-otel-collector   Up
# clickhouse              Up
# zookeeper               Up

Truy cập UI tại http://<server-ip>:3301. Lần đầu sẽ yêu cầu tạo tài khoản admin.

Bước 2: Gửi dữ liệu vào SigNoz bằng OpenTelemetry

SigNoz nhận data qua OpenTelemetry Collector — chuẩn mở do CNCF phát triển. Python, Go, Java, Node.js đều có SDK sẵn.

Với ứng dụng Python (Flask/FastAPI):

# Cài OpenTelemetry SDK
pip install opentelemetry-distro opentelemetry-exporter-otlp
opentelemetry-bootstrap -a install
# Chạy app với auto-instrumentation
SIGNOZ_ACCESS_TOKEN="" \
OTEL_EXPORTER_OTLP_ENDPOINT="http://<signoz-server>:4317" \
OTEL_RESOURCE_ATTRIBUTES="service.name=my-api-service" \
opentelemetry-instrument python app.py

Với Node.js (Express):

npm install @opentelemetry/auto-instrumentations-node @opentelemetry/exporter-trace-otlp-grpc
// tracing.js — chạy trước khi load app
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');

const sdk = new NodeSDK({
  traceExporter: new OTLPTraceExporter({
    url: 'http://<signoz-server>:4317',
  }),
  instrumentations: [getNodeAutoInstrumentations()],
  serviceName: 'my-node-service',
});
sdk.start();
node -r ./tracing.js server.js

Bước 3: Migrate Prometheus metrics sang SigNoz (không cần bỏ Prometheus)

Đây là phần mình thấy hay nhất — không cần đụng vào Prometheus hiện tại. SigNoz scrape thẳng từ endpoint sẵn có:

# Thêm vào otel-collector-config.yaml
receivers:
  prometheus:
    config:
      scrape_configs:
        - job_name: 'my-servers'
          static_configs:
            - targets:
              - 'server1:9100'   # node_exporter
              - 'server2:9100'
              - 'server3:9100'

exporters:
  clickhousemetricswrite:
    endpoint: tcp://clickhouse:9000

service:
  pipelines:
    metrics:
      receivers: [prometheus]
      exporters: [clickhousemetricswrite]

Restart collector sau khi thay đổi config:

docker compose -f docker/clickhouse-setup/docker-compose.yaml restart otel-collector

Bước 4: Gửi logs vào SigNoz

SigNoz nhận logs qua OTLP. Đang dùng file log hoặc Docker container logs? Cách nhanh nhất là OpenTelemetry Collector filelog receiver:

receivers:
  filelog:
    include: [/var/log/myapp/*.log]
    start_at: beginning

exporters:
  otlp:
    endpoint: <signoz-server>:4317
    tls:
      insecure: true

service:
  pipelines:
    logs:
      receivers: [filelog]
      exporters: [otlp]

Tips & Tricks từ thực tế

1. Giới hạn retention để tiết kiệm disk

Mặc định SigNoz giữ data 15 ngày. Với team nhỏ, 7 ngày là đủ:

# Truy cập ClickHouse CLI
docker exec -it signoz-clickhouse clickhouse-client

-- Đặt TTL 7 ngày cho traces
ALTER TABLE signoz_traces.signoz_index_v2
  MODIFY TTL toDateTime(timestamp) + INTERVAL 7 DAY;

-- Đặt TTL 7 ngày cho logs
ALTER TABLE signoz_logs.logs
  MODIFY TTL toDateTime(timestamp) + INTERVAL 7 DAY;

2. Đặt resource limit cho ClickHouse

Server 4GB RAM thì nên cap lại — không làm vậy, ClickHouse sẽ chiếm 2–2.5GB khi query nặng, chèn hết phần còn lại của hệ thống:

# docker-compose.yaml
clickhouse:
  deploy:
    resources:
      limits:
        memory: 2G
      reservations:
        memory: 1G

3. Alert khi error rate tăng

SigNoz có alerting tích hợp sẵn, không cần cài thêm gì. Tạo alert cho API error rate > 5%:

  • Vào AlertsNew Alert
  • Chọn metric: signoz_calls_total với filter status_code = ERROR
  • Condition: rate > 0.05 trong 5 phút
  • Notification: Telegram webhook hoặc Slack

4. Sample rate: 100% khi debug, 10% khi production

Trace toàn bộ request khi development là ổn. Production thì nên giảm xuống 10–20% — ít tải hơn, disk cũng đỡ bị ăn:

# Development: trace 100%
OTEL_TRACES_SAMPLER=always_on opentelemetry-instrument python app.py

# Production: trace 10%
OTEL_TRACES_SAMPLER=parentbased_traceidratio \
OTEL_TRACES_SAMPLER_ARG=0.1 \
opentelemetry-instrument python app.py

Kết quả sau khi setup

Workflow debug thay đổi hẳn. Thay vì mở 3 tab, giờ chỉ cần:

  1. Mở Services → xem service nào có p99 latency cao
  2. Click vào service → Traces → lọc theo status ERROR
  3. Click vào một trace cụ thể → thấy ngay request đi qua những bước nào, bước nào chậm
  4. Click tab Logs ngay trong trace view → log tương ứng với trace ID hiện ra luôn

Từ phát hiện vấn đề đến tìm ra nguyên nhân: khoảng 5 phút, so với 30–40 phút trước đây.

Chi phí: $0. RAM tiêu thụ: khoảng 3GB cho toàn bộ SigNoz stack với 5 service gửi traces. Nếu đang dùng Prometheus + Grafana và thấy thiếu traces/logs tích hợp — SigNoz là bước tiếp theo hợp lý. Không cần đập đi làm lại, chỉ cần thêm một layer observability đúng nghĩa.

Share: