Azure Functions Timer Trigger Not Executing Python Code - No Logs Appearing

Geoff Barton 0 Reputation points
2023-08-17T02:21:18.47+00:00

Hello,

I've implemented an Azure Function using Python that is supposed to be triggered based on a timer. The main goal of the function is to fetch data from an external API and save the results to OneDrive.

Here's the full code for reference:

import os
import logging
import datetime
import requests
import json
import math
import azure.functions as func
from msal import ConfidentialClientApplication

def main(mytimer: func.TimerRequest) -> None:
    logging.info('Python timer trigger function ran at %s', datetime.datetime.utcnow())

    url = "https://clm.perfectgym.com.au/Api/v2/odata/members?$count=true&"

    perfectgym_client_id = os.getenv('PERFECTGYM_CLIENT_ID')
    if not perfectgym_client_id:
        logging.error('Missing PERFECTGYM_CLIENT_ID environment variable.')
        return

    perfectgym_client_secret = os.getenv('PERFECTGYM_CLIENT_SECRET')
    if not perfectgym_client_secret:
        logging.error('Missing PERFECTGYM_CLIENT_SECRET environment variable.')
        return

    headers = {
        'X-Client-Id': perfectgym_client_id,
        'X-Client-Secret': perfectgym_client_secret
    }

    results = call_api(url, headers)
    filename = 'MembersData01.json'
    save_to_onedrive(results, filename)

def call_api(url, headers):
    results = []
    
    try:
        j_response = requests.get(url, headers=headers).json()
        count = j_response.get('@odata.count', 0)
    except (KeyError, json.JSONDecodeError):
        count = 0
        logging.error("Error in getting count from API response.")

    for i in range(math.ceil(count / 500)):
        response = requests.get(url + "$skip=" + str(i*500), headers=headers)
        if response.status_code != 200:
            logging.error(f"API returned non-200 status code: {response.status_code}")
            continue
        for v in response.json().get('value', []):
            results.append(v)

    return results

def save_to_onedrive(json_data, filename):
    authority_host_uri = 'https://login.microsoftonline.com'
    azure_tenant = os.getenv('AZURE_TENANT_ID')
    if not azure_tenant:
        logging.error('Missing AZURE_TENANT_ID environment variable.')
        return

    authority_uri = authority_host_uri + '/' + azure_tenant
    resource_uri = 'https://graph.microsoft.com'
    azure_client_id = os.getenv('AZURE_CLIENT_ID')
    if not azure_client_id:
        logging.error('Missing AZURE_CLIENT_ID environment variable.')
        return

    azure_client_secret = os.getenv('AZURE_CLIENT_SECRET')
    if not azure_client_secret:
        logging.error('Missing AZURE_CLIENT_SECRET environment variable.')
        return

    onedrive_user_id = os.getenv('ONEDRIVE_USER_ID')
    if not onedrive_user_id:
        logging.error('Missing ONEDRIVE_USER_ID environment variable.')
        return
    
    app = ConfidentialClientApplication(
        azure_client_id,
        authority=authority_uri,
        client_credential=azure_client_secret,
        azure_region="australiasoutheast"
    )

    scopes = ['https://graph.microsoft.com/.default']
    result = app.acquire_token_silent(scopes, account=None)
    if not result:
        result = app.acquire_token_for_client(scopes)
    if "access_token" in result:
        token = result['access_token']
        onedrive_url = f"https://graph.microsoft.com/v1.0/users/{onedrive_user_id}/drive/root:/z-CLM PG All Data/Members Data/{filename}:/content"
        headers = {'Authorization': 'Bearer ' + token}
        response = requests.put(onedrive_url, headers=headers, data=json.dumps(json_data, ensure_ascii=False, indent=4))
        if response.status_code in [200, 201]:  # Handling both 200 and 201 status codes
            logging.info('Successfully saved data to OneDrive.')
        else:
            logging.error(f"Failed to save data to OneDrive: {response.json()}")
    else:
        logging.error(f"Could not get an access token: {result}")

Issues:

  1. When I test/run the function in Azure, there is no sign of it working.
  2. No results are showing in monitoring, not even errors.

What I've tried:

  1. Checked the CRON expression to ensure the function should be triggered.
  2. Ensured all required dependencies are installed.
  3. Made sure all environment variables are correctly set in the Azure Function App settings.
  4. Checked the Azure Portal "Monitor" and "Logs" section, but no relevant logs found.
  5. Re-deployed the function.

Questions:

  1. Are there any issues in the code that might prevent it from running?
  2. Could there be any configuration-related problems in the Azure portal that might be causing this?
  3. How can I get more detailed logs or error messages to better understand what's happening?

Any help or guidance would be greatly appreciated. Thank you!

Azure Functions
Azure Functions
An Azure service that provides an event-driven serverless compute platform.
5,709 questions
{count} votes

1 answer

Sort by: Most helpful
  1. MuthuKumaranMurugaachari-MSFT 22,421 Reputation points
    2023-08-21T16:12:39.6966667+00:00

    Geoff Barton Thanks for sharing the details. From the expression above, this function will be executed at 05:00 PM, 08:00 PM, 11:00 PM, 02:00 AM, 05:00 AM and 08:00 AM and note, by default, time zone is UTC unless you specify WEBSITE_TIME_ZONE. Please validate if the function executes during this time or not or you can change to a simple format for testing purposes.

    For manually invoking this timer function, suggest you follow https://learn.microsoft.com/en-us/azure/azure-functions/functions-manually-run-non-http and call the function from Postman tool (not portal). Then monitor the function call via Code+Test window.

    Please let me know if it helps.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.