إشعار
يتطلب الوصول إلى هذه الصفحة تخويلاً. يمكنك محاولة تسجيل الدخول أو تغيير الدلائل.
يتطلب الوصول إلى هذه الصفحة تخويلاً. يمكنك محاولة تغيير الدلائل.
توضح هذه المقالة دعم OpenTelemetry في Azure Function، الذي يتيح تتبع موزع عبر استدعاءات وظائف متعددة باستخدام Application Insights المدمج ودعم OpenTelemetry. لمساعدتك على البدء، يتم استخدام قالب Azure Developer CLI (azd) لإنشاء مشروع الكود الخاص بك وكذلك نشر Azure لتشغيل تطبيقك.
في هذا الدرس، تستخدم الأداة azd ل:
- قم بتهيئة مشروع مفعل بنظام OpenTelemetry من قالب معين.
- راجع الكود الذي يتيح تكامل OpenTelemetry.
- شغل وتحقق من تطبيقك المفعل عبر OpenTelemetry محليا.
- أنشئ تطبيق وظائف وموارد ذات صلة في Azure.
- قم بنشر مشروع الكود الخاص بك على تطبيق الدوال في Azure.
- تحقق من التتبع الموزع في Application Insights.
الموارد المطلوبة من Azure التي ينشئها هذا القالب تتبع أفضل الممارسات الحالية لنشر تطبيقات الوظائف الآمنة والقابلة للتوسع في Azure. نفس azd الأمر ينشر مشروع الكود الخاص بك أيضا في تطبيق الوظائف الجديد في Azure.
بشكل افتراضي، تتبع خطة الاستهلاك المرن نموذج الفوترة بالدفع مقابل ما تستخدمه ، مما يعني أن إكمال هذه البداية السريعة يكلف تكلفة صغيرة بضعة سنتات أمريكية أو أقل في حساب Azure الخاص بك.
مهم
تدعم هذه المقالة حاليا فقط C# وبايثون وTypeScript. لإكمال التشغيل السريع، حدد إحدى هذه اللغات المدعومة في أعلى المقالة.
المُتطلَّبَات الأسَاسِية
حساب Azure مع اشتراك نشط. أنشئ حساباً مجاناً.
تهيئة المشروع
استخدم الأمر azd init لإنشاء مشروع كود محلي ل Azure Functions من قالب يتضمن تتبع OpenTelemetry الموزع.
في الوحدة الطرفية المحلية أو موجه الأوامر، قم بتشغيل هذا
azd initالأمر في مجلد فارغ:azd init --template functions-quickstart-python-azd-otel -e flexquickstart-otelيسحب هذا الأمر ملفات المشروع من مستودع القالب ويهيئ المشروع في المجلد الحالي.
-eتعين العلامة اسما للبيئة الحالية. فيazd، تحتفظ البيئة بسياق توزيع فريد لتطبيقك، ويمكنك تحديد أكثر من واحد. اسم البيئة يظهر أيضا في اسم مجموعة الموارد التي تنشئها في Azure.
في الوحدة الطرفية المحلية أو موجه الأوامر، قم بتشغيل هذا
azd initالأمر في مجلد فارغ:azd init --template functions-quickstart-typescript-azd-otel -e flexquickstart-otelيسحب هذا الأمر ملفات المشروع من مستودع القالب ويهيئ المشروع في المجلد الحالي.
-eتعين العلامة اسما للبيئة الحالية. فيazd، تحتفظ البيئة بسياق توزيع فريد لتطبيقك، ويمكنك تحديد أكثر من واحد. اسم البيئة يظهر أيضا في اسم مجموعة الموارد التي تنشئها في Azure.
في الوحدة الطرفية المحلية أو موجه الأوامر، قم بتشغيل هذا
azd initالأمر في مجلد فارغ:azd init --template functions-quickstart-dotnet-azd-otel -e flexquickstart-otelيسحب هذا الأمر ملفات المشروع من مستودع القالب ويهيئ المشروع في المجلد الحالي.
-eتعين العلامة اسما للبيئة الحالية. فيazd، تحتفظ البيئة بسياق توزيع فريد لتطبيقك، ويمكنك تحديد أكثر من واحد. اسم البيئة يظهر أيضا في اسم مجموعة الموارد التي تنشئها في Azure.
مراجعة الرمز
ينشئ القالب سيناريو تتبع موزع كامل بثلاث وظائف تعمل معا. دعونا نستعرض الجوانب الرئيسية المتعلقة ب OpenTelemetry:
تكوين OpenTelemetry
يتيح الملف src/otel-sample/host.json OpenTelemetry لمضيف Functions:
{
"version": "2.0",
"telemetryMode": "OpenTelemetry",
"extensions": {
"serviceBus": {
"maxConcurrentCalls": 10
}
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[4.*, 5.0.0)"
}
}
يتيح إعداد "telemetryMode": "OpenTelemetry" المفتاح التتبع الموزع عبر استدعاءات الوظائف.
يتيح الملف src/OTelSample/host.json OpenTelemetry لمضيف Functions:
{
"version": "2.0",
"telemetryMode": "OpenTelemetry",
"logging": {
"OpenTelemetry": {
"logLevel": {
"Host.General": "Warning"
}
}
}
}
يتيح إعداد "telemetryMode": "OpenTelemetry" المفتاح التتبع الموزع عبر استدعاءات الوظائف.
التبعيات ل OpenTelemetry
يتضمن الملف src/otel-sample/requirements.txt الحزم اللازمة لتكامل OpenTelemetry:
azure-functions
azure-monitor-opentelemetry
requests
توفر الحزمة azure-monitor-opentelemetry تكامل OpenTelemetry مع Application Insights.
يتضمن الملف src/otel-sample/package.json الحزم اللازمة لتكامل OpenTelemetry:
{
"dependencies": {
"@azure/functions": "^4.0.0",
"@azure/functions-opentelemetry-instrumentation": "^0.1.0",
"@azure/monitor-opentelemetry-exporter": "^1.0.0",
"axios": "^1.6.0"
}
}
توفر حزم @azure/functions-opentelemetry-instrumentation AND @azure/monitor-opentelemetry-exporter تكامل OpenTelemetry مع Application Insights.
يتضمن الملف .csproj الحزم اللازمة لتكامل OpenTelemetry:
<PackageReference Include="Azure.Monitor.OpenTelemetry.Exporter" Version="1.4.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.OpenTelemetry" Version="1.4.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.10.0" />
توفر هذه الحزم تكامل OpenTelemetry مع Application Insights وأجهزة HTTP للتتبع الموزع.
تنفيذ الدوال
تظهر الدوال في src/otel-sample/function_app.py تدفق تتبع موزع:
أول وظيفة HTTP
@app.function_name("first_http_function")
@app.route(route="first_http_function", auth_level=func.AuthLevel.ANONYMOUS)
def first_http_function(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Python HTTP trigger function (first) processed a request.')
# Call the second function
base_url = f"{req.url.split('/api/')[0]}/api"
second_function_url = f"{base_url}/second_http_function"
response = requests.get(second_function_url)
second_function_result = response.text
result = {
"message": "Hello from the first function!",
"second_function_response": second_function_result
}
return func.HttpResponse(
json.dumps(result),
status_code=200,
mimetype="application/json"
)
الدالة الثانية ل HTTP
@app.function_name("second_http_function")
@app.route(route="second_http_function", auth_level=func.AuthLevel.ANONYMOUS)
@app.service_bus_queue_output(arg_name="outputsbmsg", queue_name="%ServiceBusQueueName%",
connection="ServiceBusConnection")
def second_http_function(req: func.HttpRequest, outputsbmsg: func.Out[str]) -> func.HttpResponse:
logging.info('Python HTTP trigger function (second) processed a request.')
message = "This is the second function responding."
# Send a message to the Service Bus queue
queue_message = "Message from second HTTP function to trigger ServiceBus queue processing"
outputsbmsg.set(queue_message)
logging.info('Sent message to ServiceBus queue: %s', queue_message)
return func.HttpResponse(
message,
status_code=200
)
مشغل طابور حافلة الخدمة
@app.service_bus_queue_trigger(arg_name="azservicebus", queue_name="%ServiceBusQueueName%",
connection="ServiceBusConnection")
def servicebus_queue_trigger(azservicebus: func.ServiceBusMessage):
logging.info('Python ServiceBus Queue trigger start processing a message: %s',
azservicebus.get_body().decode('utf-8'))
time.sleep(5) # Simulate processing work
logging.info('Python ServiceBus Queue trigger end processing a message')
إعداد تكوين OpenTelemetry في src/otel-sample/index.ts:
import { AzureFunctionsInstrumentation } from '@azure/functions-opentelemetry-instrumentation';
import { AzureMonitorTraceExporter, AzureMonitorLogExporter } from '@azure/monitor-opentelemetry-exporter';
import { getNodeAutoInstrumentations, getResourceDetectors } from '@opentelemetry/auto-instrumentations-node';
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import { detectResources } from '@opentelemetry/resources';
import { LoggerProvider, SimpleLogRecordProcessor } from '@opentelemetry/sdk-logs';
import { NodeTracerProvider, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-node';
const resource = detectResources({ detectors: getResourceDetectors() });
const tracerProvider = new NodeTracerProvider({
resource,
spanProcessors: [new SimpleSpanProcessor(new AzureMonitorTraceExporter())]
});
tracerProvider.register();
const loggerProvider = new LoggerProvider({
resource,
processors: [new SimpleLogRecordProcessor(new AzureMonitorLogExporter())],
});
registerInstrumentations({
tracerProvider,
loggerProvider,
instrumentations: [getNodeAutoInstrumentations(), new AzureFunctionsInstrumentation()],
});
يتم تعريف الدوال في src/otel-sample/src/functions المجلد:
أول وظيفة HTTP
export async function firstHttpFunction(
request: HttpRequest,
context: InvocationContext
): Promise<HttpResponseInit> {
context.log("TypeScript HTTP trigger function (first) processed a request.");
try {
// Call the second function
const baseUrl = request.url.split("/api/")[0];
const secondFunctionUrl = `${baseUrl}/api/second_http_function`;
const response = await axios.get(secondFunctionUrl);
const secondFunctionResult = response.data;
const result = {
message: "Hello from the first function!",
second_function_response: secondFunctionResult,
};
return {
status: 200,
body: JSON.stringify(result),
headers: { "Content-Type": "application/json" },
};
} catch (error) {
return {
status: 500,
body: JSON.stringify({ error: "Failed to process request" }),
};
}
}
الدالة الثانية ل HTTP
export async function secondHttpFunction(
request: HttpRequest,
context: InvocationContext
): Promise<HttpResponseInit> {
context.log("TypeScript HTTP trigger function (second) processed a request.");
const message = "This is the second function responding.";
// Send a message to the Service Bus queue
const queueMessage =
"Message from second HTTP function to trigger ServiceBus queue processing";
context.extraOutputs.set(serviceBusOutput, queueMessage);
context.log("Sent message to ServiceBus queue:", queueMessage);
return {
status: 200,
body: message,
};
}
مشغل طابور حافلة الخدمة
export async function serviceBusQueueTrigger(
message: unknown,
context: InvocationContext
): Promise<void> {
context.log("TypeScript ServiceBus Queue trigger start processing a message:", message);
// Simulate processing time
await new Promise((resolve) => setTimeout(resolve, 5000));
context.log("TypeScript ServiceBus Queue trigger end processing a message");
}
إعداد تكوين OpenTelemetry في src/OTelSample/Program.cs:
using Azure.Monitor.OpenTelemetry.Exporter;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.OpenTelemetry;
using OpenTelemetry.Trace;
var builder = FunctionsApplication.CreateBuilder(args);
builder.ConfigureFunctionsWebApplication();
builder.Logging.AddOpenTelemetry(logging =>
{
logging.IncludeFormattedMessage = true;
logging.IncludeScopes = true;
});
builder.Services.AddOpenTelemetry()
.WithTracing(tracing =>
{
tracing.AddHttpClientInstrumentation();
});
builder.Services.AddOpenTelemetry().UseAzureMonitorExporter();
builder.Services.AddOpenTelemetry().UseFunctionsWorkerDefaults();
builder.Services.AddHttpClient();
builder.Build().Run();
يتم تعريف الدوال في ملفات فئات منفصلة:
أول وظيفة HTTP
public class FirstHttpTrigger
{
private readonly ILogger<FirstHttpTrigger> _logger;
private readonly IHttpClientFactory _httpClientFactory;
public FirstHttpTrigger(ILogger<FirstHttpTrigger> logger, IHttpClientFactory httpClientFactory)
{
_logger = logger;
_httpClientFactory = httpClientFactory;
}
[Function("first_http_function")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req)
{
_logger.LogInformation("first_http_function function processed a request.");
var baseUrl = $"{req.Url.AbsoluteUri.Split("/api/")[0]}/api";
var targetUri = $"{baseUrl}/second_http_function";
var client = _httpClientFactory.CreateClient();
var response = await client.GetAsync(targetUri);
var content = await response.Content.ReadAsStringAsync();
return new OkObjectResult($"Called second_http_function, status: {response.StatusCode}, content: {content}");
}
}
الدالة الثانية ل HTTP
public class SecondHttpTrigger
{
private readonly ILogger<SecondHttpTrigger> _logger;
public SecondHttpTrigger(ILogger<SecondHttpTrigger> logger)
{
_logger = logger;
}
[Function("second_http_function")]
public MultiResponse Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req)
{
_logger.LogInformation("second_http_function function processed a request.");
return new MultiResponse
{
Messages = new string[] { "Hello" },
HttpResponse = req.CreateResponse(System.Net.HttpStatusCode.OK)
};
}
}
public class MultiResponse
{
[ServiceBusOutput("%ServiceBusQueueName%", Connection = "ServiceBusConnection")]
public string[]? Messages { get; set; }
[HttpResult]
public HttpResponseData? HttpResponse { get; set; }
}
مشغل طابور حافلة الخدمة
public class ServiceBusQueueTrigger
{
private readonly ILogger<ServiceBusQueueTrigger> _logger;
public ServiceBusQueueTrigger(ILogger<ServiceBusQueueTrigger> logger)
{
_logger = logger;
}
[Function("servicebus_queue_trigger")]
public async Task Run(
[ServiceBusTrigger("%ServiceBusQueueName%", Connection = "ServiceBusConnection")]
ServiceBusReceivedMessage message,
ServiceBusMessageActions messageActions)
{
_logger.LogInformation("Message ID: {id}", message.MessageId);
_logger.LogInformation("Message Body: {body}", message.Body);
// Complete the message
await messageActions.CompleteMessageAsync(message);
}
}
تدفق التتبع الموزع
تخلق هذه البنية سيناريو تتبع موزع كامل، مع هذا السلوك:
- تستقبل دالة HTTP الأولى طلب HTTP وتستدعي دالة HTTP الثانية
- تستجيب دالة HTTP الثانية وترسل رسالة إلى ناقل الخدمة
- يقوم مشغل ناقل الخدمة بمعالجة الرسالة مع تأخير لمحاكاة عمل المعالجة
الجوانب الرئيسية لتنفيذ OpenTelemetry:
-
تكامل OpenTelemetry: يتيح
host.jsonالملف OpenTelemetry مع"telemetryMode": "OpenTelemetry" - تسلسل الدوال: تستدعي الدالة الأولى الثانية باستخدام طلبات HTTP، مما يخلق مسارات مترابطة
- تكامل ناقل الخدمة: تخرج الدالة الثانية إلى ناقل الخدمة، مما يؤدي إلى تفعيل الوظيفة الثالثة
-
المصادقة المجهولة: تستخدم
auth_level=func.AuthLevel.ANONYMOUSدوال HTTP ، لذا لا حاجة لمفاتيح الوظائف
يمكنك مراجعة مشروع القالب الكامل هنا.
-
تكامل OpenTelemetry: يقوم الملف
index.tsبتكوين OpenTelemetry مع مصدرات Azure Monitor للتتبع والسجلات - تسلسل الدوال: تستدعي الدالة الأولى الثانية باستخدام أكسيوس مع انتشار تلقائي للتتبع
- تكامل ناقل الخدمة: تخرج الدالة الثانية إلى ناقل الخدمة باستخدام روابط الإخراج، مما يؤدي إلى تفعيل الوظيفة الثالثة
- الهوية المدارة: جميع اتصالات ناقل الخدمة تستخدم الهوية المدارة بدلا من سلاسل الاتصال
- محاكاة المعالجة: يحاكي تأخير 5 ثوان في مشغل ناقل الخدمة عمل معالجة الرسائل
يمكنك مراجعة مشروع القالب الكامل هنا.
-
تكامل OpenTelemetry: يقوم الملف
Program.csبتكوين OpenTelemetry مع Azure Monitor exporter - تسلسل الدوال: تستدعي الدالة الأولى الثانية باستخدام HttpClient مع أجهزة OpenTelemetry
- تكامل ناقل الخدمة: تخرج الدالة الثانية إلى ناقل الخدمة باستخدام روابط الإخراج، مما يؤدي إلى تفعيل الوظيفة الثالثة
- الهوية المدارة: جميع اتصالات ناقل الخدمة تستخدم الهوية المدارة بدلا من سلاسل الاتصال
- .NET 8 Isolated Worker: يستخدم أحدث نموذج Azure Functions .NET Isolated Worker لتحقيق أداء ومرونة أفضل
يمكنك مراجعة مشروع القالب الكامل هنا.
بعد التحقق من وظائفك محليا، حان الوقت لنشرها على Azure.
نشر في Azure
تم تكوين هذا المشروع لاستخدام azd up الأمر لنشر هذا المشروع على تطبيق وظيفة جديد ضمن خطة استهلاك مرنة في Azure مع دعم OpenTelemetry.
تلميح
يشمل هذا المشروع مجموعة من ملفات Bicep التي azd تستخدم لإنشاء نشر آمن في خطة استهلاك مرنة تتبع أفضل الممارسات، بما في ذلك اتصالات الهوية المدارة.
قم بتشغيل هذا الأمر لإنشاء
azdموارد Azure المطلوبة في Azure ونشر مشروع التعليمات البرمجية إلى تطبيق الوظائف الجديد:azd upيحتوي المجلد الجذر على
azure.yamlملف التعريف المطلوب من قبلazd.إذا لم تكن مسجلا الدخول بالفعل، يطلب منك المصادقة باستخدام حساب Azure الخاص بك.
عند المطالبة، قم بتوفير معلمات النشر المطلوبة هذه:
المعلمة الوصف اشتراك Azure الاشتراك الذي يتم فيه إنشاء مواردك. موقع Azure منطقة Azure التي يتم فيها إنشاء مجموعة الموارد التي تحتوي على موارد Azure الجديدة. يتم عرض المناطق التي تدعم حاليا خطة استهلاك Flex فقط. azd upيستخدم الأمر استجابتك لهذه المطالبات مع ملفات تكوين Bicep لإكمال مهام النشر هذه:إنشاء وتكوين موارد Azure المطلوبة هذه (ما يعادل
azd provision):- خطة وتطبيق الاستهلاك المرن من Azure Functions مع تفعيل OpenTelemetry
- Azure Storage (مطلوب) وApplication Insights (مستحسن)
- مساحة أسماء ناقل الخدمة وقائمة الانتظار لعرض التتبع الموزع
- نهج الوصول والأدوار لحسابك
- اتصالات الخدمة إلى الخدمة باستخدام الهويات المدارة (بدلا من سلسلة الاتصال المخزنة)
قم بحزم التعليمات البرمجية ونشرها في حاوية التوزيع (ما يعادل
azd deploy). ثم يتم بدء تشغيل التطبيق وتشغيله في الحزمة المنشورة.
بعد اكتمال الأمر بنجاح، سترى ارتباطات إلى الموارد التي قمت بإنشائها.
التتبع الموزع للاختبار
الآن يمكنك اختبار وظيفة التتبع الموزع في OpenTelemetry عن طريق استدعاء الوظائف التي تم نشرها وملاحظة التتبع في Application Insights.
استدعاء الدالة في Azure
يمكنك استدعاء نقاط نهاية الوظائف في Azure عن طريق تقديم طلبات HTTP إلى عناوين URLها. نظرا لأن دوال HTTP في هذا القالب مهيأة بالوصول المجهول، فلا حاجة لمفاتيح الوظائف.
في طرفك المحلي أو موجه الأوامر، شغل هذا الأمر للحصول على اسم تطبيق الدالة وبناء الرابط:
APP_NAME=$(azd env get-value AZURE_FUNCTION_NAME) echo "Function URL: https://$APP_NAME.azurewebsites.net/api/first_http_function"azd env get-valueيحصل الأمر على اسم تطبيق الوظائف من البيئة المحلية.اختبر الوظيفة في متصفحك عن طريق التنقل إلى الرابط:
https://your-function-app.azurewebsites.net/api/first_http_functionاستبدل
your-function-appاسم تطبيق الوظيفة الفعلي من الخطوة السابقة. هذا الطلب الواحد ينشئ مسارا موزعا يمر عبر جميع الوظائف الثلاث.
عرض التتبع الموزع في Application Insights
بعد تفعيل الوظيفة، يمكنك ملاحظة التتبع الموزع الكامل في Application Insights:
ملاحظة
قد يستغرق الأمر بضع دقائق لظهور بيانات التليمترية في Application Insights بعد استدعاء وظيفتك. إذا لم تر البيانات فورا، انتظر بضع دقائق وقم بتحديث العرض.
اذهب إلى مورد Application Insights الخاص بك في بوابة Azure (يمكنك إيجاده في نفس مجموعة الموارد التي تستخدمها تطبيق الوظائف الخاص بك).
افتح خريطة التطبيق لرؤية التتبع الموزع عبر الوظائف الثلاث جميعها. يجب أن ترى التدفق من طلب HTTP عبر وظائفك وإلى ناقل الخدمة.
تحقق من بحث المعاملات للعثور على طلبك ورؤية الجدول الزمني الكامل للتتبع. ابحث عن المعاملات من تطبيق الوظيفة الخاص بك.
اختر معاملة محددة لرؤية التتبع من البداية إلى النهاية الذي يظهر:
- طلب HTTP إلى
first_http_function - استدعاء HTTP الداخلي إلى
second_http_function - رسالة حافلة الخدمة التي يتم إرسالها
- معالجة
servicebus_queue_triggerالرسالة من ناقل الخدمة
- طلب HTTP إلى
في تفاصيل الأثر، يمكنك أن ترى:
- معلومات التوقيت: كم من الوقت تستغرق كل خطوة
- التبعيات: الاتصالات بين الوظائف
- السجلات: سجلات التطبيقات مرتبطة بالتتبع
- مقاييس الأداء: أوقات الاستجابة وسرعة النقل
يوضح هذا المثال التتبع الموزع من طرف إلى طرف عبر عدة وظائف Azure مع تكامل OpenTelemetry، مما يوفر رؤية كاملة لسلوك وأداء تطبيقك.
إعادة نشر التعليمات البرمجية الخاصة بك
شغل azd up الأمر عدة مرات تحتاج لتوفير موارد Azure ونشر تحديثات الكود إلى تطبيق الوظائف الخاص بك.
ملاحظة
دائما ما تقوم حزمة النشر الأخيرة بكتابة ملفات الشيفرة المنشورة.
يتم تخزين استجاباتك الأولية للمطالبات azd وأي متغيرات بيئة تم إنشاؤها بواسطة azd محليا في البيئة المسماة. استخدم الأمر azd env get-values لمراجعة جميع المتغيرات في بيئتك التي يستخدمها الأمر عند إنشاء موارد Azure.
تنظيف الموارد
عندما تنتهي من العمل مع تطبيق الوظائف والموارد ذات الصلة، استخدم هذا الأمر لحذف تطبيق الوظائف وموارده ذات الصلة من Azure وتجنب تحمل أي تكاليف إضافية:
azd down --no-prompt
ملاحظة
يرشد --no-promptazd الخيار إلى حذف مجموعة الموارد الخاصة بك دون تأكيد منك.
لا يؤثر هذا الأمر على مشروع التعليمات البرمجية المحلية.