From 19ace35857d37fdc391574b5ad9047f3caecb23c Mon Sep 17 00:00:00 2001 From: Frisle <47441164+Frisle@users.noreply.github.com> Date: Tue, 9 Jul 2024 10:46:06 +0600 Subject: [PATCH 1/3] FEAT: add audit system Audit mechanism is simple the globals holding the runtime date each time when elements are called --- MDX2JSON/Utils.cls | 143 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 139 insertions(+), 4 deletions(-) diff --git a/MDX2JSON/Utils.cls b/MDX2JSON/Utils.cls index 0f054a5..9d99805 100644 --- a/MDX2JSON/Utils.cls +++ b/MDX2JSON/Utils.cls @@ -60,6 +60,8 @@ ClassMethod WriteJSONfromMDX(MDX As %String, Timeout As %Integer = 0) As %Status Set tSC = $$$OK #dim RS As MDX2JSON.ResultSet + set start = $PIECE($NOW(),",",2) + set RS = ..GetResultSet(MDX, .tSC) set cube = ##class(%DeepSee.Utils).%IsCubeCompound(RS.%Cube) // check if cube is compound type return:$$$ISERR(tSC) tSC @@ -87,6 +89,14 @@ ClassMethod WriteJSONfromMDX(MDX As %String, Timeout As %Integer = 0) As %Status return:$$$ISERR(tSC) tSC $$$DynObjToJSON(obj) } + + set stop = $PIECE($NOW(),",",2) + + set executionTime = stop - start + set query = RS.%GetQuery() + + set audit = ..WriteAudit(MDX, "query", executionTime) + return $$$OK } @@ -108,7 +118,6 @@ ClassMethod WriteJSONfromQuery(CubeKey As %String, QueryKey As %String, Timeout return $$$OK } - /// Execute SQL query taken from KPI and extract column values by name of column /// Output array with list of values like so pValue(n) = $LB(sNameList(i)...) ClassMethod GetSQLValues(pSQL, Output pValues As %String, Output tResultSet As %SQL.Statement) As %Status @@ -133,7 +142,6 @@ ClassMethod GetSQLValues(pSQL, Output pValues As %String, Output tResultSet As % return st } - /// This method provides listing execution for KPI. /// tKPI as a name of KPI class. pFilters not yet implemented /// as a pSelection. Thats for future use. @@ -309,7 +317,8 @@ ClassMethod GetDataSource(pDataSource As %String) set st = $$$OK try { - + set start = $PIECE($NOW(),",",2) + if ($FIND(pDataSource, ".pivot") = ($LENGTH(pDataSource) + 1) && pDataSource '="") { set st = ..OpenPivotByName(pDataSource, .dataSource) return:($$$ISERR(st)) st @@ -320,8 +329,16 @@ ClassMethod GetDataSource(pDataSource As %String) set dataSource.mdx = mdx } set st = ##class(%ZEN.Auxiliary.jsonProvider).%ObjectToJSON(dataSource, .out) + + set stop = $PIECE($NOW(),",",2) + + set executionTime = stop - start + + set audit = ..WriteAudit(pDataSource, "pivot", executionTime) + } + } catch ex { set st = ex.AsStatus() @@ -409,12 +426,22 @@ ClassMethod GetWidgetsList(pDashName As %String) As %Status ClassMethod GetDashboard(pDashName As %String) As %Status { try { + set start = $PIECE($NOW(),",",2) + set st = ##class(MDX2JSON.DashboardFilters).OpenDashboardByName(pDashName, .dash) return:($$$ISERR(st)) st set st = ##class(MDX2JSON.DashboardFilters).WidgetsToProxyObject(dash, .widgetlist) return:($$$ISERR(st)) st w "" // weird hack required for 15.3 + + set stop = $PIECE($NOW(),",",2) + + set executionTime = stop - start + + set audit = ..WriteAudit(pDashName, "dashboard", executionTime) + + $$$DynObjToJSON(widgetlist) } catch ex { set st = ex.AsStatus() @@ -557,6 +584,115 @@ ClassMethod CreateAddonClass(Class As %Dictionary.CacheClassname) As %Status quit classObj.%Save() } +ClassMethod WriteAudit(element, elementName, executionTime = 0) As %Status +{ + set st = $$$OK + + set ^CallAmount($INCREMENT(^CallAmount)) = 1 + + + if ^AuditState = "on" + { + if elementName = "dashboard" + { + set ^MyBIAuditLogDash($INCREMENT(^MyBIAuditLogDash)) = $lb($ZDT($H,3), $USERNAME, element, executionTime) + } + elseif elementName = "pivot" + { + set ^MyBIAuditLogPivot($INCREMENT(^MyBIAuditLogPivot)) = $lb($ZDT($H,3), $USERNAME, element, executionTime) + } + elseif elementName = "query" + { + set ^MyBIAuditLogQuery($INCREMENT(^MyBIAuditLogQuery)) = $lb($ZDT($H,3), $USERNAME, element, executionTime) + } + + + }else{ + + quit st + } + + + return st +} + +ClassMethod ReadAudit(metricName) As %Status +{ + set st = $$$OK + + if ^AuditState = "on" + { + if metricName = "query" + { + + set len = $order(^MyBIAuditLogQuery(""),-1) + for n=1:1:len + { + set log = $Get(^MyBIAuditLogQuery(n)) + write ! + write "Element call time: ", $lg(log, 1), ! + write "User: ", $lg(log, 2), ! + write "Execution time in sec.: ", $lg(log, 4), ! + write "Query: ", $lg(log, 3), ! + } + } + elseif metricName = "pivot" + { + + set len = $order(^MyBIAuditLogPivot(""),-1) + for n=1:1:len + { + set log = $Get(^MyBIAuditLogPivot(n)) + write ! + write "Element call time: ", $lg(log, 1), ! + write "User: ", $lg(log, 2), ! + write "Execution time in sec.: ", $lg(log, 4), ! + write "Pivot: ", $lg(log, 3), ! + } + } + elseif metricName = "dashboard" + { + set len = $order(^MyBIAuditLogDash(""),-1) + for n=1:1:len + { + set log = $Get(^MyBIAuditLogDash(n)) + write ! + write "Element call time: ", $lg(log, 1), ! + write "User: ", $lg(log, 2), ! + write "Execution time in sec.: ", $lg(log, 4), ! + write "Dashboard: ", $lg(log, 3), ! + } + } + } + + quit st +} + +ClassMethod AuditStateSwitch(auditstate = 0) As %Status +{ + set st = $$$OK + + if auditstate = 0 + { + set ^AuditState = "off" + + }else{ + + set ^AuditState = "on" + } + + write "Audit state: " _ ^AuditState +} + +ClassMethod AuditKill() As %Status +{ + kill ^MyBIAuditLogDash + kill ^MyBIAuditLogPivot + kill ^MyBIAuditLogQuery + + write "All globals are cleaned" +} + /// Add new widgets and edit existing ones directly from DeepSeeWeb /// it takes widget name(key) as unique identifier as string, dashboard name as string /// and object with parameters as zen.proxyObject @@ -672,7 +808,6 @@ ClassMethod DeleteWidget(wName As %String, sDashboard As %String) As %Status return st } - /// the collection of necessary parameters for building widget ClassMethod UpdateWidget(widgetToUpdate As %DeepSee.Dashboard.Widget, data As %ZEN.proxyObject) As %Status { From 281d8df66dec42ec8d2553aa28602d958c40ef00 Mon Sep 17 00:00:00 2001 From: Frisle <47441164+Frisle@users.noreply.github.com> Date: Thu, 11 Jul 2024 08:59:32 +0600 Subject: [PATCH 2/3] FEAT: added globals check to corresponding methods --- MDX2JSON/Utils.cls | 146 ++++----------------------------------------- 1 file changed, 11 insertions(+), 135 deletions(-) diff --git a/MDX2JSON/Utils.cls b/MDX2JSON/Utils.cls index 9d99805..efaf587 100644 --- a/MDX2JSON/Utils.cls +++ b/MDX2JSON/Utils.cls @@ -60,8 +60,6 @@ ClassMethod WriteJSONfromMDX(MDX As %String, Timeout As %Integer = 0) As %Status Set tSC = $$$OK #dim RS As MDX2JSON.ResultSet - set start = $PIECE($NOW(),",",2) - set RS = ..GetResultSet(MDX, .tSC) set cube = ##class(%DeepSee.Utils).%IsCubeCompound(RS.%Cube) // check if cube is compound type return:$$$ISERR(tSC) tSC @@ -78,6 +76,10 @@ ClassMethod WriteJSONfromMDX(MDX As %String, Timeout As %Integer = 0) As %Status set obj = RS.ToProxyObject(.tSC) return:$$$ISERR(tSC) tSC + + // check if audit global hold something and execute it + try {xecute ^DeepSee.AuditQueryCode} catch {} + $$$DynObjToJSON(obj) }else{ // if cube is not compound execute the query in usual way @@ -87,15 +89,12 @@ ClassMethod WriteJSONfromMDX(MDX As %String, Timeout As %Integer = 0) As %Status set obj = RS.ToProxyObject(.tSC) return:$$$ISERR(tSC) tSC - $$$DynObjToJSON(obj) - } - set stop = $PIECE($NOW(),",",2) + // check if audit global hold something and execute it + try {xecute ^DeepSee.AuditQueryCode} catch {} - set executionTime = stop - start - set query = RS.%GetQuery() - - set audit = ..WriteAudit(MDX, "query", executionTime) + $$$DynObjToJSON(obj) + } return $$$OK } @@ -317,7 +316,6 @@ ClassMethod GetDataSource(pDataSource As %String) set st = $$$OK try { - set start = $PIECE($NOW(),",",2) if ($FIND(pDataSource, ".pivot") = ($LENGTH(pDataSource) + 1) && pDataSource '="") { set st = ..OpenPivotByName(pDataSource, .dataSource) @@ -329,13 +327,6 @@ ClassMethod GetDataSource(pDataSource As %String) set dataSource.mdx = mdx } set st = ##class(%ZEN.Auxiliary.jsonProvider).%ObjectToJSON(dataSource, .out) - - set stop = $PIECE($NOW(),",",2) - - set executionTime = stop - start - - set audit = ..WriteAudit(pDataSource, "pivot", executionTime) - } @@ -426,22 +417,16 @@ ClassMethod GetWidgetsList(pDashName As %String) As %Status ClassMethod GetDashboard(pDashName As %String) As %Status { try { - set start = $PIECE($NOW(),",",2) - set st = ##class(MDX2JSON.DashboardFilters).OpenDashboardByName(pDashName, .dash) return:($$$ISERR(st)) st set st = ##class(MDX2JSON.DashboardFilters).WidgetsToProxyObject(dash, .widgetlist) return:($$$ISERR(st)) st w "" // weird hack required for 15.3 - - set stop = $PIECE($NOW(),",",2) - - set executionTime = stop - start - - set audit = ..WriteAudit(pDashName, "dashboard", executionTime) - + // check if audit global hold something and execute it + try {xecute ^DeepSee.AuditCode} catch {} + $$$DynObjToJSON(widgetlist) } catch ex { set st = ex.AsStatus() @@ -584,115 +569,6 @@ ClassMethod CreateAddonClass(Class As %Dictionary.CacheClassname) As %Status quit classObj.%Save() } -ClassMethod WriteAudit(element, elementName, executionTime = 0) As %Status -{ - set st = $$$OK - - set ^CallAmount($INCREMENT(^CallAmount)) = 1 - - - if ^AuditState = "on" - { - if elementName = "dashboard" - { - set ^MyBIAuditLogDash($INCREMENT(^MyBIAuditLogDash)) = $lb($ZDT($H,3), $USERNAME, element, executionTime) - } - elseif elementName = "pivot" - { - set ^MyBIAuditLogPivot($INCREMENT(^MyBIAuditLogPivot)) = $lb($ZDT($H,3), $USERNAME, element, executionTime) - } - elseif elementName = "query" - { - set ^MyBIAuditLogQuery($INCREMENT(^MyBIAuditLogQuery)) = $lb($ZDT($H,3), $USERNAME, element, executionTime) - } - - - }else{ - - quit st - } - - - return st -} - -ClassMethod ReadAudit(metricName) As %Status -{ - set st = $$$OK - - if ^AuditState = "on" - { - if metricName = "query" - { - - set len = $order(^MyBIAuditLogQuery(""),-1) - for n=1:1:len - { - set log = $Get(^MyBIAuditLogQuery(n)) - write ! - write "Element call time: ", $lg(log, 1), ! - write "User: ", $lg(log, 2), ! - write "Execution time in sec.: ", $lg(log, 4), ! - write "Query: ", $lg(log, 3), ! - } - } - elseif metricName = "pivot" - { - - set len = $order(^MyBIAuditLogPivot(""),-1) - for n=1:1:len - { - set log = $Get(^MyBIAuditLogPivot(n)) - write ! - write "Element call time: ", $lg(log, 1), ! - write "User: ", $lg(log, 2), ! - write "Execution time in sec.: ", $lg(log, 4), ! - write "Pivot: ", $lg(log, 3), ! - } - } - elseif metricName = "dashboard" - { - set len = $order(^MyBIAuditLogDash(""),-1) - for n=1:1:len - { - set log = $Get(^MyBIAuditLogDash(n)) - write ! - write "Element call time: ", $lg(log, 1), ! - write "User: ", $lg(log, 2), ! - write "Execution time in sec.: ", $lg(log, 4), ! - write "Dashboard: ", $lg(log, 3), ! - } - } - } - - quit st -} - -ClassMethod AuditStateSwitch(auditstate = 0) As %Status -{ - set st = $$$OK - - if auditstate = 0 - { - set ^AuditState = "off" - - }else{ - - set ^AuditState = "on" - } - - write "Audit state: " _ ^AuditState -} - -ClassMethod AuditKill() As %Status -{ - kill ^MyBIAuditLogDash - kill ^MyBIAuditLogPivot - kill ^MyBIAuditLogQuery - - write "All globals are cleaned" -} - /// Add new widgets and edit existing ones directly from DeepSeeWeb /// it takes widget name(key) as unique identifier as string, dashboard name as string /// and object with parameters as zen.proxyObject From 87840c0544aba7bcc6bb323326e99ec55393126d Mon Sep 17 00:00:00 2001 From: Frisle <47441164+Frisle@users.noreply.github.com> Date: Fri, 12 Jul 2024 15:14:55 +0600 Subject: [PATCH 3/3] FEAT: add audit callback and global audit globals --- MDX2JSON/Utils.cls | 57 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/MDX2JSON/Utils.cls b/MDX2JSON/Utils.cls index efaf587..88201d1 100644 --- a/MDX2JSON/Utils.cls +++ b/MDX2JSON/Utils.cls @@ -53,6 +53,11 @@ ClassMethod ExecuteResultSet(RS As MDX2JSON.ResultSet, QueryKey As %String = "", quit Status } +ClassMethod QuerySet(MDX) As %Status +{ + set ^Query($I(^Query), "%dsQuery") = MDX +} + /// Automatic processing of MDX query and outputting resulting JSON.
/// MDX - String containing MDX query.
ClassMethod WriteJSONfromMDX(MDX As %String, Timeout As %Integer = 0) As %Status @@ -77,6 +82,13 @@ ClassMethod WriteJSONfromMDX(MDX As %String, Timeout As %Integer = 0) As %Status set obj = RS.ToProxyObject(.tSC) return:$$$ISERR(tSC) tSC + set %dsQuery = MDX + + // initiate an RS object to a global variable %dsResultSet + set %dsResultSet = RS + + set %dsCubeName = RS.%Cube + // check if audit global hold something and execute it try {xecute ^DeepSee.AuditQueryCode} catch {} @@ -90,12 +102,16 @@ ClassMethod WriteJSONfromMDX(MDX As %String, Timeout As %Integer = 0) As %Status set obj = RS.ToProxyObject(.tSC) return:$$$ISERR(tSC) tSC + set %dsQuery = MDX + set %dsResultSet = RS + // check if audit global hold something and execute it try {xecute ^DeepSee.AuditQueryCode} catch {} $$$DynObjToJSON(obj) } + return $$$OK } @@ -417,13 +433,16 @@ ClassMethod GetWidgetsList(pDashName As %String) As %Status ClassMethod GetDashboard(pDashName As %String) As %Status { try { + set st = ##class(MDX2JSON.DashboardFilters).OpenDashboardByName(pDashName, .dash) return:($$$ISERR(st)) st set st = ##class(MDX2JSON.DashboardFilters).WidgetsToProxyObject(dash, .widgetlist) return:($$$ISERR(st)) st w "" // weird hack required for 15.3 - + + set %dsDashboard = pDashName + // check if audit global hold something and execute it try {xecute ^DeepSee.AuditCode} catch {} @@ -435,6 +454,42 @@ ClassMethod GetDashboard(pDashName As %String) As %Status return st } +/// the method initiate the audit for %dsDashboard +ClassMethod SetAuditCode() As %Status +{ + set ^DeepSee.AuditCode = "Do ##class(MDX2JSON.Utils).SetAuditDash()" + + quit $$$OK +} + +/// the method initiate the audit for %dsQueryText, %dsCubeName, %dsResultSet +ClassMethod SetAuditQueryCode() As %Status +{ + set ^DeepSee.AuditQueryCode = "Do ##class(MDX2JSON.Utils).SetAuditQuery()" + + quit $$$OK +} + +/// zw ^AuditLogDash to get the dashboard audit dashboard readings +ClassMethod SetAuditDash() As %Status +{ + set ^AuditLogDash($INCREMENT(^AuditLogDash),"%dsDashoard") = %dsDashboard + + quit $$$OK +} + +/// zw ^AuditLogQuery to get the query audit readings +/// zw ^AuditLogCube to get the cube audit readings +/// zw ^AuditLogRS to get the RS audit readings +ClassMethod SetAuditQuery() As %Status +{ + set ^AuditLogQuery($INCREMENT(^AuditLogQuery),"%dsQueryText") = %dsQueryText + set ^AuditLogCube($INCREMENT(^AuditLogQuery),"%dsCubeName") = %dsCubeName + set ^AuditLogRS($INCREMENT(^AuditLogRS),"%dsResultSet") = %dsResultSet + + quit $$$OK +} + /// Get format defaults. ClassMethod GetFormat() As %Status {