API Logging without rollback due to hard errors

In a current API connection in a customer project I have just dealt with the topic of API request logging again. I had already built a small prototype that allows logging via webservice.

But it is much easier than that. Namely by using background sessions. This can persist the information despite hard errors in the foreground session. This is extremely useful for API implementations where you would like to have the explicit rollback in case of api errors but keep the request or response in a log for further debugging.

In our example we have an temporary api parameter table, in which we have various settings for calling the api interface like the url, rest method, parameters and payloads. And additionally an api log table with the fields we want to save:

codeunit 79007 "MyApi Log Management"
{
    TableNo = "MyApi Api Parameters";

    trigger OnRun()
    begin
        LogWebserviceCall(Rec);
    end;

    procedure LogWebserviceCall(MyApiSetup: Record "MyApi API Setup"; var MyApiParameters: Record "MyApi API Parameters" temporary)
    var
        SessionID: Integer;
    begin
        if not MyApiSetup."Log API Calls" then
            exit;
        
        //The codeunit is calling itself in a background session
        StartSession(SessionID, Codeunit::"MyApi Log Management", CompanyName, MyApiParameters);
    end;

    procedure LogWebserviceCall(var MyApiParameters: Record "MyApi API Parameters" temporary)
    var
        MyApiLog: Record "MyApi Api Log";
    begin
        MyApiLog.Init();
        MyApiLog."No." := 0;
        
        //Request
        MyApiLog."Query DateTime" := CurrentDateTime;
        MyApiLog."Request Parameters" := MyApiParameters.Method;
        MyApiLog."Request Method" := CopyStr(Format(MyApiParameters.RestMethod), 1, MaxStrLen(MyApiLog."Request Method"));
        MyApiLog."Request URL" := MyApiParameters.URL;

        //Response
        MyApiLog."Response Code" := MyApiParameters."Response Code";
        MyApiLog."Error Message" := CopyStr(MyApiParameters."Error Message", 1, MaxStrLen(MyApiLog."Error Message"));

        //Blob fields
        MyApiLog."Request Content" := MyApiParameters."Request Content";
        MyApiLog."Response Content" := MyApiParameters."Response Content";

        MyApiLog.User := CopyStr(UserId, 1, MaxStrLen(MyApiLog.User));

        if not MyApiLog.Insert() then;
    end;
}

Now, if an error happens in the web service call, we can still pass all the parameters into the background session and thus persist them. So, basically the logging codeunit is calling itself in a background session.

//Send webservice query
WebClient.Send(RequestMessage, ResponseMessage);

//Persist for Logging
MyApiParameters."Response Code" := ResponseMessage.HttpStatusCode();

//Fetch result
if not ResponseMessage.IsSuccessStatusCode() then begin
    ErrorMessage := StrSubstNo('API Error: %1', ResponseMessage.ReasonPhrase());

    //Write to temp. parameter table
    MyApiParameters."Error Message" := CopyStr(ErrorMessage, 1, MaxStrLen(MyApiParameters."Error Message"));

    //Log to API Log Entries
    MyApiApiLog.LogWebserviceCall(MyApiSetup, MyApiParameters);

    Error(ErrorMessage);
end else begin
    //...
end;
image 15

... is a technical consultant and developer at Comsol Unternehmenslösungen AG in Kronberg/Taunus. Major tasks are the architecture and implementation of complex, usually cross-system applications in and around Microsoft Dynamics 365 Business Central.

Leave a Reply

Your email address will not be published.