2016-10-24 3 views
1

여러 프로세스에서 로그를 생성 할 때 Google 클라우드 로깅을 수집하고 보내는 기본 방법은 무엇입니까?여러 프로세스에서 CloudLoggingHandler로 로깅

내 CloudLoggingHandler 기반 제안이 여기 있습니다. 비판 하시겠습니까?

import google 
from multiprocessing import Process 
from logging import getLogger 

class Worker(Process): 
    def __init__(self): 
     super(Worker, self).__init__() 

    def __setup_logger(self): 
     handler = CloudLoggingHandler(google.cloud.logging.Client(), name='log-name')       
     logger = logging.getLogger() 
     logger.setLevel(logging.DEBUG) 
     google.cloud.logging.handlers.setup_logging(handler) 

    def run(self): 
     self.__setup_logger() 
     for i in range(10): 
      logging.warning("i=%d", i) 

if __name__ == "__main__": 
    for _ in range(2): 
     w = Worker() 
     w.start() 

나는 큐 기반 로그 핸들러 here에 대해 읽을 수 있지만 큐 기반의 핸들러가 과잉 될 수 있도록 CloudLoggingHandler는 고립 된 스레드에서 커밋 배치를 사용합니다. 나 맞아 ?

Sources은 CloudLoggingHandler가 스레드로부터 안전하다는 것을 나타내므로 모든 프로세스가 하나의 CloudLoggingHandler 인스턴스를 공유하면 충분할 수 있습니다. 작동할까요? 그렇다면 가혹한가?


@ thomas-schultz.

나는 프로토 타입을 작성했기 때문에 대부분 내 제안에 집착했는데, "즉시 사용할 수있는"상태였으며 성능 문제가 있는지 확인하지 않았습니다. 나는이 선택을 재고하고있다.

사실 내가 이해 한대로 BackgroundThreadTransport이있는 CloudLoggingHandler은 로깅 엔드 포인트로 로그가 전송 될 때까지 기본 스레드를 차단합니다. 이것은 각 로그 라인마다 거의 발생합니다. 실제로 일괄 처리는 하나의 로그 레코드 (cf source)가있는 즉시 전송됩니다.

내 dev 환경에서 여러 프로세스가 동시에 로그 할 때 하나의 프로세스가 로그를 보내기 위해 최대 1 초 동안 대기하는 것으로 나타납니다. 나는 그것이 대부분 네트워크 비용이라고 생각하며 Google 데이터 센터 내에서 "그리 많지는 않습니다"로 축소 될 것입니다.

모든 로그 레코드를 Queue으로 푸시하는 StreamHandler을 정의하려고합니다. 이 큐는 로깅 엔드 포인트에 로그를 전송하는 담당 할 것 Process 읽을 수있다. 이 프로세스는 관련성이있는 경우 CloudLoggingHandler를 사용하여이를 수행 할 수 있습니다.

의미가 있습니까?

답변

0

다음은 여러 프로세스에서 Google Cloud Logging에 로그인하는 방법입니다. 이 솔루션은 파이썬 3 기본 로깅 처리기 (doc) 만 사용합니다. 아래 예에서 메인 프로세스가 메시지를 기록하는 데 걸리는 시간을 측정합니다. 결과는 로그가 로깅 엔드 포인트로 전송되는 동안이 솔루션을 사용하면 주 프로세스가 차단되는 것을 방지 할 수 있음을 보여줍니다. 물론 시간이 많이 걸리는 작업이 주 프로세스에서 수행되지 않는 경우에만 유용합니다.

이 접근 방식에 대해 어떻게 생각하십니까?

Queue: avg log call duration: 0.00004s 
Queue: min log call duration: 0.00002s 
Queue: max log call duration: 0.00018s 

Cloud: avg log call duration: 0.03019s 
Cloud: min log call duration: 0.00003s 
Cloud: max log call duration: 0.16630s 

다음은 포괄적 인 예입니다.

