Not able to run Cosmos DB Change Feed Trigger Azure Function locally - c#

I am not able to run Cosmos DB Change Feed Trigger function locally.
Cosmos DB Change Feed Trigger Azure Function:
public static class NotificationChangeFeed
{
[FunctionName("NotificationChangeFeed")]
public static async Task Run([CosmosDBTrigger(
databaseName: "FleetHubNotifications",
collectionName: "Notification",
ConnectionStringSetting = "CosmosDBConnection",
CreateLeaseCollectionIfNotExists = true,
LeaseCollectionName = "leases")]IReadOnlyList<Document> input,
[Inject] ILoggingService loggingService,
[Inject] IEmailProcessor emailProcessor)
{
var logger = new Logger(loggingService);
try
{
if (input != null && input.Count > 0)
{
foreach (Document document in input)
{
string requestBody = document.ToString();
var notification = requestBody.AsPoco<Notification>();
var result = await emailProcessor.HandleEmailAsync(notification, logger);
if (result)
{
logger.Info($"Email Notification sent successfully for file name: {document.Id}");
}
else
{
logger.Warning($"Unable to process document for Email Notification for file with name: {document.Id}");
}
}
}
}
catch (Exception ex)
{
logger.Error($"Unable to process Documents for Email Notification for Files: {input?.Count}", ex,
nameof(NotificationChangeFeed));
throw;
}
}
}
local.settings.json
{
"IsEncrypted": "false",
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"AzureWebJobsDashboard ": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"CosmosDbId": "FleetHubNotifications",
//Localhost
"CosmoDbAuthKey": "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==",
"CosmoDbEndpoint": "https://localhost:8081/",
"CosmosDBConnection": "AccountEndpoint=https://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==",
}
}
When I press F5, it got stuck in the console window.(As shown in the below screen shot)
Also not able call http trigger functions. Getting below error while calling:
Error: connect ECONNREFUSED 127.0.0.1:7071
Any thoughts?

Yeah in that part you only get the endpoints of the http functions. The other functions are also initialized and waiting for an event of whatever type. Yo can see it here: Found the following functions, 4 http trigger the other 2 are blob trigger.
If you want to debug your NotificationChangeFeed function you will have to create a new document on the DB and have the function runing and waiting for that event. And you will see the telemetry in the console and you can debug the function.

Related

Azure function app blob trigger cannot upload file

I've created a blob trigger that accepts a file from a blob, unzips it and moves it to another blob using streams.
My code looks like this
[FunctionName("Requests")]
[StorageAccount("samplecontainer")]
public static void Run([BlobTrigger("incoming/{name}")]Stream myBlob,
[Blob("processing/{name}.xml", FileAccess.Write)] TextWriter output,
string name, ILogger log)
{
log.LogInformation($"C# Blob trigger function Processed blob\n Name:{name} \n Size: {myBlob.Length} Bytes");
string returnValue;
using (Stream blob = myBlob)
{
using (GZipStream decompressionStream = new GZipStream(blob, CompressionMode.Decompress))
{
log.LogInformation($"Unzipping file");
name = name.Replace(".gz", "");
var content = String.Empty;
using (StreamReader reader = new StreamReader(decompressionStream))
{
content = reader.ReadToEnd();
reader.Close();
}
returnValue = content;
}
}
log.LogInformation($"C# Blob trigger function finished processing blob\n Name:{name} \n Now writing to xml");
output.WriteLine(returnValue);
}
This will in fact work while running this locally using "AzureWebJobsStorage": "UseDevelopmentStorage=true" in my local.settings.json file.
However, once I've deployed this app and upload a file to the real container using Azure Storage Explorer nothing happens and the activity log shows that the operation failed in Write.Tiny.txt.gz, Could not find file 'D:\home\site\wwwroot\Requests\tiny.txt.gz'.
I have http triggers that do work, and I have tried turning off the configuration WEBSITE_RUN_FROM_PACKAGE to no effect. Am I maybe missing some setting or config?
When I console into this path in the function app and cat the function.json I get this:
{
"generatedBy": "Microsoft.NET.Sdk.Functions-1.0.29",
"configurationSource": "attributes",
"bindings": [
{
"type": "blobTrigger",
"connection": "samplecontainer",
"path": "incoming/{name}",
"name": "myBlob"
}
],
"disabled": false,
"scriptFile": "../bin/azure-functions.dll",
"entryPoint": "Requests.Run"
}
OK, I can reproduce your problem.
Since you can work on local, then it should be no problem about your code.
I can explain why this happened. Your function app on azure don't have the RBAC that can write data to azure blob storage.
Below steps can solve the problem:
First, create identity of your function app.
Second, add RBAC role of your function app to storage account.
By the way, the above settings will not take effect immediately, you need to wait a few minutes for it to take effect.
I fully believe I also needed Bowman Zhu's answer for this to work, but in my specific case I had forgotten to add the storage account as a connection string in my appSettings.json, as we had recently updated to Microsoft.Azure.WebJobs.Extensions.Storage version 3 and this was our first blob trigger.
In appSettings.json:
{
"ConnectionStrings": {
"AzureWebJobsStorage": "{endpoint}"
}
}

