全部產品
Search
文件中心

Cloud Monitor:配置 Sentry 控制台讀取使用者體驗監控資料

更新時間:Feb 12, 2026

本文介紹如何部署定製版 Sentry 容器,使 Sentry 控制台能夠讀取儲存在阿里雲中的應用資料。

前提條件

  • 該功能目前處於灰階試用階段,請通過工單申請。

  • 已完成配置 Sentry SDK 資料寫入

  • 已有可用的 Sentry 自建環境,或具備部署 Sentry 服務的能力。

  • 已安裝 Docker 和 Docker Compose。

背景資訊

原生 Sentry 服務的資料讀取鏈路依賴 ClickHouse 作為事件儲存、PostgreSQL 作為中繼資料存放區。為實現從 SLS 讀取資料,需要替換以下兩個核心組件:

組件

原始功能

定製版功能

Sentry Web

從 PostgreSQL 讀取 Group、Nodestore 等資料

將部分資料來源重新導向至 SLS

Snuba API

從 ClickHouse 查詢事件數目據

將查詢引擎切換至 SLS

定製版容器僅修改資料讀取邏輯,不影響 Sentry 控制台的介面和互動體驗。

步驟一:擷取定製版容器鏡像

阿里雲提供了適配 SLS 的定製版 Sentry 容器鏡像。

組件

鏡像地址

Sentry Web(SLS 定製版)

sls-registry.cn-hangzhou.cr.aliyuncs.com/sentry/sentry:25.9.0-rum-251230

Snuba API(SLS 定製版)

sls-registry.cn-hangzhou.cr.aliyuncs.com/sentry/snuba:25.9.0-rum-251230

步驟二:配置 SLS 訪問憑證

定製版容器需要訪問 SLS 讀取資料,需要配置 AccessKey 憑證。

建立 RAM 使用者並授權

  1. 登入 RAM 控制台,建立一個 RAM 使用者。

  2. 為該使用者授予以下許可權:

    • AliyunLogReadOnlyAccess(Log Service唯讀許可權)。

  3. 建立 AccessKey 並記錄 AccessKey ID 和 AccessKey Secret。

重要 建議使用 RAM 使用者的 AccessKey,避免使用主帳號 AccessKey。

步驟三:配置環境變數

在 Sentry 服務根目錄的 .env 檔案中添加以下配置:

# RUM 鏡像配置
SENTRY_RUM_IMAGE=sls-registry.cn-hangzhou.cr.aliyuncs.com/sentry/sentry:25.9.0-rum-251230
SNUBA_RUM_IMAGE=sls-registry.cn-hangzhou.cr.aliyuncs.com/sentry/snuba:25.9.0-rum-251230
SENTRY_RUM_BIND=9001

# SLS 配置
SLS_ENDPOINT=<endpoint>
SLS_ACCESS_KEY_ID=<your_access_key_id>
SLS_ACCESS_KEY_SECRET=<your_access_key_secret>
SLS_PROJECT=<your_sls_project>
SLS_LOGSTORE=logstore-rum
SLS_TTL=30
ENABLE_SLS_NODESTORE=true
USE_SLS_GROUP_STORAGE=true

參數說明

參數

說明

樣本

SLS_ENDPOINT

SLS 服務訪問網域名稱

cn-chengdu.log.aliyuncs.com

SLS_ACCESS_KEY_ID

RAM 使用者 AccessKey ID

LTAI5t***

SLS_ACCESS_KEY_SECRET

RAM 使用者 AccessKey Secret

HQsEf***

SLS_PROJECT

SLS Project 名稱(需要在控制台擷取RUM Service底層儲存的project)

proj-xtrace-xxxxx-cn-hangzhou

SLS_LOGSTORE

SLS Logstore 名稱,固定值

logstore-rum

SLS_TTL

資料查詢天數

30

ENABLE_SLS_NODESTORE

啟用 SLS 儲存事件詳情

true

USE_SLS_GROUP_STORAGE

啟用 SLS 儲存 Issue 彙總資訊

true

步驟四:建立 Docker Compose 覆蓋配置

在 Sentry 服務根目錄建立 docker-compose.override.yml 檔案:

services:
  # ============================================
  # Snuba API - RUM 版本
  # ============================================
  snuba-api-rum:
    restart: unless-stopped
    image: "${SNUBA_RUM_IMAGE}"
    depends_on:
      clickhouse:
        condition: service_healthy
      kafka:
        condition: service_healthy
      redis:
        condition: service_healthy
    environment:
      SNUBA_SETTINGS: self_hosted
      CLICKHOUSE_HOST: clickhouse
      DEFAULT_BROKERS: "kafka:9092"
      REDIS_HOST: redis
      UWSGI_MAX_REQUESTS: "10000"
      UWSGI_DISABLE_LOGGING: "true"
      SENTRY_EVENT_RETENTION_DAYS:
      # 配置
      SLS_ENDPOINT: ${SLS_ENDPOINT:-cn-chengdu.log.aliyuncs.com}
      SLS_ACCESS_KEY_ID: ${SLS_ACCESS_KEY_ID:-}
      SLS_ACCESS_KEY_SECRET: ${SLS_ACCESS_KEY_SECRET:-}
      SLS_PROJECT: ${SLS_PROJECT:-}
      SLS_LOGSTORE: ${SLS_LOGSTORE:-logstore-rum}
      SLS_TTL: ${SLS_TTL:-30}
      USE_SLS_FOR_REFERRERS: sls
    healthcheck:
      test:
        - "CMD"
        - "/bin/bash"
        - "-c"
        - 'exec 3<>/dev/tcp/127.0.0.1/1218 && echo -e "GET /health HTTP/1.1\r\nhost: 127.0.0.1\r\n\r\n" >&3 && grep ok -s -m 1 <&3'
      interval: "$HEALTHCHECK_INTERVAL"
      timeout: "$HEALTHCHECK_TIMEOUT"
      retries: $HEALTHCHECK_RETRIES
      start_period: "$HEALTHCHECK_START_PERIOD"

  # ============================================
  # Web 服務 - RUM 版本
  # ============================================
  web-rum:
    restart: unless-stopped
    image: "${SENTRY_RUM_IMAGE}"
    depends_on:
      redis:
        condition: service_healthy
      kafka:
        condition: service_healthy
      pgbouncer:
        condition: service_healthy
      memcached:
        condition: service_started
      smtp:
        condition: service_started
      seaweedfs:
        condition: service_started
      snuba-api-rum:
        condition: service_healthy
      symbolicator:
        condition: service_started
    entrypoint: "/etc/sentry/entrypoint.sh"
    command: ["run", "web"]
    ulimits:
      nofile:
        soft: 4096
        hard: 4096
    environment:
      PYTHONUSERBASE: "/data/custom-packages"
      SENTRY_CONF: "/etc/sentry"
      SNUBA: "http://snuba-api-rum:1218"
      VROOM: "http://vroom:8085"
      DEFAULT_CA_BUNDLE: "/etc/ssl/certs/ca-certificates.crt"
      REQUESTS_CA_BUNDLE: "/etc/ssl/certs/ca-certificates.crt"
      GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR: "/etc/ssl/certs/ca-certificates.crt"
      COMPOSE_PROFILES:
      SENTRY_EVENT_RETENTION_DAYS:
      SENTRY_MAIL_HOST:
      SENTRY_MAX_EXTERNAL_SOURCEMAP_SIZE:
      # 配置
      SLS_ENDPOINT: ${SLS_ENDPOINT:-cn-chengdu.log.aliyuncs.com}
      SLS_ACCESS_KEY_ID: ${SLS_ACCESS_KEY_ID:-}
      SLS_ACCESS_KEY_SECRET: ${SLS_ACCESS_KEY_SECRET:-}
      SLS_PROJECT: ${SLS_PROJECT:-}
      SLS_LOGSTORE: ${SLS_LOGSTORE:-logstore-rum}
      SLS_TTL: ${SLS_TTL:-30}
      ENABLE_SLS_NODESTORE: ${ENABLE_SLS_NODESTORE:-true}
      USE_SLS_GROUP_STORAGE: ${USE_SLS_GROUP_STORAGE:-true}
    volumes:
      - "sentry-data:/data"
      - "./sentry:/etc/sentry"
      - "./geoip:/geoip:ro"
      - "./certificates:/usr/local/share/ca-certificates:ro"
    healthcheck:
      test:
        - "CMD"
        - "/bin/bash"
        - "-c"
        - 'exec 3<>/dev/tcp/127.0.0.1/9000 && echo -e "GET /_health/ HTTP/1.1\r\nhost: 127.0.0.1\r\n\r\n" >&3 && grep ok -s -m 1 <&3'
      interval: "$HEALTHCHECK_INTERVAL"
      timeout: "$HEALTHCHECK_TIMEOUT"
      retries: $HEALTHCHECK_RETRIES
      start_period: "$HEALTHCHECK_START_PERIOD"

  # ============================================
  # Nginx - 雙連接埠配置
  # ============================================
  nginx:
    ports:
      - "$SENTRY_BIND:80/tcp"
      - "${SENTRY_RUM_BIND:-9001}:81/tcp"
    depends_on:
      web:
        condition: service_healthy
        restart: true
      web-rum:
        condition: service_healthy
        restart: true
      relay:
        condition: service_healthy
        restart: true

