Skip to content

activity_trigger is not showing logging #586

@ChingChuan-Chen

Description

@ChingChuan-Chen

🐛 Describe the bug

A clear and concise description of what the bug is.

The logging in acritvity_trigger function will not appear.
But if there is another request coming to a synchronized Function which means thread_local_storage.invocation_id has value. Then the logs will pop up, but once the request is finished, the log stops.

🤔 Expected behavior

What should have happened?

I expect that the logging should work anytime.

Steps to reproduce

What Durable Functions patterns are you using, if any?
Any minimal reproducer we can use?
Are you running this locally or on Azure?
I tested this situation in local.

function_app.py:

import time
import azure.functions as func
from durable_func import bp
import fastapi
from fastapi.responses import JSONResponse
from functools import wraps

fastapi_app = fastapi.FastAPI(
    title="SCHIE Rel Functions App",
    description="SCHIE Reliability Team Azure Functions App",
    summary="SCHIE Reliability Team Azure Functions App",
    version="0.1.0",
    contact={
        "name": "Ching-Chuan Chen",
        "email": "chingchen@microsoft.com",
    }
)

logger = logging.getLogger("test")
logger.setLevel(logging.INFO)

def logging_context_wrapper(func):
    """Passes invocation_id to the thread local context to enable proper Azure Functions logging.

    Can be applied to a sync handler which has request: Request parameter - to get the context from.

    source: https://stackoverflow.com/questions/78672450/fastapi-logging-in-routes-in-azure-functions
    """

    request_param = next((param for (param, annotation) in func.__annotations__.items() if annotation is fastapi.Request), None)
    if not request_param:
        raise Exception("Function must have a request parameter of type Request.")

    @wraps(func)
    def wrapper(*args, **kwargs):
        request = kwargs[request_param]
        logging.debug(f"Setting invocation_id in thread local storage for request: {request.url.path}")
        thread_local_storage = request.scope.get("azure_functions.thread_local_storage")
        if thread_local_storage is not None:
            thread_local_storage.invocation_id = request.scope.get("azure_functions.invocation_id")
            logging.debug(f"Set invocation_id: {thread_local_storage.invocation_id}")
        return func(*args, **kwargs)

    return wrapper

@fastapi_app.get("/fastapi_long_response")
@logging_context_wrapper
def long_response(request: fastapi.Request):
    time.sleep(300)
    return JSONResponse(status_code=200)

app = func.FunctionApp()
app.register_functions(bp)

# create once at module import time
_asgi = func.AsgiMiddleware(fastapi_app)

@app.route(route="/{*path}", auth_level=auth_level)
@app.durable_client_input("client")
def api(
    req: func.HttpRequest, context: func.Context, client: df.DurableOrchestrationClient
) -> func.HttpResponse:
    durable_client_var.set(client)
    logging.info(f"Request path: {req.url}")
    return _asgi.handle_async(req, context)

durable_func.py:

import time
import logging
import azure.durable_functions as df

bp = df.Blueprint()

@bp.orchestration_trigger(context_name="context")
def data_flow_orchestration(context: df.DurableOrchestrationContext):
      input_context = context.get_input()
      extra_input = input_context.get("extra_input", {})
      output = yield context.call_activity("test", extra_input)
      return output


@bp.activity_trigger(input_name="extra_input")
def test(extra_input: Dict[str, Any]):
    i = 0
    con = True
    while con:
        logging.info(f"[{request_path}] Received request to organize PKG/FRU data from MoAD, {extra_input}.")
        con = i < 100
        i += 1
        time.sleep(5)

If deployed to Azure

We have access to a lot of telemetry that can help with investigations. Please provide as much of the following information as you can to help us investigate!

  • Timeframe issue observed:
  • Function App name:
  • Function name(s):
  • Azure region:
  • Orchestration instance ID(s):
  • Azure storage account name:

If you don't want to share your Function App or storage account name GitHub, please at least share the orchestration instance ID. Otherwise it's extremely difficult to look up information.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions