Here's a tiny example. When running under functions framework on a GCE VM with an appropriate service account,

import logging
import google.cloud.logging

logging_client = google.cloud.logging.Client()
logging_client.setup_logging()

def test(request):
    logging.warning("testing warning")
    return "done"

does not log a warning message.

Changing it to:

import logging
import google.cloud.logging

logging_client = google.cloud.logging.Client()


def test(request):
    logging_client.setup_logging()
    logging.warning("testing warning")
    return "done"

does produce the correct message.

And if I take the version that doesn't work, add a call to the function and run it normally without functions framework, it produces a warning as expected.

import logging
import google.cloud.logging

logging_client = google.cloud.logging.Client()
logging_client.setup_logging()

def test(request):
    logging.warning("testing warning")
    return "done"

test("foo")

Can someone explain what's going on, either with how the functions frameworks works, or how the logging handler works?

Thanks!

1

There are 1 best solutions below

0
On

I had a similar issue using gcsfs with functions framework that provided the answer. It looks like when you use functions framework the function call runs in a different process from the initialization.

I mimicked this with:

import logging
import google.cloud.logging
import os
import time

logging_client = google.cloud.logging.Client()
logging_client.setup_logging()

def test(request):
    logging.warning("testing warning")
    return "done"

pid = os.fork()

if pid > 0:
    time.sleep(10)
else:

    test("foo")

and it does not work. Move the setup_logging to inside of the function call, and it does. So it seems that you have to do the setup_logging() in the subprocess for it to work, and that's why it has to be done in the function call rather than as part of initialization in function framework.