Skip to main content

Notifications

Dynamics 365 Community / Forums / Finance forum / How to log external AP...
Finance forum
Suggested answer

How to log external API integration ?

Posted on by 898
Hi guys,
 
I'm pretty new on handling API integration inside D365 FO. And currently seek an advice : If we have API for external vendor (party) to add record in table, lets say the API is to insert (create) new PO inside D365 FO, how actually the practice to log all the attempt ? Since there will be few attempt which will be /unsuccessful/ to them to add the record. What do we, as the party who receive the attempt, log whenever they tried and failed and tried until it is succeed.
 
Similarly, in the next process, the external party would also post GRN the PO and invoice. Because this external vendor / party is act as our front-end system who will receive the PO and receive everything, and then send all these activities to D365 FO as the backend system. Like the PO creation attempt, GRN or invoice attempt might also be several time failed. I'd like to capture this in a log so we will be aware how may time they failed before it is succeed.
 
I can only imagine the scenario is similar like when someone wants to visit us or sending us a parcel, without us knowing when it will come. The parcel may already arrived but as I don't know it is come nor the parcel is put somewhere so it maybe bring back to the sender, or maybe already come and go several time without successfully being received / accepted.
 
May I know what need to be done ? the process, the logic and what need to be developed.
 
I could imagine I will need to create some integration log table to record that, but at this point, that's it,  I'm still blank of what it needs to make all this happens. Do we need a DLL or what ? 
 
