Skip to content

Instantly share code, notes, and snippets.

@eduard93
Last active March 31, 2016 18:04
Show Gist options
  • Save eduard93/3af3e1f31604fef81df6 to your computer and use it in GitHub Desktop.
Save eduard93/3af3e1f31604fef81df6 to your computer and use it in GitHub Desktop.
<?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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment