Question
· May 9, 2018

Standardizing Error Logging

I have been tasked with creating a class that will handle error logging in a consistent manor for an application I am working on.  The need is to have all variables in the calling method logged along with some other information. 

The example given was zwrite which is exactly what I need, however, I somehow need to capture the output of ZW and put it into a database table.  Any easy way to capture this data?  I was able to dump ZW to a file, but that is not ideal.

Any help is appreciated!

Discussion (8)2
Log in or sign up to continue

This is a bit of an experimental (not released) error dump utility that I developed not so long back to explore the idea of dumping all variables into a JSON string.

It uses undocumented $zu functions which are listed on this site...

http://www.cachewiki.org/index.php/Undocumented_Syntax

Essentially you use $zu(42 to $order over the variables at a specific stack level.

In this instance I build an exception object with all of the primitives and objects at the stack level in error.

I then use the Cogs JSON library to covert the entire error object into a serialised JSON string that is embedded into a Status string. The good thing here is that it will do a deep serialisation of objects which often get clipped in other solutions.

From here I can pass the JSON part of the Status string to an error log viewing tool that formats the JSON into an HTML view.

It doesn't look like I fully got the stack levels into the object, so the code would need some further tweaking.

Class Cogs.Lib.Status Extends Cogs.JsonClass
{

Property Error As %String(MAXLEN = 50000);

Property Stack As array Of %String(MAXLEN = 50000);

Property Objects As array Of Cogs.Lib.Status.Object;

Property Primatives As array Of %String(MAXLEN = 50000);

ClassMethod AsStatus(pException As %Exception.AbstractException) As %Status
{
    set sc=pException.AsStatus()
    try {
        do pException.Log()
        set status=##class(Cogs.Lib.Status).%New()
        set status.Error=$zerror
        for i=1:1:$stack-1 do status.Stack.SetAt($stack(i,"PLACE")_" : "_$zstrip($stack(i, "MCODE"),"<W"),i)
        set level=$ZU(41)-2
        set var=$zu(42,level,"~")
        while var'="" {
            set name=$p(var,"~",2)
            set item=$zu(43,level,var)
            if $data(item),item'["%Exception.SystemException" {
                if $IsObject(item) {
                    set object=##class(Cogs.Lib.Status.Object).%New()
                    set object.Reference=item
                    set object.Properties=##class(Cogs.JsonObject).toJSON(item)
                    do status.Objects.SetAt(object,name)
                } else {
                    do status.Primatives.SetAt(item,name)
                }
            }
            set var=$zu(42,level,var)
        }
        set sc=$$$ERROR($p(##class(%SYSTEM.Status).GetErrorCodes(sc),","),status.toJSON())
    } catch err {}
    quit sc
}

}

Example in use...

Class Foo.Exception Extends %RegisteredObject
{

ClassMethod Foo()
{
    try {
        set customer=##class(Northwind.Customers).%OpenId("ALFKI")
        set foo="Hello, World"
        set sc=$$$ERROR($$$GeneralError,"A general error type")
        $$$ThrowOnError(sc)
    } catch exception {
        set errorString=##class(Cogs.Lib.Status).AsStatus(exception)
        write !,errorString
    }
}

}

The error object...

{
   "Error":"",
   "Objects":{
      "customer":{
         "Properties":{
            "Address":"Obere Str. 57",
            "City":"Berlin",
            "CompanyName":"Alfreds Futterkiste",
            "ContactName":"Maria Anders",
            "ContactTitle":"Sales Representative",
            "Country":"Germany",
            "CustomerID":"ALFKI",
            "Fax":"030-0076545",
            "Phone":"030-0074321",
            "PostalCode":"12209",
            "Region":""
         },
         "Reference":"1@Northwind.Customers"
      },
      "exception":{
         "Properties":{
            "NextException":""
         },
         "Reference":"2@%Exception.StatusException"
      }
   },
   "Primatives":{
      "foo":"Hello, World",
      "sc":"0 $\u0001\u0004\u0004‰\u0013\u0016\u0001A general error type\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"
   },
   "Stack":{
      "1":"zFoo+7^Foo.Exception.1 +1 : set errorString=##class(Cogs.Lib.Status).AsStatus(exception)"
   }
}