- JQ란?
- 로그 파싱
GitLab logs를 jq
로 파싱하기
가능한 경우 Kibana 및 Splunk와 같은 로그 집계 및 검색 도구를 사용하는 것이 좋지만 사용할 수 없는 경우 GitLab logs를 JSON 형식으로 빠르게 파싱할 수 있습니다.
jq
를 사용하여 파싱할 수 있습니다.
참고:
특히 오류 이벤트 및 기본 사용 통계를 요약하기 위해 GitLab 지원팀은 전용 fast-stats
도구를 제공합니다.
JQ란?
그것의 매뉴얼에 언급된대로, jq
는 명령 줄 JSON 프로세서입니다. 다음 예제는 GitLab 로그 파일을 파싱하기 위해 대상을 둔 사용 사례를 포함합니다.
로그 파싱
리스트된 예제는 각각의 로그 파일을 해당하는 상대적인 리눅스 패키지 설치 경로와 기본 파일 이름으로 다룹니다. GitLab logs 섹션에서 해당되는 전체 경로를 찾을 수 있습니다.
압축된 로그
로그 파일이 회전될 때, 파일은 Unix 타임스탬프 형식으로 이름이 변경되고 gzip
로 압축됩니다. 결과 파일 이름은 @40000000624492fa18da6f34.s
와 같이 보입니다. 이러한 파일은 최근 로그 파일과 다르게 파싱하기 위해 별도로 처리되어야 합니다.
- 파일의 압축을 푸려면,
gunzip -S .s @40000000624492fa18da6f34.s
를 사용하여 압축된 로그 파일의 이름으로 대체합니다. - 파일을 직접 읽거나 pipe로 이용하려면
zcat
또는zless
를 사용합니다. - 파일 내용을 검색하려면
zgrep
을 사용합니다.
일반적인 명령어
색깔로 칠한 jq
출력을 less
에 pipe
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
파싱
요청 볼륨 상위 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
gitlab-rails/api_json.log
파싱
요청 수 상위 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
상위 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 # 브라우저 세부 정보 포함; OK
567 5.6.7.8, 127.0.0.1 /api/:version/jobs/:id/trace gitlab-runner # 버전 세부 정보 포함; OK
1234 98.76.54.31, 127.0.0.1 some_bot /api/:version/projects/:id/repository/files/:file_path/raw
이 예시는 특정 도구나 스크립트로 인해 예상치 못한 수의 요청이 발생하는 상황을 보여줍니다.
이러한 상황에서의 사용자 에이전트는 제3자 클라이언트나 curl
과 같은 일반 도구 등이 될 수 있습니다.
또한 해당 사용자나 봇의 성능 통계를 얻으려면 빠른 통계의 상위 항목을 사용할 수도 있습니다.
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
, 그리고 브라우저가 포함됩니다.
예를 들어, 새로운 작업을 검사하는 러너의 성능 영향을 줄일 수 있도록 체크 간격 설정을 증가시킴으로써 러너의 성능 영향을 줄일 수 있습니다.
gitlab-rails/geo.log
구문 분석
가장 흔한 Geo 동기화 오류 찾기
만약 the 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 호출을 조사하기 위한 것입니다.
프로젝트 및 사용자별 상위 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