Code States/TIL

[0331] (페어) 데이터베이스 - 로그 파이프라인

ki1111m2 2023. 3. 31. 17:34

1. nginx 로그 분석

parse.js 파일을 수정하여 로그를 json 형식으로 출력하기

sample.log 를 보고 로그의 형식을 파악한다.

 

2. 파서(parser) 작성

const customParseFormat = require('dayjs/plugin/customParseFormat')
dayjs.extend(customParseFormat)

process.stdin.on("data", data => {

	// log 파일의 한줄을 저장
  let raw = data.toString()

	// [\] : 대괄호([]) 로 묶인 문자열을 검색
	// .+ :  모든 문자열이든 1개 이상 존재 가능
	// g : 전역에서 검
  let regex = /\[(.+)\]/g
  let match = regex.exec(raw)[1]
  let timestamp = dayjs(match, 'DD/MMM/YYYY:hh:mm:ss +ZZ').toISOString()

	// d{1,3} : 1~3자리 숫자 검색
	// . : 마침표('.') 검색
	// -> 1~3 자리 숫자와 마침표가 4번 반복되는 패턴 
  let ipRegex = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/;
  let source_ip = raw.match(ipRegex);

	// /GET|POST|PUT|DELETE|HEAD|OPTIONS/ :  | 사이에 있는 단어 검색
  let methodRegex = /GET|POST|PUT|DELETE|HEAD|OPTIONS/;
  let method = raw.match(methodRegex);

  // [1-5] : 1~5 사이 숫자
	// d{2} : 1~9사이의 연속된 두 숫자
	// s : 공백
  let statusRegex = /[1-5]\d{2}\s/;
  // ip의 세자리 숫자를 가지고 오는 경우가 있어 공백까지 검색한 후 trim()으로 공백제거
  let status_code =  raw.match(statusRegex)[0].trim();

	// (?<=GET|POST|PUT|DELETE|HEAD|OPTIONS) :
	// GET, POST, PUT, DELETE, HEAD, OPTIONS 중 하나가 바로 앞에 오는 부분을 검색
	// s : 공백
	// S* : 공백 문자가 아닌 모든 문자
	// (?=\sHTTP) : 공백 문자 뒤 'HTTP'가 오는 부분 검색
  let pathRegex = /(?<=GET|POST|PUT|DELETE|HEAD|OPTIONS)\s\S*(?=\sHTTP)/;
	// trim()으로 공백제거
  let path = raw.match(pathRegex)[0].trim();

  let jsonString = `
{
  "source_ip": "${source_ip}",
  "method": "${method}",
  "status_code": ${status_code},
  "path": "${path}",
  "timestamp": "${timestamp}"
}`

  process.stdout.write(jsonString)
})

 

3. 데이터 웨어하우스 준비

ElephantSQL로 PostSQL을 생성한다.

 

4. 데이터베이스 연결 테스트

.env 파일 작성

테스트

 

5. 수집기(collector) 작성

collector.js 의 queryString 부분을 수정하여 수집한 로그를 테이블 컬럼에 맞게 insert 되도록한다. 수정한 파일은 아래와 같다.

sample.json에 작성된 로그파일이 테이블에 잘 저장되는지 확인

nginx를 사용할 시 찍히는 access.log 확인

access.log를 collector.js 를 사용하여 디비에 저장

 

6. 잘못 쌓인 데이터 지우기

4_clean_up_table.sql에 테이블 데이터를 삭제하는 쿼리 작성

 

7. 파이프라인 완성

 


정규표현식 작성이 진짜 너무 어려웠다 ..

쓸 일이 없다보니 익숙하지 않아서 계속 구글링하면서 작성했는데

정규식을 다른 메소드들과 함게 써야하는데 메소드랑 매치시키는 것도 쉽지 않았고

처음엔 띄어쓰기를 기준으로 스플릿해서 접근하는 방식을 해봤는데 간단하지만 너무 야매인 느낌이었다

정규식 이용해서 제대로? 정석으로? 하고싶었는데 불러온 문자열에 문자열 메소드들이 다 적용이 안돼서 엄청 해맸다..

결국엔 정규식을 이용하더라도 인덱스를 이용해서 접근해야했다

어차피 정규식을 제대로 썼으면 0번에 원하는 값이 있으니 틀린 것은 아니지만 인덱스 없이 깔끔하게 하고싶은 마음이랄까

정규식 작성에서 너무 힘들었어서 콜렉터 작성에 겁먹고있었는데 콜렉터는 생각보다 쉽게 끝났다

그래도 걱정한 것 보단 쉽게 끝낸 것 같은 이번 스프린트 ..

한 분이 나가서 페어를 셋이 하게된게 점점 더 다행인 기분이다 ㅋㅋㅋ ㅠㅠ 

프로젝트 할 때는 한 명 분의 역할이 부족하겠지만.. 내가 좀 더 열심히 해서 매꾸면 되겠지

당장 다음 주 월요일부터 첫 번째 프로젝트 시작인데 너무 긴장되고 두렵다

아자아자 해내자 ~~!