How to include CorrelationId in microservice architecture? - microservices

I am creating a microservices architecture using ASP.NET Core web api. All the services are decoupled from each other, and may be deployed in different environments. Every service has its own logging. When requests flows through these services it could fail in any of the service, We need a way of tracing a series of events back to the source, even if it means traversing multiple services.
So to handle this issue, the service that originates the request creates a CorrelationId and pass it to the next service. The 2nd service pass it to 3rd service and so on. If exception occurs the corresponding service will log the exception message along with CorrelationId.
I wanted to know what would be a best place for the caller of the service to pass the correlationid?
Should the caller pass correlationid in HttpHeader or should it pass it as a part method parameter something like below
This is the service that is getting called
public class RequestDTO
{
public string CorrelationId {get;set;}
public string SomeOtherData {get;set;}
}
public Service2Controller:Controller
{
public Task<in> DoSomething(RequestDTO request)
{
// add the correlationid in current request Items collection
// So global exception handling can access it and log it
// along with the exception
HttpContext.Items.Add("CorrelationId", request.CorrelationId);
}
}
in the approach above if there is an exception before this method is invoked, the CorrelationId will not be available for global exception handler for logging.
Any suggestions? or alternate approach

The correlation identifier should not be something that you add yourself, some framework that sends the messages should do this. This way a developer can't forget it and it has a consistent behaviour all over the place.
Put a MessageId and CorrelationId in the headers of the message. On first message, both will be the same. On second message, CorrelationId is set to the MessageId of the previous one.
You could also set a unique ConversationId which never changes, to track all messages spawning from one originator. Useful when using pub/sub and/or calling back to the originator of a message.

Generally the best approach is to
let a library do it for you and
to follow standards where available
For example, see here and here how Application Insights does dependency & correlation tracking across different levels, using headers. And see this answer for a good description of it too.

Related

HTTP Status to return if resources are partially created in Spring boot - rest api?

