使用 Azure Functions 开发 C# 类库函数Develop C# class library functions using Azure Functions

本文介绍了如何在 .NET 类库中使用 C# 开发 Azure Functions。This article is an introduction to developing Azure Functions by using C# in .NET class libraries.


本文支持在进程内与运行时配合运行的 .NET 类库函数。This article supports .NET class library functions that run in-process with the runtime. Functions 还通过在进程外独立于运行时运行 C# 函数,来支持 .NET 1.5。Functions also supports .NET 5.x by running your C# functions out-of-process and isolated from the runtime. 有关详细信息,请参阅 .NET 隔离进程函数To learn more, see .NET isolated process functions.

作为 C# 开发人员,你可能还会对以下文章之一感兴趣:As a C# developer, you may also be interested in one of the following articles:

入门Getting started 概念Concepts 引导式学习/示例Guided learning/samples

Azure Functions 支持 C# 和 C# 脚本编程语言。Azure Functions supports C# and C# script programming languages. 如果要寻找有关在 Azure 门户中使用 C# 的指南,请参阅 C# 脚本 (.csx) 开发人员参考If you're looking for guidance on using C# in the Azure portal, see C# script (.csx) developer reference.

支持的版本Supported versions

Functions 运行时版本使用特定版本的 .NET。Versions of the Functions runtime work with specific versions of .NET. 若要详细了解 Functions 版本,请参阅 Azure Functions 运行时版本概述To learn more about Functions versions, see Azure Functions runtime versions overview

下表显示了可与特定版本的 Functions 配合使用的 .NET Core 或 .NET Framework 的最高级别。The following table shows the highest level of .NET Core or .NET Framework that can be used with a specific version of Functions.

Functions 运行时版本Functions runtime version 最大 .NET 版本Max .NET version
Functions 3.xFunctions 3.x .NET Core 3.1.NET Core 3.1
.NET 5.01.NET 5.01
Functions 2.xFunctions 2.x .NET Core 2.22.NET Core 2.22
Functions 1.xFunctions 1.x .NET Framework 4.7.NET Framework 4.7

1 必须在进程外运行。1 Must run out-of-process.
2 有关详细信息,请参阅 Functions v2.x 注意事项2 For details, see Functions v2.x considerations.

有关 Azure Functions 版本的最新消息,包括删除较旧的特定次要版本,请关注 Azure 应用服务公告For the latest news about Azure Functions releases, including the removal of specific older minor versions, monitor Azure App Service announcements.

Functions v2.x 注意事项Functions v2.x considerations

面向最新 2.x 版 (~2) 的函数应用将自动升级,以在 .NET Core 3.1 上运行。Function apps that target the latest 2.x version (~2) are automatically upgraded to run on .NET Core 3.1. 由于 .NET Core 版本之间存在中断性变更,因此,针对 .NET Core 2.2 开发和编译的所有应用并非都可以安全升级到 .NET Core 3.1。Because of breaking changes between .NET Core versions, not all apps developed and compiled against .NET Core 2.2 can be safely upgraded to .NET Core 3.1. 可以通过将函数应用固定为 ~2.0 来选择退出此升级。You can opt out of this upgrade by pinning your function app to ~2.0. Functions 还会检测不兼容的 API,并可将应用固定为 ~2.0,以防止在 .NET Core 3.1 上错误执行。Functions also detects incompatible APIs and may pin your app to ~2.0 to prevent incorrect execution on .NET Core 3.1.


如果函数应用已固定为 ~2.0,而你将此版本目标更改为 ~2,则函数应用可能会中断工作。If your function app is pinned to ~2.0 and you change this version target to ~2, your function app may break. 如果使用 ARM 模板进行部署,请检查模板中的版本。If you deploy using ARM templates, check the version in your templates. 如果发生这种情况,请改回版本以面向 ~2.0,并解决兼容性问题。If this occurs, change your version back to target ~2.0 and fix compatibility issues.

面向 ~2.0 的函数应用将继续在 .NET Core 2.2 上运行。Function apps that target ~2.0 continue to run on .NET Core 2.2. 此 .NET Core 版本不再接收安全更新和其他维护更新。This version of .NET Core no longer receives security and other maintenance updates. 有关详细信息,请参阅此公告页To learn more, see this announcement page.

应该尽快使函数与 .NET Core 3.1 兼容。You should work to make your functions compatible with .NET Core 3.1 as soon as possible. 解决这些问题后,将版本改回到 ~2 或升级到 ~3After you've resolved these issues, change your version back to ~2 or upgrade to ~3. 若要详细了解如何选择 Functions 运行时的目标版本,请参阅如何选择 Azure Functions 运行时的目标版本To learn more about targeting versions of the Functions runtime, see How to target Azure Functions runtime versions.

