Chopin Ballade No.1 G minor 연주



1월 27일 연습.. 아직 끝까지 못 침 (...)

크라켄 로그디비 파이썬 클라이언트 크라켄북

아래 링크에서 egg 파일을 받을 수 있다.
아직 setup.py나 메타데이터가 제대로 들어있지는 않고, 예외처리가 완전하지는 않다.


파이썬 2.6 버전 이상이라면 아래와 같이 쉽게 쿼리 콘솔을 실행할 수 있다.

D:\>python kraken-logdb-client-0.1.egg
Kraken LogDB Console 0.1 (2013-01-04)
Type "help" for more information
logdb>

사용할 수 있는 명령어는 help 쳤을 때 출력된다.

logdb> help
connect <host> <loginname> <password>
        connect to specified kraken logdb instance
disconnect
        disconnect database connection
queries
        print all queries initiated by this session
query <query string>
        create, start and fetch query result at once
create_query <query string>
        create query with specified query string, and return allocated query id
start_query <query id>
        start query
stop_query <query_id>
        stop running query
remove_query <query_id>
        stop and remove query
fetch <query_id> <offset> <limit>
        fetch result set of specifeid window. you can fetch partial result before query is ended

가장 단순하게는 connect 한 후에 query 명령을 치면 된다. 데모는 아래의 동영상을 참고하도록 하자.


클라이언트 라이브러리를 직접 사용한다면 아래의 LogDbConnector 클래스 설명을 참고하자.
현재는 Long polling 기반의 HTTP 메시지버스 RPC 통신을 이용하기 때문에 쿼리 반응이 좀 느리다.
이 부분은 나중에 네이티브 TCP 프로토콜을 추가하면서 해결할 것이다.

def connect(self, host, nick, password)

host - 도메인 혹은 IP 주소
nick - 로그인 계정
password - 암호

데이터베이스 서버에 접속한 이후에 다른 메소드들을 정상적으로 수행할 수 있다. 서버에 접속이 안 되면 소켓에서 예외가 날 것이고, 계정이 없다거나 암호가 일치하지 않는다면 MessageException을 던진다. 의도된 크라켄 로그 데이터베이스 서버가 아닌 일반 웹서버라면 JSON 디코드 예외가 날 수 있다.

현재는 80으로 접속 시도하므로, 만약 접속이 안 된다면 크라켄 로그DB 구성을 확인해보자. 80 포트가 열려있어야 하고 webconsole HTTP 컨텍스트가 바인드 되어야 한다.

def close(self)

데이터베이스 접속을 해제하고 할당된 스레드 및 자원을 해제한다. 접속이 된 상태라면 HTTP Long Polling을 수행하는 스레드가 타임아웃 될 때까지 몇 초간 종료가 지연될 수 있다.

def query(self, query_string)

가장 간단하게는 connect 직후에 이 query 메소드를 사용해서 쿼리 결과를 얻으면 된다. 접속이 되어있지 않거나, 쿼리 문법이 틀린 경우에는 예외가 발생한다. 제네레이터를 사용한 커서를 리턴하므로, 원하는만큼 순회하면서 결과 행을 얻어오면 된다. 마지막행까지 순회하면 쿼리가 삭제된다. 부분적인 결과 행만 얻어냈다면 직접 쿼리를 삭제해야 한다.

def create_query(self, query_string)

현재 접속 세션에서 쿼리를 생성하고 쿼리 ID를 반환한다. 접속되지 않은 상태이거나 쿼리 문법이 틀린 경우에는 예외가 발생한다.

def start_query(self, query_id, page_size=10, timeline_size=10)

query_id - 쿼리 ID
page_size - 페이징 단위 갯수
timeline_size - 타임라인에 표시할 항목 수

지정된 쿼리 ID를 가진 쿼리를 시작시킨다. 페이징 크기와 타임라인 크기는 향후 페이지 로딩, 타임라인 업데이트 콜백이 추가되면 의미를 가질 것이지만 지금은 무시하면 된다. 접속되지 않은 상태이거나, 현재 세션에서 생성한 쿼리가 아니라면 예외가 발생한다.

def wait_until(self, query_id, count)

query_id - 쿼리 ID
count - 결과 행 수가 지정된 임계값 이상 준비될 때까지 대기

