프로덕션 메트릭

프로덕션 메트릭 (Production Metrics)

이 페이지는 SGLang이 Prometheus를 통해 노출하는 메트릭을 설명해요. 서버 실행 시 --enable-metrics를 추가하면 활성화할 수 있어요. 언어 모델 메트릭과 확산(diffusion) 메트릭, 모니터링 스택(Prometheus + Grafana) 설정 방법, MFU 관련 추정 성능 메트릭까지 다뤄요.

출처: 문서

본문

SGLang은 Prometheus를 통해 다음 메트릭을 노출해요. 서버 실행 시 --enable-metrics를 추가하면 활성화할 수 있어요.

모니터링 대시보드의 예시는 examples/monitoring/grafana.json에서 확인할 수 있어요.

언어 모델 메트릭 (Language model metrics)

메트릭의 예시는 다음과 같아요:

$ curl http://localhost:30000/metrics
# HELP sglang:prompt_tokens_total Number of prefill tokens processed.
# TYPE sglang:prompt_tokens_total counter
sglang:prompt_tokens_total{model_name="meta-llama/Llama-3.1-8B-Instruct"} 8.128902e+06
# HELP sglang:generation_tokens_total Number of generation tokens processed.
# TYPE sglang:generation_tokens_total counter
sglang:generation_tokens_total{model_name="meta-llama/Llama-3.1-8B-Instruct"} 7.557572e+06
# HELP sglang:token_usage The token usage
# TYPE sglang:token_usage gauge
sglang:token_usage{model_name="meta-llama/Llama-3.1-8B-Instruct"} 0.28
# HELP sglang:cache_hit_rate The cache hit rate
# TYPE sglang:cache_hit_rate gauge
sglang:cache_hit_rate{model_name="meta-llama/Llama-3.1-8B-Instruct"} 0.007507552643049313
# HELP sglang:time_to_first_token_seconds Histogram of time to first token in seconds.
# TYPE sglang:time_to_first_token_seconds histogram
sglang:time_to_first_token_seconds_sum{model_name="meta-llama/Llama-3.1-8B-Instruct"} 2.3518979474117756e+06
sglang:time_to_first_token_seconds_bucket{le="0.001",model_name="meta-llama/Llama-3.1-8B-Instruct"} 0.0
sglang:time_to_first_token_seconds_bucket{le="0.005",model_name="meta-llama/Llama-3.1-8B-Instruct"} 0.0
sglang:time_to_first_token_seconds_bucket{le="0.01",model_name="meta-llama/Llama-3.1-8B-Instruct"} 0.0
sglang:time_to_first_token_seconds_bucket{le="0.02",model_name="meta-llama/Llama-3.1-8B-Instruct"} 0.0
sglang:time_to_first_token_seconds_bucket{le="0.04",model_name="meta-llama/Llama-3.1-8B-Instruct"} 1.0
sglang:time_to_first_token_seconds_bucket{le="0.06",model_name="meta-llama/Llama-3.1-8B-Instruct"} 3.0
sglang:time_to_first_token_seconds_bucket{le="0.08",model_name="meta-llama/Llama-3.1-8B-Instruct"} 6.0
sglang:time_to_first_token_seconds_bucket{le="0.1",model_name="meta-llama/Llama-3.1-8B-Instruct"} 6.0
sglang:time_to_first_token_seconds_bucket{le="0.25",model_name="meta-llama/Llama-3.1-8B-Instruct"} 6.0
sglang:time_to_first_token_seconds_bucket{le="0.5",model_name="meta-llama/Llama-3.1-8B-Instruct"} 6.0
sglang:time_to_first_token_seconds_bucket{le="0.75",model_name="meta-llama/Llama-3.1-8B-Instruct"} 6.0
sglang:time_to_first_token_seconds_bucket{le="1.0",model_name="meta-llama/Llama-3.1-8B-Instruct"} 27.0
sglang:time_to_first_token_seconds_bucket{le="2.5",model_name="meta-llama/Llama-3.1-8B-Instruct"} 140.0
sglang:time_to_first_token_seconds_bucket{le="5.0",model_name="meta-llama/Llama-3.1-8B-Instruct"} 314.0
sglang:time_to_first_token_seconds_bucket{le="7.5",model_name="meta-llama/Llama-3.1-8B-Instruct"} 941.0
sglang:time_to_first_token_seconds_bucket{le="10.0",model_name="meta-llama/Llama-3.1-8B-Instruct"} 1330.0
sglang:time_to_first_token_seconds_bucket{le="15.0",model_name="meta-llama/Llama-3.1-8B-Instruct"} 1970.0
sglang:time_to_first_token_seconds_bucket{le="20.0",model_name="meta-llama/Llama-3.1-8B-Instruct"} 2326.0
sglang:time_to_first_token_seconds_bucket{le="25.0",model_name="meta-llama/Llama-3.1-8B-Instruct"} 2417.0
sglang:time_to_first_token_seconds_bucket{le="30.0",model_name="meta-llama/Llama-3.1-8B-Instruct"} 2513.0
sglang:time_to_first_token_seconds_bucket{le="+Inf",model_name="meta-llama/Llama-3.1-8B-Instruct"} 11008.0
sglang:time_to_first_token_seconds_count{model_name="meta-llama/Llama-3.1-8B-Instruct"} 11008.0
# HELP sglang:e2e_request_latency_seconds Histogram of End-to-end request latency in seconds
# TYPE sglang:e2e_request_latency_seconds histogram
sglang:e2e_request_latency_seconds_sum{model_name="meta-llama/Llama-3.1-8B-Instruct"} 3.116093850019932e+06
sglang:e2e_request_latency_seconds_bucket{le="0.3",model_name="meta-llama/Llama-3.1-8B-Instruct"} 0.0
sglang:e2e_request_latency_seconds_bucket{le="0.5",model_name="meta-llama/Llama-3.1-8B-Instruct"} 6.0
sglang:e2e_request_latency_seconds_bucket{le="0.8",model_name="meta-llama/Llama-3.1-8B-Instruct"} 6.0
sglang:e2e_request_latency_seconds_bucket{le="1.0",model_name="meta-llama/Llama-3.1-8B-Instruct"} 6.0
sglang:e2e_request_latency_seconds_bucket{le="1.5",model_name="meta-llama/Llama-3.1-8B-Instruct"} 6.0
sglang:e2e_request_latency_seconds_bucket{le="2.0",model_name="meta-llama/Llama-3.1-8B-Instruct"} 6.0
sglang:e2e_request_latency_seconds_bucket{le="2.5",model_name="meta-llama/Llama-3.1-8B-Instruct"} 6.0
sglang:e2e_request_latency_seconds_bucket{le="5.0",model_name="meta-llama/Llama-3.1-8B-Instruct"} 7.0
sglang:e2e_request_latency_seconds_bucket{le="10.0",model_name="meta-llama/Llama-3.1-8B-Instruct"} 10.0
sglang:e2e_request_latency_seconds_bucket{le="15.0",model_name="meta-llama/Llama-3.1-8B-Instruct"} 11.0
sglang:e2e_request_latency_seconds_bucket{le="20.0",model_name="meta-llama/Llama-3.1-8B-Instruct"} 14.0
sglang:e2e_request_latency_seconds_bucket{le="30.0",model_name="meta-llama/Llama-3.1-8B-Instruct"} 247.0
sglang:e2e_request_latency_seconds_bucket{le="40.0",model_name="meta-llama/Llama-3.1-8B-Instruct"} 486.0
sglang:e2e_request_latency_seconds_bucket{le="50.0",model_name="meta-llama/Llama-3.1-8B-Instruct"} 845.0
sglang:e2e_request_latency_seconds_bucket{le="60.0",model_name="meta-llama/Llama-3.1-8B-Instruct"} 1513.0
sglang:e2e_request_latency_seconds_bucket{le="+Inf",model_name="meta-llama/Llama-3.1-8B-Instruct"} 11228.0
sglang:e2e_request_latency_seconds_count{model_name="meta-llama/Llama-3.1-8B-Instruct"} 11228.0
# HELP sglang:time_per_output_token_seconds Histogram of time per output token in seconds.
# TYPE sglang:time_per_output_token_seconds histogram
sglang:time_per_output_token_seconds_sum{model_name="meta-llama/Llama-3.1-8B-Instruct"} 866964.5791549598
sglang:time_per_output_token_seconds_bucket{le="0.005",model_name="meta-llama/Llama-3.1-8B-Instruct"} 1.0
sglang:time_per_output_token_seconds_bucket{le="0.01",model_name="meta-llama/Llama-3.1-8B-Instruct"} 73.0
# ... (히스토그램 버킷 생략) ...
sglang:func_latency_seconds_count{name="generate_request"} 14007.0
# HELP sglang:num_running_reqs The number of running requests
# TYPE sglang:num_running_reqs gauge
sglang:num_running_reqs{model_name="meta-llama/Llama-3.1-8B-Instruct"} 162.0
# HELP sglang:num_used_tokens The number of used tokens
# TYPE sglang:num_used_tokens gauge
sglang:num_used_tokens{model_name="meta-llama/Llama-3.1-8B-Instruct"} 123859.0
# HELP sglang:gen_throughput The generate throughput (token/s)
# TYPE sglang:gen_throughput gauge
sglang:gen_throughput{model_name="meta-llama/Llama-3.1-8B-Instruct"} 86.50814177726902
# HELP sglang:num_queue_reqs The number of requests in the waiting queue
# TYPE sglang:num_queue_reqs gauge
sglang:num_queue_reqs{model_name="meta-llama/Llama-3.1-8B-Instruct"} 2826.0
# HELP sglang:spec_num_steps Currently active speculative_num_steps.
# TYPE sglang:spec_num_steps gauge
sglang:spec_num_steps{model_name="meta-llama/Llama-3.1-8B-Instruct"} 3.0
# HELP sglang:spec_num_draft_tokens Currently active speculative_num_draft_tokens (decouples from steps under topk>1).
# TYPE sglang:spec_num_draft_tokens gauge
sglang:spec_num_draft_tokens{model_name="meta-llama/Llama-3.1-8B-Instruct"} 4.0