在 Linux 上的高级或专用(应用服务)计划中运行时,请通过将 linuxFxVersion 站点配置设置指定为 DOCKER|mcr.microsoft.com/azure-functions/dotnet:2.0.14786-appservice 来固定版本,而不要选择特定的映像作为目标。若要了解如何设置 linuxFxVersion,请参阅 Linux 上的手动版本更新When running on Linux in a Premium or dedicated (App Service) plan, you pin your version by instead targeting a specific image by setting the linuxFxVersion site config setting to DOCKER|mcr.microsoft.com/azure-functions/dotnet:2.0.14786-appservice To learn how to set linuxFxVersion, see Manual version updates on Linux.

Functions 类库项目Functions class library project

在 Visual Studio 中,Azure Functions 项目模板会创建一个 C# 类库项目,它包含以下文件:In Visual Studio, the Azure Functions project template creates a C# class library project that contains the following files:

  • host.json - 存储着在本地或者在 Azure 中运行时会影响项目中的所有函数的配置设置。host.json - stores configuration settings that affect all functions in the project when running locally or in Azure.
  • local.settings.json - 存储着在本地运行时使用的应用设置和连接字符串。local.settings.json - stores app settings and connection strings that are used when running locally. 此文件包含机密且不会发布到 Azure 中的函数应用中。This file contains secrets and isn't published to your function app in Azure. 而是,应将应用设置添加到函数应用Instead, add app settings to your function app.

生成项目时,在生成输出目录中生成如下例所示的文件夹结构:When you build the project, a folder structure that looks like the following example is generated in the build output directory:

 | - bin
 | - MyFirstFunction
 | | - function.json
 | - MySecondFunction
 | | - function.json
 | - host.json

部署到 Azure 中函数应用的正是此目录。This directory is what gets deployed to your function app in Azure. Functions 运行时 2.x 版 中所需的绑定扩展作为 NuGet 包添加到项目中The binding extensions required in version 2.x of the Functions runtime are added to the project as NuGet packages.


生成过程将为每个函数创建一个 function.json 文件。The build process creates a function.json file for each function. function.json 文件不应直接编辑。This function.json file is not meant to be edited directly. 无法通过编辑此文件来更改绑定配置或禁用函数。You can't change binding configuration or disable the function by editing this file. 要了解如何禁用函数,请参阅如何禁用函数To learn how to disable a function, see How to disable functions.

识别为函数的方法Methods recognized as functions

在类库中,函数是具有 FunctionName 和触发器属性的静态方法,如以下示例中所示:In a class library, a function is a static method with a FunctionName and a trigger attribute, as shown in the following example:

public static class SimpleExample
    public static void Run(
        [QueueTrigger("myqueue-items")] string myQueueItem, 
        ILogger log)
        log.LogInformation($"C# function processed: {myQueueItem}");

FunctionName 属性将该方法标记为函数入口点。The FunctionName attribute marks the method as a function entry point. 该名称在项目中必须是唯一的,以字母开头,并且只包含字母、数字、_-,长度不得超过 127 个字符。The name must be unique within a project, start with a letter and only contain letters, numbers, _, and -, up to 127 characters in length. 项目模板通常创建一个名为 Run 的方法,但方法名称可以是任何有效的 C# 方法名称。Project templates often create a method named Run, but the method name can be any valid C# method name.

触发器属性指定触发器类型并将输入数据绑定到一个方法参数。The trigger attribute specifies the trigger type and binds input data to a method parameter. 示例函数将由一条队列消息触发,并且队列消息将传递到该方法中的 myQueueItem 参数。The example function is triggered by a queue message, and the queue message is passed to the method in the myQueueItem parameter.

方法签名参数Method signature parameters

方法签名可能包含不与触发器属性一起使用的参数。The method signature may contain parameters other than the one used with the trigger attribute. 下面是可以包含的其他一些参数:Here are some of the other parameters that you can include:

函数签名中的参数顺序并不重要。The order of parameters in the function signature doesn't matter. 例如,可以在其他绑定之前或之后放置触发器参数,也可以在触发器或绑定参数之前或之后添加记录器参数。For example, you can put trigger parameters before or after other bindings, and you can put the logger parameter before or after trigger or binding parameters.

输出绑定Output bindings

一个函数可以有零个或一个使用输出参数定义的输出绑定。A function can have zero or one output bindings defined by using output parameters.