쿼리 시작 후 일정 갯수 이상의 결과 행이 서버에서 준비될 때까지 대기한다. count에 None을 넘기면 쿼리가 완료될 때까지 대기한다. 접속되지 않은 상태이거나, 현재 세션에서 생성한 쿼리가 아니라면 예외가 발생한다. 쿼리를 시작시키지 않은 상태에서는 무한히 대기하게 될 수도 있으므로 주의한다.

def get_result(self, query_id, offset, limit)

query_id - 쿼리 ID
offset - 건너뛸 행 갯수
limit - 가져올 최대 행 갯수 (모자랄 수도 있음)

쿼리 결과를 조회한다. 쿼리가 완료되지 않은 상태라도 호출 시점까지 조회된 부분적인 결과를 조회할 수 있다. result와 count 키를 포함한 dict를 반환하는데, result는 결과 행의 리스트를 담고 있으며, count는 현재까지 조회된 전체 결과 행 수를 담고 있다. count를 통해 추가로 조회 가능한 결과 행을 확인할 수 있다. 보통 결과 페이징 조회 시에 이 메소드를 호출한다.

접속되지 않은 상태이거나, 현재 세션에서 생성한 쿼리가 아닌 경우에는 예외가 발생한다.

def open_cursor(self, query_id, offset, limit, close=False)

query_id - 쿼리 ID
offset - 건너뛸 행 갯수
limit - 가져올 최대 행 갯수 (모자랄 수도 있음)
close - 마지막 결과 행 조회 후에 쿼리 삭제 여부

결과 행을 순회하는 커서를 연다. 접속되지 않은 상태이거나, 현재 세션에서 생성한 쿼리가 아닌 경우에는 예외가 발생한다.

def stop_query(self, query_id)

query_id - 쿼리 ID

쿼리 실행 중에 이 메소드를 호출하면 쿼리를 중단한다. 쿼리를 중단하는 시점까지 기록된 결과 집합은 중단 후에도 get_result로 조회할 수 있다. 접속되지 않은 상태이거나, 현재 세션에서 생성한 쿼리가 아닌 경우에는 예외가 발생한다.

def remove_query(self, query_id)

query_id - 쿼리 ID

지정된 쿼리를 삭제한다. 삭제된 쿼리의 쿼리 결과는 더 이상 조회할 수 없다. 명시적으로 쿼리를 삭제하지 않더라도, 메시지버스 세션이 종료되면 (타임아웃되어 종료되는 것 포함) 해당 세션에서 생성했던 모든 쿼리는 자동으로 삭제된다.


log4j 설정만으로 크라켄 로그 DB에 로그 전송하기 크라켄북

다수의 WAS 서버에서 발생하는 애플리케이션 감사 로그를 실시간으로 수집 및 관제하려고 할 때 유용할 것이다. kraken-logdb-log4j 1.0.0은 아직 experimental 단계이므로 테스트용으로만 사용한다.

가령 크라켄 코어를 실행할 때 아래와 같이 log4j.properties를 편집해 둘 수 있다.
(아래 글의 HTTP 로그 입력 설정을 참고하도록 한다.)

log4j.rootLogger = INFO, logdb
log4j.appender.logdb = org.krakenapps.logdb.log4j.HttpAppender
log4j.appender.logdb.URL = http://IP주소/logdb/inputs/http-input-sample-url-token

로그DB log4j 어댑터를 다운로드한다.

아래와 같이 커스텀 log4j appender를 클래스패스에 잡고 실행한다.
java -cp kraken-logdb-log4j-1.0.0-package.jar;kraken-core-2.2.0-package.jar org.krakenapps.main.Kraken

그러면 적당히 1초 주기마다 설정된 HTTP 엔드포인트로 log4j로 기록된 모든 로그가 전송된다.


TODO
- HTTPS 및 프록시 설정 추가
- 서버 통신 끊겼을 때 디스크 버퍼링하고 다시 연결되면 전송하는 기능 추가
(적당한 버퍼링 한계 설정 필요)
- 전송 주기 및 내부 메모리 버퍼 크기 설정 추가
- Tomcat, Jeus 등 일반화된 개발 환경의 설정 예시 정리
- HTTP 이외에 TCP 소켓 기반 고속 전송 프로토콜 추가

