[컴] Semantic logging 이란

semantic logging. / structured logging 이란 / strongly-typed logging 이란 /schematized logging 이란

Semantic Logging 이란

MS patterns & practices 에 올라온 글 중에 Embracing Semantic Logging 이라는 글을 보았다.
EventSource 라는 logging class 을 의 wrapper class 인 Semantic Logging Aplication Block 을 소개하는 글이었다. 그 글을 읽다보니 semantic logging 이 뭔지 궁금하였다.
semanctic logging 을 하는 것이라고 하는데, ref. 1 을 읽어보면 뭐, 그리 어려운 것은 아니고, 말 그대로 구조를 갖춘 로그를 얘기하는 듯 하다. 그래서 semantic logging / structured logging / strongly-typed logging /schematized logging 등 다양하게 불리는 듯 하다. 이 logging 의 차이점을 보여주자면,
일반적으로
printf("log: %s %s", tag, time)
or
System.out.println("log here");
이런 간단한 log 를 찍게 되는데, 한 두 개 찍는 것에는 큰 문제가 없다. 물론 많이 찍는 것도 문제는 없다. 하지만 이 녀석이 너무 많아지면 이것을 확인하는 주체가 사람인데, 보기가 너무 힘들다. text editor 로 불러다가 ctrl+f 로 열심히 뒤져봐야 할 것이다. 그래서 이것을 보기 쉽게 해주기 위해 이 log 들을 parsing 해서 특정조건에 맞게 정렬 해 준 program을 작성할 수 있을 것이다.
문제는 이 때 이 프로그램을 짜려면 조금 힘들어 진다. 물론 regular expression 등의 string parser 를 이용하면 크게 어렵지 않지만, 그래도 코드가 아무래도 길어지고, parsing 의 속도는 더딜 수 밖에 없다.
그래서 이것을 구별하기 위해 애쓰지 말고, 구별해 놓은 상태로 log 찍는 법을 일정 틀 안에 놓은 것이다. 이것을 class 로 구현을 한다면 id 나 tag 에 따라서 다른 함수를 호출하는 것이다.
손쉽게 Android 의 Log class 를 확인 해 보자.
Log.d(tag, "message");
Log.i(tag, "message");
이런 식으로 log 를 찍는데 이렇게 해서 log 를 특정 id(tag, priority 등) 별로 구분 하기 쉽게 하는 것이다. 그러면 나중에 log 분석 tool 등과 관련된 프로그래밍이 수월해 진다. ref. 1 을 보면 쉽게 짐작할 수 있다.

Log class

그런 의미에서 android 의 Log class 를 살펴 보는 것도 좋은 공부가 될 듯 하다. 아래는 Log class 의 함수호출 stack 이라고 보면 되겠다. 자세한 사항은 ref. 2를 참고하도록 하자.

잡담

개인적으로 아래 code 가 신선했다. 그래서 옮겨 놓는다.
static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr);
static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init;



static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
{
#ifdef HAVE_PTHREADS
    pthread_mutex_lock(&log_init_lock);
#endif

    if (write_to_log == __write_to_log_init) {
        log_fds[LOG_ID_MAIN] = log_open("/dev/"LOGGER_LOG_MAIN, O_WRONLY);
        log_fds[LOG_ID_RADIO] = log_open("/dev/"LOGGER_LOG_RADIO, O_WRONLY);
        log_fds[LOG_ID_EVENTS] = log_open("/dev/"LOGGER_LOG_EVENTS, O_WRONLY);
        log_fds[LOG_ID_SYSTEM] = log_open("/dev/"LOGGER_LOG_SYSTEM, O_WRONLY);

        write_to_log = __write_to_log_kernel;

        if (log_fds[LOG_ID_MAIN] < 0 || log_fds[LOG_ID_RADIO] < 0 ||
                log_fds[LOG_ID_EVENTS] < 0) {
            log_close(log_fds[LOG_ID_MAIN]);
            log_close(log_fds[LOG_ID_RADIO]);
            log_close(log_fds[LOG_ID_EVENTS]);
            log_fds[LOG_ID_MAIN] = -1;
            log_fds[LOG_ID_RADIO] = -1;
            log_fds[LOG_ID_EVENTS] = -1;
            write_to_log = __write_to_log_null;
        }

        if (log_fds[LOG_ID_SYSTEM] < 0) {
            log_fds[LOG_ID_SYSTEM] = log_fds[LOG_ID_MAIN];
        }
    }

#ifdef HAVE_PTHREADS
    pthread_mutex_unlock(&log_init_lock);
#endif

    return write_to_log(log_id, vec, nr);
}


References

  1. http://gregoryszorc.com/blog/category/logging/
  2. Android Log 분석, 2012년 1월, 땅뚱 블로그

댓글 없음:

댓글 쓰기