`jq`로 GitLab 로그 파싱
Offering: GitLab Self-Managed
가능한 경우 Kibana 및 Splunk와 같은 로그 집계 및 검색 도구를 사용하는 것이 좋습니다. 특히 오류 이벤트 요약 및 기본 사용 통계를 위해 GitLab 지원 팀은 특화된 fast-stats 도구를 제공합니다.
가능한 경우 Kibana 및 Splunk와 같은 로그 집계 및 검색 도구를 사용하는 것이 좋습니다. 그러나 사용할 수 없는 경우에도 jq를 사용하여 JSON 형식의 GitLab 로그를 빠르게 파싱할 수 있습니다.
특히 오류 이벤트 요약 및 기본 사용 통계를 위해
GitLab 지원 팀은 특화된
fast-stats 도구를 제공합니다.
이 도구는 일반적으로 jq보다 훨씬 빠르게 더 큰 로그를 처리하고
더 많은 통계 정보를 출력합니다.
JQ란?#
매뉴얼에 명시된 바와 같이 jq는 명령줄 JSON 프로세서입니다. 다음 예시에는 GitLab 로그 파일 파싱을 위한 사용 사례가 포함되어 있습니다.
로그 파싱#
아래 나열된 예시는 각각의 Linux 패키지 설치 경로 및 기본 파일명으로 해당 로그 파일을 참조합니다. 각 전체 경로는 GitLab 로그 섹션에서 찾을 수 있습니다.
압축된 로그#
로그 파일이 교체되면 Unix 타임스탬프 형식으로 이름이 변경되고 gzip으로 압축됩니다. 결과 파일 이름은 @40000000624492fa18da6f34.s처럼 보입니다. 이 파일들은 최근 로그 파일들과 다르게 처리해야 합니다:
- 파일의 압축을 해제하려면
gunzip -S .s @40000000624492fa18da6f34.s를 사용하여 파일명을 압축된 로그 파일의 이름으로 바꿉니다. - 파일을 직접 읽거나 파이프하려면
zcat또는zless를 사용합니다. - 파일 내용을 검색하려면
zgrep을 사용합니다.
일반 명령#
색상화된 jq 출력을 less로 파이프#
jq . -C | less -R
용어 검색 및 일치하는 모든 줄 예쁘게 출력#
grep | jq .
JSON의 잘못된 줄 건너뛰기#
jq -cR 'fromjson?' file.json | jq
기본적으로 jq는 유효한 JSON이 아닌 줄을 만나면 오류가 발생합니다. 이는 모든 잘못된 줄을 건너뛰고 나머지를 파싱합니다.
JSON 로그의 시간 범위 출력#
cat log.json | (head -1; tail -1) | jq '.time'
파일이 교체되고 압축된 경우 zcat을 사용합니다:
zcat @400000006026b71d1a7af804.s | (head -1; tail -1) | jq '.time'
zcat some_json.log.25.gz | (head -1; tail -1) | jq '.time'
여러 JSON 로그에서 상관 관계 ID에 대한 활동을 시간 순서로 가져오기#
grep -hR <correlationID> | jq -c -R 'fromjson?' | jq -C -s 'sort_by(.time)' | less -R
gitlab-rails/production_json.log 및 gitlab-rails/api_json.log 파싱#
5XX 상태 코드가 있는 모든 요청 찾기#
jq 'select(.status >= 500)'
가장 느린 요청 상위 10개#
jq -s 'sort_by(-.duration_s) | limit(10; .[])'
프로젝트 관련 모든 요청 찾기 및 예쁘게 출력#
grep | jq .
총 기간이 5초 초과인 모든 요청 찾기#
jq 'select(.duration_s > 5000)'
Gitaly 호출이 5번 이상인 모든 프로젝트 요청 찾기#
grep | jq 'select(.gitaly_calls > 5)'
Gitaly 기간이 10초 초과인 모든 요청 찾기#
jq 'select(.gitaly_duration_s > 10000)'
대기 기간이 10초 초과인 모든 요청 찾기#
jq 'select(.queue_duration_s > 10000)'
Gitaly 호출 수 기준 상위 10개 요청#
jq -s 'map(select(.gitaly_calls != null)) | sort_by(-.gitaly_calls) | limit(10; .[])'
특정 시간 범위 출력#
jq 'select(.time >= "2023-01-10T00:00:00Z" and .time <= "2023-01-10T12:00:00Z")'
gitlab-rails/production_json.log 파싱#
요청 볼륨 기준 상위 3개 컨트롤러 메서드 및 가장 긴 기간 3개 출력#
jq -s -r 'group_by(.controller+.action) | sort_by(-length) | limit(3; .[]) | sort_by(-.duration_s) | "CT: \(length)\tMETHOD: \(.[0].controller)#\(.[0].action)\tDURS: \(.[0].duration_s), \(.[1].duration_s), \(.[2].duration_s)"' production_json.log
출력 예시
CT: 2721 METHOD: SessionsController#new DURS: 844.06, 713.81, 704.66
CT: 2435 METHOD: MetricsController#index DURS: 299.29, 284.01, 158.57
CT: 1328 METHOD: Projects::NotesController#index DURS: 403.99, 386.29, 384.39
대안으로 fast-stats를 사용합니다:
fast-stats --verbose --limit=3 production_json.log
gitlab-rails/api_json.log 파싱#
요청 수와 가장 긴 기간 3개가 있는 상위 3개 라우트 출력#
jq -s -r 'group_by(.route) | sort_by(-length) | limit(3; .[]) | sort_by(-.duration_s) | "CT: \(length)\tROUTE: \(.[0].route)\tDURS: \(.[0].duration_s), \(.[1].duration_s), \(.[2].duration_s)"' api_json.log
출력 예시
CT: 2472 ROUTE: /api/:version/internal/allowed DURS: 56402.65, 38411.43, 19500.41
CT: 297 ROUTE: /api/:version/projects/:id/repository/tags DURS: 731.39, 685.57, 480.86
CT: 190 ROUTE: /api/:version/projects/:id/repository/commits DURS: 1079.02, 979.68, 958.21
대안으로 fast-stats를 사용합니다:
fast-stats --verbose --limit=3 api_json.log
상위 API 사용자 에이전트 출력#
jq --raw-output '
select(.remote_ip != "127.0.0.1") | [
(.time | split(".")[0] | strptime("%Y-%m-%dT%H:%M:%S") | strftime("…%m-%dT%H…")),
."meta.caller_id", .username, .ua
] | @tsv' api_json.log | sort | uniq -c \
| grep --invert-match --extended-regexp '^\s+\d{1,3}\b'
출력 예시:
1234 …01-12T01… GET /api/:version/projects/:id/pipelines some_user # 브라우저 세부 정보 포함; 정상
54321 …01-12T01… POST /api/:version/projects/:id/repository/files/:file_path/raw some_bot
5678 …01-12T01… PATCH /api/:version/jobs/:id/trace gitlab-runner # 버전 세부 정보 포함; 정상
이 예시는 커스텀 도구 또는 스크립트가 예상치 못하게 높은 요청 빈도 (>15 RPS)를 유발하는 것을 보여줍니다. 이 상황의 사용자 에이전트는 특화된 타사 클라이언트이거나 curl과 같은 일반 도구일 수 있습니다.
시간별 집계는 다음에 도움이 됩니다:
- Prometheus와 같은 모니터링 도구의 데이터와 봇 또는 사용자 활동 급증 상관관계 파악.
- 속도 제한 설정 평가.
jq와 함께 fast-stats top을 사용하여 해당 사용자 및 봇의 성능 영향을 검토합니다:
fast-stats top --display=percentage --sort-by=cpu-s api_json.log
높은 요청 빈도 자체가 자동으로 문제가 되는 것은 아니지만 리소스의 많은 비율을 사용하는 것은 문제입니다.
gitlab-rails/importer.log 파싱#
프로젝트 임포트 또는 마이그레이션 문제 해결을 위해 다음 명령을 실행합니다:
jq 'select(.project_path == "<namespace>/<project>").error_messages' importer.log
일반적인 문제는 문제 해결을 참조하세요.
gitlab-workhorse/current 파싱#
상위 Workhorse 사용자 에이전트 출력#
jq --raw-output '
select(.remote_ip != "127.0.0.1") | [
(.time | split(".")[0] | strptime("%Y-%m-%dT%H:%M:%S") | strftime("…%m-%dT%H…")),
.remote_ip, .uri, .user_agent
] | @tsv' current |
sort | uniq -c
API ua 예시와 유사하게 이 출력에서 예상치 못한 사용자 에이전트가 많으면 최적화되지 않은 스크립트를 나타냅니다. 예상되는 사용자 에이전트에는 gitlab-runner, GitLab-Shell 및 브라우저가 포함됩니다.
예를 들어 check_interval 설정을 늘려 러너가 새 작업을 확인하는 성능 영향을 줄일 수 있습니다.
gitlab-rails/geo.log 파싱#
가장 일반적인 Geo 동기화 오류 찾기#
gitlab:geo:status Rake 태스크가 일부 항목이 100%에 도달하지 않는다고 반복적으로 보고하는 경우 다음 명령이 가장 일반적인 오류에 집중하는 데 도움이 됩니다.
jq --raw-output 'select(.severity == "ERROR") | [
(.time | split(".")[0] | strptime("%Y-%m-%dT%H:%M:%S") | strftime("…%m-%dT%H:%M…")),
.class, .id, .message, .error
] | @tsv' geo.log \
| sort | uniq -c
특정 오류 메시지에 대한 조언은 Geo 문제 해결 페이지를 참조하세요.
gitaly/current 파싱#
다음 예시를 사용하여 Gitaly 문제를 해결합니다.
웹 UI에서 전송된 모든 Gitaly 요청 찾기#
jq 'select(."grpc.meta.client_name" == "gitlab-web")' current
실패한 모든 Gitaly 요청 찾기#
jq 'select(."grpc.code" != null and ."grpc.code" != "OK")' current
30초보다 오래 걸린 모든 요청 찾기#
jq 'select(."grpc.time_ms" > 30000)' current
요청 볼륨 기준 상위 10개 프로젝트 및 가장 긴 기간 3개 출력#
jq --raw-output --slurp '
map(
select(
."grpc.request.glProjectPath" != null
and ."grpc.request.glProjectPath" != ""
and ."grpc.time_ms" != null
)
)
| group_by(."grpc.request.glProjectPath")
| sort_by(-length)
| limit(10; .[])
| sort_by(-."grpc.time_ms")
| [
length,
.[0]."grpc.time_ms",
.[1]."grpc.time_ms",
.[2]."grpc.time_ms",
.[0]."grpc.request.glProjectPath"
]
| @sh' current |
awk 'BEGIN { printf "%7s %10s %10s %10s\t%s\n", "CT", "MAX DURS", "", "", "PROJECT" }
{ printf "%7u %7u ms, %7u ms, %7u ms\t%s\n", $1, $2, $3, $4, $5 }'
출력 예시
CT MAX DURS PROJECT
206 4898 ms, 1101 ms, 1032 ms 'groupD/project4'
109 1420 ms, 962 ms, 875 ms 'groupEF/project56'
663 106 ms, 96 ms, 94 ms 'groupABC/project123'
...
대안으로 fast-stats를 사용합니다:
fast-stats top --sort-by=duration current
사용자 및 프로젝트 활동 유형 개요#
jq --raw-output '[
(.time | split(".")[0] | strptime("%Y-%m-%dT%H:%M:%S") | strftime("…%m-%dT%H…")),
.username, ."grpc.method", ."grpc.request.glProjectPath"
] | @tsv' current | sort | uniq -c \
| grep --invert-match --extended-regexp '^\s+\d{1,3}\b'
출력 예시:
5678 …01-12T01… ReferenceTransactionHook # Praefect 작업; 정상
54321 …01-12T01… some_bot GetBlobs namespace/subgroup/project
1234 …01-12T01… some_user FindCommit namespace/subgroup/project
이 예시는 커스텀 도구 또는 스크립트가 Gitaly에서 예상치 못하게 높은 요청 빈도 (>15 RPS)를 유발하는 것을 보여줍니다. 시간별 집계는 다음에 도움이 됩니다:
- Prometheus와 같은 모니터링 도구의 데이터와 봇 또는 사용자 활동 급증 상관관계 파악.
- 속도 제한 설정 평가.
jq와 함께 fast-stats top을 사용하여 해당 사용자 및 봇의 성능 영향을 검토합니다:
fast-stats top --display=percentage --sort-by=cpu-s current
높은 요청 빈도 자체가 자동으로 문제가 되는 것은 아니지만 리소스의 많은 비율을 사용하는 것은 문제입니다.
치명적인 Git 문제의 영향을 받는 모든 프로젝트 찾기#
grep "fatal: " current |
jq '."grpc.request.glProjectPath"' |
sort | uniq
gitlab-shell/gitlab-shell.log 파싱#
SSH를 통한 Git 호출 조사를 위해.
프로젝트 및 사용자별 상위 20개 호출 찾기:
jq --raw-output --slurp '
map(
select(
.username != null and
.gl_project_path !=null
)
)
| group_by(.username+.gl_project_path)
| sort_by(-length)
| limit(20; .[])
| "count: \(length)\tuser: \(.[0].username)\tproject: \(.[0].gl_project_path)" ' \
gitlab-shell.log
프로젝트, 사용자 및 명령별 상위 20개 호출 찾기:
jq --raw-output --slurp '
map(
select(
.command != null and
.username != null and
.gl_project_path !=null
)
)
| group_by(.username+.gl_project_path+.command)
| sort_by(-length)
| limit(20; .[])
| "count: \(length)\tcommand: \(.[0].command)\tuser: \(.[0].username)\tproject: \(.[0].gl_project_path)" ' \
gitlab-shell.log
