상관 ID로 관련 로그 항목 찾기
GitLab v19.5Offering: GitLab Self-Managed
요약
GitLab 인스턴스는 대부분의 요청에 대해 고유한 요청 추적 ID("상관관계 ID"라고 합니다)를 기록합니다. 상관관계 ID는 구조화된 로그에 correlation_id 키로 기록되며 GitLab이 보내는 모든 응답 헤더에는 x-request-id 헤더로 담깁니다.
GitLab 인스턴스는 대부분의 요청에 대해 고유한 요청 추적 ID("상관관계 ID"라고 합니다)를 기록합니다. GitLab에 들어오는 각 요청마다 고유한 상관관계 ID가 부여되며, 이 ID는 해당 요청에 대해 각 GitLab 구성 요소의 로그에 기록됩니다. 덕분에 분산 시스템의 동작을 더 쉽게 추적할 수 있습니다. 이 ID가 없으면 서로 연관된 로그 항목을 맞추기가 어렵거나 불가능합니다.
요청의 상관관계 ID 확인#
상관관계 ID는 구조화된 로그에 correlation_id 키로 기록되며
GitLab이 보내는 모든 응답 헤더에는 x-request-id 헤더로 담깁니다.
둘 중 어느 쪽에서 검색해도 상관관계 ID를 찾을 수 있습니다.
브라우저에서 상관관계 ID 확인#
브라우저의 개발자 도구를 사용하면 방문 중인 사이트와 주고받는 네트워크 활동을 확인하고 검사할 수 있습니다. 주요 브라우저의 네트워크 모니터링 문서는 아래 링크를 참고합니다.
- Network Monitor - Firefox Developer Tools
- Inspect Network Activity In Chrome DevTools
- Safari Web Development Tools
- Microsoft Edge Network panel
관련 요청을 찾아 상관관계 ID를 확인하려면 다음 단계를 따릅니다:
- 네트워크 모니터에서 영구 로깅을 활성화합니다. GitLab의 일부 동작은 양식을 제출한 뒤 빠르게 리디렉션되므로, 이렇게 하면 관련 활동을 모두 수집할 수 있습니다.
- 찾으려는 요청을 분리하려면
document요청으로 필터링할 수 있습니다. - 확인하려는 요청을 선택해 세부 정보를 봅니다.
- Headers 섹션으로 이동해 Response Headers를 찾습니다. 거기에서 GitLab이 해당 요청에 대해
무작위로 생성한 값이 담긴
x-request-id헤더를 확인할 수 있습니다.
다음 예시를 참고합니다:

로그에서 상관관계 ID 확인#
올바른 상관관계 ID를 찾는 또 다른 방법은 로그를 검색하거나 관찰하면서
찾으려는 로그 항목의 correlation_id 값을
확인하는 것입니다.
예를 들어 GitLab에서 특정 동작을 재현할 때 무슨 일이 일어나거나 무엇이 실패하는지 알아보려면, GitLab 로그를 tail로 따라가면서 본인 사용자의 요청으로 필터링한 다음 관심 있는 내용이 보일 때까지 요청을 지켜볼 수 있습니다.
curl에서 상관관계 ID 확인#
curl을 사용한다면 verbose 옵션으로 요청 및 응답 헤더와 그 밖의 디버그 정보를 확인할 수 있습니다.
➜ ~ curl --verbose "https://gitlab.example.com/api/v4/projects"
# look for a line that looks like this
< x-request-id: 4rAMkV3gof4
jq 사용#
이 예시는 jq를 사용해 결과를 필터링하고 관심 있는 값을 표시합니다.
sudo gitlab-ctl tail gitlab-rails/production_json.log | jq 'select(.username == "bob") | "User: \(.username), \(.method) \(.path), \(.controller)#\(.action), ID: \(.correlation_id)"'
"User: bob, GET /root/linux, ProjectsController#show, ID: U7k7fh6NpW3"
"User: bob, GET /root/linux/commits/master/signatures, Projects::CommitsController#signatures, ID: XPIHpctzEg1"
"User: bob, GET /root/linux/blob/master/README, Projects::BlobController#show, ID: LOt9hgi1TV4"
grep 사용#
이 예시는 jq보다 설치되어 있을 가능성이 높은 grep과 tr만 사용합니다.
sudo gitlab-ctl tail gitlab-rails/production_json.log | grep '"username":"bob"' | tr ',' '\n' | egrep 'method|path|correlation_id'
{"method":"GET"
"path":"/root/linux"
"username":"bob"
"correlation_id":"U7k7fh6NpW3"}
{"method":"GET"
"path":"/root/linux/commits/master/signatures"
"username":"bob"
"correlation_id":"XPIHpctzEg1"}
{"method":"GET"
"path":"/root/linux/blob/master/README"
"username":"bob"
"correlation_id":"LOt9hgi1TV4"}
상관관계 ID로 로그 검색#
상관관계 ID를 확보하면 관련 로그 항목을 검색할 수 있습니다.
상관관계 ID 자체로 로그 줄을 필터링할 수 있습니다.
find와 grep을 조합하면 찾으려는 항목을 충분히 찾을 수 있습니다.
# find <gitlab log directory> -type f -mtime -0 exec grep '<correlation ID>' '{}' '+'
find /var/log/gitlab -type f -mtime 0 -exec grep 'LOt9hgi1TV4' '{}' '+'
/var/log/gitlab/gitlab-workhorse/current:{"correlation_id":"LOt9hgi1TV4","duration_ms":2478,"host":"gitlab.domain.tld","level":"info","method":"GET","msg":"access","proto":"HTTP/1.1","referrer":"https://gitlab.domain.tld/root/linux","remote_addr":"68.0.116.160:0","remote_ip":"[filtered]","status":200,"system":"http","time":"2019-09-17T22:17:19Z","uri":"/root/linux/blob/master/README?format=json&viewer=rich","user_agent":"Mozilla/5.0 (Mac) Gecko Firefox/69.0","written_bytes":1743}
/var/log/gitlab/gitaly/current:{"correlation_id":"LOt9hgi1TV4","grpc.code":"OK","grpc.meta.auth_version":"v2","grpc.meta.client_name":"gitlab-web","grpc.method":"FindCommits","grpc.request.deadline":"2019-09-17T22:17:47Z","grpc.request.fullMethod":"/gitaly.CommitService/FindCommits","grpc.request.glProjectPath":"root/linux","grpc.request.glRepository":"project-1","grpc.request.repoPath":"@hashed/6b/86/6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b.git","grpc.request.repoStorage":"default","grpc.request.topLevelGroup":"@hashed","grpc.service":"gitaly.CommitService","grpc.start_time":"2019-09-17T22:17:17Z","grpc.time_ms":2319.161,"level":"info","msg":"finished streaming call with code OK","peer.address":"@","span.kind":"server","system":"grpc","time":"2019-09-17T22:17:19Z"}
/var/log/gitlab/gitlab-rails/production_json.log:{"method":"GET","path":"/root/linux/blob/master/README","format":"json","controller":"Projects::BlobController","action":"show","status":200,"duration":2448.77,"view":0.49,"db":21.63,"time":"2019-09-17T22:17:19.800Z","params":[{"key":"viewer","value":"rich"},{"key":"namespace_id","value":"root"},{"key":"project_id","value":"linux"},{"key":"id","value":"master/README"}],"remote_ip":"[filtered]","user_id":2,"username":"bob","ua":"Mozilla/5.0 (Mac) Gecko Firefox/69.0","queue_duration":3.38,"gitaly_calls":1,"gitaly_duration":0.77,"rugged_calls":4,"rugged_duration_ms":28.74,"correlation_id":"LOt9hgi1TV4"}
분산 아키텍처에서의 검색#
GitLab 인프라를 수평으로 확장했다면 모든 GitLab 노드에서 검색해야 합니다. Loki, ELK, Splunk 같은 로그 집계 소프트웨어로 이 작업을 수행할 수 있습니다.
Ansible이나 PSSH(parallel SSH)처럼 여러 서버에서 동일한 명령을 병렬로 실행할 수 있는 도구를 사용하거나, 직접 만든 방법을 쓸 수도 있습니다.
성능 바에서 요청 확인#
성능 바를 사용하면 SQL과 Gitaly 호출을 비롯한 유용한 데이터를 확인할 수 있습니다.
데이터를 보려면 요청의 상관관계 ID가 성능 바를 보고 있는 사용자의 세션과 일치해야 합니다. API 요청이라면 인증된 사용자의 세션 쿠키로 요청을 수행해야 한다는 뜻입니다.
예를 들어 다음 API 엔드포인트에서 실행된 데이터베이스 쿼리를 확인하려는 경우를 살펴봅니다:
https://gitlab.com/api/v4/groups/2564205/projects?with_security_reports=true&page=1&per_page=1
먼저 Developer Tools 패널을 활성화합니다. 방법은 브라우저에서 상관관계 ID 확인을 참고합니다.
개발자 도구를 활성화한 뒤에는 다음과 같이 세션 쿠키를 가져옵니다:
- 로그인한 상태로 https://gitlab.com을 방문합니다.
- 선택 사항입니다. Developer Tools 패널에서 Fetch/XHR 요청 필터를 선택합니다. 이 단계는 Google Chrome 개발자 도구를 기준으로 설명한 것이며 반드시 필요하지는 않습니다. 올바른 요청을 더 쉽게 찾을 수 있게 해 줄 뿐입니다.
- 왼쪽에서
results?request_id=<some-request-id>요청을 선택합니다. - 세션 쿠키는
Headers패널의Request Headers섹션에 표시됩니다. 쿠키 값을 오른쪽 클릭하고Copy value를 선택합니다.

