mnjstwins
3/31/2016 - 6:04 PM

App.Log.cls.xml

<?xml version="1.0" encoding="UTF-8"?>
<Export generator="Cache" version="25" zv="Cache for Windows (x86-64) 2015.1.1 (Build 505U)" ts="2015-06-17 22:55:48">
<Class name="App.Log">
<Super>%Persistent</Super>
<TimeChanged>63720,82487.41709</TimeChanged>
<TimeCreated>63685,63064.148177</TimeCreated>

<Parameter name="Null">
<Description>
Replacement for missing values</Description>
<Default>Null</Default>
</Parameter>

<Property name="EventType">
<Description>
Type of event</Description>
<Type>%String</Type>
<InitialExpression>"INFO"</InitialExpression>
<Parameter name="MAXLEN" value="10"/>
<Parameter name="VALUELIST" value=",NONE,FATAL,ERROR,WARN,INFO,STAT,DEBUG,RAW"/>
</Property>

<Property name="ClassName">
<Description>
Name of class, where event happened</Description>
<Type>%String</Type>
<Parameter name="MAXLEN" value="256"/>
</Property>

<Property name="MethodName">
<Description>
Name of method, where event happened</Description>
<Type>%String</Type>
<Parameter name="MAXLEN" value="128"/>
</Property>

<Property name="Source">
<Description>
Line of int code</Description>
<Type>%String</Type>
<Parameter name="MAXLEN" value="2000"/>
</Property>

<Property name="UserName">
<Description>
Cache user</Description>
<Type>%String</Type>
<InitialExpression>$username</InitialExpression>
<Parameter name="MAXLEN" value="128"/>
</Property>

<Property name="Arguments">
<Description>
Arguments' values passed to method</Description>
<Type>%String</Type>
<Parameter name="MAXLEN" value="32000"/>
<Parameter name="TRUNCATE" value="1"/>
</Property>

<Property name="TimeStamp">
<Description>
Date and time</Description>
<Type>%TimeStamp</Type>
<InitialExpression>$zdt($h, 3, 1)</InitialExpression>
</Property>

<Property name="Message">
<Description>
User message</Description>
<Type>%String</Type>
<Parameter name="MAXLEN" value="32000"/>
<Parameter name="TRUNCATE" value="1"/>
</Property>

<Property name="ClientIPAddress">
<Description>
User IP address</Description>
<Type>%String</Type>
<InitialExpression>..GetClientAddress()</InitialExpression>
<Parameter name="MAXLEN" value="32"/>
</Property>

<Index name="idxEventType">
<Type>bitmap</Type>
<Properties>EventType</Properties>
</Index>

<Index name="idxUserName">
<Type>bitmap</Type>
<Properties>UserName</Properties>
</Index>

<Index name="idxClassName">
<Type>bitmap</Type>
<Properties>ClassName</Properties>
</Index>

<Index name="idxTimeStamp">
<Type>bitslice</Type>
<Properties>TimeStamp</Properties>
</Index>

<Index name="idxClientIPAddress">
<Properties>ClientIPAddress</Properties>
</Index>

<Method name="GetClientAddress">
<Description>
Determine user IP address</Description>
<ClassMethod>1</ClassMethod>
<Implementation><![CDATA[
	// %CSP.Session source is preferable
	#dim %request As %CSP.Request
	If ($d(%request)) {
		Return %request.CgiEnvs("REMOTE_ADDR")
	}
	Return $system.Process.ClientIPAddress()
]]></Implementation>
</Method>

<Method name="AddRecord">
<Description>
Add new log event
Use via $$$LogEventTYPE().</Description>
<ClassMethod>1</ClassMethod>
<FormalSpec>ClassName:%String="",MethodName:%String="",Source:%String="",EventType:%String="",Arguments:%String="",Message:%String=""</FormalSpec>
<Implementation><![CDATA[
	Set record = ..%New()
	Set record.Arguments = Arguments
	Set record.ClassName = ClassName
	Set record.EventType = EventType
	Set record.Message = Message
	Set record.MethodName = MethodName
	Set record.Source = Source
	Do record.%Save()
]]></Implementation>
</Method>

