Back to Blog
Part 7 of 8
AzureServerlessAzure FunctionObservabilityLogging

Azure Functions Tutorial: Logging with App Insight

October 1, 20222 min read
Share:

Logging with Application Insights#

Before starting, verify your Function App is connected to an Application Insights instance in the Azure Portal.

Get App Insight Connection String#

  1. Open the App Insight resource attached to your Function App
  2. Copy the Instrumentation Key and Connection String from the overview tab

Implementation#

Key Concepts#

  1. Role Name: AI uses role_name to separate events from different apps
  2. Azure Log Handler: Custom logger that emits to App Insights
  3. Trace Integrations: Enable for logging and requests modules

Custom Logger (src/appinsight/logger.py)#

import logging
from opencensus.ext.azure.log_exporter import AzureLogHandler
from opencensus.trace import config_integration

config_integration.trace_integrations(['logging', 'requests'])

AI_CONNECTION_STRING = "InstrumentationKey=xxx;IngestionEndpoint=https://..."
WEBSITE_NAME = "function-demo"

class CustomDimensionsFilter(logging.Filter):
    def __init__(self, custom_dimensions=None):
        super().__init__()
        self.custom_dimensions = custom_dimensions or {}

    def filter(self, record):
        dim = {**self.custom_dimensions, **getattr(record, "custom_dimensions", {})}
        record.custom_dimensions = dim
        return True

def callback_add_role_name(envelope):
    envelope.tags['ai.cloud.role'] = WEBSITE_NAME
    envelope.tags["ai.cloud.roleInstance"] = WEBSITE_NAME

def get_logger(name: str, propagate: bool = True) -> logging.Logger:
    azure_log_handler = AzureLogHandler(connection_string=AI_CONNECTION_STRING)
    azure_log_handler.add_telemetry_processor(callback_add_role_name)
    azure_log_handler.setLevel(logging.DEBUG)
    
    formatter = logging.Formatter(
        '%(asctime)s traceId=%(traceId)s api=%(name)s.%(funcName)s '
        '[%(levelname)-7s]: %(message)s'
    )
    azure_log_handler.setFormatter(formatter)
    azure_log_handler.addFilter(CustomDimensionsFilter())
    
    logger = logging.getLogger(name)
    logger.setLevel(logging.DEBUG)
    logger.addHandler(azure_log_handler)
    logger.propagate = propagate
    return logger

Update Your Code#

Replace standard logging:

# Before
import logging
logger = logging.getLogger(__name__)

# After
from src.appinsight.logger import get_logger
logger = get_logger(__name__)

Testing#

  1. Run the function locally
  2. Make requests to /vault?secret=name with and without auth
  3. Check Transaction Search in App Insights
Note

It takes 3-5 minutes for logs to appear in App Insights

Architecture#

flowchart LR
    subgraph Azure Function
        A[Flask App] --> B[AzureLogHandler]
    end
    B --> C[Application Insights]
    C --> D[Transaction Search]
    C --> E[Metrics]
    C --> F[Alerts]
YS

Yogesh Sharma

Principal Software Engineer @ Intuit