步驟五:配置 Sentry Python 檔案

修改 sentry/sentry.conf.example.py 檔案,在檔案末尾追加以下配置:

# ---------------------------------------------------------
# RUM NodeStore Configuration
# ---------------------------------------------------------
import os

# 擷取環境變數配置
_enable_sls_nodestore = os.environ.get("ENABLE_SLS_NODESTORE", "").lower() in ("true", "1", "yes")
_use_sls_group_storage = os.environ.get("USE_SLS_GROUP_STORAGE", "").lower() in ("true", "1", "yes")
_sls_endpoint = os.environ.get("SLS_ENDPOINT", "")
_sls_access_key_id = os.environ.get("SLS_ACCESS_KEY_ID", "")
_sls_access_key_secret = os.environ.get("SLS_ACCESS_KEY_SECRET", "")
_sls_project = os.environ.get("SLS_PROJECT", "")
_sls_nodestore_logstore = os.environ.get("SLS_LOGSTORE", "logstore-rum")
_sls_ttl = int(os.environ.get("SLS_TTL", "30") or 30)

if _enable_sls_nodestore and _sls_endpoint and _sls_access_key_id and _sls_access_key_secret and _sls_project:
    SENTRY_NODESTORE = "sentry_nodestore_sls.SLSNodeStorage"
    SENTRY_NODESTORE_OPTIONS = {
        "endpoint": _sls_endpoint,
        "access_key_id": _sls_access_key_id,
        "access_key_secret": _sls_access_key_secret,
        "project": _sls_project,
        "logstore": _sls_nodestore_logstore,
        "compression": True,
        "retry_attempts": 3,
        "retry_delay": 0.5,
        "default_ttl_days": _sls_ttl or None,
    }
    print("=" * 70)
    print("==> NodeStore: SLS (Direct Mode ONLY)")
    print(f"==> SLS Endpoint: {_sls_endpoint}")
    print(f"==> SLS Project:  {_sls_project}")
    print(f"==> SLS Logstore: {_sls_nodestore_logstore}")
    print(f"==> TTL (days):   {SENTRY_NODESTORE_OPTIONS['default_ttl_days']}")
    print("=" * 70)
else:
    print("=" * 70)
    print("==> NodeStore: Django (Database)")
    print("==> Data stored in PostgreSQL")
    if not _enable_sls_nodestore:
        print("==> Info: Set ENABLE_SLS_NODESTORE=true in .env.custom to use SLS")
    elif not _sls_endpoint or not _sls_access_key_id:
        print("==> Warning: SLS credentials not configured in .env.custom")
    print("=" * 70)

# ---------------------------------------------------------
# RUM Group Search Configuration
# ---------------------------------------------------------
if _use_sls_group_storage and _sls_endpoint and _sls_access_key_id and _sls_access_key_secret and _sls_project:
    SENTRY_SEARCH = "sentry.search.sls.backend.SLSGroupSearchBackend"
    print("=" * 70)
    print("==> Search Backend: SLS Group Search")
    print(f"==> Backend: {SENTRY_SEARCH}")
    print("=" * 70)
