- JQ란?
- 로그 파싱
GitLab logs의 jq
로 파싱하기
가능한 경우에는 Kibana나 Splunk와 같은 로그 집계 및 검색 도구를 사용하는 것이 좋습니다.
그러나 사용할 수 없는 경우 GitLab 로그를 JSON 형식(12.0 버전 이후 기본 형식)으로 여전히 빠르게 파싱할 수 있습니다.
jq
를 사용합니다.
fast-stats
도구를 제공합니다.JQ란?
매뉴얼에 기재된 대로, jq
는 명령줄 JSON 프로세서입니다. 다음 예시는 GitLab 로그 파일 파싱을 위한 사용 사례를 포함합니다.
로그 파싱
아래 나열된 예시들은 각각의 로그 파일을 해당하는 Linux 패키지 설치 경로와 기본 파일명으로 다루고 있습니다. GitLab 로그 섹션에서 해당 전체 경로를 찾을 수 있습니다.
일반 명령어
색이 칠해진 jq
출력을 less
로 파이프
jq . <FILE> -C | less -R
용어 검색 및 매칭 라인들을 예쁘게 출력
grep <TERM> <FILE> | jq .
유효하지 않은 JSON 라인 건너뛰기
jq -cR 'fromjson?' file.json | jq <COMMAND>
기본적으로 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 로그에서 correlation 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)' <FILE>
상위 10개 지연 요청
jq -s 'sort_by(-.duration_s) | limit(10; .[])' <FILE>
프로젝트와 관련된 모든 요청 찾아 예쁘게 출력
grep <PROJECT_NAME> <FILE> | jq .
총 지속 시간이 5초를 초과하는 모든 요청 찾기
jq 'select(.duration_s > 5000)' <FILE>
5개 이상의 Gitaly 호출이 있는 모든 프로젝트 요청 찾기
grep <PROJECT_NAME> <FILE> | jq 'select(.gitaly_calls > 5)'
Gitaly 지속 시간이 10초를 초과하는 모든 요청 찾기
jq 'select(.gitaly_duration_s > 10000)' <FILE>
큐 지속 시간이 10초를 초과하는 모든 요청 찾기
jq 'select(.queue_duration_s > 10000)' <FILE>
Gitaly 호출 수에 따른 상위 10개 요청
jq -s 'map(select(.gitaly_calls != null)) | sort_by(-.gitaly_calls) | limit(10; .[])' <FILE>
특정 시간 범위 출력
jq 'select(.time >= "2023-01-10T00:00:00Z" and .time <= "2023-01-10T12:00:00Z")' <FILE>
gitlab-rails/production_json.log
파싱
요청 볼륨이 많은 상위 세 개의 컨트롤러 메서드와 가장 긴 지속 시간 출력
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
gitlab-rails/api_json.log
파싱
요청 횟수 및 가장 긴 지속 시간을 가진 상위 세 개의 라우트 출력
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
상위 API 사용자 에이전트 출력
jq --raw-output 'select(.remote_ip != "127.0.0.1") | [.remote_ip, .username, .route, .ua] | @tsv' api_json.log |
sort | uniq -c | sort -n | tail
예시 출력:
89 1.2.3.4, 127.0.0.1 some_user /api/:version/projects/:id/pipelines # plus browser details; OK
567 5.6.7.8, 127.0.0.1 /api/:version/jobs/:id/trace gitlab-runner # plus version details; OK
1234 98.76.54.31, 127.0.0.1 some_bot /api/:version/projects/:id/repository/files/:file_path/raw
이 예시는 커스텀 도구나 스크립트로 인해 예상치 못한 높은 요청 수를 유발합니다. 이 경우 사용자 에이전트는 다음과 같을 수 있습니다:
-
python-requests
나curl
과 같은 제3자 라이브러리. - GitLab CLI 클라이언트.
또한 해당 사용자나 봇에 대한 성능 통계를 추출하려면 fast-stats top
을 사용할 수 있습니다.
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") | [.remote_ip, .uri, .user_agent] | @tsv' current |
sort | uniq -c | sort -n | tail
API ua
예제와 유사하게, 이 출력에서 예기치 않은 사용자 에이전트가 나타나면 최적화되지 않은 스크립트를 나타냅니다. gitlab-runner
, GitLab-Shell
, 그리고 브라우저가 예상 사용자 에이전트입니다.
러너(runner)가 새 작업을 확인하는 성능 영향을 줄이려면 예를 들어 check_interval 설정을 늘릴 수 있습니다.
gitlab-rails/geo.log
구문 분석
가장 일반적인 Geo 동기화 오류 찾기
만약 geo:status Rake task가 몇몇 아이템이 100%에 이르지 않았다고 반복적으로 보고한다면, 아래 명령은 가장 일반적인 오류에 집중하는 데 도움이 됩니다.
jq --raw-output 'select(.severity == "ERROR") | [.project_path, .class, .message, .error] | @tsv' geo.log | sort | uniq -c | sort | tail
특정 오류 메시지에 대한 조언은 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
요청 볼륨 상위 열 개의 프로젝트와 각각의 세 가지 가장 긴 지속 기간 출력
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'
...
사용자 및 프로젝트 활동 종류 개요
jq --raw-output '[.username, ."grpc.method", ."grpc.request.glProjectPath"] | @tsv' current | sort | uniq -c | sort -n
치명적인 Git 문제로 영향 받는 모든 프로젝트 찾기
grep "fatal: " current |
jq '."grpc.request.glProjectPath"' |
sort | uniq
gitlab-shell/gitlab-shell.log
구문 분석
SSH를 통한 Git 호출 조사를 위해 GitLab 12.10부터.
프로젝트 및 사용자별 상위 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