크라켄 로그 DB에 HTTP로 로그 입력하기 크라켄북

크라켄 로그 DB에 외부 스크립트를 통해 로그를 수집하여 저장하고 싶을 때, Syslog나 SNMP Trap으로 로그를 쏜다든지 하는 방법도 있지만 일반적으로 스크립터들에게 익숙한 방법은 HTTP 통신일 것이다.

아래와 같이 번들을 설치한다.

kraken> bundle.install org.krakenapps kraken-logdb-httpinput 1.0.0

그 다음에 로거 팩토리 목록을 조회하면 http-input을 확인할 수 있다.

kraken> logapi.loggerFactories
Logger Factories
---------------------
fullname=local\http-input, type=http input, description=receives json logs through http post requests
fullname=local\textfile, type=text file logger, description=text file logger

http-input 로거를 생성한다.

kraken> logapi.createLogger http-input local http-input-sample
Input Token (required)? http-input-sample-url-token
logger created: name=local\http-input-sample, factory=local\http-input, status=stopped (interval=0ms), log count=0, last start=null, last log=null

URL에 사용될 토큰을 임의로 지정하였는데 GUID 생성해서 쓰거나 자기가 편한 경로를 사용하면 된다. (다만 누군가 쓰레기 로그를 쏟아붓는 일이 없도록 외부에 쉽게 노출되지 않을 경로 이름를 사용하자)

로거를 시작(활성화)시킨다.

kraken> logapi.startLogger local\http-input-sample
logger started

파이프라인을 통해 전달되는 로그를 스토리지에 저장되도록 설정한다.

kraken> siem.createLogger localhost local\http-input-sample
created

웹서버를 열어두어야 한다. 가령, 아래와 같이 기본 webconsole 컨텍스트를 80 포트에 바인딩할 수 있다.

kraken> httpd.open 80 webconsole

이제 CURL로 밀어넣어보자. Content-Type은 text/json 이어야 하고, 본문은 JSON 형식으로 로그 객체의 리스트를 기입한다. 가령, 다음과 같다.

$ curl -S -v -X POST -H "Content-Type: text/json" -d '[{"line": "hello kraken world"} , {"line": "happy new year!"}]' http://1.2.3.4/logdb/inputs/http-input-sample-url-token
* About to connect() to 1.2.3.4 port 80
*   Trying 1.2.3.4... connected
* Connected to 1.2.3.4 (1.2.3.4) port 80
> POST /logdb/inputs/http-input-sample-url-token HTTP/1.1
> User-Agent: curl/7.15.5 (x86_64-redhat-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5
> Host: 1.2.3.4
> Accept: *-*
> Content-Type:text/json
> Content-Length: 62
>
> [{"line": "hello kraken world"} , {"line": "happy new year!"}]HTTP/1.1 200 OK
< Content-Length: 0
* Connection #0 to host 1.2.3.4 left intact
* Closing connection #0

그러면 쿼리를 했을 때 아래와 같이 데이터가 들어간 것을 확인할 수 있을 것이다.

kraken> logdb.query "table local\http-input-sample"
{_id=2, _table=local\http-input-sample, _time=Tue Jan 01 16:47:55 KST 2013, line=happy new year!}
{_id=1, _table=local\http-input-sample, _time=Tue Jan 01 16:47:55 KST 2013, line=hello kraken world}
0.1s

기본적으로는 로그가 수신된 시각으로 기록되므로, 임의의 로그 시각을 박아서 넣고 싶은 경우에는 _time 키를 yyyy-MM-dd HH:mm:ssZ 형식으로 기입하면 된다. (예시: 2013-01-01 16:56:00+0900)

자기가 선호하는 스크립트 언어로 간단하게 로그 입력 작업을 자동화 할 수 있다. 파이썬이라면 아래와 같이 될 것이다.

headers = {'Content-Type': 'text/json'}
body = '[{"line": "hello kraken world"} , {"line": "happy new year!"}]'
con = httplib.HTTPConnection('1.2.3.4')
con.request('POST', '/logdb/inputs/http-input-sample-url-token', body, headers)
resp = con.getresponse(False)
print resp.read()
con.close()

1 2 3 4 5 6 7 8 9 10 다음