확산 메트릭 (Diffusion metrics)

SGLang Diffusion은 --enable-metrics로 요청, 큐, 단계 및 LoRA 메트릭을 노출해요. 메트릭 참조, 카운팅 의미, 분리 스크레이프 설정은 Diffusion production metrics를 참고해 주세요.

설정 가이드 (Setup Guide)

이 섹션은 examples/monitoring 디렉터리에 제공된 모니터링 스택(Prometheus + Grafana)을 설정하는 방법을 설명해요.

전제 조건 (Prerequisites)

  • Docker와 Docker Compose 설치
  • 메트릭이 활성화된 SGLang 서버 실행

사용법 (Usage)

  1. 메트릭을 활성화해 SGLang 서버 시작:

    python -m sglang.launch_server \
      --model-path <your_model_path> \
      --port 30000 \
      --enable-metrics \
      --enable-mfu-metrics
    

    <your_model_path>를 실제 모델 경로(예: meta-llama/Meta-Llama-3.1-8B-Instruct)로 바꿔 주세요. 모니터링 스택에서 서버에 접근할 수 있는지 확인하세요(Docker에서 실행한다면 --host 0.0.0.0이 필요할 수 있어요). 기본적으로 메트릭 엔드포인트는 http://<sglang_server_host>:30000/metrics에서 사용할 수 있어요.

  2. 모니터링 예시 디렉터리로 이동:

    cd examples/monitoring
    
  3. 모니터링 스택 시작:

    docker compose up -d
    

    이 명령은 Prometheus와 Grafana를 백그라운드에서 시작해요.

  4. 모니터링 인터페이스 접근:

  5. Grafana 로그인:

    • 기본 사용자명: admin
    • 기본 비밀번호: admin 첫 로그인 시 비밀번호 변경을 요청받을 거예요.
  6. 대시보드 보기: SGLang 대시보드는 사전 구성되어 자동으로 사용 가능해야 해요. DashboardsBrowseSGLang Monitoring 폴더 → SGLang Dashboard로 이동하세요.

