 |
|
파서 만들기
센서는 데이터를 읽는다. extractor는 데이터를 레코드로 세분화한다. 파서의 역할은 각 레코드에서 특정 필드를 추출해내고, CBE XML 레코드를 완벽하게 만들기 위해 이 값들을 사용한다.
파서의 역할
파서는 로그 파일에서 타임 스탬프, 호스트 이름, 데몬 이름 텍스트 메시지와 같은 몇 가지 필드를 직접 추출해낸다. 파서는 또한 레코드에서 데이터를 추론해낸다. 예를 들어, 파서는 소프트웨어 서비스에서 시작된 레코드를 찾고, CBE componentIdType 속성을 ServiceName으로 정하기도 한다. 또 다른 예로, 파서는 레코드에 데이터를 추가할 수도 있다. 특히 입력된 로그가 일, 월, 년, 시간과 이벤트의 시간대에 대한 레코드를 갖고 있지 않다면, 파서는 유요한 CBE를 만들기 위해 위 데이터를 추가해야만 한다.
perspective의 daemon.log 예제를 위한 파서를 넣기 위해 Listing 15는 Mar 2 06:27:35 db popa3d[7964]: Session from 71.65.224.25라는 로그 엔트리를 위한 유효한 CBE XML 레코드를 보여준다. 몇몇 속성은 원래 로그 엔트리에서 나온 것이고, 다른 것들은 암시적인 데이터에서 구해냈다(CBE 명세에서 받아온 속성의 값이 대부분이다. 파서가 만드는 동안 이 문서가 유용할 것이다).
Listing 15. daemon.log의 첫 번째 레코드에 대한 CBE
<CommonBaseEvent
creationTime="2006-03-02T13:27:35.000Z"
globalInstanceId="A1DAABECA2ACB4F0E8E9E8C475042F1B"
msg="Session from 71.65.224.25"
version="1.0.1">
<sourceComponentId
component="popa3d"
componentIdType="ServiceName"
location="db.linux-mag.com"
locationType="Hostname"
subComponent="7964"
componentType="daemon"
/>
<situation
categoryName="StartSituation">
<situationType
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="StartSituation"
reasoningScope="EXTERNAL"
successDisposition="SUCCESSFUL"
situationQualifier="START INITIATED"/>
</situation>
</CommonBaseEvent>
|
모든 CBE는 반드시 creationTime 속성, msg 속성과 sourceComponentId 요소를 정의해야 함을 명심하라. Listing 15에서 볼 수 있는 것과 같이 차례대로 여섯 개의 속성을 포함해야 한다. situation 요소는 선택이지만, 이벤트를 제대로 설명하기 위해 예제의 일부로 포함시켰다.
파서는 어떻게 작동하나
파서를 정의하는 과정을 시작하기 위해 Generic Log Adapter perspective에서 Parser를 클릭하자. 완료된 파서는 그림 11처럼 보일 것이다. Listing 15에서 보이는 CBE처럼 하나의 파서는 모든 속성과 요소를 위한 작업(task)이다.
그림 11. daemon.log용으로 완성된 파서
파서는 두 단계로 작동한다. 첫 번째 단계에서는 extractor에서 받은 레코드를 위치(position)나 숫자가 부여된 부분으로 나눈다. 각각의 부분은 분리 부호 토큰(separator token)에 의해 분할된다. 분리 부호 토큰이 지정되지 않았다면, 이 단계는 건너뛴다. 그리고 나서 파서는 레코드를 지시자(designations)나 (이름, 값) 쌍(pair)으로 분할하며, 각 쌍은 지시자 토큰(designation token)에 의해 합쳐지는 두 개의 문자열이다. 지시자 토큰이 정의되지 않았다면, 후자의 단계는 건너뛴다.
예를 들어 보자. 분리 부호 토큰이 정규 표현식 [ ]+이고, 지시자 토큰은 =(같다는 표시)이고, 파서가 다음 레코드를 처리하고 있다고 가정해 보자.
03/05/06 12:51:06EST Mail name=joe action=login authentication=password
|
파서는 표 1에서 보이는 것처럼 여섯 개의 위치와 세 개의 지시자를 정의할 것이다.
표 1. 파서에서의 위치와 지시자
| 위치 / 지시자 | 값 |
|---|
| 1 |
03/05/06
| | 2 |
12:51:06EST
| | 3 |
Mail
| | 4 |
name=joe
| | 5 |
action=login
| | 6 |
authentication=password
| | h{'name'} |
joe
| | h{'action'} |
login
| | h{'authentication'} |
password
|
주의: 지시자 토큰으로 시작하는 레코드를 받았다면, 위치 1은 만들어지지만, 값은 비어있는 상태(empty)일 것이다.
각 파서 작업을 간단하게 하기 위해 정의된 위치와 지시자를 모두 사용할 수 있다. 예를 들어, creationTime 속성을 만들려면 위치 2만 파싱하면 된다. 물론, 원본 레코드 전체는 언제나 사용할 수 있다. 하지만 소스 문자열이 더 작기 때문에, 위치와 지시자를 이용하면 각 파싱 작업이 더 빠르고 관리하기 쉬워진다. 많은 경우에, CBE 값을 위해 위치나 지시자를 직접 사용할 것이다.
로그 엔트리 예제 파싱하기
Parser를 다시 클릭하자. 편의를 위해, 각 daemon.log 엔트리를 :[ ]+(하나 이상의 스페이스가 연달아 나오는 콜론) 식별자 토큰을 사용해 두 개의 위치로 나누자. daemon.log 엔트리는 (이름과 값) 쌍을 갖고 있지 않기 때문에 지시자 토큰은 생략한다. 이 설정은 그림 12와 같다. 이제 작업 내용을 저장하자.
그림 12. 레코드를 위치로 분할하기
creationTime 설정
CBE에서 첫 번째 필수 필드인 creationTime을 설정하자. 목적은 daemon.log 레코드에서 제공되는 타임 스탬프를 XML 스키마 dateTime데이터 타입에 호환성 있는 포맷으로 변환하는 것이다. 편리하게도 어댑터는
java.text.SimpleDateFormat
클래스에 의해 분석된 시간 포맷을 XML 스키마 데이터 타입으로 자동으로 변경할 수 있다.
creationTime 필드를 설정하기 위해, 다음 단계를 완료하자.
- 파서를 확장하고, creationTime을 선택하자. 이것은 필수 CBE 속성이기 때문에, Required by parent 체크 박스를 선택하자.
-
creationTime과 관련된 변환 규칙을 클릭하자.
-
Positions는 추출하기 위한 타임 스탬프를 포함하고 있는 위치
1이기 때문에 1을 입력하자.
-
Match에는
^(\w{3})\s+(\d{1,2})\s+([\d:]+)\s+.*$ 정규 표현식을 입력하자. 이 표현식은 $1로 달(month) 이름을, $2로 달의 일자를, 그리고 $3으로는 날짜의 시간을 추출해낸다.
-
Substitute에는
$1 $2 @YEAR $3 @TIMEZONE을 입력하자. Substitute는 특정 파싱 작업에서 받아온 전체 레코드 대신 사용된다. $1, $2와 $3은 이전 단계에서 받아온 값이다. 하지만, 타임 스탬프는 연도나 시간대를 포함하고 있지 않기 때문에, 현재 컨텍스트 인스턴스와 관련된 연도와 시간대는 @YEAR와 @TIMEZONE을 사용해 각각 표현한다. 그러므로 첫 번째 daemon.log 레코드의 경우 Substitute에 설정된 값은 Mar 02 2006 06:27:35 -0700 문자열을 내놓는다.
-
Substitute extension class 필드는 무시하라. 이 필드를 이용하면 자바 클래스로 추가 변환과 변환 결과를 적절한 타입으로 변경해주는 기능을 하는 자바 클래스를 제공할 수 있다.
java.text.SimpleDateFormat 포맷 문자열을 사용할 수도 있다. Time format을 MMM dd yyyy hh:mm:ss Z로 설정하자. 이 설정은 월의 이름은 문자 세 개로, 월의 일자는 숫자 두 개로, 연도는 숫자 네 개로, 시간·분·초는 콜론에 의해 구분되며, 시간대는 RFC 822로 표현한다는 것을 의미한다.
그림 13은 creationTime을 위한 최종 설정 값을 보여준다. 설정 파일을 저장하고, 어댑터를 다시 시작하면, Formatter Result 패널은 creationTime="2006-03-02T13:27:35.000Z" 속성의 값을 포함한 새로운 XML 레코드를 보여줄 것이다.
그림 13. 타임 스탬프를 creationTime 속성으로 파싱하기
메시지 얻기
msg 속성은 또 다른 필수 CBE 속성이다. 이 속성을 추가하고, 적절한 값을 추출하는 파서를 만들어보자.
-
CommonBaseEvent에서 마우스 오른쪽을 클릭하고, Add > msg를 클릭하자.
-
msg를 클릭한 다음 Required by parent 체크 박스를 선택하자.
-
msg를 확장한 다음, Substitution Rule을 클릭하자.
- 로그 엔트리에서 메시지 위치가 위치
2에 있기 때문에 Positions는 2를 설정하자(분리 토큰 뒤에 있는 것들이다).
-
Match에는 전체 문자열을 선택할 수 있는 정규 표현식으로 설정하자.
$1에 있는 모든 내용은 정규 표현식 ^(.*)$로 받아 올 수 있다.
-
Substitute에
$1을 설정하자.
그림 14는 최종 설정 값을 보여준다.
그림 14. 메시지 추출을 위한 설정 값
설정 파일을 저장하고, Extractor Result 패널에서 찾을 수 있는 Rerun adapter를 클릭하자. Next event를 클릭하고, Formatter Result 패널로 변경해보자. msg="Session from 71.65.224.25"와 같은 새로운 msg 속성을 볼 수 있다.
소스 찾기
CBE 레코드의 마지막 필수 요소는 sourceComponentId로 이벤트에 의해 영향을 받는 컴포넌트(서비스, 시스템 등) 레코드에 쓰인다. daemon.log 예에서 영향을 받는 컴포넌트는 특정 호스트에서 실행되는 소프트웨어 서비스다. 파서의 일은 이 특정 서비스를 기록하는 것이다.
일단 다시 CommonBaseEvent에서 마우스 오른쪽을 클릭하고, Add > sourceComponentId를 클릭하자(그림 15는 CBE에 추가할 수 있는 가능한 속성과 요소를 모두 보여준다). 표 2는 sourceComponentId에 필요한 설정에 대해 요약해 보여준다. 한 가지 새로운 설정은 Default value이다. 파싱 규칙에 의해 만들어진 match가 있지만, 제공되는 substitute value가 없다면 Default value가 사용된다.
그림 15. CBE 레코드에 추가할 수 있는 요소와 속성 목록
표 2. SourceComponentId를 위한 설정
| 항목 | 기본값 | 부모에서 요구하는지 여부 | 위치 | 매치 | 대치 | 주의 |
|---|
| component | | Yes | 1 |
^.* db (\w+)\[.*$
|
$1
|
pop3ad나 mysqld와 같은 소프트웨어 서비스의 이름 획득 | | componentIdType |
ServiceName
| Yes | |
^(.*)
| | 컴포넌트가 기록하는 서비스 이름 명시. ServiceName은 CBE 명세에 따라 이 속성을 위해 정해지는 값 중 하나다. | | componentType |
daemon
| Yes | |
^(.*)
| | 컴포넌트의 클래스에 대한 설명 | | location |
db.linux-mag.com
| Yes | |
^(.*)
| | 컴포넌트의 위치에 상응하는 물리적인 주소 상술. location의 값 포맷은 locationType 속성에 의해 기술된다. 이 값을 위해 완전한 호스트 이름을 사용할 것을 추천한다. 여기서 로그 엔트리는 호스트 이름을 포함하고 있지 않기 때문에, 기본 값을 통해 추가하는 방법이 하나 있다. 또 다른 경우는 로그에서 직접 호스트 이름을 파싱할 수 있다. | | locationType |
Hostname
| Yes | 1 |
^(.*)
| | location 속성 값의 의미와 포맷 기술. Hostname 키워드는 여기서 사용할 수 있는 많은 키워드 중 하나다. | | subComponent | | Yes | |
^.*\[(\d+)\].*
|
$1
| 이벤트에 영향을 미치는 특정 데몬 프로세스 정의 |
표 2에 있는 리스트의 내용을 모두 변경하고 저장한 다음 어댑터를 다시 시작하면, Listing 15와 비슷한 CBE 이벤트 레코드가 산출될 것이다. 추가 연습을 위해, CBE에
situation
을 추가하자. situation은 이벤트에서 시작되는 상황의 유형을 분류해준다. 예를 들어, 데몬이 처음으로 서비스에 접근했을 때 StartSituation을 만드는 파서를 생성하거나 요청이 만들어졌을 때 RequestSituation을 생성하기 위해 또 다른 파서를 만들 수도 있다.
situation은 필수 요소가 아니지만(그러므로 Required by parent는 사용할 수 없음), CBE 레코드에 granularity를 추가하기 위해 유용하게 쓰인다는 것을 알 수 있다. situation을 만들고, 일련의 가능한 situation 파서를 추가한다면, 첫 번째 match가 만들어진 후 처리 작업을 멈출 수 있도록 Child choice 체크 박스를 선택하자.
파서 디버깅을 위한 유용한 팁 몇 가지를 소개하겠다. 속성이 필수지만, 받아온 레코드(extractor에서 파서로 전달된)에서 찾을 수 없는 경우, 레코드에 대한 Formatter Result 패널은 비어있을 것이다. 다시 말해 필수 속성은 논리적인 AND처럼 작동한다. 하나의 match가 실패하면 모든 레코드 처리 작업이 중단된다. 규칙 디버그를 위해 Required by parent 체크 박스를 해제하는 것은 종종 유용하게 사용된다. 천천히, 그리고 점진적으로 규칙을 빌드하고, 문제의 실마리를 잡기 위해 Problem 패널을 확인하라.
|