<Method name="GetMethodArguments">
<Description>
Entry point to get method arguments string </Description>
<ClassMethod>1</ClassMethod>
<FormalSpec>ClassName:%String,MethodName:%String</FormalSpec>
<ReturnType>%String</ReturnType>
<Implementation><![CDATA[
	Set list = ..GetMethodArgumentsList(ClassName,MethodName)
	Set string = ..ArgumentsListToString(list)
	Return string
]]></Implementation>
</Method>

<Method name="GetMethodArgumentsList">
<Description>
Get a list of method arguments</Description>
<ClassMethod>1</ClassMethod>
<FormalSpec>ClassName:%String,MethodName:%String</FormalSpec>
<ReturnType>%List</ReturnType>
<Implementation><![CDATA[
	Set result = ""
	Set def = ##class(%Dictionary.CompiledMethod).%OpenId(ClassName _ "||" _ MethodName)
	If ($IsObject(def)) {
		Set result = def.FormalSpecParsed
	}
	Return result
]]></Implementation>
</Method>

<Method name="ArgumentsListToString">
<Description>
Convert list of method arguments to string</Description>
<ClassMethod>1</ClassMethod>
<FormalSpec>List:%List</FormalSpec>
<ReturnType>%String</ReturnType>
<Implementation><![CDATA[
	Set result = ""
	For i=1:1:$ll(List) {
		Set result = result _ $$$quote($s(i>1=0:"",1:"; ") _ $lg($lg(List,i))_"=") 
		_ ..GetArgumentValue($lg($lg(List,i)),$lg($lg(List,i),2))
		_$S(i=$ll(List)=0:"",1:$$$quote(";"))
	}
	Return result
]]></Implementation>
</Method>

<Method name="GetArgumentValue">
<ClassMethod>1</ClassMethod>
<FormalSpec>Name:%String,ClassName:%Dictionary.CacheClassname</FormalSpec>
<ReturnType>%String</ReturnType>
<Implementation><![CDATA[
	If $ClassMethod(ClassName, "%Extends", "%RegisteredObject") {
		// it's an object
		Return "_##class(App.Log).SerializeObject("_Name _ ")_"
	} Else {
		// it's a datatype
		Return "_$g(" _ Name _ ","_$$$quote(..#Null)_")_"
	}
]]></Implementation>
</Method>

<Method name="SerializeObject">
<ClassMethod>1</ClassMethod>
<FormalSpec>Object</FormalSpec>
<ReturnType>%String</ReturnType>
<Implementation><![CDATA[
	Return:'$IsObject(Object) Object
	Return ..WriteJSONFromObject(Object)
]]></Implementation>
</Method>

<Method name="WriteJSONFromObject">
<ClassMethod>1</ClassMethod>
<FormalSpec>Object</FormalSpec>
<ProcedureBlock>0</ProcedureBlock>
<ReturnType>%String</ReturnType>
<Implementation><![CDATA[
    // Create a string that we will redirect to
    Set Str = ""

    Use $io::("^"_$ZNAME)
 
    // Enable redirection
    Do ##class(%Device).ReDirectIO(1)
 
    // Any write statements here will be redirected to the labels defined below
    Do ##class(%ZEN.Auxiliary.jsonProvider).%ObjectToJSON(Object)
 
    // Disable redirection
    Do ##class(%Device).ReDirectIO(0)
    
    Return Str
 
    // Labels that allow for IO redirection
    // Read Character - we don't care about reading
rchr(c)      Quit
    // Read a string - we don't care about reading
rstr(sz,to)  Quit
    // Write a character - call the output label
wchr(s)      Do output($char(s))  Quit
    // Write a form feed - call the output label
wff()        Do output($char(12))  Quit
    // Write a newline - call the output label
wnl()        Do output($char(13,10))  Quit
    // Write a string - call the output label
wstr(s)      Do output(s)  Quit
    // Write a tab - call the output label
wtab(s)      Do output($char(9))  Quit
    // Output label - this is where you would handle what you actually want to do.
    // in our case, we want to write to Str
output(s)    Set Str = Str_s Quit
]]></Implementation>
</Method>

<Method name="LoadContext">
<ClassMethod>1</ClassMethod>
<FormalSpec>Id</FormalSpec>
<ProcedureBlock>0</ProcedureBlock>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
	Return:'..%ExistsId(Id) $$$OK
	Set Obj = ..%OpenId(Id)
	Set Arguments = Obj.Arguments
	Set List = ..GetMethodArgumentsList(Obj.ClassName,Obj.MethodName)
	For i=1:1:$Length(Arguments,";")-1 {
		Set Argument = $Piece(Arguments,";",i)
		Set @$lg($lg(List,i)) = ..DeserializeObject($Piece(Argument,"=",2),$lg($lg(List,i),2))
	}
	Kill Obj,Arguments,Argument,i,Id,List
]]></Implementation>
</Method>

