I am trying to use Azure function with to invoke the same function with different time and different param(url).
I didn't find any good example that shows how to pass some data. I want to pass link to function.
My code is:
var rp = require('request-promise');
var request = require('request');
module.exports = function (context //need to get the url) {
and the function
{
"bindings": [
{
"name": "myTimer",
"type": "timerTrigger",
"direction": "in",
"schedule": "0 0 */1 * * *"
}
],
"disabled": false
}
If your settings are relatively static (but you still don't want to hard code them), you may use app settings to store them, and then read e.g.
let url = process.env['MyUrl'];
If URL should be determined per request, you may use HTTP trigger and read the URL from query parameters:
let url = req.query.myurl;
I'm not sure what exactly you are trying to achieve with parameterized timer-triggered function.
Another possibility is if your parameters are stored somewhere in e.g. Azure Document DB (Cosmos).
You could still use a TimerTrigger to invoke the function, and include a DocumentDB input binding allowing you to query for the specific parameter values needed to execute the function.
Here's a C# example triggered by Timer, with a DocumentDB input binding. Note: I'm using the latest VS2017 Preview tooling for Azure functions.
[FunctionName("TimerTriggerCSharp")]
public static void Run(
[TimerTrigger("0 */1 * * * *")]TimerInfo myTimer, TraceWriter log,
[DocumentDB("test-db-dev", "TestingCollection", SqlQuery = "select * from c where c.doc = \"Test\"")] IEnumerable<dynamic> incomingDocuments)
{..}
With the following binding json:
{
"bindings": [
{
"name": "myTimer",
"type": "timerTrigger",
"direction": "in",
"schedule": "0 */5 * * * *"
},
{
"type": "documentDB",
"name": "incomingDocuments",
"databaseName": "test-db-dev",
"collectionName": "TestingCollection",
"sqlQuery": "select * from c where c.docType = \"Test\"",
"connection": "my-testing_DOCUMENTDB",
"direction": "in"
}
],
"disabled": false
}
Related
I have an Azure Function with a Timer trigger. The schedule is "*/6 * * * *" (running every six minutes). I cannot run it manually and it does not fire automatically. Below is my function.json:
{
"generatedBy": "Microsoft.NET.Sdk.Functions-1.0.31",
"configurationSource": "attributes",
"bindings": [
{
"type": "timerTrigger",
"schedule": "%TimerTriggerPeriod%",
"useMonitor": true,
"runOnStartup": false,
"name": "myTimer"
}
],
"disabled": false,
"scriptFile": "../bin/AccessChangeMonitoring.dll",
"entryPoint": "Microsoft.IT.Security.AccessChangeMonitoring.AccessChangeMonitoring.InitiateChangeMonitoring"
}
%TimerTriggerPeriod% is defined in my local.settings.json file ("TimerTriggerPeriod": "0 */6 * * * *"). Looking at the Application Function Count metric display on the dashboard, it shows that my function has been executed 0 times:
Below is my host.json:
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingExcludedTypes": "Request",
"samplingSettings": {
"isEnabled": true
}
}
},
"functionTimeout": "00:07:00"
}
Below is the function code:
[FunctionName("InitiateChangeMonitoring")]
public static async Task InitiateChangeMonitoring([TimerTrigger("%TimerTriggerPeriod%")] TimerInfo myTimer, ILogger log)
{
log.LogInformation("Change Monitoring started.");
// Reset the listing of app ids we need to retrieve delta role assignments for
oneAuthZAppIds = new List<string>();
await GetOneAuthZAppIdsAsync();
// Create the necessary Cosmos DB infastructure
await CreateDatabaseAsync();
await CreateContainerAsync();
await CreateDeltaAPICallDatabaseAsync();
await CreateDeltaAPICallContainerAsync();
await CreateManagerMappingDatabaseAsync();
await CreateManagerMappingContainerAsync();
// Compute the authentication token needed to access the PAP Service API
log.LogInformation("\nRetrieve PAPServiceAPIToken");
string PAPServiceAPIToken = await GetTokenAsync(Environment.GetEnvironmentVariable("OneAuthZAppUri"), Environment.GetEnvironmentVariable("OneAuthZAppId"),
PAPAuthenticationSecret);
log.LogInformation("PAPServiceAPIToken = " + PAPServiceAPIToken);
string GraphAPIAuthenticationToken = await GetTokenAsync(Environment.GetEnvironmentVariable("GraphAppUri"), Environment.GetEnvironmentVariable("GraphClientId"),
graphKey);
log.LogInformation("graphAPIAuthenticationToken = " + GraphAPIAuthenticationToken);
await runChangeMonitoringSystemAsync(PAPServiceAPIToken);
}
First, I notice you specify you are using local.settings.json to save the environment variable and at the same time you show the metric on azure.
So, I think the first problem why your azure function can not be triggered is because you don't set the environment variable on azure.
You should set in this place instead of local.settings.json (because when a function is deployed to Azure, it will never take environment variable from local.settings.json):
(Don't forget to save the edit.)
Second, as Ivan says, your format of cron is wrong. The format of timetrigger should be in this format:
{second} {minute} {hour} {day} {month} {day of week}
I have an Azure-Function with the following configuration
{
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"type": "cosmosDB",
"name": "inputDocument",
"databaseName": "MeasureInputData",
"collectionName": "hubs",
"connectionStringSetting": "measure-cosmosdb_DOCUMENTDB",
"direction": "in",
"sqlQuery": "SELECT * FROM c WHERE c.uuid = {hub}"
}
],
"disabled": false
}
As you can see above, I have the {hub} in the sqlQuery passed as a url parameter.
Doing a request like
https://<my-function-url>?code=<my-function-key>&hub=<my-hub-id>
returns the matching hub.
If leaving the value <my-hub-id> empty
https://<my-function-url>?code=<my-function-key>&hub=
returns an empty object.
The issue is when I donĀ“t provide the hub parameter in the URL the function crashes.
https://<my-function-url>?code=<my-function-key>
requesting the above returns http status code 500
Shouldn't missing query parameters be handled in some way?
Thanks
It seems the sql will be
SELECT * FROM c WHERE c.uuid =
but not
SELECT * FROM c WHERE c.uuid = "" or SELECT * FROM c WHERE c.uuid = null
when the parameter "hub" missing.
Azure function cosmos db binding will not handle the missing parameter in query. If you want to handle this error, I think we can create another api or function and put(call) the original function url in this new api/function. Then we can handle this error in the new api/function.
If you hope azure function to add this feature, you can raise your idea to the azure function feedback page.
No, you should handled that. If you check the hello world sample:
[FunctionName("HttpTriggerCSharp")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
HttpRequest req, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string name = req.Query["name"];
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
name = name ?? data?.name;
return name != null
? (ActionResult)new OkObjectResult($"Hello, {name}")
: new BadRequestObjectResult("Please pass a name on the query string or in the request body");
}
It tries to read value from query string and from body. In case it's null, it will return
new BadRequestObjectResult("Please pass a name on the query string or in the request body")
so you should do the same, in case there's no hub provided in the querystring, return 400 (bad request)
I have the following C# function code:
[FunctionName("UpdateCohortsByTenantFunction")]
[return: Queue("my-queue", Connection = "MyStorage")]
//note - I have tried both method decoration and parameter decoration
public static async Task Run([TimerTrigger("* * * * * *")]TimerInfo myTimer, IAsyncCollector<AudienceMessage> output)
{
//some logic
foreach (var audience in audiences)
{
await output.AddAsync(new AudienceMessage
{
AudienceId = audience.Id,
TenantId = tenant.Id
});
}
}
Which produces the following function.json:
{
"generatedBy": "Microsoft.NET.Sdk.Functions.Generator-1.0.6",
"configurationSource": "attributes",
"bindings": [
{
"type": "timerTrigger",
"schedule": "* * * * * *",
"useMonitor": true,
"runOnStartup": false,
"name": "myTimer"
}
],
"disabled": false,
"scriptFile": "../bin/MyApp.App.Tasks.Functions.dll",
"entryPoint": "MyApp.App.Tasks.Functions.UpdateCohortsByTenantFunction.Run"
}
According to the documentation here the json output should contain an binding to my queue with an "out" direction. Ie:
{
"type": "queue",
"direction": "out",
"name": "$return",
"queueName": "outqueue",
"connection": "MyStorageConnectionAppSetting",
}
When I try to run the queue via the npm tools (config described here), I get the following error:
Run: Microsoft.Azure.WebJobs.Host: Error indexing method 'UpdateCohortsByTenantFunction.Run'. Microsoft.Azure.WebJobs.Host: Cannot bind parameter 'output' to type IAsyncCollector`1. Make sure the parameter Type is supported by the binding. If you're using binding extensions (e.g. ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. config.UseServiceBus(), config.UseTimers(), etc.).
The documentation contains no references to binding via startup code. My understanding is that this is done via the attributes described in the Microsoft documentation linked above, and in my example code, but the error message suggests otherwise.
You should decorate your parameter with attribute, not return value:
public static async Task Run(
[TimerTrigger("* * * * * *")]TimerInfo myTimer,
[Queue("my-queue", Connection = "MyStg")] IAsyncCollector<AudienceMessage> output)
No output binding in function.json is to be expected. Attribute-defined bindings are not transferred to generated function.json. They will still work, don't worry.
I am trying to run an http trigger Azure function with Cosmos DB input binding. I would like the url of the http trigger to include several parameters on the query string that become bound to the SQL query of the input Cosmos DB binding. I am trying the following bindings in function.json, but it does not work (the function does not even get triggered):
{
"direction": "in",
"type": "httpTrigger",
"authLevel": "anonymous",
"name": "req",
"methods": [ "get" ],
"route": "users/{age=age?}/{gender=gender?}"
},
{
"direction": "in",
"type": "documentDB",
"name": "users",
"databaseName": "Database",
"collectionName": "Users",
"sqlQuery": "SELECT * FROM x where x.age = {age} and x.gender = {gender}",
"connection": "COSMOSDB_CONNECTION_STRING"
},
According to this answer the route constraint users/{age=age?}/{gender=gender?} is valid for Web API, and according to the documentation you can use any Web API Route Constraint with your parameters. Ultimately I would to like make a GET request to the Azure function that looks like api/users?age=30&gender=male. How should this be done then?
I don't think you can configure a Cosmos DB binding to values defined in query parameters e.g. ?age=30. At least I haven't seen any examples like that in the functions documentation.
But you can bind them to the route parameters to achieve the same outcome, which you have pretty much done already.
Keeping that route of users/{age}/{gender}, your Cosmos SqlQuery will then pick up those route parameters when invoking a GET on http://yourfunctionhost/yourfunction/users/30/male
GET and POST parameter will be bound, so they can be used inside the sqlQuery without any additional configuration. Just give it a try, this has definitely changed in the past
You can bind the Query-Values to CosmosDB Input Binding:
Azure Cosmos DB input binding for Azure Functions 2.x and higher
[FunctionName("DocByIdFromQueryString")]
public static IActionResult Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]
HttpRequest req,
[CosmosDB(
databaseName: "ToDoItems",
collectionName: "Items",
ConnectionStringSetting = "CosmosDBConnection",
Id = "{Query.id}",
PartitionKey = "{Query.partitionKey}")] ToDoItem toDoItem,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
if (toDoItem == null)
{
log.LogInformation($"ToDo item not found");
}
else
{
log.LogInformation($"Found ToDo item, Description={toDoItem.Description}");
}
return new OkResult();
}
I have an Azure Function that I created in the Azure portal and now want to recreate it using the visual studio azure tooling associated with VS2017 Preview.
My function is Timer triggered, and also has an input binding for Azure DocumentDB (with a query) and an output binding to an Azure Service Bus queue.
Here's the functions.json definition from the portal:
{
"bindings": [
{
"name": "myTimer",
"type": "timerTrigger",
"direction": "in",
"schedule": "0 */5 * * * *"
},
{
"type": "serviceBus",
"name": "outputQueue",
"queueName": "test-output-requests",
"connection": "send-refresh-request",
"accessRights_": "Send",
"direction": "out"
},
{
"type": "documentDB",
"name": "incomingDocuments",
"databaseName": "test-db-dev",
"collectionName": "TestingCollection",
"sqlQuery": "select * from c where c.docType = \"Test\"",
"connection": "my-testing_DOCUMENTDB",
"direction": "in"
}
],
"disabled": false
}
In VS2017, I create an Azure Function project, then a Azure function using the TimerTriggered template:
public static void Run([TimerTrigger("0 */5 * * * *")] TimerInfo myTimer, TraceWriter log, ICollector<dynamic> outputQueue, IEnumerable<dynamic> incomingDocuments)
{
log.Info($"C# Timer trigger function executed at: {DateTime.Now}");
//Inspect incomingDocuments .. push messages to outputQueue
}
Running locally, the timer is triggered as expected - but how do I recreate the input and output bindings in code? I'm not sure what attributes I should use, and what I need in json config files to wire it up.
Add reference to following nuget pacakge
https://www.nuget.org/packages/Microsoft.Azure.WebJobs.Extensions.DocumentDB/
Add using Microsoft.Azure.WebJobs
Update the documentDb Parameter as follows (Add other properties as well)
[DocumentDB(ConnectionStringSetting = "")]IEnumerable<dynamic> incomingDocuments
Update the serviceBus Parameter as follows
[ServiceBus("test-output-requests",Connection = "ConnectionValue")]
Verify the generated function.json in the bin/functionName/function.json
Thanks,
Naren