문제 해결 (Troubleshooting)

  • 포트 충돌: "port is already allocated" 같은 오류가 발생하면 다른 서비스(이전 Prometheus/Grafana 인스턴스 포함)가 9090 또는 3000 포트를 사용 중인지 확인하세요. docker ps로 실행 중인 컨테이너를 찾고 docker stop <container_id>로 중지하거나, lsof -i :<port>로 포트를 사용 중인 다른 프로세스를 찾으세요. 포트가 시스템의 다른 필수 서비스와 영구적으로 충돌한다면 docker-compose.yaml 파일에서 포트를 조정해야 할 수 있어요.

Docker Compose 파일에서 Grafana의 포트를 다른 포트(예: 3090)로 변경하려면 grafana 서비스 아래에 포트 매핑을 명시적으로 지정해야 해요.

옵션 1: environment 섹션에 GF_SERVER_HTTP_PORT 추가:

  environment:
- GF_AUTH_ANONYMOUS_ENABLED=true
- GF_SERVER_HTTP_PORT=3090  # <-- Add this line

옵션 2: 포트 매핑 사용:

grafana:
  image: grafana/grafana:latest
  container_name: grafana
  ports:
  - "3090:3000"  # <-- Host:Container port mapping
  • 연결 문제:
    • Prometheus와 Grafana 컨테이너가 모두 실행 중인지 확인(docker ps).
    • Grafana의 Prometheus 데이터 소스 구성을 확인(보통 grafana/datasources/datasource.yaml로 자동 구성). ConnectionsData sourcesPrometheus로 이동. URL이 Prometheus 서비스(예: http://prometheus:9090)를 가리켜야 해요.
    • SGLang 서버가 실행 중이고 메트릭 엔드포인트(http://<sglang_server_host>:30000/metrics)가 Prometheus 컨테이너에서 접근 가능한지 확인. SGLang이 호스트 머신에서 실행 중이고 Prometheus가 Docker 안에 있다면 prometheus.yaml 스크레이프 구성에서 localhost 대신 host.docker.internal(Docker Desktop) 또는 머신의 네트워크 IP를 사용해요.
  • 대시보드에 데이터 없음:
    • 메트릭을 만들기 위해 SGLang 서버에 트래픽을 생성해요. 예를 들어 벤치마크 실행:
      python3 -m sglang.bench_serving --backend sglang --dataset-name random --num-prompts 100 --random-input 128 --random-output 128
      
    • Prometheus UI(http://localhost:9090)의 StatusTargets에서 SGLang 엔드포인트가 성공적으로 스크레이프되는지 확인.
    • Prometheus 메트릭의 model_nameinstance 라벨이 Grafana 대시보드에 사용된 변수와 일치하는지 확인. Grafana 대시보드 변수나 Prometheus 구성의 라벨을 조정해야 할 수 있어요.

구성 파일 (Configuration Files)

모니터링 설정은 examples/monitoring 디렉터리 내부의 다음 파일들로 정의돼요:

  • docker-compose.yaml: Prometheus와 Grafana 서비스를 정의.
  • prometheus.yaml: 스크레이프 대상을 포함한 Prometheus 구성.
  • grafana/datasources/datasource.yaml: Grafana용 Prometheus 데이터 소스를 구성.
  • grafana/dashboards/config/dashboard.yaml: Grafana가 지정된 경로에서 대시보드를 로드하도록 지시.
  • grafana/dashboards/json/sglang-dashboard.json: JSON 형식의 실제 Grafana 대시보드 정의.

이 파일들을 수정해 구성을 커스터마이즈할 수 있어요. 예를 들어 SGLang 서버가 다른 호스트나 포트에서 실행된다면 prometheus.yamlstatic_configs 대상을 업데이트해야 할 수 있어요.

메트릭이 수집되는지 확인 (Check if the metrics are being collected)

다음을 실행해 요청을 생성해요:

python3 -m sglang.bench_serving \
  --backend sglang \
  --dataset-name random \
  --num-prompts 3000 \
  --random-input 1024 \
  --random-output 1024 \
  --random-range-ratio 0.5

그러면 Grafana 대시보드에서 메트릭을 볼 수 있어야 해요.

추정 성능 메트릭 (Estimated Performance Metrics, MFU 관련)

SGLang은 Model FLOPs Utilization(MFU) 관련 신호를 유도하는 데 사용할 수 있는 다음 추정 GPU별 카운터를 내보내요:

  • sglang:estimated_flops_per_gpu_total: 추정 부동소수점 연산 수.
  • sglang:estimated_read_bytes_per_gpu_total: 메모리에서 읽은 추정 바이트 수.
  • sglang:estimated_write_bytes_per_gpu_total: 메모리에 쓴 추정 바이트 수.

이 메트릭은 --enable-metrics--enable-mfu-metrics가 모두 활성화됐을 때 사용할 수 있어요.

이는 누적 카운터(cumulative counters)예요. 초당 값을 얻으려면 Prometheus rate(...)를 사용해요.

PromQL 예시

GPU당 평균 TFLOPS:

rate(sglang:estimated_flops_per_gpu_total[1m]) / 1e12

GB/s 단위의 평균 추정 메모리 대역폭:

(rate(sglang:estimated_read_bytes_per_gpu_total[1m]) +
 rate(sglang:estimated_write_bytes_per_gpu_total[1m])) / 1e9

참고 사항 (Notes)

  • 이 메트릭들은 관찰 가능성과 추세 분석을 위한 추정치예요.
  • 추정 메모리 바이트는 모델링된 트래픽을 반영하며 GPU 프로파일러의 직접적인 하드웨어 카운터가 아니에요.

더 알아보기