I've a scenario where a post request from first microservice creates new user and creates a wallet for newly created user from different microservice.
I'm returning HTTP status 201 when both user and wallet created. I'm bit confused what status should I return if user is created but wallet isn't.
I came across some articles and found two relevant to my confusion but are contradictory on returning HTTP status 207 due to its limitation related to WebDAV.
Is Http response 207 MULTI-STATUS appropriate for multi task operations?
REST API response in partial success
refer my code -
#PostMapping("/register")
public ResponseEntity<User> saveUser(#RequestBody User user) {
user.setUserId(sequenceGeneratorService.generateSequence(User.SEQUENCE_NAME));
user.getRoles().forEach(role -> role.setRoleId(sequenceGeneratorService.generateSequence(Role.SEQUENCE_NAME)));
User savedUser = userService.saveUser(user);
ResponseEntity<Wallet> createdWallet = createUserWallet(savedUser);
if (createdWallet.getStatusCode().is2xxSuccessful()) {
savedUser.setWallet(createdWallet.getBody());
return new ResponseEntity<User>(savedUser, HttpStatus.CREATED);
} else {// here is the confusion
return new ResponseEntity<User>(savedUser, HttpStatus.MULTI_STATUS);
}
}
private ResponseEntity<Wallet> createUserWallet(User savedUser) {
Wallet userWallet = Wallet.builder()
.walletId(sequenceGeneratorService.generateSequence(Wallet.SEQUENCE_NAME))
.userId(savedUser.getUserId())
.balance(BigDecimal.ZERO).build();
return walletServiceProxy.createWallet(userWallet);
}
May I know which status should I return here?
I'm returning HTTP status 201 when both user and wallet created. I'm bit confused what status should I return if user is created but wallet isn't.
HTTP status codes are metadata of the transfer-of-documents-over-a-network domain (see Webber 2011); they are there so that general purpose HTTP components can correctly interpret the response, and do intelligent things (like invalidating previously cached responses, when appropriate).
Your HTTP API is a facade: a costume that your implementation wears that makes it look like an HTTP aware document store. (The fact that your implementation doesn't have "documents" is an implementation detail, hidden behind this facade.)
The responses you send should be understood in this same way - you are telling the HTTP client (and also any intermediary components who can read the response metadata) how your (imaginary) web page reacted to the request that was sent.
Was the message processed successfully? Did it create a new (imaginary) web page with its own identifier, that clients can send messages to? Then you should normally be sending back a 201 Created, even if the implementation didn't achieve that outcome via the "happy path".
On the other hand, if you want general purpose components to understand that request processing failed, you send a 4XX Client Error or a 5XX Server Error, as appropriate.
(You probably shouldn't be using 207 MultiStatus unless you are deliberately doing WebDav things and are expecting requests from WebDav aware components; it doesn't achieve anything useful unless the client implementation knows how to handle multistatus XML documents).
Reminder: the part of an HTTP response where you describe in detail what happened and how the end consumer can respond to it is the body of the HTTP response.
201 Created
Location: /users/12345
Content-Type: text/plain
Hey, we created the new user you asked us to. Isn't that great?
You can review the details of the user at: /users/12345
But, we weren't able to create a wallet for the user. If that's
kind of important to you, could you fill in this form and send it
to us: /lost-wallets#form ?
Thanks, and have a great day

How can you publish using the ConsumeContext<T>() when using IReceiveObserver

When consuming faults implementing the IReceiveObserver, we are unable to publish via the ConsumeContext.Publish() method? The published messages aren't being received, what could be missing?
public Task ConsumeFault<T>(ConsumeContext<T> context, TimeSpan elapsed, string consumerType, Exception exception) where T : class
{
// called when the message is consumed but the consumer throws an exception
context.Publish(new {...}); //--> Doesn't publish the msg
}
To provide some context, we are firing off long running jobs and maintain a job dashboard to view their current status. Process flow is CreateJob->Send JobMessage-> JobConsumer receives and executes the task-> UpdateJob. All jobConsumer faults are being handled appropriately. In order to monitor Bus faults, we are looking to use the observers, so as to handle serialization/configuration errors etc. Aside from logging these faults, would also want to update the job state so that the dashboard would reflect the appropriate state. The IReceiveObserver receives the fault, however we would like to publish it to a central consumer to handle the updates as well. What am I missing?
For posterity was able to address this by registering an generic Fault consumer i.e IConsumer. As job context was in the message headers further actions were taken appropriately. Thank you Chris Patterson for the "MassTransit Commute - Consuming Fault Events" video!

Background processing on C# web api controller

I'm new on .NET technology and come into some problem. Currenlty i'm trying to build a REST API that handle long processing before sending the result to client.
What i'm trying to achieve is, i would like to do a background processing after receiving request from client. But, i would also like to send a response to client.
In short, it would be something like this.
Client Request -> Handled by controller ( doing some processing ) -> send response directly, ignoring the background that still running.
On Java, i can do this using Runnable Thread. How can i achieve this on C# Web API ?
Thank you.
In short, don't do this.
The job of an API is not to perform heavy duty, long running tasks.
You could simply let the API receive the request to perform something, then delegate that to another service. The API can then send a 200 response to show it received the request and maybe a URL to another resource which allows a user to track the progress.
The API needs to be available and responsive at all times. It needs to serve a number of users and if a number of them all request something that uses a lot of resources and takes a lot of time, chances are the API will simply go down and not serve anyone.
This is why you do not do such things in an API. Let other services do the heavy lifting.
Your api can call another async method and return 200/OK response without waiting for the request to complete.
You can learn more about async programing in c#.
static async Task Main(string[] args)
{
Console.WriteLine("coffee is ready");
var toastTask = MakeToastWithButterAndJamAsync(2);
async Task<Toast> MakeToastWithButterAndJamAsync(int number)
{
//Do something here.
}
}
This can be achieve this using loosed coupled architecture, by introducing service bus or blob storage, once you receive request in web api you can save it to blob/service bus and return acknowlegement response from web api. From service bus/blob storage use webjob/function/ durable function app to process the message using event.

Access HttpRequestMessage outside Controller Context

Is it possible to access the current request information (HttpRequestMessage) outside of the context of a controller?
I would like to setup a tenant strategy (ITenantIdentificationStrategy) that involves the incoming request headers. In self hosted mode HttpContext.Current is not an option and I haven't found any other solutions.
It sounds like a HttpMessageHandler is what you are looking for. MessageHandlers allow you to perform some kind of processing on every request and provides full access to the request and response message.

How does WCF RIA Services handle authentication/authorization/security?

Since no one answered this question:
What issues to consider when rolling your own data-backend for Silverlight / AJAX on non-ASP.NET server?
Let me ask it another way:
How does WCF RIA Services handle authentication/authorization/security at a low level?
e.g. how does the application on the server determine that the incoming http request to change data is coming from a valid client and not from non-desirable source, e.g. a denial-of-service bot?
From my investigation, all calls into the RIA service classes are forced through a custom IOperationInvoker class (enforced by a custom IOperationBehavior class). This invoker calls into DomainService to have the operation executed.
Before it is executed, the method call is validated any/all AuthorizationAttribute attributes marked on the operation in question. Each AuthorizationAttribute (two provided are RequiresAuthenticationAttribute & RequiresRoleAttribute) is given an opportunity to accept or reject the call via the abstract IsAuthorized method.
If any of these attributes returns something other than "AuthorizationResult.Allowed", an UnauthorizedAccessException exception is thrown with the ErrorMessage from the AuthorizationResult returned.

Resources