GitLab 로그를 jq로 파싱하기

Tier: Free, Premium, Ultimate Offering: Self-Managed

가능하다면 Kibana나 Splunk와 같은 로그 집계 및 검색 도구를 사용하는 것이 좋지만, 사용할 수 없는 경우에도 GitLab 로그를 JSON 형식으로 빠르게 파싱할 수 있습니다. jq를 사용합니다.

note
특히 오류 이벤트를 요약하고 기본 사용 통계를 위해 GitLab 지원팀은 전문적인 fast-stats 도구를 제공합니다.

JQ란?

그것의 메뉴얼에 언급된대로, jq는 명령줄 JSON 프로세서입니다. 다음 예제는 GitLab 로그 파일을 파싱하기 위해 대상으로 하는 사용 사례를 포함합니다.

로그 파싱

아래 디렉터리에 있는 예제들은 각각의 로그 파일을 주소 상의 Linux 패키지 설치 경로와 기본 파일 이름으로 참조합니다. 해당 전체 경로는 GitLab 로그 섹션에서 확인하십시오.

압축된 로그

로그 파일이 로테이트될 때, 해당 파일은 유닉스 타임스탬프 형식으로 이름이 바뀌고 gzip로 압축됩니다. 그 결과 파일 이름은 @40000000624492fa18da6f34.s와 같이 보입니다. 이러한 파일은 최신 로그 파일보다 파싱하기 전에 다르게 처리해야 합니다:

  • 파일을 압축 해제하기 위해, gunzip -S .s @40000000624492fa18da6f34.s와 같이 압축된 로그 파일의 이름으로 대체하여 사용합니다.
  • 파일을 직접 읽거나 파이핑하기 위해 zcat 또는 zless를 사용합니다.
  • 파일 내용을 검색하기 위해 zgrep을 사용합니다.

일반 명령어

컬러 출력을 가진 jq 출력을 less로 파이핑

jq . <FILE> -C | less -R

용어를 검색하고 일치하는 모든 라인을 보기 좋게 출력

grep <TERM> <FILE> | jq .

부적합한 JSON 라인 건너뛰기

jq -cR 'fromjson?' file.json | jq <COMMAND>

기본 설정대로 jq는 유효하지 않은 라인을 만나면 오류를 반환합니다. 이 명령어는 모든 부적절한 라인을 건너뛰고 나머지 부분을 파싱합니다.

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'

연관 ID에 대한 여러 JSON 로그에서 활동 가져오기

grep -hR <correlationID> | jq -c -R 'fromjson?' | jq -C -s 'sort_by(.time)'  | less -R

gitlab-rails/production_json.loggitlab-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개 컨트롤러 메소드 및 최장 기간 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개 라우트 및 최장 기간 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  # 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

이 예시는 예상치 못하게 높은 요청 수를 발생시키는 사용자나 봇을 나타냅니다. 이런 경우 사용자 에이전트는 다음과 같을 수 있습니다:

또한, 이러한 사용자나 봇에 대한 성능 통계를 추출하기 위해 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 호출 조사를 위해.

프로젝트 및 사용자별 상위 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