<Method name="DeserializeObject">
<ClassMethod>1</ClassMethod>
<FormalSpec>String,ClassName</FormalSpec>
<ReturnType>%String</ReturnType>
<Implementation><![CDATA[
	If $ClassMethod(ClassName, "%Extends", "%RegisteredObject") {
		// it's an object
		Set st = ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject(String,,.obj)
		Return:$$$ISOK(st) obj
	}
	Return String
]]></Implementation>
</Method>

<Storage name="Default">
<Type>%Library.CacheStorage</Type>
<DataLocation>^App.LogD</DataLocation>
<DefaultData>LogDefaultData</DefaultData>
<IdLocation>^App.LogD</IdLocation>
<IndexLocation>^App.LogI</IndexLocation>
<StreamLocation>^App.LogS</StreamLocation>
<Data name="LogDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
<Value name="2">
<Value>EventType</Value>
</Value>
<Value name="3">
<Value>ClassName</Value>
</Value>
<Value name="4">
<Value>UserName</Value>
</Value>
<Value name="5">
<Value>MethodName</Value>
</Value>
<Value name="6">
<Value>Arguments</Value>
</Value>
<Value name="7">
<Value>TimeStamp</Value>
</Value>
<Value name="8">
<Value>Message</Value>
</Value>
<Value name="9">
<Value>ClientIPAddress</Value>
</Value>
<Value name="10">
<Value>Source</Value>
</Value>
</Data>
</Storage>
</Class>


<Routine name="App.LogMacro" type="INC" timestamp="63698,56142.070147"><![CDATA[
#define StackPlace 		$st($st(-1),"PLACE")
#define CurrentClass 	##Expression($$$quote(%classname))
#define CurrentMethod 	##Expression($$$quote(%methodname))

#define MethodArguments ##Expression(##class(App.Log).GetMethodArguments(%classname,%methodname))

#define LogEvent(%type, %message) Do ##class(App.Log).AddRecord($$$CurrentClass,$$$CurrentMethod,$$$StackPlace,%type,$$$MethodArguments,%message)
#define LogNone(%message) 		$$$LogEvent("NONE", %message)
#define LogError(%message) 		$$$LogEvent("ERROR", %message)
#define LogFatal(%message) 		$$$LogEvent("FATAL", %message)
#define LogWarn(%message) 		$$$LogEvent("WARN", %message)
#define LogInfo(%message) 		$$$LogEvent("INFO", %message)
#define LogStat(%message) 		$$$LogEvent("STAT", %message)
#define LogDebug(%message) 		$$$LogEvent("DEBUG", %message)
#define LogRaw(%message) 		$$$LogEvent("RAW", %message)

]]></Routine>


<Class name="App.Use">
<CompileAfter>App.Log</CompileAfter>
<IncludeCode>App.LogMacro</IncludeCode>
<TimeChanged>63720,81865.648288</TimeChanged>
<TimeCreated>63691,73040.917631</TimeCreated>

<Method name="Test">
<Description>
do ##class(App.Use).Test()</Description>
<ClassMethod>1</ClassMethod>
<FormalSpec><![CDATA[a:%Integer=1,&b=2]]></FormalSpec>
<Implementation><![CDATA[	$$$LogWarn("User message") // just place this macro in user code you wish to log
]]></Implementation>
</Method>

<Method name="TestWithObjects">
<Description>
do ##class(App.Use).TestWithObjects()</Description>
<ClassMethod>1</ClassMethod>
<FormalSpec>a:%Integer=1,b:%ZEN.proxyObject</FormalSpec>
<Implementation><![CDATA[	$$$LogWarn("User message")
]]></Implementation>
</Method>
</Class>
</Export>