Feedback
Did this article resolve your question/issue?

   

Article

Sample Code for Analyzing PASOE Agent Log for Possible Memory Leaks

« Go Back

Information

 
TitleSample Code for Analyzing PASOE Agent Log for Possible Memory Leaks
URL Namesample-code-for-analyzing-pasoe-agent-log-for-possible-memory-leaks
Article Number000179127
EnvironmentProduct: OpenEdge
Version: 11.6
OS: All Supported Platforms
Other: Progress Application Server for OpenEdge (PASOE)
Question/Problem Description
Sample Code for Analyzing PASOE Agent Log for Possible Memory Leaks
Steps to Reproduce
Clarifying Information
Error Message
Defect/Enhancement Number
Cause
Resolution
// This Program Walks Through A PASOE AppServer Agent Log File And Produces
// A Report Showing All DynObjects That Were Created But Not Deleted.
// 
// Please Note That You Should Not Use This Code Against A Log File Where
// The PASOE Instance Was Shut Down Normally As Then It Won't Show Anything
// Useful Because All Left Over DynObjects Will Get Deleted At Shutdown
// And The Log File Will Contain Deleted Entries For Each Left Over Object.
// 
// One Future Enhancement To This Code Will Implement A User Defined Time Check
// In Minutes Between Object Creation and Object Deletion To Determine Whether
// To Report An Object That Hung Around Longer Than <N> Minutes As A Potential
// Problem. This Will Allow This Program To Be Used Against A Log File Where
// The PASOE Instance Was Shut Down.  A Second Future Enhancement To This Code
// Will Handle The Allocated/Deallocated Logging Which DynObjects.* Writes To
// The Agent Log.
// 
// NOTE: The PASOE AppServer Must Have The Following Values Set
//       In The <PAS-Instance>\conf\openedge.properties file:
// 
//       AgentLoggingLevel=4
//       AgenLogEntryTypes=ASPlumbing,DB.Connects,DynObjects.*

DEFINE TEMP-TABLE TTObject NO-UNDO
    FIELD CreateLine       AS INTEGER   FORMAT "ZZZ,ZZZ,ZZ9"
    FIELD DeleteLine       AS INTEGER   FORMAT "ZZZ,ZZZ,ZZ9"
    FIELD LogDateTime      AS CHARACTER FORMAT "X(28)"
    FIELD ProcessID        AS CHARACTER FORMAT "X(20)"
    FIELD ThreadID         AS CHARACTER FORMAT "X(20)"
    FIELD ObjectType       AS CHARACTER FORMAT "X(50)"
    FIELD Created          AS LOGICAL
    FIELD Deleted          AS LOGICAL
    FIELD Allocated        AS LOGICAL
    FIELD Deallocated      AS LOGICAL
    FIELD ObjectHandle     AS INTEGER
    FIELD ObjectDetails    AS CHARACTER
    INDEX HandleIndex      AS UNIQUE ProcessID ThreadID ObjectType ObjectHandle
    INDEX MainIndex        AS UNIQUE CreateLine.
        
DEFINE VARIABLE ILineNumber AS INTEGER   NO-UNDO.
DEFINE VARIABLE CData       AS CHARACTER NO-UNDO.

// Change This To Correlate To The Date Format Used By Your <PasInstance>.Agent.log File

SESSION:DATE-FORMAT = "YMD".

// Change This To Point To Your <PasInstance>.Agent.log File

INPUT FROM C:\DLCWORK\OEPAS1\logs\OEPAS1.Agent.log.
REPEAT:
    ASSIGN ILineNumber = ILineNumber + 1.
    IMPORT UNFORMATTED CData.
    IF INDEX(CData, 'DYNOBJECTS') > 0 THEN
        // Grab Object Action From Line & Append To Prefix Then Run As Internal Procedure
        // Ignoring Any Error That May Arise Because We Haven't Implemented An Internal
        // Procedure For Said Object Action 
        RUN VALUE('Handle' + TRIM(SUBSTRING(CData, 74, 11))) IN THIS-PROCEDURE NO-ERROR.
END.    
INPUT CLOSE.

RUN ProduceReport IN THIS-PROCEDURE.

QUIT.

PROCEDURE HandleCreated:
    DO TRANSACTION:
        CREATE TTObject.
        ASSIGN TTObject.CreateLine    = ILineNumber
               TTObject.LogDateTime   = SUBSTRING(CData, 2, 26)
               TTObject.ProcessID     = TRIM(ENTRY(2, CData, ' '))
               TTObject.ThreadID      = TRIM(ENTRY(3, CData, ' '))
               TTObject.ObjectType    = TRIM(SUBSTRING(CData, 89, (INDEX(CData, 'Handle:') - 89)))
               TTObject.Created       = TRUE
               TTObject.ObjectHandle  = INTEGER(ENTRY(1, SUBSTRING(CData, (INDEX(CData, 'Handle:') + 7), 20), ' '))
               TTObject.ObjectDetails = CData.
   END.
