Python: почему он отправляет дубликаты журналов в Stackdriver?

Я отправляю журналы, созданные из моего конвейера данных, в Stackdriver на GCP. Но по какой-то причине он отправляет несколько дубликатов одних и тех же журналов событий. В моей функции ensure_stackdriver_logging я проверяю, существует ли уже обработчик, чтобы предотвратить ситуацию, когда при повторном запуске task обработчик не будет добавлен несколько раз. Кто-нибудь знает, в чем проблема?

def ensure_stackdriver_logging():
    logger = get_logger()
    lg_client = google.cloud.logging.Client()
    lg_handler = CloudLoggingHandler(lg_client, 'thinknum_etl_logging')
    if lg_handler not in logger.handlers:
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        lg_handler.setFormatter(formatter)
        logger.setLevel(logging.INFO)
        logger.addHandler(lg_handler)


def task():
    ensure_stackdriver_logging()
    ...

Обновлять:

Я тоже пробовал это -

def ensure_stackdriver_logging():
    logger = get_logger()

    if hasattr(logger, 'initialized'):
        return logger
    else:
        setattr(logger, 'initialized', True)

    lg_client = google.cloud.logging.Client()
    lg_handler = CloudLoggingHandler(lg_client, 'thinknum_etl_logging')
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    lg_handler.setFormatter(formatter)
    logger.setLevel(logging.INFO)
    logger.addHandler(lg_handler)

Но это не сработало.


person Riley Hun    schedule 05.08.2020    source источник


Ответы (1)


Если вы вызываете метод ensure_stackdriver_logging() в другом месте или даже ранее добавляли обработчик журнала, это произойдет дважды (или больше), потому что ваша проверка if не работает так, как вы ожидаете.

Когда вы выполняете if lg_handler not in logger.handlers: проверку, выполняется сравнение между lg_handler идентификатором объекта и другими объектами в списке, но поскольку вы только что создали lg_handler в строке перед списком, его не будет в списке.

Возьмем, к примеру, следующее:

class Foo():
    pass

l = [Foo()]
b = Foo()
print(b in l)
>>> False

b отсутствует в списке, потому что тот объект, на который указывает b, отсутствует в списке, а скорее объект Foo с такими же значениями.

person Or Y    schedule 05.08.2020
comment
Спасибо - в этом есть смысл. Итак, как мне проверить, существует ли обработчик для регистратора, который уже предварительно настроен с другими обработчиками? В этом случае я хочу проверить обработчик GCP Stackdriver. - person Riley Hun; 05.08.2020
comment
@RileyHun Вам, вероятно, следует реализовать функцию __eq__ вашего обработчика, которая будет проверять, совпадают ли два экземпляра обработчика, сравнивая их поля. Когда вы реализуете эту функцию, она также будет работать с вашим кодом из вопроса, поскольку оператор in попытается использовать вашу реализацию __eq__. - person Or Y; 05.08.2020
comment
Я пробовал использовать hasattr и setattr, но тоже не работал. - person Riley Hun; 05.08.2020
comment
@RileyHun Можете ли вы прикрепить код, который вы пытались использовать? - person Or Y; 06.08.2020