以下示例对上一个示例进行了修改,其中添加了一个名为 myQueueItemCopy 的输出队列绑定。The following example modifies the preceding one by adding an output queue binding named myQueueItemCopy. 该函数将触发函数的消息内容写入到另一个队列中的新消息。The function writes the contents of the message that triggers the function to a new message in a different queue.

public static class SimpleExampleWithOutput
    public static void Run(
        [QueueTrigger("myqueue-items-source")] string myQueueItem, 
        [Queue("myqueue-items-destination")] out string myQueueItemCopy,
        ILogger log)
        log.LogInformation($"CopyQueueMessage function processed: {myQueueItem}");
        myQueueItemCopy = myQueueItem;

该函数退出时,将写入分配给输出绑定的值。Values assigned to output bindings are written when the function exits. 只需将值分配给多个输出参数,即可在一个函数中使用多个输出绑定。You can use more than one output binding in a function by simply assigning values to multiple output parameters.

绑定参考文章(例如,存储队列)说明了可用于触发器、输入或输出绑定特性的参数类型。The binding reference articles (Storage queues, for example) explain which parameter types you can use with trigger, input, or output binding attributes.

绑定表达式示例Binding expressions example

以下代码从应用设置中获取要监视的队列的名称,并在 insertionTime 参数中获取队列消息创建时间。The following code gets the name of the queue to monitor from an app setting, and it gets the queue message creation time in the insertionTime parameter.

public static class BindingExpressionsExample
    public static void Run(
        [QueueTrigger("%queueappsetting%")] string myQueueItem,
        DateTimeOffset insertionTime,
        ILogger log)
        log.LogInformation($"Message content: {myQueueItem}");
        log.LogInformation($"Created at: {insertionTime}");

自动生成的 function.jsonAutogenerated function.json

生成过程会在生成文件中的一个函数文件夹中创建一个 function.json 文件。The build process creates a function.json file in a function folder in the build folder. 如前所述,此文件不应直接编辑。As noted earlier, this file is not meant to be edited directly. 无法通过编辑此文件来更改绑定配置或禁用函数。You can't change binding configuration or disable the function by editing this file.

此文件的用途是向缩放控制器提供用于对消耗计划做出缩放决策的信息。The purpose of this file is to provide information to the scale controller to use for scaling decisions on the Consumption plan. 因此,该文件仅包含触发器信息,而不包含输入/输出绑定。For this reason, the file only has trigger info, not input/output bindings.