Send Azure SignalR message from Azure Function with CosmosDB Trigger

I’m developing a app that used CosmosDB to store data and then when anyone updates the data i want the clients to be updated.
For this i have decided to use the changefeed and then Azure Functions and Azure SignalR.
I have set up 2 functions.
A negotiate function (This one works and the clients connect correctly to the SignalR server)
And a OnDocumentsChanged function, and my problem is getting the function to actually sending the message, when something is changed.
I have the following function:
[FunctionName("OnDocumentsChanged")]
public static async Task Run(
[CosmosDBTrigger(
databaseName: "NewOrder",
collectionName: "NewOrder",
CreateLeaseCollectionIfNotExists = true,
ConnectionStringSetting = "myserver_DOCUMENTDB",
LeaseCollectionName = "leases")]
IReadOnlyList<Document> updatedNewOrder,
[SignalR(ConnectionStringSetting = "AzureSignalRConnectionString", HubName = "NewOrder")] IAsyncCollector<SignalRMessage> signalRMessages,
ILogger log)
{
if (updatedNewOrder != null && updatedNewOrder.Count > 0)
{
foreach (var Orders in updatedNewOrder)
{
await signalRMessages.AddAsync(new SignalRMessage
{
Target = "NewOrderUpdated",
Arguments = new[] { Orders.Id }
});
}
}
}
I can see that it is correctly triggered when a change is made to the database, but no messages are send.
I guess I’m missing a out part that actually send the SignalRMessages I’m just not sure how to implement.
Thanks.

Azure function is not logging custom events, dependencies to app insights

We have a Azure Function V3 developed in C#. We tried to log some custom events, dependencies, etc to Azure Application Insights. We are not able to log in app insights using TelemetryClient. The code runs fine without any errors. Also, could see instrumentation key retrieved from config file. However Ilogger logs can be found in app insights traces table. Please find below code that we used,
public class CommunityCreate
{
private readonly TelemetryClient telemetryClient;
public CommunityCreate(TelemetryConfiguration telemetryConfiguration)
{
this.telemetryClient = new TelemetryClient(telemetryConfiguration);
}
[FunctionName("Function1")]
[return: ServiceBus("sample", Connection = "ServiceBusProducerConnection")]
public async Task<string> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "Account/{id:int?}")] HttpRequest req, string id, ILogger log)
{
//log.LogInformation("C# HTTP trigger function processed a request.");
DateTime start = DateTime.UtcNow;
string name = req.Query["name"];
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
name = name ?? data?.name;
var evt = new EventTelemetry("Function called");
evt.Context.User.Id = name;
this.telemetryClient.TrackEvent(evt);
// Generate a custom metric, in this case let's use ContentLength.
this.telemetryClient.GetMetric("contentLength").TrackValue(req.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;
this.telemetryClient.TrackDependency(dependency);
telemetryClient.TrackEvent("Ack123 Recieved");
telemetryClient.TrackMetric("Test Metric", DateTime.Now.Millisecond);
return name;
}
}
Please make sure you're using the correct packages as below:
Microsoft.Azure.WebJobs.Logging.ApplicationInsights, version 3.0.18
and
update the package Microsoft.NET.Sdk.Functions the latest version 3.0.9.
If you're running the project locally, please add the APPINSIGHTS_INSTRUMENTATIONKEY in local.settings.json, like below:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "xxxx",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"APPINSIGHTS_INSTRUMENTATIONKEY": "xxx"
}
}
Or if you're running it on azure portal, please configure the Application insights with azure function.
Then I tested your code, the custom events or dependency are correctly logged into Application insights. Here is the screenshot:
If you still have the issue, please let me know(and please also provide more details).

Azure Function Not Publishing Message to Service Bus