else:
    print("=" * 70)
    print("==> Search Backend: Snuba (Default)")
    print(f"==> Backend: {SENTRY_SEARCH}")
    if not _use_sls_group_storage:
        print("==> Info: Set USE_SLS_GROUP_STORAGE=true to use SLS Group Search")
    print("=" * 70)

# 清理臨時變數
del _enable_sls_nodestore, _use_sls_group_storage, _sls_endpoint, _sls_access_key_id, _sls_access_key_secret
del _sls_project, _sls_nodestore_logstore

步驟六:配置 Nginx 雙連接埠

修改 nginx.conf 檔案,添加 RUM 版服務的連接埠監聽,支援雙環境訪問(連接埠 80 → 標準版,連接埠 81 → 阿里雲版):

user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;


events {
	worker_connections 1024;
}


http {
	include /etc/nginx/mime.types;
	default_type application/octet-stream;

	log_format main '$remote_addr - $remote_user [$time_local] "$request" '
	'$status $body_bytes_sent "$http_referer" '
	'"$http_user_agent" "$http_x_forwarded_for"';

	access_log /var/log/nginx/access.log main;

	sendfile on;
	tcp_nopush on;
	tcp_nodelay on;
	reset_timedout_connection on;

	keepalive_timeout 75s;

	gzip off;
	server_tokens off;

	server_names_hash_bucket_size 64;
	types_hash_max_size 2048;
	types_hash_bucket_size 64;
	client_body_buffer_size 64k;
	client_max_body_size 100m;

	proxy_http_version 1.1;
	proxy_redirect off;
	proxy_buffer_size          128k;
	proxy_buffers              4 256k;
	proxy_busy_buffers_size    256k;
	proxy_next_upstream error timeout invalid_header http_502 http_503 non_idempotent;
	proxy_next_upstream_tries 2;

	# Docker default address pools
	set_real_ip_from 172.17.0.0/16;
	set_real_ip_from 172.18.0.0/16;
	set_real_ip_from 172.19.0.0/16;
	set_real_ip_from 172.20.0.0/14;
	set_real_ip_from 172.24.0.0/14;
	set_real_ip_from 172.28.0.0/14;
	set_real_ip_from 192.168.0.0/16;
	set_real_ip_from 10.0.0.0/8;
	real_ip_header X-Forwarded-For;
	real_ip_recursive on;

	proxy_set_header Connection '';
	proxy_set_header Host $host;
	proxy_set_header X-Forwarded-For $remote_addr;
	proxy_set_header X-Forwarded-Proto $scheme;
	proxy_set_header X-Request-Id $request_id;
	proxy_read_timeout 30s;
	proxy_send_timeout 5s;

	upstream relay {
		server relay:3000;
		keepalive 2;
	}

	# 標準版 Sentry
	upstream sentry {
		server web:9000;
		keepalive 2;
	}

	# RUM 版 Sentry
	upstream sentry_rum {
		server web-rum:9000;
		keepalive 2;
	}

    # RUM 資料轉寄到阿里雲 RUM(僅在啟用鏡像雙寫時使用)
    upstream rum_forwarder {
        # endpoint
		server <endpoint>:80;
		keepalive 2;
	}
    # ============================================
    # RUM 轉寄路徑映射
    # 根據 Sentry Project ID 映射到對應的阿里雲 RUM 服務
    # ============================================
	map $request_uri $forwarder_path {
        # 預設轉寄路徑(請替換為實際的 workspace_name 和 rum_service_id)
        default /rum/sentry/<workspace_name>/<rum_service_id>;
        # 按專案 ID 配置不同的轉寄路徑樣本:
        # "~^/api/1/envelope/"  /rum/sentry/<workspace_name>/<rum_service_id_for_project_1>;
        # "~^/api/2/envelope/"  /rum/sentry/<workspace_name>/<rum_service_id_for_project_2>;
	}
	# 標準版 Sentry - 連接埠 80
	server {
		listen 80;

		location /api/store/ {
			proxy_pass http://relay;
		}
		location ~ ^/api/[1-9]\d*/ {
			proxy_pass http://relay;
			mirror /rum_mirror;
			mirror_request_body on;
		}
		location = /rum_mirror {
			internal;
			
			proxy_pass http://rum_forwarder$forwarder_path$request_uri;
			# endpoint
			proxy_set_header Host <endpoint>;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			proxy_set_header X-Forwarded-Proto $scheme;
			proxy_set_header X-Request-Id $request_id;
			proxy_set_header Connection '';

			proxy_read_timeout 5s;
			proxy_send_timeout 5s;
			proxy_connect_timeout 5s;

			proxy_ignore_client_abort on;
		}
		location ^~ /api/0/relays/ {
			proxy_pass http://relay;
		}
		location ^~ /js-sdk/ {
			root /var/www/;
			add_header Access-Control-Allow-Origin *;
		}
		location / {
			proxy_pass http://sentry;
		}
		location /_assets/ {
			proxy_pass http://sentry/_static/dist/sentry/;
			proxy_hide_header Content-Disposition;
		}
		location /_static/ {
			proxy_pass http://sentry;
			proxy_hide_header Content-Disposition;
		}
	}

	# RUM 版 Sentry - 連接埠 81
	server {
		listen 81;

		location /api/store/ {
			proxy_pass http://relay;
		}
		location ~ ^/api/[1-9]\d*/ {
			proxy_pass http://relay;
			mirror /rum_mirror;
			mirror_request_body on;
		}
		location = /rum_mirror {
			internal;
			
			proxy_pass http://rum_forwarder$forwarder_path$request_uri;
			# endpoint
			proxy_set_header Host <endpoint>;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			proxy_set_header X-Forwarded-Proto $scheme;
			proxy_set_header X-Request-Id $request_id;
			proxy_set_header Connection '';

			proxy_read_timeout 5s;
			proxy_send_timeout 5s;
			proxy_connect_timeout 5s;

			proxy_ignore_client_abort on;
		}
		location ^~ /api/0/relays/ {
			proxy_pass http://relay;
		}
		location ^~ /js-sdk/ {
			root /var/www/;
			add_header Access-Control-Allow-Origin *;
		}
		location / {
			proxy_pass http://sentry_rum;
		}
		location /_assets/ {
			proxy_pass http://sentry_rum/_static/dist/sentry/;
			proxy_hide_header Content-Disposition;
		}
		location /_static/ {
			proxy_pass http://sentry_rum;
			proxy_hide_header Content-Disposition;
		}
	}
}

