import logging
import azure.functions as func
from dotenv import load_dotenv
import requests
from data_process import delete_article_given_guid, index_all, process_contact_and_about, published_a_new_article
from share_function import sync_deleted_content, transfer_files
from azure.storage.fileshare import ShareClient
from azure.storage.blob import BlobServiceClient
import os
app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS)
load_dotenv()
logging.basicConfig(level=logging.INFO)
@app.route(route="remove_article_by_id")
def remove_article_by_id(req: func.HttpRequest) -> func.HttpResponse:
logging.info(f"Remove article by ID function processed a request with with params: {req.params}")
guid = req.params.get("guid")
language = req.params.get("language")
api_method = req.params.get("api_method")
new_guid = f"{api_method}-{guid}"
if not guid or not language or not api_method:
return func.HttpResponse(
"Please pass a guid and a language in the query string.", status_code=400
)
# Call the function to delete the article by GUID
logging.info(f"Removing {api_method} article in {language}, with guid {new_guid}.")
status_code = delete_article_given_guid(new_guid,api_method, language)
if status_code != 200:
return func.HttpResponse(
f"Article with guid {guid} not found.", status_code=status_code
)
else:
return func.HttpResponse(f"Article with guid {guid} removed successfully.")
@app.route(route="publish_new_article")
def publish_new_article(req: func.HttpRequest) -> func.HttpResponse:
logging.info(
f"Publish new article function received a request with params: {req.params}"
)
published = req.params.get("published", "false").lower() in ["true", "1", "yes"]
api_method = req.params.get("api_method", "")
language = req.params.get("language", "")
id =req.params.get("id", "")
createdDate=req.params.get("createdDate", "")
name=req.params.get("name", "")
if published and api_method and language:
result = published_a_new_article(api_method=api_method, language=language, Article_id=id,createdDate=createdDate,name=name)
if result == "done":
logging.info("A new article published successfully.")
return func.HttpResponse("New articles have been published successfully.")
elif result == "noData":
return func.HttpResponse(
"No new articles found to publish.", status_code=406
)
else:
logging.error(result)
return func.HttpResponse(result, status_code=400)
else:
logging.error(
"Publish action failed. Invalid paramters. Please provide valid published, api_method, and language params."
)
return func.HttpResponse(
"Publish action failed. Invalid paramters. Please provide valid published, api_method, and language params.",
status_code=400,
)
@app.route(route="index_all", auth_level=func.AuthLevel.ANONYMOUS)
def index_all_trigger(req: func.HttpRequest) -> func.HttpResponse:
logging.info("Processing request to index all content.")
try:
index_all()
logging.info("Indexing completed successfully.")
return func.HttpResponse("Indexing completed successfully.")
except Exception as e:
logging.error(f"Failed to index all content: {str(e)}")
return func.HttpResponse(
f"Failed to index all content: {str(e)}", status_code=500
)
@app.function_name(name="index_contact_and_about")
@app.timer_trigger(schedule="0 0 0 * * *", arg_name="mytimer", run_on_startup=False)
def index_contact_and_about(mytimer: func.TimerRequest) -> None:
logging.info('Contact Us and About Us indexing function started')
for language in ['fr-FR', 'de-DE', 'es-ES', 'ar-QA', 'en']:
try:
result = process_contact_and_about(language)
if result == "error":
logging.error(f"Failed to index Contact Us and About Us for language: {language}")
else:
logging.info(f"Successfully indexed Contact Us and About Us for language: {language}, {result}")
except Exception as e:
logging.error(f"Exception occurred while indexing Contact Us and About Us for language {language}: {e}")
Итак, проблема в том, что он работает в моей разработке, но тот же код не работает в производственной среде клиента. На стороне клиента мы используем конвейер Azure Devops (который отлично строится, когда я развернул артефакт в своей среде разработки, он работает). С приведенными ниже журналами развертывания от Kudus -
.env и конфигурации практически идентичны. После недельной попытки отладить его, используя все подходы из https://github.com/Azure/azure-function ... ssues/1262, все сводилось к этому конкретному журналу ошибок: функции задания не найдены. Попробуйте сделать свои классы и методы заданий общедоступными.
Это очень расплывчато. Итак, попробовал загрузить простой шаблон скрипта, чтобы убедиться, что модули работают правильно -
import logging
import azure.functions as func
import sys
import os
from importlib.metadata import distributions
import json
import traceback
logging.basicConfig(level=logging.INFO)
# Initialize FunctionApp first
app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS)
# Global tracking variables
services_initialized = False
initialization_error = None
# Try importing all your required services
try:
# Import your potentially problematic modules here
from azure.storage.blob import BlobServiceClient
from azure.storage.fileshare import ShareClient
from azure.search.documents import SearchClient
from dotenv import load_dotenv
# from data_process import _index_all, delete_article_given_guid, published_a_new_article
# from share_function import sync_deleted_content, transfer_files
import asyncio
import ssl
import aiohttp
import time
import uuid
import datetime
import requests
import pytz
import bs4
# Initialize your services
load_dotenv()
services_initialized = True
logging.info("All services initialized successfully")
except Exception as e:
initialization_error = str(e)
logging.error(f"Initialization error: {str(e)}")
# Don't raise the error - let functions register
@app.route(route="health", methods=["GET"])
def health(req: func.HttpRequest) -> func.HttpResponse:
try:
health_info = {
"status": "available",
"initialization": {
"services_initialized": services_initialized,
"initialization_error": initialization_error,
},
"environment": {
"python_version": sys.version,
"current_directory": os.getcwd(),
"python_path": sys.path,
"environment_variables": {
"PYTHONPATH": os.getenv("PYTHONPATH", "not set"),
"AzureWebJobsScriptRoot": os.getenv("AzureWebJobsScriptRoot", "not set"),
# Add other relevant environment variables
"AZURE_FUNCTIONS_ENVIRONMENT": os.getenv("AZURE_FUNCTIONS_ENVIRONMENT", "not set"),
"FUNCTIONS_WORKER_RUNTIME": os.getenv("FUNCTIONS_WORKER_RUNTIME", "not set"),
"FUNCTIONS_EXTENSION_VERSION": os.getenv("FUNCTIONS_EXTENSION_VERSION", "not set"),
# Storage settings
"WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "present" if os.getenv("WEBSITE_CONTENTAZUREFILECONNECTIONSTRING") else "not set",
"WEBSITE_CONTENTSHARE": os.getenv("WEBSITE_CONTENTSHARE", "not set"),
# Search service settings
"SEARCH_SERVICE_ENDPOINT": os.getenv("SEARCH_SERVICE_ENDPOINT", "not set"),
"SEARCH_INDEX_VERSION": os.getenv("SEARCH_INDEX_VERSION", "not set"),
"SEARCH_API_VERSION": os.getenv("SEARCH_API_VERSION", "not set"),
# Reports settings
"REPORTS_SEARCH_SERVICE_ENDPOINT": os.getenv("REPORTS_SEARCH_SERVICE_ENDPOINT", "not set"),
"REPORTS_SEARCH_INDEX_VERSION": os.getenv("REPORTS_SEARCH_INDEX_VERSION", "not set"),
# Container settings
"REPORTS_SOURCE_CONTAINER_NAME": os.getenv("REPORTS_SOURCE_CONTAINER_NAME", "not set"),
"REPORTS_TARGET_CONTAINER_NAME": os.getenv("REPORTS_TARGET_CONTAINER_NAME", "not set"),
# API settings
"UMBRACO_API_URL": os.getenv("UMBRACO_API_URL", "not set"),
"MAX_CONCURRENT_REQUESTS": os.getenv("MAX_CONCURRENT_REQUESTS", "not set")
},
},
"azure_services": {
"blob_storage": "available" if "BlobServiceClient" in globals() else "not imported",
"file_share": "available" if "ShareClient" in globals() else "not imported",
"search_client": "available" if "SearchClient" in globals() else "not imported",
"data_process": {
"_index_all": "available" if "_index_all" in globals() else "not imported",
"delete_article": "available" if "delete_article_given_guid" in globals() else "not imported",
"publish_article": "available" if "published_a_new_article" in globals() else "not imported"
},
"share_function": {
"sync_deleted_content": "available" if "sync_deleted_content" in globals() else "not imported",
"transfer_files": "available" if "transfer_files" in globals() else "not imported"
}
},
"dependencies": {
"installed_packages": [f"{dist.metadata['Name']}=={dist.version}" for dist in distributions()]
}
}
return func.HttpResponse(
json.dumps(health_info, indent=2),
mimetype="application/json"
)
except Exception as e:
error_info = {
"status": "error",
"error_type": type(e).__name__,
"error_message": str(e),
"error_traceback": traceback.format_exc(),
}
logging.error(f"Health check failed: {str(e)}")
return func.HttpResponse(
json.dumps(error_info, indent=2),
status_code=500,
mimetype="application/json"
)
Это тоже не удалось. Это заставляет меня думать, что это связано с поврежденными модулями. Есть идеи, как решить эту проблему, поскольку клиент отказывается создавать другой ресурс? Как удалить старые поврежденные модули.
ПРИМЕЧАНИЕ № 1. Код работает в двух моих функциях Azure для разработчиков.
ПРИМЕЧАНИЕ № 2. Это показывает успешное развертывание, но в обзоре нет функций, а также файлы не видны.
Итак, у меня есть функциональное приложение Python v2 для CMS, которое работает со следующими пакетами (requirements.txt) - [code]azure-storage-blob pytz python-dotenv azure-search-documents azure-storage-file-share aiohttp requests beautifulsoup4 [/code] С помощью function_app.py – [code]import logging import azure.functions as func from dotenv import load_dotenv import requests from data_process import delete_article_given_guid, index_all, process_contact_and_about, published_a_new_article from share_function import sync_deleted_content, transfer_files from azure.storage.fileshare import ShareClient from azure.storage.blob import BlobServiceClient import os
@app.route(route="remove_article_by_id") def remove_article_by_id(req: func.HttpRequest) -> func.HttpResponse: logging.info(f"Remove article by ID function processed a request with with params: {req.params}")
guid = req.params.get("guid") language = req.params.get("language") api_method = req.params.get("api_method") new_guid = f"{api_method}-{guid}" if not guid or not language or not api_method: return func.HttpResponse( "Please pass a guid and a language in the query string.", status_code=400 )
# Call the function to delete the article by GUID logging.info(f"Removing {api_method} article in {language}, with guid {new_guid}.") status_code = delete_article_given_guid(new_guid,api_method, language) if status_code != 200: return func.HttpResponse( f"Article with guid {guid} not found.", status_code=status_code ) else: return func.HttpResponse(f"Article with guid {guid} removed successfully.")
@app.route(route="publish_new_article") def publish_new_article(req: func.HttpRequest) -> func.HttpResponse: logging.info( f"Publish new article function received a request with params: {req.params}" ) published = req.params.get("published", "false").lower() in ["true", "1", "yes"] api_method = req.params.get("api_method", "") language = req.params.get("language", "") id =req.params.get("id", "") createdDate=req.params.get("createdDate", "") name=req.params.get("name", "")
if published and api_method and language: result = published_a_new_article(api_method=api_method, language=language, Article_id=id,createdDate=createdDate,name=name)
if result == "done": logging.info("A new article published successfully.") return func.HttpResponse("New articles have been published successfully.") elif result == "noData": return func.HttpResponse( "No new articles found to publish.", status_code=406 ) else: logging.error(result) return func.HttpResponse(result, status_code=400) else: logging.error( "Publish action failed. Invalid paramters. Please provide valid published, api_method, and language params." ) return func.HttpResponse( "Publish action failed. Invalid paramters. Please provide valid published, api_method, and language params.", status_code=400, )
@app.route(route="index_all", auth_level=func.AuthLevel.ANONYMOUS) def index_all_trigger(req: func.HttpRequest) -> func.HttpResponse: logging.info("Processing request to index all content.") try: index_all() logging.info("Indexing completed successfully.") return func.HttpResponse("Indexing completed successfully.") except Exception as e: logging.error(f"Failed to index all content: {str(e)}") return func.HttpResponse( f"Failed to index all content: {str(e)}", status_code=500 )
@app.function_name(name="index_contact_and_about") @app.timer_trigger(schedule="0 0 0 * * *", arg_name="mytimer", run_on_startup=False) def index_contact_and_about(mytimer: func.TimerRequest) -> None: logging.info('Contact Us and About Us indexing function started')
for language in ['fr-FR', 'de-DE', 'es-ES', 'ar-QA', 'en']: try: result = process_contact_and_about(language) if result == "error": logging.error(f"Failed to index Contact Us and About Us for language: {language}") else: logging.info(f"Successfully indexed Contact Us and About Us for language: {language}, {result}") except Exception as e: logging.error(f"Exception occurred while indexing Contact Us and About Us for language {language}: {e}") [/code] С хостом.json как - [code]{ "version": "2.0", "logging": { "applicationInsights": { "samplingSettings": { "isEnabled": true, "excludedTypes": "Request" } } }, "extensionBundle": { "id": "Microsoft.Azure.Functions.ExtensionBundle", "version": "[4.*, 5.0.0)" } } [/code] Итак, проблема в том, что он [b]работает в моей разработке[/b], но тот же код [b]не работает в производственной среде клиента[/b]. На стороне клиента мы используем конвейер Azure Devops (который отлично строится, когда я развернул артефакт в своей среде разработки, он работает). С приведенными ниже журналами развертывания от Kudus - [code]{"timestamp": "2024-11-11T06:39:16.093Z", "level": "Message", "containerName": "", "machineName": "", "message": "Updating submodules."} {"timestamp": "2024-11-11T06:39:16.275Z", "level": "Message", "containerName": "", "machineName": "", "message": "Preparing deployment for commit id '2f415e91-a'."} {"timestamp": "2024-11-11T06:39:16.808Z", "level": "Message", "containerName": "", "machineName": "", "message": "PreDeployment: context.CleanOutputPath False"} {"timestamp": "2024-11-11T06:39:16.975Z", "level": "Message", "containerName": "", "machineName": "", "message": "PreDeployment: context.OutputPath /home/site/wwwroot"} {"timestamp": "2024-11-11T06:39:17.175Z", "level": "Message", "containerName": "", "machineName": "", "message": "Skipping build. Project type: Run-From-Zip"} {"timestamp": "2024-11-11T06:39:17.335Z", "level": "Message", "containerName": "", "machineName": "", "message": "Skipping post build. Project type: Run-From-Zip"} {"timestamp": "2024-11-11T06:39:17.568Z", "level": "Message", "containerName": "", "machineName": "", "message": "Triggering recycle (preview mode disabled)."} {"timestamp": "2024-11-11T06:39:17.984Z", "level": "Message", "containerName": "", "machineName": "", "message": "Updating /home/data/SitePackages/packagename.txt with deployment 20241111063909.zip"} {"timestamp": "2024-11-11T06:39:18.228Z", "level": "Message", "containerName": "", "machineName": "", "message": "Deployment successful. deployer = VSTS_ZIP_DEPLOY_FUNCTIONS_V2 deploymentPath = Functions App ZipDeploy. Run from package."} [/code] .env и конфигурации практически идентичны. После недельной попытки отладить его, используя все подходы из https://github.com/Azure/azure-functions-python-worker/issues/1262, все сводилось к этому конкретному журналу ошибок: функции задания не найдены. Попробуйте сделать свои классы и методы заданий общедоступными. Это очень расплывчато. Итак, попробовал загрузить простой шаблон скрипта, чтобы убедиться, что модули работают правильно - [code]import logging import azure.functions as func import sys import os from importlib.metadata import distributions import json import traceback
logging.basicConfig(level=logging.INFO)
# Initialize FunctionApp first app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS)
# Global tracking variables services_initialized = False initialization_error = None
# Try importing all your required services try: # Import your potentially problematic modules here from azure.storage.blob import BlobServiceClient from azure.storage.fileshare import ShareClient from azure.search.documents import SearchClient from dotenv import load_dotenv # from data_process import _index_all, delete_article_given_guid, published_a_new_article # from share_function import sync_deleted_content, transfer_files import asyncio import ssl import aiohttp import time import uuid import datetime import requests import pytz import bs4
# Initialize your services load_dotenv()
services_initialized = True logging.info("All services initialized successfully") except Exception as e: initialization_error = str(e) logging.error(f"Initialization error: {str(e)}") # Don't raise the error - let functions register
# API settings "UMBRACO_API_URL": os.getenv("UMBRACO_API_URL", "not set"), "MAX_CONCURRENT_REQUESTS": os.getenv("MAX_CONCURRENT_REQUESTS", "not set") }, }, "azure_services": { "blob_storage": "available" if "BlobServiceClient" in globals() else "not imported", "file_share": "available" if "ShareClient" in globals() else "not imported", "search_client": "available" if "SearchClient" in globals() else "not imported", "data_process": { "_index_all": "available" if "_index_all" in globals() else "not imported", "delete_article": "available" if "delete_article_given_guid" in globals() else "not imported", "publish_article": "available" if "published_a_new_article" in globals() else "not imported" }, "share_function": { "sync_deleted_content": "available" if "sync_deleted_content" in globals() else "not imported", "transfer_files": "available" if "transfer_files" in globals() else "not imported" } }, "dependencies": { "installed_packages": [f"{dist.metadata['Name']}=={dist.version}" for dist in distributions()] } }
return func.HttpResponse( json.dumps(health_info, indent=2), mimetype="application/json" ) except Exception as e: error_info = { "status": "error", "error_type": type(e).__name__, "error_message": str(e), "error_traceback": traceback.format_exc(), } logging.error(f"Health check failed: {str(e)}") return func.HttpResponse( json.dumps(error_info, indent=2), status_code=500, mimetype="application/json" ) [/code] Это тоже не удалось. Это заставляет меня думать, что это связано с поврежденными модулями. Есть идеи, как решить эту проблему, поскольку клиент отказывается создавать другой ресурс? Как удалить старые поврежденные модули. ПРИМЕЧАНИЕ № 1. Код работает в двух моих функциях Azure для разработчиков. ПРИМЕЧАНИЕ № 2. Это показывает успешное развертывание, но в обзоре нет функций, а также файлы не видны.
Мне не удалось найти четкую документацию по этой теме.
Кроме того, все ли функции в приложении-функции должны находиться в одном файле function_app.py или могут они разделены на разные файлы? Если разделение возможно, как должна выглядеть структура...
Мне не удалось найти четкую документацию по этой теме.
Кроме того, все ли функции в приложении-функции должны находиться в одном файле function_app.py или могут они разделены на разные файлы? Если разделение возможно, как должна выглядеть структура...
Я разрабатываю приложение Spring Boot с использованием gRPC и столкнулся со следующей ошибкой:
io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2Exception: HTTP/2 client preface string missing or corrupt. Hex dump for received bytes:...
У меня есть веб-сайт ilias lms на нашем сервере, но мы хотим скрыть имя действия формы в исходном коде и веб-разработчике, есть ли какое-либо решение по этому вопросу. это html-файл.
У меня есть веб-сайт ilias lms на нашем сервере, но мы хотим скрыть имя действия формы в исходном коде и веб-разработчике, есть ли какое-либо решение по этому вопросу. это html-файл.