I created a Function App which is triggered via Http. The function app should publish a message to Azure Service Bus Topic. I am not getting any message published in the topic for some reasons. I have the function app successfully triggered. I am not sure what I am doing wrong here. Below is my code.
[FunctionName("MessageProcessorFunction")]
[return: ServiceBus("mytopic", Connection = "Endpoint=sb://abcsb.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=wBCZ4ssssssohbg1ZUYKw4q8cpKaoZLIG9NR28ZoUDhBG8=")]
public async Task<string> Run(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "sms")] HttpRequest req,
ILogger log)
{
log.LogInformation("HTTP trigger function processed a request.");
return "hello World";
}
However, the console app below successfully published a message to service bus topic. Here is the code
TopicClient _topicClient = new TopicClient("Endpoint=sb://abcsb.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=wBCZ4ssssssohbg1ZUYKw4q8cpKaoZLIG9NR28ZoUDhBG8=", "whispir");
string data = JsonConvert.SerializeObject("Hello world");
Message message = new Message(Encoding.UTF8.GetBytes(data));
try
{
await _topicClient.SendAsync(message);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
local.settings.json
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"ServiceBusConnectionString": "Endpoint=sb://abcsb.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=wBCZ4okoohbg1ZUYKw4q8cpKaoZLIG9NR28ZoUDhBG8="
}
Any idea?
-Alan-
The Connection property should receive a settings key, not the actual connection string.
If you want to try it locally, you'll have to change the local.settings.json file and add the connection string to a specific key:
{
"Values": {
"ServiceBusConnectionString": "Endpoint=sb://abcsb.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=wBCZ4ssssssohbg1ZUYKw4q8cpKaoZLIG9NR28ZoUDhBG8="
}
}
Then, use it in your function like this:
[FunctionName("MessageProcessorFunction")]
[return: ServiceBus("mytopic", Connection = "ServiceBusConnectionString")]
public async Task<string> Run(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "sms")] HttpRequest req,
ILogger log)
{
log.LogInformation("HTTP trigger function processed a request.");
return "hello World";
}
Should be working.
Let me know if not. :)

Lambda Function using c# cannot invoke external HTTPS APIs

I am trying to invoke External APIs from AWS lambda function written in c#. The Lamda function is deployed in No VPC mode. I am calling this function from Alexa skill. The code works fine for an http request, but its not working for https.
The below code works when I use http://www.google.com.
But, if I replace http with https, then I get the error in the cloud watch saying:
"Process exited before completing request."
Even the log written in catch is not getting logged in cloud watch.
public class Function
{
public const string INVOCATION_NAME = "bingo";
public async Task<SkillResponse> FunctionHandler(SkillRequest input, ILambdaContext context)
{
var requestType = input.GetRequestType();
if (requestType == typeof(IntentRequest))
{
string response = "";
IntentRequest request = input.Request as IntentRequest;
response += $"About {request.Intent.Slots["carmodel"].Value}";
try
{
using (var httpClient = new HttpClient())
{
Console.WriteLine("Trying to access internet");
//var resp=httpClient.GetAsync("http://www.google.com").Result // this works perfect!
var resp = httpClient.GetAsync("https://www.google.com").Result; // this throws error
Console.WriteLine("Call was successful");
}
}
catch (Exception ex)
{
Console.WriteLine("Exception from main function " + ex.Message);
Console.WriteLine(ex.InnerException.Message);
Console.WriteLine(ex.StackTrace);
}
return MakeSkillResponse(response, true);
}
else
{
return MakeSkillResponse(
$"I don't know how to handle this intent. Please say something like Alexa, ask {INVOCATION_NAME} about Tesla.",
true);
}
}
private SkillResponse MakeSkillResponse(string outputSpeech, bool shouldEndSession,
string repromptText = "Just say, tell me about car models to learn more. To exit, say, exit.")
{
var response = new ResponseBody
{
ShouldEndSession = shouldEndSession,
OutputSpeech = new PlainTextOutputSpeech { Text = outputSpeech }
};
if (repromptText != null)
{
response.Reprompt = new Reprompt() { OutputSpeech = new PlainTextOutputSpeech() { Text = repromptText } };
}
var skillResponse = new SkillResponse
{
Response = response,
Version = "1.0"
};
return skillResponse;
}
}
The issue was resolved by updating the library version.
System.Net.Http v4.3.4 was not completely compatible with dotnet core v1.
So outbound http calls were working but not https calls. Changing the version of System.net.http resolved the issue.

Categories

Resources