生成的 function.json 文件包括一个 configurationSource 属性,该属性告诉运行时使用 .NET 属性进行绑定,而不是使用 function.json 配置。The generated function.json file includes a configurationSource property that tells the runtime to use .NET attributes for bindings, rather than function.json configuration. 下面是一个示例:Here's an example:

  "generatedBy": "Microsoft.NET.Sdk.Functions-",
  "configurationSource": "attributes",
  "bindings": [
      "type": "queueTrigger",
      "queueName": "%input-queue-name%",
      "name": "myQueueItem"
  "disabled": false,
  "scriptFile": "..\\bin\\FunctionApp1.dll",
  "entryPoint": "FunctionApp1.QueueTrigger.Run"


function.json 文件生成是由 NuGet 包 Microsoft.NET.Sdk.Functions 生成的。The function.json file generation is performed by the NuGet package Microsoft.NET.Sdk.Functions.

Functions 运行时的 1.x 版本和 2.x 版本使用相同的包。The same package is used for both version 1.x and 2.x of the Functions runtime. 1.x 项目和 2.x 项目的不同之处在于目标框架。The target framework is what differentiates a 1.x project from a 2.x project. 下面是 .csproj 文件的相关部分,其中显示了包含相同 Sdk 包的不同目标框架:Here are the relevant parts of .csproj files, showing different target frameworks with the same Sdk package:

  <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="1.0.8" />

Sdk 包的依赖关系是触发器和绑定。Among the Sdk package dependencies are triggers and bindings. 1.x 项目是指 1.x 触发器和绑定,因为这些触发器和绑定面向 .NET Framework,而 2.x 触发器和绑定面向 .NET Core。A 1.x project refers to 1.x triggers and bindings because those triggers and bindings target the .NET Framework, while 2.x triggers and bindings target .NET Core.

Sdk 包也依赖于 Newtonsoft.Json,并间接依赖于 WindowsAzure.StorageThe Sdk package also depends on Newtonsoft.Json, and indirectly on WindowsAzure.Storage. 这些依赖关系确保项目使用的包版本与项目面向的 Functions 运行时版本兼容。These dependencies make sure that your project uses the versions of those packages that work with the Functions runtime version that the project targets. 例如,Newtonsoft.Json 的 11 版可用于 .NET Framework 4.6.1,但面向 .NET Framework 4.6.1 的 Functions 运行时仅与 Newtonsoft.Json 9.0.1 兼容。For example, Newtonsoft.Json has version 11 for .NET Framework 4.6.1, but the Functions runtime that targets .NET Framework 4.6.1 is only compatible with Newtonsoft.Json 9.0.1. 因此该项目中的函数代码也只能使用 Newtonsoft.Json 9.0.1。So your function code in that project also has to use Newtonsoft.Json 9.0.1.

GitHub 存储库 azure-functions-vs-build-sdk 中提供了适用于 Microsoft.NET.Sdk.Functions 的源代码。The source code for Microsoft.NET.Sdk.Functions is available in the GitHub repo azure-functions-vs-build-sdk.

运行时版本Runtime version

Visual Studio 使用 Azure Functions Core Tools 运行 Functions 项目。Visual Studio uses the Azure Functions Core Tools to run Functions projects. Core Tools 是适用于 Functions 运行时的命令行接口。The Core Tools is a command-line interface for the Functions runtime.

如果使用 npm 安装 Core Tools,则不会影响 Visual Studio 使用的 Core Tools 版本。If you install the Core Tools by using npm, that doesn't affect the Core Tools version used by Visual Studio. 对于 Functions 运行时版本 1.x,Visual Studio 在 %USERPROFILE%\AppData\Local\Azure.Functions.Cli 中存储 Core Tools 版本且存储最新版本 。For the Functions runtime version 1.x, Visual Studio stores Core Tools versions in %USERPROFILE%\AppData\Local\Azure.Functions.Cli and uses the latest version stored there. 对于 Functions 2.x,Core Tools 包含在 Azure Functions 和 Web Jobs Tools 扩展中 。For Functions 2.x, the Core Tools are included in the Azure Functions and Web Jobs Tools extension. 对于 1.x 和 2.x,运行 Functions 项目时可以看到控制台输出中正在使用何种版本:For both 1.x and 2.x, you can see what version is being used in the console output when you run a Functions project:

[3/1/2018 9:59:53 AM] Starting Host (HostId=contoso2-1518597420, Version=2.0.11353.0, ProcessId=22020, Debug=False, Attempt=0, FunctionsExtensionVersion=)


可以将函数应用编译为 ReadyToRun 二进制文件You can compile your function app as ReadyToRun binaries. ReadyToRun 是一种预先编译形式,可以提高启动性能,帮助降低在消耗计划中运行时的冷启动的影响。ReadyToRun is a form of ahead-of-time compilation that can improve startup performance to help reduce the impact of cold-start when running in a Consumption plan.

ReadyToRun 在 .NET 3.0 中提供,并且需要 Azure Functions 运行时版本 3.0ReadyToRun is available in .NET 3.0 and requires version 3.0 of the Azure Functions runtime.

若要将项目编译为 ReadyToRun,请通过添加 <PublishReadyToRun><RuntimeIdentifier> 元素来更新项目文件。To compile your project as ReadyToRun, update your project file by adding the <PublishReadyToRun> and <RuntimeIdentifier> elements. 以下是用于发布到 Windows 32 位函数应用的配置。The following is the configuration for publishing to a Windows 32-bit function app.



ReadyToRun 目前不支持交叉编译。ReadyToRun currently doesn't support cross-compilation. 必须在与部署目标相同的平台上生成应用。You must build your app on the same platform as the deployment target. 此外,请注意函数应用中配置的“位数”。Also, pay attention to the "bitness" that is configured in your function app. 例如,如果 Azure 中的函数应用为 Windows 64 位,则在 Windows 上编译应用时必须使用 win-x64 作为运行时标识符For example, if your function app in Azure is Windows 64-bit, you must compile your app on Windows with win-x64 as the runtime identifier.

也可以通过命令行使用 ReadyToRun 生成应用。You can also build your app with ReadyToRun from the command line. 有关详细信息,请参阅 dotnet publish 中的 -p:PublishReadyToRun=true 选项。For more information, see the -p:PublishReadyToRun=true option in dotnet publish.

绑定支持的类型Supported types for bindings

每个绑定都具有其自己支持的类型;例如,blob 触发器属性可以应用于字符串参数、POCO 参数、CloudBlockBlob 参数或任何其他几种受支持的类型之一。Each binding has its own supported types; for instance, a blob trigger attribute can be applied to a string parameter, a POCO parameter, a CloudBlockBlob parameter, or any of several other supported types. 适用于 blob 绑定的绑定参考文章列出了所有受支持的参数类型。The binding reference article for blob bindings lists all supported parameter types. 有关详细信息,请参阅触发器和绑定每个绑定类型的绑定参考文档For more information, see Triggers and bindings and the binding reference docs for each binding type.


如果计划使用 HTTP 或 WebHook 绑定,请制定计划来避免因实例化 HttpClient 不当导致的端口耗尽现象。If you plan to use the HTTP or WebHook bindings, plan to avoid port exhaustion that can be caused by improper instantiation of HttpClient. 有关详细信息,请参阅如何在 Azure Functions 中管理连接For more information, see How to manage connections in Azure Functions.

绑定到方法返回值Binding to method return value

通过将属性应用于方法返回值,可以对输出绑定使用方法返回值。You can use a method return value for an output binding, by applying the attribute to the method return value. 有关示例,请参阅触发器和绑定For examples, see Triggers and bindings.

仅当成功的函数执行始终将返回值传递给输出绑定时,才使用返回值。Use the return value only if a successful function execution always results in a return value to pass to the output binding. 否则,请使用 ICollectorIAsyncCollector,如以下部分所示。Otherwise, use ICollector or IAsyncCollector, as shown in the following section.

写入多个输出值Writing multiple output values

若要将多个值写入输出绑定,或者如果成功的函数调用可能无法将任何内容传递给输出绑定,请使用 ICollectorIAsyncCollector 类型。To write multiple values to an output binding, or if a successful function invocation might not result in anything to pass to the output binding, use the ICollector or IAsyncCollector types. 这些类型是只写集合,当方法完成时写入输出绑定。These types are write-only collections that are written to the output binding when the method completes.

此示例使用 ICollector 将多个队列消息写入到同一队列:This example writes multiple queue messages into the same queue using ICollector:

public static class ICollectorExample
    public static void Run(
        [QueueTrigger("myqueue-items-source-3")] string myQueueItem,
        [Queue("myqueue-items-destination")] ICollector<string> myDestinationQueue,
        ILogger log)
        log.LogInformation($"C# function processed: {myQueueItem}");
        myDestinationQueue.Add($"Copy 1: {myQueueItem}");
        myDestinationQueue.Add($"Copy 2: {myQueueItem}");


要使函数异步,请使用 async 关键字并返回 Task 对象。To make a function asynchronous, use the async keyword and return a Task object.

public static class AsyncExample
    public static async Task RunAsync(
        [BlobTrigger("sample-images/{blobName}")] Stream blobInput,
        [Blob("sample-images-copies/{blobName}", FileAccess.Write)] Stream blobOutput,
        CancellationToken token,
        ILogger log)
        log.LogInformation($"BlobCopy function processed.");
        await blobInput.CopyToAsync(blobOutput, 4096, token);

不能在异步函数中使用 out 参数。You can't use out parameters in async functions. 对于输出绑定,请改用函数返回值收集器对象For output bindings, use the function return value or a collector object instead.

取消令牌Cancellation tokens

函数可以接受 CancellationToken 参数,以使操作系统能够在函数即将终止时通知代码。A function can accept a CancellationToken parameter, which enables the operating system to notify your code when the function is about to be terminated. 可以使用此通知来确保该函数不会意外终止,导致数据处于不一致状态。You can use this notification to make sure the function doesn't terminate unexpectedly in a way that leaves data in an inconsistent state.

下面的示例演示了如何检查即将发生的函数终止。The following example shows how to check for impending function termination.

public static class CancellationTokenExample
    public static void Run(
        [QueueTrigger("inputqueue")] string inputText,
        TextWriter logger,
        CancellationToken token)
        for (int i = 0; i < 100; i++)
            if (token.IsCancellationRequested)
                logger.WriteLine("Function was cancelled at iteration {0}", i);
            logger.WriteLine("Normal processing for queue message={0}", inputText);


在函数代码中,可以将输出写入日志,这些日志在 Application Insights 中显示为跟踪。In your function code, you can write output to logs that appear as traces in Application Insights. 若要将内容写入日志,建议的方法是包括一个 ILogger 类型的参数(通常名为 log)。The recommended way to write to the logs is to include a parameter of type ILogger, which is typically named log. Functions 运行时的版本 1.x 使用了 TraceWriter,后者也将内容写入 Application Insights,但不支持结构化日志记录。Version 1.x of the Functions runtime used TraceWriter, which also writes to Application Insights, but doesn't support structured logging. 不要使用 Console.Write 来写入日志,因为 Application Insights 不会捕获此数据。Don't use Console.Write to write your logs, since this data isn't captured by Application Insights.


在函数定义中包括一个 ILogger 参数,该参数支持结构化日志记录In your function definition, include an ILogger parameter, which supports structured logging.

使用 ILogger 对象,可以调用 ILogger 上的 Log<level> 扩展方法来创建日志。With an ILogger object, you call Log<level> extension methods on ILogger to create logs. 以下代码会写入类别为“Function.<YOUR_FUNCTION_NAME>.User.”的 Information 日志:The following code writes Information logs with category Function.<YOUR_FUNCTION_NAME>.User.:

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, ILogger logger)
    logger.LogInformation("Request for item with key={itemKey}.", id);

若要详细了解 Functions 如何实现 ILogger,请参阅收集遥测数据To learn more about how Functions implements ILogger, see Collecting telemetry data. Function 为前缀的类别假定你使用的是 ILogger 实例。Categories prefixed with Function assume you are using an ILogger instance. 如果选择改用 ILogger<T>,则类别名称可能改为基于 TIf you choose to instead use an ILogger<T>, the category name may instead be based on T.

结构化日志记录Structured logging

占位符的顺序(而不是其名称)确定日志消息中使用的参数。The order of placeholders, not their names, determines which parameters are used in the log message. 假设有以下代码:Suppose you have the following code:

string partitionKey = "partitionKey";
string rowKey = "rowKey";
logger.LogInformation("partitionKey={partitionKey}, rowKey={rowKey}", partitionKey, rowKey);

如果保留相同的消息字符串并颠倒参数的顺序,则生成的消息文本将在错误的位置生成值。If you keep the same message string and reverse the order of the parameters, the resulting message text would have the values in the wrong places.

以这种方式处理占位符,以便可以执行结构化日志记录。Placeholders are handled this way so that you can do structured logging. Application Insights 存储参数名称值对和消息字符串。Application Insights stores the parameter name-value pairs and the message string. 结果是消息参数变为可以查询的字段。The result is that the message arguments become fields that you can query on.

如果记录器方法调用类似于前面的示例,则可以查询字段 customDimensions.prop__rowKeyIf your logger method call looks like the previous example, you can query the field customDimensions.prop__rowKey. 添加 prop__ 前缀以确保运行时添加的字段和函数代码添加的字段之间没有冲突。The prop__ prefix is added to ensure there are no collisions between fields the runtime adds and fields your function code adds.

此外,可以通过引用字段 customDimensions.prop__{OriginalFormat} 查询原始消息字符串。You can also query on the original message string by referencing the field customDimensions.prop__{OriginalFormat}.

下面是 customDimensions 数据的示例 JSON 表示形式:Here's a sample JSON representation of customDimensions data:

  "customDimensions": {
    "prop__{OriginalFormat}":"C# Queue trigger function processed: {message}",

记录自定义遥测数据Log custom telemetry

Functions 特定版本的 Application Insights SDK 可用于将自定义遥测数据从函数发送到 Application Insights:Microsoft.Azure.WebJobs.Logging.ApplicationInsightsThere is a Functions-specific version of the Application Insights SDK that you can use to send custom telemetry data from your functions to Application Insights: Microsoft.Azure.WebJobs.Logging.ApplicationInsights. 在命令提示符中使用以下命令来安装此包:Use the following command from the command prompt to install this package:

dotnet add package Microsoft.Azure.WebJobs.Logging.ApplicationInsights --version <VERSION>

在此命令中,将 <VERSION> 替换为此包的版本,该版本支持 Microsoft.Azure.WebJobs 的已安装版本。In this command, replace <VERSION> with a version of this package that supports your installed version of Microsoft.Azure.WebJobs.

以下 C# 示例使用自定义遥测 APIThe following C# examples uses the custom telemetry API. 示例针对的是 .NET 类库,但对于 C# 脚本,Application Insights 代码是相同的。The example is for a .NET class library, but the Application Insights code is the same for C# script.

版本 2.x 和更高版本运行时使用 Application Insights 中的较新功能自动将遥测与当前操作进行关联。Version 2.x and later versions of the runtime use newer features in Application Insights to automatically correlate telemetry with the current operation. 不需要手动设置操作 IdParentIdName 字段。There's no need to manually set the operation Id, ParentId, or Name fields.

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;

using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.Extensibility;
using System.Linq;

namespace functionapp0915
    public class HttpTrigger2
        private readonly TelemetryClient telemetryClient;

        /// Using dependency injection will guarantee that you use the same configuration for telemetry collected automatically and manually.
        public HttpTrigger2(TelemetryConfiguration telemetryConfiguration)
            this.telemetryClient = new TelemetryClient(telemetryConfiguration);

        public Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)]
            HttpRequest req, ExecutionContext context, ILogger log)
            log.LogInformation("C# HTTP trigger function processed a request.");
            DateTime start = DateTime.UtcNow;

            // Parse query parameter
            string name = req.Query
                .FirstOrDefault(q => string.Compare(q.Key, "name", true) == 0)

            // Write an event to the customEvents table.
            var evt = new EventTelemetry("Function called");
            evt.Context.User.Id = name;

            // Generate a custom metric, in this case let's use ContentLength.

            // Log a custom dependency in the dependencies table.
            var dependency = new DependencyTelemetry
                Name = "GET api/planets/1/",
                Target = "swapi.co",
                Data = "https://swapi.co/api/planets/1/",
                Timestamp = start,
                Duration = DateTime.UtcNow - start,
                Success = true
            dependency.Context.User.Id = name;

            return Task.FromResult<IActionResult>(new OkResult());

在此示例中,自定义指标数据在发送到 customMetrics 表之前由主机聚合。In this example, the custom metric data gets aggregated by the host before being sent to the customMetrics table. 若要了解详细信息,请参阅 Application Insights 中的 GetMetric 文档。To learn more, see the GetMetric documentation in Application Insights.

在本地运行时,必须使用 Application Insights 键将 APPINSIGHTS_INSTRUMENTATIONKEY 设置添加到 local.settings.json 文件中。When running locally, you must add the APPINSIGHTS_INSTRUMENTATIONKEY setting, with the Application Insights key, to the local.settings.json file.

请勿调用 TrackRequestStartOperation<RequestTelemetry>,因为将显示函数调用的重复请求。Don't call TrackRequest or StartOperation<RequestTelemetry> because you'll see duplicate requests for a function invocation. Functions 运行时自动跟踪请求。The Functions runtime automatically tracks requests.

不要设置 telemetryClient.Context.Operation.IdDon't set telemetryClient.Context.Operation.Id. 当多个函数同时运行时,这种全局设置会导致不正确的关联。This global setting causes incorrect correlation when many functions are running simultaneously. 请改为创建新的遥测实例(DependencyTelemetryEventTelemetry)并修改其 Context 属性。Instead, create a new telemetry instance (DependencyTelemetry, EventTelemetry) and modify its Context property. 然后将遥测实例传入到 TelemetryClient 的相应 Track 方法(TrackDependency()TrackEvent()TrackMetric())。Then pass in the telemetry instance to the corresponding Track method on TelemetryClient (TrackDependency(), TrackEvent(), TrackMetric()). 此方法可确保遥测具有当前函数调用的正确关联详细信息。This method ensures that the telemetry has the correct correlation details for the current function invocation.

环境变量Environment variables

若要获取环境变量或应用设置值,请使用 System.Environment.GetEnvironmentVariable,如以下代码示例所示:To get an environment variable or an app setting value, use System.Environment.GetEnvironmentVariable, as shown in the following code example:

public static class EnvironmentVariablesExample
    public static void Run([TimerTrigger("0 */5 * * * *")]TimerInfo myTimer, ILogger log)
        log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");

    private static string GetEnvironmentVariable(string name)
        return name + ": " +
            System.Environment.GetEnvironmentVariable(name, EnvironmentVariableTarget.Process);

在本地开发和在 Azure 中运行时,都可以从环境变量读取应用设置。App settings can be read from environment variables both when developing locally and when running in Azure. 在本地开发时,应用设置来自 local.settings.json 文件中的 Values 集合。When developing locally, app settings come from the Values collection in the local.settings.json file. 在这两个环境(本地和 Azure)中,GetEnvironmentVariable("<app setting name>") 都会检索命名应用设置的值。In both environments, local and Azure, GetEnvironmentVariable("<app setting name>") retrieves the value of the named app setting. 例如,在本地运行时,如果 local.settings.json 文件包含 { "Values": { "WEBSITE_SITE_NAME": "My Site Name" } },则会返回“My Site Name”。For instance, when you're running locally, "My Site Name" would be returned if your local.settings.json file contains { "Values": { "WEBSITE_SITE_NAME": "My Site Name" } }.

System.Configuration.ConfigurationManager.AppSettings 属性是用于获取应用设置值的替代 API,但我们建议你使用 GetEnvironmentVariable,如下所示。The System.Configuration.ConfigurationManager.AppSettings property is an alternative API for getting app setting values, but we recommend that you use GetEnvironmentVariable as shown here.

在运行时绑定Binding at runtime

在 C# 和其他 .NET 语言中,可以使用 imperative 绑定模式,而不是在属性中使用声明性绑定。In C# and other .NET languages, you can use an imperative binding pattern, as opposed to the declarative bindings in attributes. 当绑定参数需要在运行时(而非在设计时)计算时,命令性绑定很有用。Imperative binding is useful when binding parameters need to be computed at runtime rather than design time. 通过此模式,可以在函数代码中动态绑定到受支持的输入和输出绑定。With this pattern, you can bind to supported input and output bindings on-the-fly in your function code.

