Merged PR 11569: added local error services and removed error services common
added local error services and removed error services common
This commit is contained in:
parent
7a389414c5
commit
c238f339ba
@ -22,10 +22,10 @@ $insert LOGICAL
|
|||||||
$insert RTI_DEBUG_COMMON
|
$insert RTI_DEBUG_COMMON
|
||||||
$insert ENVIRON_CONSTANTS
|
$insert ENVIRON_CONSTANTS
|
||||||
|
|
||||||
Equ CRLF$ to \0D0A\
|
|
||||||
|
|
||||||
Common /ErrorServices/ ErrorMessages@, ErrorSources@, ErrorCodes@, RetStacks@, EsSpStatCode@, EsSpStatMessage@, Unused7@, Unused8@
|
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 function Environment_Services, Logging_Services, GetSessionCallStack, Error_Services, RetStack
|
||||||
Declare subroutine Logging_Services, Get_Status, Set_Env
|
Declare subroutine Logging_Services, Get_Status, Set_Env
|
||||||
|
|
||||||
|
404
LSL2/STPROC/ERROR_SERVICES.txt
Normal file
404
LSL2/STPROC/ERROR_SERVICES.txt
Normal file
@ -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<MTEXT$> = ErrorMessage
|
||||||
|
MsgStruct<MTYPE$> = 'BO'
|
||||||
|
MsgStruct<MMODAL$> = 'W'
|
||||||
|
MsgStruct<MICON$> = '!'
|
||||||
|
MsgStruct<MCOL$> = -1
|
||||||
|
MsgStruct<MROW$> = -1
|
||||||
|
MsgStruct<MJUST$> = Justification
|
||||||
|
MsgStruct<MCAPTION$> = 'Error Services'
|
||||||
|
MsgStruct<MFONT$> = 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 = '<Service Response>'
|
||||||
|
|
||||||
|
End Service
|
||||||
|
|
||||||
|
|
||||||
|
Service GetSources()
|
||||||
|
|
||||||
|
// Business logic goes here. Data that needs to be returned should be assigned to the Response parameter.
|
||||||
|
Response = '<Service Response>'
|
||||||
|
|
||||||
|
End Service
|
||||||
|
|
||||||
|
|
||||||
|
Service GetCode()
|
||||||
|
|
||||||
|
// Business logic goes here. Data that needs to be returned should be assigned to the Response parameter.
|
||||||
|
Response = '<Service Response>'
|
||||||
|
|
||||||
|
End Service
|
||||||
|
|
||||||
|
|
||||||
|
Service GetCodes()
|
||||||
|
|
||||||
|
// Business logic goes here. Data that needs to be returned should be assigned to the Response parameter.
|
||||||
|
Response = '<Service Response>'
|
||||||
|
|
||||||
|
End Service
|
||||||
|
|
||||||
|
|
||||||
|
Service GetStackTrace()
|
||||||
|
// Business logic goes here. Data that needs to be returned should be assigned to the Response parameter.
|
||||||
|
Response = '<Service 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
|
@ -1,4 +0,0 @@
|
|||||||
Compile Insert ERROR_SERVICES_COMMON
|
|
||||||
|
|
||||||
Common /ErrorServices/ ErrorMessages@, ErrorSources@, ErrorCodes@, RetStacks@, EsSpStatCode@, EsSpStatMessage@, Unused7@, Unused8@
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user