步驟七:啟動服務

執行以下命令啟動服務:

docker compose -f docker-compose.yml -f docker-compose.override.yml up -d

查看服務狀態:

docker compose ps

確認 web-rumsnuba-api-rum 容器狀態為 Up (healthy)

步驟八:驗證讀取功能

  1. 訪問 RUM 版 Sentry 控制台:http://<your-host>:9001

  2. 進入已建立的專案,查看 Issues 列表。

  3. 確認是否能正常展示從 SLS 讀取的錯誤和事件數目據。

若 Issues 列表為空白,請檢查:

  • 資料寫入是否正常。

  • SLS 訪問憑證是否正確配置。

  • 容器日誌是否有錯誤資訊

    • 查看容器日誌:

      docker compose logs -f web-rum
      docker compose logs -f snuba-api-rum

訪問地址

環境

訪問地址

說明

標準版 Sentry

http://<your-host>:9000

官方鏡像,資料存放區在 ClickHouse

RUM 版 Sentry

http://<your-host>:9001

定製版鏡像,資料存放區在 SLS

常見問題

Q:替換定製版容器後,Sentry 控制台的功能是否有影響?

A:定製版容器僅修改資料讀取邏輯,控制台的介面、互動和功能與原生版本一致。

Q:是否支援同時讀取 ClickHouse 和 SLS 的資料?

A:目前的版本不支援混合讀取。定製版容器啟用後,所有事件數目據均從 SLS 讀取。

Q:如何復原到原生 Sentry 容器?

A:將 web-rumsnuba-api-rum 服務停止,使用標準版 Sentry(連接埠 9000)即可。

SLS 中的資料保留多長時間?

A:資料保留時間預設 30 天。