0

I have this code that I use to log activity to the Cosmos DB.

protected override async void OnStart()
{
   await Helper.LogActivity("OnStart");

public static partial class Helper
{
    public static async Task LogActivity(string activity)
    {
        var logItem = new LogItem()
        {
            Activity = activity,
        };
        await CosmosDBService.InsertLogItem(logItem);
    }
}

public class CosmosDBService
{
    static DocumentClient docClient = null;

    static readonly string databaseName = "Test";
    static readonly string collectionName = "Logs";

    static async Task<bool> Initialize()
    {
        if (docClient != null)
            return true;
        try
        {
            docClient = new DocumentClient(new Uri(APIKeys.CosmosEndpointUrl), APIKeys.CosmosAuthKey);
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex);
            docClient = null;
            return false;
        }
        return true;
    }

    public async static Task InsertLogItem(LogItem item)
    {
        if (!await Initialize())
            return;
        await docClient.CreateDocumentAsync(
            UriFactory.CreateDocumentCollectionUri(databaseName, collectionName),
            item);
    }

}

What I am concerned with is if there was no internet connection. Would it be a good idea to somehow test for this first or should I add some try catch exception to the code for the logging?

Would appreciate any suggestions on how I could make this code bullet proof so that even if there is no connection then there is no exception thrown in the OnStart.

If the logging fails then it's not a problem for me but I want to be sure the code will not fail if there is no internet connection or if the cosmos db call fails.

Alan2
  • 23,493
  • 79
  • 256
  • 450
  • You cant make it *bullet proof*. You could always ping google ( Cosmos DB, ect) which would be fairly redundant, yet that is no guarantee the internet or that site hasn't dropped out by the time to make your call, so you will need to handle accordingly anyway – TheGeneral Feb 18 '20 at 08:44
  • I am okay if the call fails as the logging is not so critical. Just want to be sure that does not cause some issues with the application and wondering how to handle the exception case if there is no internet. – Alan2 Feb 18 '20 at 08:47
  • Does this answer your question? [Checking network status in C#](https://stackoverflow.com/questions/314213/checking-network-status-in-c-sharp) – Arthur Grigoryan Feb 18 '20 at 09:20
  • https://stackoverflow.com/questions/314213/checking-network-status-in-c-sharp – Arthur Grigoryan Feb 18 '20 at 09:21

1 Answers1

1

Maybe make a checklist of concerned cases:

1) No Internet 2) Internet but database is offline 3) etc..

Then test your code and see how it behaves, and ensure you are handling the cases. Then you can be (somewhat) sure how your code behaves under these circumstances. It will also show you where the exception occures, so you might want to add a try..catch block to prevent other failures.

UPDATE - Regarding Handling error cases:

So if your program fails to initialize the docClient it would mean that it will not be able to write any logs.

So there might be a few ways to handle this,

1) you could have a "fallback" logging method, meaning if docClient == null log to console. (So that later you can investigate on the server what went wrong) This allows you to keep crucial logs saved if the server keeps these logs.

2) Another fallback method would be to buffer the events in a memory list, and retry to connect every 10 minutes to the database. If connection was succesfull you empty your buffer into the database.

3) You can implement a retry count, like retry to connect X times at startup, if it fails you can fallback to another method or combination of above ideas. Additionally you could have a system that alerts you via E-MAIL or SMS, depending how critical this service is.

These ideas center around issues with connecting to the database. This will however still not help you to much with the actual insert, for example if your DB connection dies midway.

So you might still need a try catch inside the InsertLogItem-method around the actual insert code. So that would hide the try catch around every await Helper.LogActivity("OnStart"); statement, as it is integrated. and if that log fails you could again concider fallback methods or actions

UPDATE2) Looking at CreateDocumentAsync return object here: https://learn.microsoft.com/en-us/dotnet/api/microsoft.azure.documents.client.resourceresponse-1?view=azure-dotnet

ResourceResponse<Document> response = await client.CreateDocumentAsync(collectionLink, document);
Console.WriteLine(response.RequestCharge);
Console.WriteLine(response.ActivityId); 
Console.WriteLine(response.StatusCode); // HttpStatusCode.Created or 201

It seems you are able to get a status code indicating the result, I would try to close the server midway and observe if the async response returns with an appropriate error code or if it throws. If it does not throw you might not need a try catch and just check return code and then take actions.

Sebastian
  • 159
  • 6
  • What I am unsure of is how to handle the cases where it fails. Would appreciate any advice / suggestions on this. Ideally I would like to avoid needing a try-catch around the await call in the OnStart. – Alan2 Feb 18 '20 at 08:49
  • I updated my answer to address some of the concerns and a proposal to avoid try..catch, let me know if it helps or it did not answer the question well enough, thanks! – Sebastian Feb 18 '20 at 10:37