Thanks in advance.
  • Voltes Profile Picture
    Voltes 898 on at
    How to log external API integration ?
    Hi,
     
    I'm sorry, after thoroughly check, finally found the wrong doing, and it is shown in SQL Server instead. It is not "gone", but wrong dataareaid.
    So basically, in the services class, I have statement to changecompany(). and it was unintentionally, the "insert_to_log" is put before changecompany(), in some of the method.
    Anyway this is the service class before I fix it:
    class MyService
    {
         public MyResponse createPO (MyRequest  _request)
         {
             Notes json = FormJsonSerializer::serializeClass(_request);
             str logId = MyIntegrationGlobal::logInbound("MyService", "createPO", json);
    
             changeCompany(_request.parmDataAreaId());
             {
                try{
                .
                . <code>
                . response(True);
                }
                catch(
                   response(False)
                }
             
                MyIntegrationGlobal::logOutbound(logId, "MyService", "createPO", response.parmSuccess(), response.parmMessage());
    
                return response;
             }
    
         }
    }
     
    Whereby my global class for logging is : 
    class MyAPIIntegrationGlobal
    {
        public static str logInbound(str _classname, str _methodname, Notes _param)
        {
            MyIntegrationLog   logTable;
    
            System.DateTime localDateTime = DateTimeUtil::applyTimeZoneOffset(DateTimeUtil::getSystemDateTime(), DateTimeUtil::getUserPreferredTimeZone());
            
            ttsbegin;
                    
            logTable.clear();
            logTable.ID = localDateTime.ToString('yyyyMMdd_HHmmss');
            str logId = logTable.ID;
            logTable.DateTimeExecuted = localDateTime;        
            logTable.DateTimeAnswered = localDateTime;
            logTable.Direction = InboundOutbound::Inbound;
            logTable.ClassName = strFmt("%1 - %2", _classname, _methodname);
            logTable.InputParameter =  _param;
            logTable.insert();
            
            ttscommit;
    
            return logTable.ID;
        }
    
        public static void logOutbound(str _id, str _classname, str _methodname, NoYesId _success, Description1000 _responsemessage)
        {
    
            MyIntegrationLog   logTableInbound, logTableOutbound;
            System.DateTime localDateTime = DateTimeUtil::applyTimeZoneOffset(DateTimeUtil::getSystemDateTime(), DateTimeUtil::getUserPreferredTimeZone());
            System.DateTime startExecDateTime = localDateTime;
            
            // look for inbound
            str classMethodname= strFmt("%1 - %2*", _classname, _methodname);
            select firstonly logTableInbound
                where logTableInbound.ID == _id
                    && logTableInbound.ClassName like classMethodname
                    && logTableInbound.Direction == InboundOutbound::Inbound;
            
            // if found, startExecTime will be override
            // if not found, startExecTime will have the current time
            if (logTableInbound)
            {
                startExecDateTime = logTableInbound.DateTimeExecuted;
            }
            
            ttsbegin;
                
            logTableOutbound.clear();
            logTableOutbound.ID = _id;
            logTableOutbound.Direction = InboundOutbound::Outbound;
            logTableOutbound.DateTimeExecuted = startExecDateTime;
            logTableOutbound.DateTimeAnswered = localDateTime;
            logTableOutbound.ClassName = strFmt("%1 - %2", _classname, _methodname);
            logTableOutbound.Success = _success;
            logTableOutbound.HasError = !logTableOutbound.Success;
            logTableOutbound.Response = _responsemessage;
            logTableOutbound.insert();
    
            ttscommit;
        }
    
    }
     
    So, if you can see, the "LogInbound" is executed before change company and inserted as 'dat'. 
     
    Thanks.
     
     
  • Martin Dráb Profile Picture
    Martin Dráb 225,446 Super User on at
    How to log external API integration ?
    Are you sure that your error handling code is called at all? If you didn't debug it and you're just guessing, you may be working with wrong assumptions.
     
    When you'll be in debugging, check out the transaction level too.
     
    I believe custom services are wrapped in transaction, and you can't catch exceptions inside a transaction.
  • Layan Jwei Profile Picture
    Layan Jwei 4,349 Super User on at
    How to log external API integration ?
    Hi Tony,
     
    Can you show us full code please in order to help? Because you said you have ttsbegin and ttscommit before the try catch for the first insert right? However your code in one of the replies doesn't show that
     
    Another question: at which line of code does the error happen?

    Also, i would advise you to catch errors like this:
     
    System.Exception ex;
    try
    {
     
    }
    catch(ex)
    {
        error(ex.Message)
    }
     
    Thanks,
    Layan Jweihan
    Please mark this answer as "Verified" if it solved your issue. In order to help others who will face a similar issue in the future
  • Voltes Profile Picture
    Voltes 898 on at
    How to log external API integration ?
    Hi guys,
     
    May I get an advice on the issue ? The problem I'm getting is now it looks like the log insertion is always roll-back, even though the "log insertion" method is put outside (before) Try..Catch.

    The roll-back happened when it hits some error, if I debug and take a look at SQL server, the 1st time insert is succeeded, and I had ttscommit right after. But when error happened, when I check again the record is gone.

    If the main process is not having issue, the 1st insertion is saved, so does the 2nd insertion. But if there is an error, only the 2nd insertion saved.

    Thanks.
  • Voltes Profile Picture
    Voltes 898 on at
    How to log external API integration ?
    The API integration is by creating custom service class, which as usual will be put in Service Group. Then the third-party will call the URL with the Service group and the specific class and method.
     
    I ended up, creates an easy approach by logging the information in each method into a custom table made for log.
    So, if lets say I have a service class with method :
    - Create PO
    - CreateGRN
     
    At each of these method, at the start of the method, there will be "insert_to_log" statement to grab the request string which the method will receive in its parameter. Then at the end of the same method, I'm logging again the result of the method (response).
    Something like this:
    class MyService
    {
         public MyResponse createPO (MyRequest  _request)
         {
             Notes json = FormJsonSerializer::serializeClass(_request);
             <insert_to_log including json>;
    
             try{
             .
             . <code>
             . response(True);
               }
             catch(
                response(False)
             }
             
             <insert_to_log including response>;
    
             return response;
    
         }
    
    
         public MyResponse CreateGRN(MyRequest  _request)
         {
             Notes json = FormJsonSerializer::serializeClass(_request);
             <insert_to_log including json>;
    
             try{
             .
             . <code>
             . response(True);
               }
             catch(
                response(False)
             }
             
             <insert_to_log including response>;
    
             return response;
    
         }
    }
     
    By this way, every time "someone" call the service class, it will be log in my log table.
     
    However there is some issue I'm encounter. Although I put the first insert_to_log before and outside Try..catch(), seems when there is some error during the "main" procedure running which produce catch error, that first log record is roll back. 
    Thanks,
     
     
  • Kevin Xia Profile Picture
    Kevin Xia Microsoft Employee on at
    How to log external API integration ?
    Hi,
    What tools did you use for API integration, and did you follow the steps described in the official Microsoft documentation? For more details: Data management package REST API - Finance & Operations | Dynamics 365 | Microsoft LearnThis article describes the Data management framework's package representational state transfer (REST) application programming interface (API). The package API lets you integrate by using data packages. The REST API can be used with both cloud deployments and on-premises deployments.
    Best regards,
    Kevin
  • Voltes Profile Picture
    Voltes 898 on at
    How to log external API integration ?
    Hi Kevin,
     
    May I know for "Your client application should generate and log a client request ID () ", this client application means F&O application or the external third-party apps that trying to reach out ? How to know the request coming from where exactly ? should we record first like a master table of what third-party apps will have interaction with us either it is incoming or outgoing ? 

    If lets say my third-party vendor will call or using my service class name /api/services/MYServiceGroup/ConfirmOrderService/PostConfirmation,
    which I can break down to be :
    1. Service group name = MYServiceGroup
    2. Service class name = ConfirmOrderService
    3. Method name = PostConfirmation.

    Can I get all that, so that I can put this info into my LogTable.

    Also about the Incoming or Outgoing, the above service is when my third-party vendor trying to call my service class to post some transactions (example: running PO post confirm). I can categorized it as Incoming, 
    And the third-party vendor will sometime call my service or call the standard entity like /data/WarehousesOnHandV2, how to identify this action ? to know what is they are calling, also what if I want to know what is their parameter when call that entity ? Like sometime we can call this entity with parameter like : /data/WarehousesOnHandV2?cross-company=false&$filter=dataAreaId eq 'TST' and ItemNumber eq 'Item0001'  

    Basically I want to capture all this, and put in the Log table.

     
    Thanks,
  • Voltes Profile Picture
    Voltes 898 on at
    How to log external API integration ?
    Hi Kevin,
     
    Thanks for your reply. I did take a look at the link you're provided. But obviously there is not much of explanation of what needs to be done ->
     
    Is there more detail explanation, like the steps to do. Like I mentioned, I barely new in this API thing, looking to this, so to be honest I don't know what the resource talking about. Sorry to say.
    Thanks
     
  • Suggested answer
    Kevin Xia Profile Picture
    Kevin Xia Microsoft Employee on at
    How to log external API integration ?
    Hi,
    There's an official Microsoft documentation here: Service request tracing - Finance & Operations | Dynamics 365 | Microsoft Learn, which introduces a best practice when you develop data integrations with finance and operations service endpoints. you should include a request identifier in the request header. In this way, you enable the request to be traced through the service. Your client application should generate and log a client request ID () value and send it in the application programming interface (API) request header.
    If the above documents do not meet your requirements, you can choose to create a table that stores the integration logs, including fields such as timestamps, request payloads, response status, error messages, etc.
    Best regards,
    Kevin

Helpful resources

Quick Links

Community Spotlight of the Month

Kudos to Saurav Dhyani!

Congratulations to the June Top 10 community leaders!

These stars go above and beyond . . .

June 2024 Dynamics 365 Community Newsletter

Catch up on the latest news, events, and plans in the community

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 285,407 Super User

#2
Martin Dráb Profile Picture

Martin Dráb 225,446 Super User

#3
nmaenpaa Profile Picture

nmaenpaa 101,148

Leaderboard

Featured topics

Product updates

Dynamics 365 release plans