Azure / azure-functions-dotnet-worker

Azure Functions out-of-process .NET language worker
MIT License
415 stars 181 forks source link

Cosmos DB Bindings Doesn't go well with Newton Json with Cosmos DB Extension 4.0.0 #1272

Open AathifMahir opened 1 year ago

AathifMahir commented 1 year ago

Setting up Dto Property Name with Newton.Json Causes System.Core.PrivateLib Exception but If we setup Dto Property Name with System.Text.Json there's no issues at all.

Logs: [2023-01-14T20:10:30.058Z] Executed 'Functions.StoreDataNewtonJson' (Failed, Id=d64be871-fa1f-415d-ad78-55db2f1b7125, Duration=6232ms) [2023-01-14T20:10:30.060Z] System.Private.CoreLib: Exception while executing function: Functions.StoreDataNewtonJson. Microsoft.Azure.Cosmos.Client: Response status code does not indicate success: BadRequest (400); Substatus: 0; ActivityId: 9a4a72af-7310-4944-896f-05aca0e304ff; Reason: (Message: {"Errors":["One of the specified inputs is invalid"]} [2023-01-14T20:10:30.061Z] ActivityId: 9a4a72af-7310-4944-896f-05aca0e304ff, Request URI: /apps/DocDbApp/services/DocDbServer2/partitions/a4cb494e-38c8-11e6-8106-8cdcd42c33be/replicas/1p/, RequestStats: [2023-01-14T20:10:30.061Z] RequestStartTime: 2023-01-14T20:10:29.9995688Z, RequestEndTime: 2023-01-14T20:10:30.0005439Z, Number of regions attempted:1 [2023-01-14T20:10:30.062Z] {"systemHistory":[{"dateUtc":"2023-01-14T20:09:33.7461822Z","cpu":4.570,"memory":13475416.000,"threadInfo":{"isThreadStarving":"False","threadWaitIntervalInMs":0.0393,"availableThreads":32766,"minThreads":12,"maxThreads":32767},"numberOfOpenTcpConnection":2},{"dateUtc":"2023-01-14T20:09:43.7471240Z","cpu":0.871,"memory":13463388.000,"threadInfo":{"isThreadStarving":"False","threadWaitIntervalInMs":0.0886,"availableThreads":32765,"minThreads":12,"maxThreads":32767},"numberOfOpenTcpConnection":2},{"dateUtc":"2023-01-14T20:09:53.7524550Z","cpu":1.419,"memory":13472224.000,"threadInfo":{"isThreadStarving":"False","threadWaitIntervalInMs":0.039,"availableThreads":32766,"minThreads":12,"maxThreads":32767},"numberOfOpenTcpConnection":2},{"dateUtc":"2023-01-14T20:10:03.7581350Z","cpu":0.846,"memory":13845824.000,"threadInfo":{"isThreadStarving":"False","threadWaitIntervalInMs":0.0221,"availableThreads":32766,"minThreads":12,"maxThreads":32767},"numberOfOpenTcpConnection":2},{"dateUtc":"2023-01-14T20:10:13.7673388Z","cpu":1.118,"memory":13775372.000,"threadInfo":{"isThreadStarving":"False","threadWaitIntervalInMs":0.0441,"availableThreads":32766,"minThreads":12,"maxThreads":32767},"numberOfOpenTcpConnection":2},{"dateUtc":"2023-01-14T20:10:23.7855365Z","cpu":5.058,"memory":13416328.000,"threadInfo":{"isThreadStarving":"False","threadWaitIntervalInMs":0.0363,"availableThreads":32766,"minThreads":12,"maxThreads":32767},"numberOfOpenTcpConnection":2}]} [2023-01-14T20:10:30.063Z] RequestStart: 2023-01-14T20:10:29.9995688Z; ResponseTime: 2023-01-14T20:10:30.0005439Z; StoreResult: StorePhysicalAddress: rntbd://127.0.0.1:10253/apps/DocDbApp/services/DocDbServer2/partitions/a4cb494e-38c8-11e6-8106-8cdcd42c33be/replicas/1p/, LSN: 28, GlobalCommittedLsn: -1, PartitionKeyRangeId: 0, IsValid: True, StatusCode: 400, SubStatusCode: 0, RequestCharge: 0, ItemLSN: -1, SessionToken: -1#28, UsingLocalLSN: False, TransportException: null, BELatencyMs: 0.219, ActivityId: 9a4a72af-7310-4944-896f-05aca0e304ff, RetryAfterInMs: , TransportRequestTimeline: {"requestTimeline":[{"event": "Created", "startTimeUtc": "2023-01-14T20:10:29.9995688Z", "durationInMs": 0.0059},{"event": "ChannelAcquisitionStarted", "startTimeUtc": "2023-01-14T20:10:29.9995747Z", "durationInMs": 0.0022},{"event": "Pipelined", "startTimeUtc": "2023-01-14T20:10:29.9995769Z", "durationInMs": 0.2442},{"event": "Transit Time", "startTimeUtc": "2023-01-14T20:10:29.9998211Z", "durationInMs": 0.4106},{"event": "Received", "startTimeUtc": "2023-01-14T20:10:30.0002317Z", "durationInMs": 0.1024},{"event": "Completed", "startTimeUtc": "2023-01-14T20:10:30.0003341Z", "durationInMs": 0}],"serviceEndpointStats":{"inflightRequests":1,"openConnections":1},"connectionStats":{"waitforConnectionInit":"False","callsPendingReceive":0,"lastSendAttempt":"2023-01-14T20:10:29.9341020Z","lastSend":"2023-01-14T20:10:29.9341020Z","lastReceive":"2023-01-14T20:10:29.9351360Z"},"requestSizeInBytes":532,"requestBodySizeInBytes":89,"responseMetadataSizeInBytes":177,"responseBodySizeInBytes":53}; [2023-01-14T20:10:30.064Z] ResourceType: Document, OperationType: Upsert [2023-01-14T20:10:30.065Z] , SDK: Microsoft.Azure.Documents.Common/2.14.0, Microsoft.Azure.Cosmos.Tracing.TraceData.ClientSideRequestStatisticsTraceDatum, Windows/10.0.22623 cosmos-netstandard-sdk/3.29.1);.

Affected Version: Microsoft.Azure.Functions.Worker.Extensions.CosmosDB - "4.0.0"

Working Version: Microsoft.Azure.Functions.Worker.Extensions.CosmosDB - "3.0.9"

Sample Code: https://github.com/AathifMahir/CosmosBindingNewtonJsonIssue

kshyju commented 1 year ago

Hi @AathifMahir Thank you for sharing the GitHub link with the repro.

You are running into that issue because you are using Newtonsoft.Json.JsonPropertyName attribute on the DTO properties, but have not configured Newtonsoft.Json as the object serializer for your function app.

To fix this, you simply need to tell the function worker runtime to use Json.net serializer as shown in this sample

Once you add the extension method from the sample I linked above to your function app, your startup code needs to look like this.

var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults((appBuilder) =>
{
    // This configures Newtonsoft.Json.NET as JsonSerializer
    appBuilder.UseNewtonsoftJson();
})
.Build();
host.Run();

Hope this helps. Let us know if you still have questions.

AathifMahir commented 1 year ago

Hi @AathifMahir Thank you for sharing the GitHub link with the repro.

You are running into that issue because you are using Newtonsoft.Json.JsonPropertyName attribute on the DTO properties, but have not configured Newtonsoft.Json as the object serializer for your function app.

To fix this, you simply need to tell the function worker runtime to use Json.net serializer as shown in this sample

Once you add the extension method from the sample I linked above to your function app, your startup code needs to look like this.

var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults((appBuilder) =>
{
    // This configures Newtonsoft.Json.NET as JsonSerializer
    appBuilder.UseNewtonsoftJson();
})
.Build();
host.Run();

Hope this helps. Let us know if you still have questions.

Thanks but I prefer we won't have to face these kinds of issues again, I guess it has to do with mediocre documentation etc..

I hope that improves in the coming months.

AathifMahir commented 1 year ago

Hi @AathifMahir Thank you for sharing the GitHub link with the repro.

You are running into that issue because you are using Newtonsoft.Json.JsonPropertyName attribute on the DTO properties, but have not configured Newtonsoft.Json as the object serializer for your function app.

To fix this, you simply need to tell the function worker runtime to use Json.net serializer as shown in this sample

Once you add the extension method from the sample I linked above to your function app, your startup code needs to look like this.

var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults((appBuilder) =>
{
    // This configures Newtonsoft.Json.NET as JsonSerializer
    appBuilder.UseNewtonsoftJson();
})
.Build();
host.Run();

Hope this helps. Let us know if you still have questions.

By the way, I have an out of topic question regarding Azure Functions Isolated Extension. Would you be able to assist?

Here's the issue, on my current Authentication Infrastructure, I pass Authorization Bearer in the header and then I need to decode that Jwt and get the user I'd from it. But I'm planning to implement all this process into Azure Isolated Binding Extension but when it comes to documents on how to move forward on creating custom binding and extension for isolated and Api Information is pretty vague on Documentation Part, No idea where to start and could you help with guiding on developing custom extension and bindings for Azure Functions Isolated and at the end of the looking to build this and binding extension as class library and share it with others, Thanks

fabiocav commented 1 year ago

Thanks but I prefer we won't have to face these kinds of issues again, I guess it has to do with mediocre documentation etc..

I hope that improves in the coming months.

@AathifMahir we'll use this issue to track a documentation update to describe the default serializer used by the SDK and point to the sample here.

Do you have additional feedback on documentation updates? Do you believe this would have prevented/helped with the issue you ran into?

AathifMahir commented 1 year ago

Thanks but I prefer we won't have to face these kinds of issues again, I guess it has to do with mediocre documentation etc..

I hope that improves in the coming months.

@AathifMahir we'll use this issue to track a documentation update to describe the default serializer used by the SDK and point to the sample here.

Do you have additional feedback on documentation updates? Do you believe this would have prevented/helped with the issue you ran into?

Of course, this issue should've been prevented with proper documentation

AathifMahir commented 1 year ago

Documentation related to Worker Process aka Isolated is Super Hard to Find, Hope that improves in coming month. In my case I was still struggling with writing own custom extension and bindings for worker process

cloudmelon commented 1 year ago

Documentation related to Worker Process aka Isolated is Super Hard to Find, Hope that improves in coming month. In my case I was still struggling with writing own custom extension and bindings for worker process

hi @AathifMahir thanks for your feedback. Would you clarify what you think that's missing from this article? Most of our customers who are working with .NET isolated functions find what they need about configurations & startup from there: https://learn.microsoft.com/en-us/azure/azure-functions/dotnet-isolated-process-guide#configuration

AathifMahir commented 1 year ago

Documentation related to Worker Process aka Isolated is Super Hard to Find, Hope that improves in coming month. In my case I was still struggling with writing own custom extension and bindings for worker process

hi @AathifMahir thanks for your feedback. Would you clarify what you think that's missing from this article? Most of our customers who are working with .NET isolated functions find what they need about configurations & startup from there: https://learn.microsoft.com/en-us/azure/azure-functions/dotnet-isolated-process-guide#configuration

I have been searching for documentation on developing Custom Binding and Extension for while now, can't seem to find any documentation regarding this

jviau commented 1 year ago

I believe there are two documentation updates here:

  1. Custom binding samples, which is mentioned in this issue: https://github.com/Azure/azure-functions-dotnet-worker/issues/361
  2. More explicitly calling out serialization behavior and customization in our docs (preferably as a code snippet). We can use this issue to track that.
cloudmelon commented 1 year ago

Documentation related to Worker Process aka Isolated is Super Hard to Find, Hope that improves in coming month. In my case I was still struggling with writing own custom extension and bindings for worker process

hi @AathifMahir thanks for your feedback. Would you clarify what you think that's missing from this article? Most of our customers who are working with .NET isolated functions find what they need about configurations & startup from there: https://learn.microsoft.com/en-us/azure/azure-functions/dotnet-isolated-process-guide#configuration

I have been searching for documentation on developing Custom Binding and Extension for while now, can't seem to find any documentation regarding this

We didn't document this officially since we have already a set of samples available on GitHub. We want to make the experience simpler for our customers to use existing bindings, however, we appreciate the contributions from the community on our repo here: https://github.com/Azure/azure-webjobs-sdk/wiki/Creating-custom-input-and-output-bindings

AathifMahir commented 1 year ago

Documentation related to Worker Process aka Isolated is Super Hard to Find, Hope that improves in coming month. In my case I was still struggling with writing own custom extension and bindings for worker process

hi @AathifMahir thanks for your feedback. Would you clarify what you think that's missing from this article? Most of our customers who are working with .NET isolated functions find what they need about configurations & startup from there: https://learn.microsoft.com/en-us/azure/azure-functions/dotnet-isolated-process-guide#configuration

I have been searching for documentation on developing Custom Binding and Extension for while now, can't seem to find any documentation regarding this

We didn't document this officially since we have already a set of samples available on GitHub. We want to make the experience simpler for our customers to use existing bindings, however, we appreciate the contributions from the community on our repo here: https://github.com/Azure/azure-webjobs-sdk/wiki/Creating-custom-input-and-output-bindings

Thanks for the response, I'll look into the documentation on webjobs SDK repo and will try to develop a custom extension based on my needs, Thanks

But end of the day, would be great if we have link to webjobs repo and webjobs wiki in the azure functions hosts wiki pages. This could help lots of developers who are looking to develop extensions and binding for isolated process

otykier commented 3 months ago

We cannot get Json.Net to work with the Cosmos DB bindings after upgrading our function app to 4.x / .NET 8 / isolated worker model. Even after refactoring the entire app to not use ASP.NET Core, and configuring the worker to use Json.Net as described in this comment, we are still getting System.Text.Json exceptions.

It turns out that the CosmosDBConverter has a hardcoded dependency on the System.Text.Json serializer, which we can't seem to avoid when using CosmosDB input bindings (at least this is where the exception originates, when we try to debug our app):

image

This is in v. 4.8.1 of Microsoft.Azure.Functions.Worker.Extensions.CosmosDB.

I'm just about to give up on bindings, and just manually deal with CosmosClient instead...

Related threads:

otykier commented 3 months ago

It's worth noting that I tried downgrading Microsoft.Azure.Functions.Worker.Extensions.CosmosDB to 4.0.0, and this actually did let me use the Json.Net serializer with a Cosmos DB input binding (i.e. I didn't get any System.Text.Json exceptions). Unfortunately, I was not able to get it to persist changes to a document even when the function completed successfully (which should work according to the documentation).

So it looks like there was a regression somewhere between 4.0.0 and 4.8.1 where the hardcoded System.Text.Json serializer was introduced, but at the same time, we can't use 4.0.0 since the automatic persist doesn't work...

samanthawalter commented 1 month ago

Custom serializer override stops working with Microsoft.Azure.Functions.Worker.Extensions.CosmosDB 4.5.0 This refactor to remove reflection hardcodes the System.Text.Json serializer: https://github.com/Azure/azure-functions-dotnet-worker/pull/1924