如下所示定义命令性绑定:Define an imperative binding as follows:

  • 不要 在函数签名中包括用于所需的命令性绑定的属性。Do not include an attribute in the function signature for your desired imperative bindings.

  • 传递输入参数 Binder binderIBinder binderPass in an input parameter Binder binder or IBinder binder.

  • 使用下面的 C# 模式执行数据绑定。Use the following C# pattern to perform the data binding.

    using (var output = await binder.BindAsync<T>(new BindingTypeAttribute(...)))

    BindingTypeAttribute 是定义了绑定的 .NET 属性,T 是该绑定类型所支持的输入或输出类型。BindingTypeAttribute is the .NET attribute that defines your binding, and T is an input or output type that's supported by that binding type. T 不能是 out 参数类型(例如 out JObject)。T cannot be an out parameter type (such as out JObject). 例如,移动应用表输出绑定支持六种输出类型,但对于命令性绑定,仅可使用 ICollector<T>IAsyncCollector<T>For example, the Mobile Apps table output binding supports six output types, but you can only use ICollector<T> or IAsyncCollector<T> with imperative binding.

单属性示例Single attribute example

下面的示例代码使用在运行时定义的 blob 路径创建存储 blob 输出绑定,然后将字符串写入此 blob。The following example code creates a Storage blob output binding with blob path that's defined at run time, then writes a string to the blob.

public static class IBinderExample
    public static void Run(
        [QueueTrigger("myqueue-items-source-4")] string myQueueItem,
        IBinder binder,
        ILogger log)
        log.LogInformation($"CreateBlobUsingBinder function processed: {myQueueItem}");
        using (var writer = binder.Bind<TextWriter>(new BlobAttribute(
                    $"samples-output/{myQueueItem}", FileAccess.Write)))
            writer.Write("Hello World!");

BlobAttribute 定义存储 blob 输入或输出绑定,TextWriter 是支持的输出绑定类型。BlobAttribute defines the Storage blob input or output binding, and TextWriter is a supported output binding type.

多属性示例Multiple attributes example

上一个示例获取函数应用的主存储帐户连接字符串(即 AzureWebJobsStorage)的应用设置。The preceding example gets the app setting for the function app's main Storage account connection string (which is AzureWebJobsStorage). 通过添加 StorageAccountAttribute 和将属性数组传入 BindAsync<T>(),可指定要用于存储帐户的自定义应用设置。You can specify a custom app setting to use for the Storage account by adding the StorageAccountAttribute and passing the attribute array into BindAsync<T>(). 使用一个 Binder 参数而非 IBinderUse a Binder parameter, not IBinder. 例如:For example:

public static class IBinderExampleMultipleAttributes
    public async static Task RunAsync(
            [QueueTrigger("myqueue-items-source-binder2")] string myQueueItem,
            Binder binder,
            ILogger log)
        log.LogInformation($"CreateBlobInDifferentStorageAccount function processed: {myQueueItem}");
        var attributes = new Attribute[]
        new BlobAttribute($"samples-output/{myQueueItem}", FileAccess.Write),
        new StorageAccountAttribute("MyStorageAccount")
        using (var writer = await binder.BindAsync<TextWriter>(attributes))
            await writer.WriteAsync("Hello World!!");

触发器和绑定Triggers and bindings

下表显示了 Azure Functions 运行时的主版本支持的绑定:This table shows the bindings that are supported in the major versions of the Azure Functions runtime:

类型Type 1.x1.x 2.x 及更高版本12.x and higher1 触发器Trigger 输入Input 输出Output
Blob 存储Blob storage
Azure Cosmos DBAzure Cosmos DB
事件网格Event Grid
事件中心Event Hubs
HTTP 和 WebhookHTTP & webhooks
IoT 中心IoT Hub
移动应用Mobile Apps
通知中心Notification Hubs
队列存储Queue storage
服务总线Service Bus
表存储Table storage

1 从版本 2.x 运行时开始,除了 HTTP 和 Timer 以外,所有绑定都必须注册。1 Starting with the version 2.x runtime, all bindings except HTTP and Timer must be registered. 请参阅注册绑定扩展See Register binding extensions.

2 消耗计划中不支持触发器。2 Triggers aren't supported in the Consumption plan. 需要运行时驱动的触发器Requires runtime-driven triggers.

3 仅支持 Kubernetes、IoT Edge 和其他自托管模式。3 Supported only in Kubernetes, IoT Edge, and other self-hosted modes only.

后续步骤Next steps