import sys 
import os 
import time 
import google 
import logging 
import multiprocessing 

from logging.handlers import QueueHandler, QueueListener 
from google.cloud.logging.handlers import CloudLoggingHandler 


def do(i): 
    """ 
     Dummy function that times the log insertion. 
    """ 
    t = time.time() 
    logging.info('%dth message.' % i) 
    return time.time() - t 


if __name__ == '__main__': 

    # The standard google cloud logging handler sends logs to the clooud logging endpoint. 
    client = google.cloud.logging.Client() 
    cloud_handler = CloudLoggingHandler(client=client, name="xyz") 

    # A local handler is used to have feedbacks on what is going on. 
    local_handler = logging.StreamHandler(sys.stdout) 

    # Log records are put in the log queue. 
    log_queue = multiprocessing.Queue() 

    # The listener dequeues log records from the log queue. Each handler registered in the 
    # listener processes the log records. 
    queue_listener = QueueListener(log_queue, local_handler, cloud_handler) 
    queue_listener.start() 

    # The queue handler pushes the log records to the log queue. 
    queue_handler = QueueHandler(log_queue) 

    # Setup the root loger to the handler we defined. 
    root_logger = logging.getLogger() 
    root_logger.setLevel(logging.INFO) 
    root_logger.addHandler(queue_handler) 

    n = 10 

    # Emits logs and measure how fast it is with the 
    durations = [do(i) for i in range(n)] 
    print('Queue: avg log call duration: %.5fs' % (sum(durations)/n)) 
    print('Queue: min log call duration: %.5fs' % min(durations)) 
    print('Queue: max log call duration: %.5fs' % max(durations)) 

    # Stop the queue listener. 
    queue_listener.stop() 

    # Remove the queue handler from the root logger. 
    root_logger.removeHandler(queue_handler) 

    # Setup the root loger to use CloudLoggingHandler. 
    root_logger.setLevel(logging.INFO) 
    root_logger.addHandler(local_handler) 
    root_logger.addHandler(cloud_handler) 

    # Emits logs and measure how fast it is with the 
    durations = [do(i) for i in range(n)] 
    print('Queue: avg log call duration: %.5fs' % (sum(durations)/n)) 
    print('Queue: min log call duration: %.5fs' % min(durations)) 
    print('Queue: max log call duration: %.5fs' % max(durations)) 
+0

니스! 흥미로운 점은 단지 10 개 이상의 항목에 대해 차이가 있다는 것입니다. 나는 결과가 그들 자신을 위해 정말로 말하는 것이라고 생각한다. –

+1

CloudLoggingHandler에서 파생 된 사용자 지정 처리기 BatchCloudLoggingHandler로 끝났습니다. CloudLoggingHandler와 달리 BatchCloudLoggingHandler는 스레드로부터 안전하지 않으며 BackgroundThreadTransport에 의존하지 않습니다. 스레드 안전성을 보장하기 위해 QueueHandler 및 QueueListener를 사용합니다. BatchCloudLoggingHandler는 로그 레코드의 실제 일괄 처리 (즉, 둘 이상의 로그 레코드가있는 일괄 처리)를 수행합니다. 그러나, 나는이 approche의 효율성을 어떻게 측정해야하는지 모른다. –

1

나는 당신이 연결 문제 또는 대기열이 요구되는 상황의 일종으로 실행하고 과도하지 않는 한있을 수 있다고 생각.

이 경우, 당신은 아마 CloudLoggingHandler의 동일한 인스턴스를 사용할 수 있지만 이렇게 거기 어쩌면 약간의 성능 병목 현상. 나는 완전히 확신하지 못한다.

여기 파이썬의 표준 라이브러리 로거와의 통합에 대해 자세히 설명합니다. https://googlecloudplatform.github.io/google-cloud-python/stable/logging-usage.html#integration-with-python-logging-module

다른 답변에 도착했는지 궁금합니다.