From c238f339ba4da99a6cd300c27ca648c4b985b3e5 Mon Sep 17 00:00:00 2001 From: "Stieber Daniel (CSC FI SPS MESLEO)" Date: Tue, 25 Feb 2025 18:59:14 +0100 Subject: [PATCH] Merged PR 11569: added local error services and removed error services common added local error services and removed error services common --- LSL2/STPROC/DEBUGGER_LOGGER.txt | 4 +- LSL2/STPROC/ERROR_SERVICES.txt | 404 ++++++++++++++++++++ SYSPROG/STPROCINS/ERROR_SERVICES_COMMON.txt | 4 - 3 files changed, 406 insertions(+), 6 deletions(-) create mode 100644 LSL2/STPROC/ERROR_SERVICES.txt delete mode 100644 SYSPROG/STPROCINS/ERROR_SERVICES_COMMON.txt diff --git a/LSL2/STPROC/DEBUGGER_LOGGER.txt b/LSL2/STPROC/DEBUGGER_LOGGER.txt index 157be60..14d8f4e 100644 --- a/LSL2/STPROC/DEBUGGER_LOGGER.txt +++ b/LSL2/STPROC/DEBUGGER_LOGGER.txt @@ -22,10 +22,10 @@ $insert LOGICAL $insert RTI_DEBUG_COMMON $insert ENVIRON_CONSTANTS -Equ CRLF$ to \0D0A\ - Common /ErrorServices/ ErrorMessages@, ErrorSources@, ErrorCodes@, RetStacks@, EsSpStatCode@, EsSpStatMessage@, Unused7@, Unused8@ +Equ CRLF$ to \0D0A\ + Declare function Environment_Services, Logging_Services, GetSessionCallStack, Error_Services, RetStack Declare subroutine Logging_Services, Get_Status, Set_Env diff --git a/LSL2/STPROC/ERROR_SERVICES.txt b/LSL2/STPROC/ERROR_SERVICES.txt new file mode 100644 index 0000000..462339d --- /dev/null +++ b/LSL2/STPROC/ERROR_SERVICES.txt @@ -0,0 +1,404 @@ +Function Error_Services(@Service, @Params) +/*********************************************************************************************************************** + + This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written + permission from SRP Computer Solutions, Inc. + + Name : Error_Services + + Description : Handler program for all error services. + + Notes : Application errors should be logged using the Error Services module. There are a few methodological + assumptions built into way errors are managed which are important to understand in order to properly + work with Error Services: + + - The term 'top' refers to the originating procedure of a call stack and the term 'bottom' refers to + the last routine (or the current routine) within a call stack. Within the OpenInsight Debugger + this will appear backwards since the originating procedure always appears at the bottom of the + list and the current routine appears at the top of the list. We are using this orientation because + it is common to refer to the process of calling other procedures as 'drilling down'. + + - The reason for defining the orientation of the call stack is because Error_Services allows for + multiple error conditions to be appended to an original error. In most cases this will happen when + a procedure at the bottom of the stack generates an error condition and then returns to its + calling procedure. This higher level procedure can optionally add more information relevant to + itself. This continues as the call stack 'bubbles' its way back to the top to where the + originating procedure is waiting. + + - Native OpenInsight commands that handle errors (e.g., Set_Status, Set_FSError, Set_EventStatus) + preserve their error state until explicitly cleared. This can hinder the normal execution of code + since subsequent procedures (usually SSPs) will fail if a pre-existing error condition exists. + Our philosophy is that error conditions should automatically be cleared before a new procedure + is executed to avoid this problem. However, the nature of Basic+ does not make this easy to + automate for any given stored procedure. Therefore, if a stored procedure wants to conform to our + philosophy then it should include a call into the 'Clear' service request at the top of the + program. Alternatively this can be done through a common insert (see SERVICE_SETUP for example.) + + - Service modules will use the SERVICE_SETUP insert and therefore automatically clear out any + error conditions that were set before. + + - The 'Set' service request is the equivelent to the various forms of setting an error within Basic+ + (e.g., Set_Status, Set_FSError, Set_EventStatus). This will clear out any pre-existing error(s) + first (see 'Clear' service request description below). In most cases the 'Add' service request + (see below) should be used since error conditions are intended to be automatically cleared by + service modules or properly managed stored procedures. + + - The 'Add' service request is similar to the 'Set' service request but it will not clear out any + pre-existing errors. Using 'Add', the error conditions can be stacked allowing the higher level + calling procedures the ability to contribute to the existing error or add additional errors. + + - The 'Clear' service request will reset all of the error condition flags. + + Parameters : + Service [in] -- Name of the service being requested + Param1-10 [in/out] -- Additional request parameter holders + Response [out] -- Response to be sent back to the Controller (MCP) or requesting procedure + + History : (Date, Initials, Notes) + 12/28/12 dmb Original programmer. + 12/31/12 dmb Add hooks for various service requests. Add comments in the Notes section to explain the + theory of operation of Error Services. + 01/01/13 dmb Add functionality to the Set, Add, GetMessage, and GetMessages service requests. + 01/02/13 dmb Remove reference to SERVICES_SETUP and put the Assigned command lines directly into this + code to avoid infinite loop problem. + 01/05/13 dmb Added HasError service request. + 03/13/13 dmb [SRPFW-9] Added NoError service request. + 10/01/13 dmb [SRPFW-18] Replace APP_INSERTS with LOGICAL and declare Error_Services. + 10/06/13 dmb [SRPFW-17] Retrofit to use the default FrameWorks system font. + 03/20/17 fjt [SRPFW-160] Conversion to EB+; addition of justification parameter to display. + 10/09/17 dmb Add SendRuntimeAlert service to act as a debugger intercept process. + +***********************************************************************************************************************/ + +#pragma precomp SRP_PreCompiler + +$Insert LOGICAL +$Insert MSG_EQUATES +$Insert RTI_DEBUG_COMMON +$Insert SRPMail_Inserts +$Insert ENVIRON_CONSTANTS + +Common /ErrorServices/ ErrorMessages@, ErrorSources@, ErrorCodes@, RetStacks@, EsSpStatCode@, EsSpStatMessage@, Unused7@, Unused8@ + +Equ Segoe_UI$ to 'Segoe UI' : @SVM : -12 : @SVM : 400 : @SVM : 0 : @SVM : 0 : @SVM : 0 : @SVM : 0 : @SVM : 34 : @SVM : 0 : @SVM : 3 : @SVM : 2 : @SVM : 1 : @SVM : 0 : @SVM : 0 : @SVM : 0 : @SVM : 0 + +// Make sure any request parameters which have not been assigned are nulled. +// Normally these would be referenced in the SERVICES_SETUP insert but there is a call to ERROR_SERVICES in that +// insert which causes an infinite loop to occur. +If Assigned(Service) else Service = '' +If Assigned(Error) else Error = '' +If Assigned(Param1) else Param1 = '' +If Assigned(Param2) else Param2 = '' +If Assigned(Param3) else Param3 = '' +If Assigned(Param4) else Param4 = '' +If Assigned(Param5) else Param5 = '' +If Assigned(Param6) else Param6 = '' +If Assigned(Param7) else Param7 = '' +If Assigned(Param8) else Param8 = '' +If Assigned(Param9) else Param9 = '' +If Assigned(Param10) else Param10 = '' +If Assigned(Response) else Response = '' + +AutoDisplayErrors = False$ ; // Set this to True$ when debugging so all errors will automatically display. + +Declare function RetStack, Error_Services, SRPSendMail, Get_Env +Declare subroutine Error_Services, Set_Env, Set_Status + +GoToService else + Error_Services('Set', Service : ' is not a valid service request within the Error services module.') +end + +Return Response else '' + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Service Parameter Options +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Options BOOLEAN = True$, False$ + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Services +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +//---------------------------------------------------------------------------------------------------------------------- +// Set +// +// Param1 - Error message. Messages should be fairly descriptive. +// +// Sets an error to the stack. This will automatically clear any existing error conditions first so this error will +// be the only one on the stack. +//---------------------------------------------------------------------------------------------------------------------- +Service Set(ErrorMessage) + + Error_Services('Clear') + Error_Services('Add', ErrorMessage) + + If AutoDisplayErrors then Error_Services('DisplayError') + +End Service + + +//---------------------------------------------------------------------------------------------------------------------- +// Add +// +// Param1 - Error message. Messages should be fairly descriptive. +// +// Adds an error to the stack. This will not clear existing error conditions first. It is intended to allow higher level +// routines to add more information to an existing error condition or simply to maintain an ongoing error log for some +// troubleshooting or debugging purposes. +//---------------------------------------------------------------------------------------------------------------------- +Service Add(ErrorMessage) + + CurStack = RetStack() + AtSelf = CurStack[1, @FM] ; // AtSelf should be the name of this routine (e.g., ERROR_SERVICES) + Loop + CurRoutine = CurStack[1, @FM] ; // Get the next routine from the program call stack. + Until CurRoutine _NEC AtSelf + CurStack = Delete(CurStack, 1, 0, 0) ; // Remove any self-references from the program call stack. + Repeat + Convert @FM to @VM in CurStack ; // Convert the delimiter so it can be added to the global common. + + If Len(ErrorMessages@) then + ErrorMessages@ := @FM : ErrorMessage + RetStacks@ := @FM : CurStack + end else + ErrorMessages@ = ErrorMessage + RetStacks@ = CurStack + end + + If AutoDisplayErrors then Error_Services('DisplayError') + +End Service + + +//---------------------------------------------------------------------------------------------------------------------- +// Clear +// +// Clears all error conditions and related information. +//---------------------------------------------------------------------------------------------------------------------- +Service Clear() + + ErrorMessages@ = '' + ErrorSources@ = '' + ErrorCodes@ = '' + RetStacks@ = '' + +End Service + + +//---------------------------------------------------------------------------------------------------------------------- +// GetMessage +// +// Returns the most current error message. +//---------------------------------------------------------------------------------------------------------------------- +Service GetMessage() + + Response = ErrorMessages@[-1, 'B' : @FM] + +End Service + + +//---------------------------------------------------------------------------------------------------------------------- +// GetMessages +// +// Returns the stack of error messages. This will be @FM delimited. +//---------------------------------------------------------------------------------------------------------------------- +Service GetMessages() + + // Business logic goes here. Data that needs to be returned should be assigned to the Response parameter. + Response = ErrorMessages@ + +End Service + + +//---------------------------------------------------------------------------------------------------------------------- +// HasError +// +// Returns True if there is an error condition, False if there is no error condition. Caller will still need to use +// the GetMessage or GetMessages service to determine what the error is. The HasError service allows the caller to +// embed the Error_Services service call inside of a conditional statement like this: +// +// If Error_Services('HasError') then +// * An error has occured. Proceed accordingly. +// ErrorMessage = Error_Services('GetMessage') +// end else +// * No error has occured. +// end +//---------------------------------------------------------------------------------------------------------------------- +Service HasError() + + If Len(ErrorMessages@) then + Response = True$ + end else + Response = False$ + end + +End Service + + +//---------------------------------------------------------------------------------------------------------------------- +// NoError +// +// Returns True if there are no error conditions, False if there is an error condition. This is the opposite of the +// HasError service and exists for improved readability. +//---------------------------------------------------------------------------------------------------------------------- +Service NoError() + + If Len(ErrorMessages@) then + Response = False$ + end else + Response = True$ + end + +End Service + + +//---------------------------------------------------------------------------------------------------------------------- +// DisplayError +// +// Displays the current error message to the end user. +//---------------------------------------------------------------------------------------------------------------------- +Service DisplayError(Justification) + + ErrorMessage = Error_Services('GetMessage') + If Len(ErrorMessage) then + MsgStruct = '' + MsgStruct = ErrorMessage + MsgStruct = 'BO' + MsgStruct = 'W' + MsgStruct = '!' + MsgStruct = -1 + MsgStruct = -1 + MsgStruct = Justification + MsgStruct = 'Error Services' + MsgStruct = Segoe_UI$ + Msg(@Window, MsgStruct) + end + +End Service + + +Service GetSource() + + // Business logic goes here. Data that needs to be returned should be assigned to the Response parameter. + Response = '' + +End Service + + +Service GetSources() + + // Business logic goes here. Data that needs to be returned should be assigned to the Response parameter. + Response = '' + +End Service + + +Service GetCode() + + // Business logic goes here. Data that needs to be returned should be assigned to the Response parameter. + Response = '' + +End Service + + +Service GetCodes() + + // Business logic goes here. Data that needs to be returned should be assigned to the Response parameter. + Response = '' + +End Service + + +Service GetStackTrace() + // Business logic goes here. Data that needs to be returned should be assigned to the Response parameter. + Response = '' +End Service + + +//---------------------------------------------------------------------------------------------------------------------- +// LogStack +// +// Uses a custom debugger intercept to log the stack including line numbers to .../LogFiles/StackTrace. +//---------------------------------------------------------------------------------------------------------------------- +Service LogStack() + + DebuggerEnabled = Get_Env(ENV_DEBUGGER_ENABLED$) + DebuggerIntercept = Get_Env(ENV_DEBUGGER_INTERCEPT_PROC$) + Set_Env(ENV_DEBUGGER_ENABLED$, 2, 1) + Set_Env(ENV_DEBUGGER_INTERCEPT_PROC$, 'DEBUGGER_LOGGER', 1) + // Save the current status code and message before forcing runtime error + // to get OI to update stack variables in RTI_DEBUG_COMMON. + EsSpStatCode@ = Get_Status(EsSpStatMessage@) + ForceRuntimeError = 1/0 + Set_Env(ENV_DEBUGGER_ENABLED$, DebuggerEnabled, 1) + Set_Env(ENV_DEBUGGER_INTERCEPT_PROC$, DebuggerIntercept, 1) + // Restore OI status variables so we don't break any logic relying on it. + Set_Status(EsSpStatCode@, EsSpStatMessage@) + +end service + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Internal GoSubs +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////? + +//---------------------------------------------------------------------------------------------------------------------- +// SendRuntimeAlert +// +// Sends out an email alert when this service is called as a debugger intercept. +//---------------------------------------------------------------------------------------------------------------------- +SendRuntimeAlert: + + Done = False$ + Error = False$ + Program = Curr_Program@ + MsgSent = '' + + If Program EQ '' then Program = 'Error Services' + + ConfigFile = '' + ConfigFile<1> = SendUsing_Port$ + ConfigFile<2> = '' + ConfigFile<3> = '' ; // Server port + ConfigFile<4> = '' ; // Mail server + ConfigFile<5> = True$ ; // Authenticate + ConfigFile<6> = '' ; // Username + ConfigFile<7> = '' ; // Password + ConfigFile<8> = False$ ; // Use SSL + + Text = '' + Text<-1> = 'App: ' : @APPID<1> + Text<-1> = 'Window: ' : @WINDOW + Text<-1> = 'User: ' : @USERNAME + Text<-1> = 'Station: ' : @STATION + Text<-1> = ' ' + Text<-1> = 'SP Status: ' : SPStatus@ + Text<-1> = 'SP Stat Code: ' : SPStatCode@ + Text<-1> = 'Program: ' : Program + Text<-1> = 'Call Depth: ' : CallDepth@ + Text<-1> = 'Line No: ' : LineNo@ + Text<-1> = ' ' + Text<-1> = 'Stack: ' + Text<-1> = CallStack@ + Convert \00\ TO ',' in Text + Swap @VM with ':@VM:' IN Text + Swap @FM with Char(13) : Char(10) IN Text + Swap @TM with Char(13) : Char(10) IN Text + + SentFrom = '' + SentTo = '' + Message = '' + Message<1> = '' : Program ; // Subject + Message<2> = SentFrom ; // From (email address) + Message<3> = SentTo ; // Send to (email address) + Message<5> = '' ; // Blind Carbon Copy (email address) + Message<6> = '' ; // Reply To (email address) + Message<7> = 'TEXT' ; // Content Type (TEXT or HTML) + Message<8> = Text ; // Content / Body + Message<9> = '' ; // Attachment(s) (path to file name(s)) + + MsgSent = SRPSendMail(Message, ConfigFile) + +return diff --git a/SYSPROG/STPROCINS/ERROR_SERVICES_COMMON.txt b/SYSPROG/STPROCINS/ERROR_SERVICES_COMMON.txt deleted file mode 100644 index 442af5e..0000000 --- a/SYSPROG/STPROCINS/ERROR_SERVICES_COMMON.txt +++ /dev/null @@ -1,4 +0,0 @@ -Compile Insert ERROR_SERVICES_COMMON - -Common /ErrorServices/ ErrorMessages@, ErrorSources@, ErrorCodes@, RetStacks@, EsSpStatCode@, EsSpStatMessage@, Unused7@, Unused8@ -