END PROCEDURE.

PROCEDURE HandleDeleted:
    DEFINE VARIABLE LVProcessID    AS CHARACTER NO-UNDO FORMAT "X(20)".
    DEFINE VARIABLE LVThreadID     AS CHARACTER NO-UNDO FORMAT "X(20)".
    DEFINE VARIABLE LVObjectType   AS CHARACTER NO-UNDO FORMAT "X(50)".
    DEFINE VARIABLE LVObjectHandle AS INTEGER   NO-UNDO.

    ASSIGN LVProcessID    = TRIM(ENTRY(2, CData, ' '))
           LVThreadID     = TRIM(ENTRY(3, CData, ' '))
           LVObjectType   = TRIM(SUBSTRING(CData, 89, (INDEX(CData, 'Handle:') - 89)))
           LVObjectHandle = INTEGER(ENTRY(1, SUBSTRING(CData, (INDEX(CData, 'Handle:') + 7), 20), ' ')).
    
    FIND TTObject WHERE TTObject.ProcessID    = LVProcessID    AND 
                        TTObject.ThreadID     = LVThreadID     AND 
                        TTObject.ObjectType   = LVObjectType   AND 
                        TTObject.ObjectHandle = LVObjectHandle AND 
                        TTObject.Created      = TRUE           NO-ERROR.
                        
    IF AVAILABLE(TTObject) THEN
        DO TRANSACTION:
            ASSIGN TTObject.DeleteLine = ILineNumber
                   TTObject.Deleted    = TRUE.
        END.
    ELSE 
        MESSAGE 'Cannot Find Record That Matches Deletion. Possible Partial Log File?' VIEW-AS ALERT-BOX.
END PROCEDURE.

PROCEDURE HandleAllocated:
    // Not Yet Implemented
END PROCEDURE.

PROCEDURE HandleDeallocated:
    // Not Yet Implemented
END PROCEDURE.

PROCEDURE ProduceReport:
    // Produce Simple Report Showing Objects That Were Created But Not Deleted.
    // This Report Can Be Changed to Report by ProcessID and ThreadID If Required.
    
    OUTPUT TO DynObjectReport.txt.
    FOR EACH TTObject NO-LOCK WHERE TTObject.Deleted = FALSE BY TTObject.CreateLine:
        PUT UNFORMATTED 'File Line (Creation) = ' TTObject.CreateLine SKIP
                        'Date/Time Stamp      = ' TTObject.LogDateTime SKIP
                        'Process ID           = ' TTObject.ProcessID SKIP 
                        'Thread ID            = ' TTObject.ThreadID SKIP 
                        'Object Type          = ' TTObject.ObjectType SKIP 
                        'Object Handle Value  = ' TTObject.ObjectHandle SKIP 
                        'Full Line From Log   = ' TTObject.ObjectDetails SKIP(1).
    END.
    OUTPUT CLOSE.
END PROCEDURE.

 
Workaround
Notes
This code is a work in progress.  It currently does not handle the Allocate/Deallocate logging that DynObjects.* provides, nor does it handle a PASOE agent log file where the PASOE instance was shut down since that will cause delete logging for all left over DynObjects.* output and the current code will be able to match each create with its corresponding delete and consequently will not report potential leaks.

Reference to other documentation:

Progress Article(s):

000012302, How to check for leaked dynamic objects?
000084455, Detect PASOE memory leaks with Dynamic Objects Logging
Last Modified Date11/6/2017 8:35 AM
Attachment 
Files
Disclaimer The origins of the information on this site may be internal or external to Progress Software Corporation (“Progress”). Progress Software Corporation makes all reasonable efforts to verify this information. However, the information provided is for your information only. Progress Software Corporation makes no explicit or implied claims to the validity of this information.

Any sample code provided on this site is not supported under any Progress support program or service. The sample code is provided on an "AS IS" basis. Progress makes no warranties, express or implied, and disclaims all implied warranties including, without limitation, the implied warranties of merchantability or of fitness for a particular purpose. The entire risk arising out of the use or performance of the sample code is borne by the user. In no event shall Progress, its employees, or anyone else involved in the creation, production, or delivery of the code be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability to use the sample code, even if Progress has been advised of the possibility of such damages.