Get current InvocationId or operation_Id

Question:

Is there a way to have one complete output log with custom_dimensions? I see in the monitor tab (of Azure Functions) that only messages with operation_Id and customDimensions['InvocationId'] are shown. Is there a way to add these two parameters all the log-messages from opencensus?

I know you can use a second logger. But that only helps for debugging. For running the Azure Functions in production, I need to look at both streams. That is possible, but inefficient and frustrating, as the information is disconnected and impossible to summarize.

However another alternative would be joining the streams on the Azure Monitor side. But I can’t do that unless I know the current InvocationIdor operation_Id. Therefore my question if I can add any of those two IDs to my current log-message

My minimal example __init__.py looks like this:

from opencensus.ext.azure.log_exporter import AzureLogHandler
import logging.config
import yaml

import azure.functions as func

# Load logging configuration
with open("logging.yaml", 'rt') as f: # for local debugging add the console handler to the output
    config_data = yaml.safe_load(f.read())
    logging.config.dictConfig(config_data)

def main(mytimer: func.TimerRequest) -> None:
    try: 
        someID = 14
        logging.debug('debug message',extra = {'custom_dimensions': {'ID': someID}})
        logging.info('info message',extra = {'custom_dimensions': {'ID': someID}})
        logging.warning('warn message',extra = {'custom_dimensions': {'ID': someID}})
        logging.error('error message',extra = {'custom_dimensions': {'ID': someID}})
        logging.critical('critical message',extra = {'custom_dimensions': {'ID': someID}})
    except Exception as e:
        logging.error("Main program failed with error: " + str(e))

I prefer to keep my logging configuration in a logging.yaml:

version: 1
formatters:
  simple:
    format: '%(asctime)s | %(levelname)-8s | %(module)s:%(funcName)s:%(lineno)d | %(message)s'
handlers:
  azure:
    class: opencensus.ext.azure.log_exporter.AzureLogHandler
    level: DEBUG
    formatter: simple
    instrumentation_key: 'your-key'
loggers:
  simpleExample:
    level: DEBUG
    handlers: [azure]
    propagate: no
root:
  level: INFO
  handlers: [azure]
Asked By: 5th

||

Answers:

After finding the right part in the documentation it was surprisingly easy:

def main(mytimer: func.TimerRequest, context: func.Context) -> None:
    try: 
        invocation_id = context.invocation_id
        # Function continues here. 

    except Exception as e:
        logging.error("Main program failed with error: " + str(e))

Be aware that this solution only works if func.Context is assigned to context. Using any other name than context results in errors for me -.-

Answered By: 5th

Just added here for the operation_Id, Based on the docs the 2nd part of the Traceparent is the trace_id which becomes the operation ID in the log console.

def main(mytimer: func.TimerRequest, context: func.Context) -> None:
    try: 
        invocation_id = context.invocation_id
        traceparent = context.trace_context.Traceparent
        try:
            operation_id = f"{traceparent}".split('-')[1]
        except IndexError as i_err:
            # as a backup option 
            logging.exception(i_err)
            operation_id = 'default_id'
        except Exception as final_err:
           logging.exception(final_err)
           # Function continues here. 
    except Exception as e:
        logging.error("Main program failed with error: " + str(e))

References:
trace_id,
Telemetry correlation in Application Insights

Answered By: Sumit Kumar Singh