분과 값별로 그룹화해야 하는 복잡한 로그가 있습니다. 다음은 몇 가지 샘플 로그입니다.
2019-08-09T19:01:53:594+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Unrecognise Request","data":{},"errMessage":"connect ECONNREFUSED 127.0.0.1:7000"},"metadata":"test1","logTime":"2019-08-09T12:01:53.594Z","responseTime":4}
2019-08-09T19:01:53:673+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Unrecognise Request","data":{},"errMessage":"connect ECONNREFUSED 127.0.0.1:7000"},"metadata":"test2","logTime":"2019-08-09T12:01:53.673Z","responseTime":4}
2019-08-09T19:14:03:773+07:00 - info: {"tag":"request /validate","tagName":{"status":"05","message":"Unrecognise Request","data":{},"errMessage":"error internal"},"metadata":"test3","logTime":"2019-08-09T12:14:03.773Z","responseTime":7}
2019-08-09T19:19:32:925+07:00 - info: {"tag":"request /validate","tagName":{"status":"05","message":"Unrecognise Request","data":{},"errMessage":"error internal"},"metadata":"test4","logTime":"2019-08-09T12:19:32.925Z","responseTime":8}
내 기대는 다음과 같습니다.
19:01 errMessage : connect ECONNREFUSED 127.0.0.1:7000 10
19:02 errMessage : error internal 20
19:03 errMessage : error internal 10
유명한:
19:01 = hour minutes
errMessage : error internal = value
20 = count message err
아래 awk를 시도했지만 여전히 결과를 그룹화하지 않았습니다.
cat file.log | strings | grep "errMessage" | awk -F'[{,]' '{print $1,$3,$4,$5,$8}' | awk -F'[-,"]' '{print $3,$11,$12,$13,$15,$16,$17}'
타임스탬프 및 개수 값을 기준으로 결과를 그룹화하는 방법을 찾는 데 도움을 주실 수 있나요?
감사해요
답변1
질문에 제공된 데이터가 너무 희박해서 확장했습니다. 이를 통해 그룹화 논리를 분 단위, 오류 메시지 및 개수별로 더 잘 시연/검증할 수 있습니다.
2019-08-09T19:02:00:000+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Unrecognise Request","data":{},"errMessage":"connect ECONNREFUSED 127.0.0.1:7000"},"metadata":"test1","logTime":"2019-08-09T12:02:00.000Z","responseTime":4}
2019-08-09T19:02:03:000+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Unrecognise Request","data":{},"errMessage":"connect ECONNREFUSED 127.0.0.1:7000"},"metadata":"test1","logTime":"2019-08-09T12:02:00.000Z","responseTime":4}
2019-08-09T19:02:10:000+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Unrecognise Request","data":{},"errMessage":"connect ECONNREFUSED 127.0.0.1:7000"},"metadata":"test2","logTime":"2019-08-09T12:02:10.000Z","responseTime":4}
2019-08-09T19:02:15:000+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Internal Server Error","data":{},"errMessage":"TypeError: Cannot read property 'name' of undefined"},"metadata":"test2","logTime":"2019-08-09T12:02:10.000Z","responseTime":10}
2019-08-09T19:02:20:000+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Unrecognise Request","data":{},"errMessage":"connect ECONNREFUSED 127.0.0.1:7000"},"metadata":"test3","logTime":"2019-08-09T12:02:20.000Z","responseTime":4}
2019-08-09T19:02:25:000+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Unrecognise Request","data":{},"errMessage":"connect ECONNREFUSED 127.0.0.1:7000"},"metadata":"test3","logTime":"2019-08-09T12:02:20.000Z","responseTime":4}
2019-08-09T19:02:30:000+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Unrecognise Request","data":{},"errMessage":"connect ECONNREFUSED 127.0.0.1:7000"},"metadata":"test4","logTime":"2019-08-09T12:02:30.000Z","responseTime":4}
2019-08-09T19:02:35:000+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Internal Server Error","data":{},"errMessage":"ReferenceError: foo is not defined"},"metadata":"test4","logTime":"2019-08-09T12:02:30.000Z","responseTime":20}
2019-08-09T19:02:40:000+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Unrecognise Request","data":{},"errMessage":"connect ECONNREFUSED 127.0.0.1:7000"},"metadata":"test5","logTime":"2019-08-09T12:02:40.000Z","responseTime":4}
2019-08-09T19:02:45:000+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Unrecognise Request","data":{},"errMessage":"connect ECONNREFUSED 127.0.0.1:7000"},"metadata":"test5","logTime":"2019-08-09T12:02:40.000Z","responseTime":4}
2019-08-09T19:02:50:000+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Unrecognise Request","data":{},"errMessage":"connect ECONNREFUSED 127.0.0.1:7000"},"metadata":"test6","logTime":"2019-08-09T12:02:50.000Z","responseTime":4}
2019-08-09T19:02:55:000+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Unrecognise Request","data":{},"errMessage":"connect ECONNREFUSED 127.0.0.1:7000"},"metadata":"test6","logTime":"2019-08-09T12:02:50.000Z","responseTime":4}
2019-08-09T19:03:00:000+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Unrecognise Request","data":{},"errMessage":"connect ECONNREFUSED 127.0.0.1:7000"},"metadata":"test7","logTime":"2019-08-09T12:03:00.000Z","responseTime":4}
2019-08-09T19:03:05:000+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Unrecognise Request","data":{},"errMessage":"connect ECONNREFUSED 127.0.0.1:7000"},"metadata":"test7","logTime":"2019-08-09T12:03:00.000Z","responseTime":4}
2019-08-09T19:03:10:000+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Unrecognise Request","data":{},"errMessage":"connect ECONNREFUSED 127.0.0.1:7000"},"metadata":"test8","logTime":"2019-08-09T12:03:10.000Z","responseTime":4}
2019-08-09T19:03:15:000+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Internal Server Error","data":{},"errMessage":"SyntaxError: Unexpected token ':'"},"metadata":"test8","logTime":"2019-08-09T12:03:10.000Z","responseTime":15}
2019-08-09T19:03:20:000+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Unrecognise Request","data":{},"errMessage":"connect ECONNREFUSED 127.0.0.1:7000"},"metadata":"test9","logTime":"2019-08-09T12:03:20.000Z","responseTime":4}
2019-08-09T19:03:25:000+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Unrecognise Request","data":{},"errMessage":"connect ECONNREFUSED 127.0.0.1:7000"},"metadata":"test9","logTime":"2019-08-09T12:03:20.000Z","responseTime":4}
2019-08-09T19:03:30:000+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Unrecognise Request","data":{},"errMessage":"connect ECONNREFUSED 127.0.0.1:7000"},"metadata":"test10","logTime":"2019-08-09T12:03:30.000Z","responseTime":4}
2019-08-09T19:03:35:000+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Internal Server Error","data":{},"errMessage":"TypeError: Cannot read property 'length' of undefined"},"metadata":"test10","logTime":"2019-08-09T12:03:30.000Z","responseTime":25}
2019-08-09T19:03:45:000+07:00 - info: {"tag":"request /browse","tagName":{"status":"05","message":"Unrecognise Request","data":{},"errMessage":"connect ECONNREFUSED 127.0.0.1:7000"},"metadata":"test11","logTime":"2019-08-09T12:03:40.000Z","responseTime":4}
지금까지 내TXR 불분명한 음성프로그램은 다음과 같은 결과를 생성합니다.
$ txr group.tl < xlog
19:02 errMessage : connect ECONNREFUSED 127.0.0.1:7000 10
19:02 errMessage : ReferenceError: foo is not defined 1
19:02 errMessage : TypeError: Cannot read property 'name' of undefined 1
19:03 errMessage : connect ECONNREFUSED 127.0.0.1:7000 7
19:03 errMessage : SyntaxError: Unexpected token ':' 1
19:03 errMessage : TypeError: Cannot read property 'length' of undefined 1
프로그램은 다음과 group.tl
같습니다.
(defstruct log ()
hour minute
err-message)
(build
(let (minute-batch cur-hh cur-mm)
(flet ((flush ()
(let ((by-message-hash (group-by .err-message (get))))
(oust)
(dohash (msg group by-message-hash)
(let ((lead (first group)))
(put-line `@{lead.hour}:@{lead.minute} errMessage : @msg @(len group)`))))))
(whilet ((line (get-line)))
(when-match `@{nil}T@hh:@mm:@nil - info: @json` line
(let ((jobj (get-json json)))
(if (or (nequal hh cur-hh)
(nequal mm cur-mm))
(flush))
(set cur-hh hh cur-mm mm)
(add (new log
hour hh minute mm
err-message [[jobj "tagName"] "errMessage"])))))
(flush))))
이 프로그램은 두 가지 최상위 형식으로 구성됩니다.
- a는 시간 및 오류 메시지에 대한 정보를 보유하는 구조를
defstruct
정의합니다 .log
build
모든 논리를 포함하는 표현식입니다.
이 build
매크로에는 프로그램 구성 및 목록 조작을 위한 환경이 포함되어 있습니다. 많은 지역 운영자를 제공합니다. 여기서는 그 중 세 가지를 사용합니다. add
암시적 목록에 항목을 추가합니다. get
목록을 검색합니다. oust
목록을 다른 목록으로 바꿉니다(인수가 주어지지 않으면 기본값은 비어 있음).
전략은 데이터를 스캔하고 각 행을 개체로 변환하는 것입니다 log
. 시간이나 분이 변경될 때마다 flush
누적된 그룹을 처리하기 위해 로컬 함수를 호출합니다. 누적된 개체 목록을 검색 하고 목록을 지우는 flush
데 사용됩니다 . 입력이 부족하면 다시 호출하여 마지막 배치를 가져옵니다.(get)
log
(oust)
flush
이 flush
함수는 오류 메시지별로 개체를 그룹화하여 해시 테이블을 형성한 다음 정보를 덤프합니다. 각 오류 메시지에 대해 시간, 오류 메시지 및 오류 메시지를 공유한 그룹의 크기를 인쇄합니다.
항목 구문 분석은 패턴 일치를 사용하여 수행됩니다. 추가적으로 JSON 부분을 하나의 단위로 추출하고 TXR Lisp에서 JSON 파서를 사용합니다. JSON 개체는 해시 테이블로 생성됩니다. 두 가지 수준의 테이블을 거쳐 도착합니다 errMessage
.