Search code examples
asp.net-coreredistask-parallel-librarypublish-subscribe

How do you perform completely asynchrouns operations in ASP NET Core


Hello i am trying to do a trail log for some of my API endpoints.These logs are generated when the endpoint is called.I would like the writing of the logs to be done in an asynchrouns manner (as lightweight as possible) as to not affect the performance of my usual logic.

I was thinking to have a component that is injectable and can be called anywhere in my endpoints when a log is produced.The problem is that i seem to not find a suitable async solution:

Important service that needs not be obstructed by delays

public interface IImportantInterface
{
    Task DoSomethingUndistrubedAsync(string value);
}

**Wrapper around Redis pub-sub**

 public interface IIOService{
     Task PublishAsync( object obj);
 }

Controller

public class Controller
{
    private IImportantInterface importantService;
    private Publisher publisher;
    [HttpPost]
    public async Task SomeEndpointAsync(){
          this.publisher.Publish([some_log]);
          await this.importantService.DoSomethingUndisturbedAsync([something]);
    }
    public Controller(IImportantInterface importantService)
    {

        this.importantService=importantService;
    }

}

Now comes the real problem.How do i make the smallest footprint for my Publisher.I came up with 3 scenarios but two of them are unfeasible due to going out of scope:

Attempt 1
Transient Service with Task scoped to method:

public class Publisher{

    private IIOService writeService{get;set;}
    public async Task PublishAsync(object obj){
         Task t1=Task.Run(async()=>await writeService.PublishAsync(obj)); //t1 might not finished when method exits
    }
}

Task t1 might not finish by the time the method ends.

Attempt 2 Task embedded in Transient Service

public class Publisher{    //publisher might get discarded when calling controller gets out of scope
     private Task t1;
     private IIOService writeService{get;set;}
     public async Task PublishAsync(object obj){        
          t1=Task.Run(async ()=> this.IIOService.writeService(obj));  
     }
}

Now task will not get collected after method scope , but it might not finish by the time the calling Controller method class gets out of scope

Attempt 3 Singleton object with a ConcurrentQueue of Tasks that get enqueued. This would not get out of scope but when would i clear the items?

public class Publisher{
     private ConcurrentQueue<Task> Queue;
     public async Task PublishAsync(object obj){
         this.Queue.Enqueue();
     }
}

P.S I want to publish these logs in a common place.From that place the target is to get published to a Redis database using the pub-sub functionality. Should i just write to Redis ?


Solution

  • Hello i am trying to do a trail log for some of my API endpoints.These logs are generated when the endpoint is called.I would like the writing of the logs to be done in an asynchrouns manner (as lightweight as possible) as to not affect the performance of my usual logic.

    I strongly recommend that you use an existing and exhaustively-tested logging library, of which there are many with modern capabilities such as semantic logging and async-compatible implicit state.

    Modern logging libraries generally have a singleton kind of design, where logs are kept in-memory (and logging methods are synchronous). Then there is a separate "processor" which publishes these messages to a collector. If you insist on writing your own logging framework (why?), I would recommend you take the same approach as all the other highly successful logging frameworks.