세션 쿠키 값이 클립보드에 복사됩니다. 예를 들면 다음과 같습니다:
experimentation_subject_id=<subject-id>; _gitlab_session=<session-id>; event_filter=all; visitor_id=<visitor-id>; perf_bar_enabled=true; sidebar_collapsed=true; diff_view=inline; sast_entry_point_dismissed=true; auto_devops_settings_dismissed=true; cf_clearance=<cf-clearance>; collapsed_gutter=false
이 세션 쿠키 값을 curl 요청의 사용자 지정 헤더에 붙여 넣어 API 요청을 만듭니다:
$ curl --include "https://gitlab.com/api/v4/groups/2564205/projects?with_security_reports=true&page=1&per_page=1" \
--header 'cookie: experimentation_subject_id=<subject-id>; _gitlab_session=<session-id>; event_filter=all; visitor_id=<visitor-id>; perf_bar_enabled=true; sidebar_collapsed=true; diff_view=inline; sast_entry_point_dismissed=true; auto_devops_settings_dismissed=true; cf_clearance=<cf-clearance>; collapsed_gutter=false'
date: Tue, 28 Sep 2021 03:55:33 GMT
content-type: application/json
...
x-request-id: 01FGN8P881GF2E5J91JYA338Y3
...
[
{
"id":27497069,
"description":"Analyzer for images used on live K8S containers based on Starboard"
},
"container_registry_image_prefix":"registry.gitlab.com/gitlab-org/security-products/analyzers/cluster-image-scanning",
"..."
]
응답에는 API 엔드포인트의 데이터와 함께, 요청의 상관관계 ID 확인 섹션에서 설명한 대로 x-request-id 헤더로 반환되는 correlation_id 값이 담겨 있습니다.
그런 다음 이 요청의 데이터베이스 세부 정보를 확인할 수 있습니다:
-
x-request-id값을 성능 바의request details필드에 붙여 넣고 Enter/Return을 누릅니다. 이 예시에서는 앞의 응답이 반환한x-request-id값01FGN8P881GF2E5J91JYA338Y3을 사용합니다:
-
성능 바 오른쪽의
Request Selector드롭다운 목록에 새 요청이 추가됩니다. 새 요청을 선택해 해당 API 요청의 지표를 확인합니다:
-
진행 바에서
pg링크를 선택해 해당 API 요청이 실행한 데이터베이스 쿼리를 확인합니다:
데이터베이스 쿼리 대화 상자가 표시됩니다:
