diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..95fcfa3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +ARG IMAGE=store/intersystems/iris-community:2021.1.0.205.0 +FROM $IMAGE + +USER root + +WORKDIR /opt/irisapp +RUN chown ${ISC_PACKAGE_MGRUSER}:${ISC_PACKAGE_IRISGROUP} /opt/irisapp +USER ${ISC_PACKAGE_MGRUSER} + +COPY src src +COPY module.xml module.xml +COPY iris.script /tmp/iris.script + +RUN iris start IRIS \ + && iris session IRIS < /tmp/iris.script \ + && iris stop IRIS quietly diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..01362e1 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,14 @@ +version: '3.6' +services: + iris: + build: + context: . + dockerfile: Dockerfile + restart: always + ports: + - 51553:51773 + - 52553:52773 + - 53773 + volumes: + - ~/iris.key:/usr/irissys/mgr/iris.key + - ./:/irisdev/app \ No newline at end of file diff --git a/iris.script b/iris.script new file mode 100644 index 0000000..475e480 --- /dev/null +++ b/iris.script @@ -0,0 +1,9 @@ +;do $System.OBJ.LoadDir("/opt/irisapp/src","ck",,1) + +zn "%SYS" +Do ##class(Security.Users).UnExpireUserPasswords("*") +set $namespace="%SYS", name="DefaultSSL" do:'##class(Security.SSLConfigs).Exists(name) ##class(Security.SSLConfigs).Create(name) set url="https://pm.community.intersystems.com/packages/zpm/latest/installer" Do ##class(%Net.URLParser).Parse(url,.comp) set ht = ##class(%Net.HttpRequest).%New(), ht.Server = comp("host"), ht.Port = 443, ht.Https=1, ht.SSLConfiguration=name, st=ht.Get(comp("path")) quit:'st $System.Status.GetErrorText(st) set xml=##class(%File).TempFilename("xml"), tFile = ##class(%Stream.FileBinary).%New(), tFile.Filename = xml do tFile.CopyFromAndSave(ht.HttpResponse.Data) do ht.%Close(), $system.OBJ.Load(xml,"ck") do ##class(%File).Delete(xml) +;zpm "install zpm" +zn "USER" +zpm "load /opt/irisapp/ -v":1:1 +halt diff --git a/module.xml b/module.xml new file mode 100644 index 0000000..f4990cc --- /dev/null +++ b/module.xml @@ -0,0 +1,14 @@ + + + + + DeepSeeButtons + 1.0.0 + Script used by the DeepSee support group at InterSystems to gather system information. + DeepSee Buttons + module + src + + + + diff --git a/src/mac/DeepSeeButtons.mac b/src/mac/DeepSeeButtons.mac new file mode 100644 index 0000000..6c93762 --- /dev/null +++ b/src/mac/DeepSeeButtons.mac @@ -0,0 +1,3756 @@ +ROUTINE DeepSeeButtons +DeepSeeButtons(namespace="ask", cubeString="ask", getLogs="", LogFile="", tracking="") +#include %occConstant + + ;DeepSeeButtons: routine to log system and DeepSee information + ;Install it in the %SYS namespace and launch it as: + ;%SYS> Do ^DeepSeeButtons + ; + ;You can use the following optional arguments: + ;namespace: namespace where this routine will run, e.g. "SAMPLES". If "" the current namespace will be chosen + ;cubeString: comma separated list of cubes, e.g. "patients,holefoods", "ALL", or "" for no cubes at all + ;getLogs: boolean flag to control inclusion of the cconsole.log, Query Log, and DeepSee logs. + ; A value of getLogs="" will prompt the user to make this choice from the interactive dialog + ;LogFile: output file. By default the output file will be stored in the /mgr directory + ;tracking: Used to log progress into ^IRIS.Temp.DeepSeeButtonsTrack and track this routine + ; + ;Example using arguments: + ;Do ^DeepSeeButtons("SAMPLES","PATIENTS",1,"/home/amarin/Desktop/DSbuttons.html",0) + ; + ; + ;DeepSee Buttons includes the following general information + ; 1) DeepSee Setup + ; -Agent Count and cores + ; -DeepSee.AuditCode, DeepSee.AuditQueryCode + ; -Most recent activity in Cube manager + ; -Config section of cpf file + ; -Important mappings + ; -Server Initialization Code + ; -Deepsee enabled webapps + ; 2) Server Details + ; -Configuration + ; -Customer name + ; -License + ; -Fully Qualified Host Name + ; -User and date + ; -Cache startup + ; -$ZV + ; -Locale + ; -Operating system + ; -Disk space + ; -RAM + ; 3) Cubes in namespace + ; -Cubes table with Cube Name, Display name, Source Class, Cube Class, Related Cubes + ; -Versioned cubes + ; -Abstract cubes + ; -Cubes with Source Classes Based on SQL Storage + ; -Cubes Based on Data Connectors + ; -Build Order for Related Cubes + ; 4) Build/Synch + ; -DSTIME + ; -BuildSynchTable Table with Cube Name, Fact Count, Build Time, Build Rate, Build Errors, DSTIME, + ; Last Compile, Last Build/Synch, Related Cubes + ; -Build Errors + ; 5) Cube Registry Map + ; 6) Cube Info: Optional Extra data on a particular cube + ; 6A) Cube Info: display name, cube type, subject area class, inherits from, resource, source class, + ; fact class, caption, fact count, + ; build restrictions (maxfacts, buildrestriction/filterspec property, %OnProcessFact, and %OnGetFilterSpec), + ; last modified, DSTIME & DSINTERVAL, cube registry, build errors + ; 6B) Dimensions: dimension list, ^DeepSee.CalcMbrs, %Analyze, FieldNameToSpec, %AnalyzeMissing + ; 6C) Other Elements: Pivot variables, listing fields, listings, resources + ; 7) Query Log + ; -Number of users runnign queries + ; -User and Queries run + ; -^DeepSee.LastQuery + ; -Last 5 queries run by each user + ; 8) DeepSee Logs + ; 9) CPF file (includes mappings) + ; 10) cconsole.log + ; 11) Mappings - Show global mappings in the namespace + ; 12) Local Databases + ; 13) Task schedule + ; 14) Journaling + ; 15) Alerts + +StartDialog + New (namespace,cubeString,getLogs,LogFile,tracking) + Set origNS=$Namespace + Try { + If '$system.Security.Check("%DeepSee_Admin","USE") { + // Require %DeepSee_Admin in order to run this utility + Write !,"This tool requires the %DeepSee_Admin resource to run" + Quit + } + + Do:tracking WriteTrack("setup","Starting DeepSeeButtons","") + Set PDev=$Principal + Use PDev + Write !,"DeepSee Diagnostic Report Evidence Logging Tool" + Write !,"This reporting tool provides the information required for" + Write !,"InterSystems Technical Support to analyze DeepSee issues. " + Set namespace=$$GetNamespace(namespace) + Quit:namespace="" + Set cubeList=$$GetCubesToLog(cubeString,namespace,tracking) + //Later do not ask to confirm to proceed if anything was passed to getLogs argument + Set proceed=(getLogs'="") + Do:getLogs="" GetLogsConfirm + Do:'proceed ReadLogTypeConfirm + Quit:'proceed + Kill:tracking ^IRIS.Temp.DeepSeeButtonsTrack + Do LaunchLogs(namespace,cubeList,getLogs) + } Catch(ex) { + Set tSC = ex.AsStatus() + Set msg = $System.Status.GetErrorText(tSC) + Do:tracking WriteTrack("error","","",msg) + Use $Principal + Write !,msg + } + zn origNS + Quit + +GetNamespace(namespace) { + //If namespace is "" choose the current namespace + If namespace="" { + Set namespace = $Namespace + Write !,"Running in namespace: "_namespace + } + + //Ask user if the namespace variable is not given + Set:namespace="ask" namespace="" + Set namespace=$$ValidateNamespace(namespace) //Make sure input namespace exists + While namespace="" { //User didn't enter a namespace when calling routine + Write !!,"Type namespace ["_$Namespace_"]" + Read namespace + Set:namespace="" namespace = $Namespace + Set namespace=$$ValidateNamespace(namespace) + } + Quit namespace +} + +GetCubesToLog(cubeString,namespace,tracking=0) { + If cubeString="ask" { + Set allcubeList=$$DialogCubes(namespace) + } ElseIf cubeString="" { + Set allcubeList="" + } ElseIf $LISTVALID(cubeString) { + Set allcubeList=cubeString + } ElseIf cubeString="ALL"{ + Set cubeString=$$GetAllCubes(namespace) + Set allcubeList=$LFS(cubeString,",") + } Else { + Set allcubeList=$LFS(cubeString,",") + } + Set cubeList=$$VerifyInputCubes(allcubeList,namespace,tracking) + Quit cubeList +} + +GetLogsConfirm + ZN "%SYS" + Write !, "Include cconsole.log, Query Log, and DeepSee Logs? [Y] " + Read getLogs + Set getLogs=$ZCONVERT(getLogs,"U") + If (getLogs="") { + Set getLogs=1 //If the user did not make a selection, add console and query logs + } ElseIf (getLogs="N")||(getLogs="NO") { + Set getLogs=0 + } ElseIf (getLogs="Y")||(getLogs="YES") { + Set getLogs=1 + } ElseIf (getLogs=+getLogs) { + //secret option: if getLogs is a number it controls the number of queries by user shown + //Just pass getLogs on + } Else { + Write !,"Please enter Y or N" + Set getLogs="" + Goto GetLogsConfirm + } + Quit + +ReadLogTypeConfirm + Write !,"Continue? [Y] " Read LogType + Set LogType=$ZCONVERT(LogType,"U") + If ((LogType="NO")!(LogType="N")!(LogType="Q")!(LogType="QUIT")) { + Set proceed=0 } + ElseIf ((LogType="YES")!(LogType="Y")!(LogType="")) { + Set proceed=1 + } Else { + Write !,"Please enter Y or N" Goto ReadLogTypeConfirm + } + Quit proceed + +LaunchLogs(namespace,cubeList,getLogs) + Try { + Set CacheVerNumber=$System.Version.GetNumber() + If +CacheVerNumber<5 { //Do Quit Return + Set Message="*** Wrong version of Diagnostic Report utility ! ***"_$Char(13,10)_$Char(13,10)_"You are running on Cache "_ + CacheVerNumber_" and this is the code for Cache 5.0 and later" + Use PDev Write:$X ! Write !,Message + Set Return="0|"_Message + Quit + } + Use PDev Write:$X ! + Write "Collecting information, please do not interrupt this process.",!,"Do not close terminal until the process has completed" + Break 0 + Set EOF=$ZUtil(68,40) + //Start logging with the DeepSee Setup section + Set output=$$LogSections(cubeList,getLogs,LogFile) + If $E(output,1,5)="Error" { + Do:tracking WriteTrack("error","","",output_". Check your output path and permissions") + W !,output," Abort",! + Return + } Else { + Set LogFile = output + } + Set rc=$$$OK + If $ZUtil(68,40,EOF) //Reset $ZEOF to the original setting + Break 1 + If LogFile="" { //Do Quit Return + Set Message="*** Log file could not be created in "_LogDirectory_". Check directory permissions. ***" + Use PDev Write:$X ! Write !,Message + Set Return="0|"_Message + Quit + } + Use PDev + Write:$X ! Write !,"DeepSeeButtons report saved to: ",!,LogFile + Write !,"Please send the html file above to InterSystems Support." + } Catch(ex) { + Set tSC = ex.AsStatus() + Do $System.Status.DisplayError(tSC) + Do:tracking WriteTrack("error","","",$System.Status.GetErrorText(tSC)) + } + Quit + + +OpenLogFile(LogFile,FileOpenTimeOut) { + //Compared to ^Buttons the file is opened here, not in NewFile + Open LogFile:"RWNSK\UTF8\":FileOpenTimeOut + If '$Test Quit "Error opening file "_LogFile + Quit LogFile +} + +LogSections(cubeList,getLogs,LogFile) + New (LogDirectory,namespace,cubeList,getLogs,LogFile,MgrDir,tracking) + Do Init + Set LogFile = $$InitLogFile + Set out = $$OpenLogFile(LogFile,FileOpenTimeOut) + If $E(out,1,5)="Error" Quit out + If OS?1"***".e Quit "" + Do LogHead(cubeList,getLogs) + Do LogOpenMainDiv + Do LogDeepSeeSetupSection //Note Ale: here rs.%Execute("") messes up my ZW in DumpToFile + Do LogServerSetup + Do LogCubeSection + Do LogBuildSynchSection + Do LogCubeRegistry + Do:(($D(cubeList)'=0) && (cubeList'="")) LogDetailedCubeInfo + Do:getLogs>0 LogQuerylog + Do:getLogs>0 LogDeepSeelog + Do LogCPF + Do:getLogs>0 LogCConsole + Do LogMappings + Do LogDataBases + Do LogTasks + Do LogJournal + Do LogAlerts + Do LogTrailer + Do LogSidePanel(cubeList,getLogs,$G(alerts,0)) + Do LogCloseBody + ZN "%SYS" + Close LogFile + Quit LogFile + + +///Log* Helper functions that log the section of a DeepSeeButtons report +LogHead(cubeList,getLogs) + //Writes the Header record + Try { + New %DAT,%TIM,x //,Build + //Set x=$Text(+1),Build=$Piece(x,";",5),Build=$Piece(Build," ",2) + Set colspan=12 If OS="UNIX" Set colspan=13 + Use LogFile + Do WriteLog("") + Do WriteLog("") + Do WriteLog("") + Do WriteLog("") + Do WriteLog("") + Do WriteLog("",2) + Do WriteLog("DeepSee Diagnostic Log for "_CustomerName ,4) + Do WriteLog("",2) + Do WriteLog("",2) + Do WriteLog("",2) + /// Style section + Do WriteLog("",2) + Do WriteLog("") + } Catch(ex) { + Set tSC = ex.AsStatus() + Do WriteLog(tSC) + } + Quit + +LogOpenMainDiv() + Do WriteLog("") + Do WriteLog("
") + Do WriteLog("") + Do WriteLog("

DeepSeeButtons - DeepSee diagnostic report

") + Quit + +LogDeepSeeSetupSection + //Begin body tag + Try { + //Do WriteLog("") + Do WriteLog("
") + Do WriteLog("",2) + Do WriteLog("
") + Do WriteUpdate("Getting system information") + Do:tracking WriteTrack("setup","Getting system information","") + Do WriteLog("
") + Do WriteParagraph("deepseesetup","DeepSee Setup in "_namespace,0) + //Agent Count + ZN namespace + Set count=##class(%DeepSee.Utils).%GetAgentCount() + If count=""{ + Set tCPU=##class(%SYSTEM.CPU).%New() + Set cores = tCPU.nCores + Set counthigh=cores*4 + Set defaultagents="Default agent count" + Set countstring=cores_" cores x 8 = "_(counthigh*2)_" agents ("_counthigh_" high- and "_counthigh_" low-priority agents)" + } Else { + Set defaultagents="Non-default agent count" + Set countstring=(count*2)_" agents ("_count_" high- and "_count_" low-priority agents)" + } + ZN "%SYS" + Use LogFile + Do WriteLog("",2) + + Do WriteLog("",4) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + /// Important Mappings subsection + Set NsMap="" + Set MirCount=0 + Set ECPCount=0 + Set isMirror=0 + Set isECP=0 + Set GlobalKSize="" + Set RoutineSize="" + Set bbsiz="" + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + //Important mapppings + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + If ECPCount'=0{ + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + } + If MirCount'=0{ + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + } + //Initialization code + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + + //Webapps that are deepsee enabled + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + + //DeepSee overrides + If (isInsight || isTrak) { + If (nOverrides<10) { + Do WriteLog("",4) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",4) + Do WriteLog("
",8) + Do WriteHeader4("Agent Count",10) + Do WriteLog("

"_defaultagents_"

",10) + Do WriteLog("

"_countstring_"

",10) + Do WriteLog("
",8) + //Audit section + Do GetDeepSeeAuditCode + Do WriteLog("
",8) + Do WriteHeader4("Most Recent Activity in Cube Manager",10) + ZN namespace + Set msgbuild=$$GetLastBuild("Build") //Get last build, synch, and update info + Set msgsynch=$$GetLastBuild("Synch") + Set msgupdate=$$GetLastBuild("Update") + Set msgrepair=$$GetLastBuild("Repair") + Do WriteLog("

Build event: "_msgbuild_"

",10) + Do WriteLog("

Synch event: "_msgsynch_"

",10) + Do WriteLog("

Registry Update event: "_msgupdate_"

",10) + Do WriteLog("

Repair event: "_msgrepair_"

",10) + //Cycle through all enabled cubes in cube manager and alert if ther are no build or repair events + Set rs=##class(%ResultSet).%New("%DeepSee.CubeManager.RegistryMap:RegistryMapTableView") + Set registered = "" + Set state = "" + Do rs.Execute() + While (rs.Next()) { + Set cube=rs.Get("CubeKey") + Set state = rs.Get("Disabled") + Set state = $S(state="Yes":"disabled",state="No":"enabled",1:"unknown") + If ((rs.Get("IsRegistered")="Yes") && (rs.Get("Disabled")="No")) { + Set msgbuild=$$GetLastBuild("Build",cube) //Get last build + Set msgrepair=$$GetLastBuild("Repair",cube) //Get last repair + Do:(state="enabled") alertInitialBuildCubeManager(cube,msgrepair,msgbuild,.alerts) + } + } + ZN "%SYS" + Do WriteLog("
",8) + Do WriteHeader4("Config section of cpf file",8) + Open ConfigFile:"R":FileOpenTimeOut + If '$Test { + Do WriteLog("

Error: could not open Caché Configuration File "_ConfigFile_"

",10) + } Else { + For { + Use ConfigFile + Read x:FileReadTimeOut + If $p(x,".",1)="[Map" { //Grab namespace we are mapping from + Set NsMap=x //Returns eg [Map.Analytics] + Set NsMap=$p($p(NsMap,".",2),"]",1) //Returns eg Analytics + Set MapCount=0 //Reset counter for number of mappings within this namespace + } + If x["Global_OBJ.DSTIME"{ //Grab OBJ.DSTIME mapping + Set DSTimeMapTo=$p(x,"=",2) //Namespace it is mapped to + Set DSTimeMapFrom(NsMap)=DSTimeMapTo + } + If x["Global_DeepSee"{ //Create array of DeepSee.* global mappings within this namespace + Set MapCount=$I(MapCount) + Set DeepSeeMap(NsMap,MapCount)=x + } + If x["[Mirrors]" Set isMirror=1 //We are in mirror section + If isMirror=1{ + If x=""{ + Set isMirror=0 //Mirror section has ended + } Else { //Store mirror information + Set MirCount=$I(MirCount) + Set MirArray(MirCount)=x + } + } + If x["[ECPServers]" Set isECP=1 //We are in ECP section + If isECP=1{ + If x=""{ + Set isECP=0 //ECP section has ended + } ElseIf x'["[ECPServers]" { + Set ECPCount=$I(ECPCount) //Store ECP info + Set ECPArray(ECPCount)=x + } + } + //Store important values from cpf - Config section + If x["[config]" Set configSect=1 //We are in Config section + If x["[Miscellaneous]" Kill configSect //Config section is over + If $D(configSect) { + If x["globals" Set GlobalKSize=$P(x,"globals=",2) + If x["routines=" Set RoutineSize= $P(x,"routines=",2) + If x["bbsiz=" Set bbsiz= $P(x,"=",2) + } + Quit:x["[Miscellaneous]" //We have passed all information we are interested in, just quit + } + Close ConfigFile + Do WriteLog("

globals="_GlobalKSize_"

",10) + Do WriteLog("

routines="_RoutineSize_"

",10) + Do WriteLog("

bbsiz="_bbsiz_"

",10) + Set sc = $$alertGlobalKSize(GlobalKSize,.alerts) + Set sc = $$alertRoutineSize(RoutineSize,.alerts) + } + Do WriteLog("
",8) + Do WriteHeader4("Important Mappings",10) + ZN "%SYS" + Set status=##Class(Config.Namespaces).Get(namespace,.nsprop) + Do:status=1 WriteLog("

Default DBs for globals and routines: "_nsprop("Globals")_", "_nsprop("Routines")_"

",10) + + If '$D(DSTimeMapFrom(namespace)){ + Do WriteLog("

^OBJ.DSTIME: no mappings defined

",10) + } Else{ + Do WriteLog("

^OBJ.DSTIME: mapped to "_DSTimeMapFrom((namespace))_"

",10) + } + //DeepSeeMap is structured as follows: DeepSeeMap(namespace,mapping number) + If NsMap'="" { + If $D(DeepSeeMap(namespace,1)){ + Set NumMaps=$O(DeepSeeMap(namespace,"")) + While NumMaps { + Do WriteLog("

"_DeepSeeMap(namespace,NumMaps)_"

",10) + Set NumMaps=$O(DeepSeeMap(namespace,NumMaps)) + } + } + Set sc = $$alertCacheMappings(namespace,.alerts) + Set sc = $$alertJoinIndexMappings(namespace,.alerts) + If $D(DSTimeMapFrom(namespace)){ + Set sc = $$alertDStimeRW(DSTimeMapFrom(namespace),.alerts) + } + } + Do WriteLog("
",8) + Do WriteHeader4("ECP Servers",10) + Do WriteLog("

",10) + For i=1:1:ECPCount{ + Write ECPArray(i),! + } + Do WriteLog("

",10) + Do WriteLog("
",8) + Do WriteHeader4("Mirroring Info",10) + Do WriteLog("

",10) + For i=1:1:MirCount{ + Write MirArray(i),! + } + Do WriteLog("

") + Do WriteLog("
",8) + Do WriteHeader4("Server Initialization Code",8,"Defined in the ^DeepSee.InitCode global") + Try { + If $D(^[namespace]DeepSee.InitCode){ + Set initcode=$g(^[namespace]DeepSee.InitCode) + Do WriteLog("

^DeepSee.InitCode: "_initcode_"

",10) + } Else{ + Do WriteLog("

^DeepSee.InitCode is undefined"_initcode_"

",10) + } + } Catch { + Do WriteLog("

Not Available

",10) + } + Do WriteLog("
",8) + Do WriteHeader4("DeepSee-enabled namespaces",10) + Do ##class(%CSP.Portal.Utils).%GetNamespaceList(.nsList) + SET ns=$o(nsList("")) + While ns'="" { + If ##class(%DeepSee.Utils).%IsDeepSeeEnabled(ns) { + Do WriteLog("

"_ns_" with default webapp: "_$system.CSP.GetDefaultApp(ns)_"

",10) + } + Set ns=$O(nsList(ns)) + } + Do WriteLog("
",6) + Do WriteHeader4("DeepSee Overrides",10) + Do PrintGlobal(namespace,"^DeepSee.Overrides",10) + Do WriteLog("
",2) + } Else { + //If there are many overrides place them in a scrollable div + Do WriteLog("",4) + Do WriteLog("",2) + Do WriteLog("
") + Do WriteLog("") + Do WriteLog("

DeepSee Overrides

") + Do WriteLog("
") + Do PrintGlobal(namespace,"^DeepSee.Overrides",2) + Do WriteLog("
") + } + } Else { + Do WriteLog("",4) + Do WriteLog("",2) + } + } Catch(ex) { + Set tSC = ex.AsStatus() + Do WriteLog("Error in LogDeepSeeSetupSection: "_tSC,0) + Do WriteLog("",4) + Do WriteLog("",2) + } + Do WriteLog("
") + Quit + +LogServerSetup() + ///Server Details section + Do WriteLog("
") + Do WriteParagraph("serverdetails","Server Details",1) + + ///The old "Configuration" section + Do WriteLog("",2) + Do WriteLog("",4) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + + //Last Caché Startup + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + + //Operating System Version section + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + + //Disk space + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + + //RAM physical memory space + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + + //Close the table + Use PDev + If OS?1"Win".e!(OS="VMS"),OS'="Win9x" + Use LogFile + Do WriteLog("",4) + Do WriteLog("
",8) + Do WriteHeader4("Configuration",10) + Do WriteLog("

"_ConfigName_" on Machine """_HostName_""""_"

",10) + Do WriteLog("
",8) + If CustomerName'?1a.e Set CustomerName="Unknown" + Do WriteHeader4("Customer Name",10) + Do WriteLog("

"_CustomerName_"

",10) + Do WriteLog("
",8) + Do WriteHeader4("License Order Number",10) + Do WriteLog("

"_OrderNumber_"

",10) + Do WriteLog("
",8) + Do WriteHeader4("Fully Qualified Host Name",10) + Do WriteLog("

"_FullHostName_" with IP Address: "_IPAddr_"

",10) + Do INT^%D,INT^%T + Do WriteLog("
",8) + Do WriteHeader4("Log created by User",10) + Do WriteLog("

"_CurUser_" on "_$ZD($ZDH(%DAT,7),3)_" at "_%TIM_"

",10) + Do WriteLog("
",8) + Do WriteHeader4("Last Caché Startup",10) + Do WriteLastStartup + Do WriteLog("
",8) + Do WriteHeader4("Caché Version String",10) + Do WriteLog("

"_CacheVerStr_"

",10) + + //Set isInsight=$$isHealthInsight(namespace) //Determine if this is a Health Insight namespace (1 if yes) + Do:isInsight WriteLog("

"_##class(%ZHSLIB.HealthShareMgr).VersionInfo()_"

",8) + Do WriteAdhocPatch //write information on Adhoc patch + + //Current Locale subsection + Do WriteLog("
",8) + Do NLS + Do WriteLog("
",8) + Do OSVer + Do WriteLog("
",8) + Do DiskSpace + Do WriteLog("
",8) + Do RAM + Do WriteLog("
",2) + Do WriteLog("
") + Use PDev + Quit + +LogCubeSection + Try { + Do WriteUpdate("Getting cube information") + Do:tracking WriteTrack("cubelog","Getting cube information","") + Do WriteLog("
") + Do WriteParagraph("cubelist","Cubes in "_namespace) + Use PDev + ZN namespace + Do ##class(%DeepSee.Utils).%GetCubeList(.plist) + Set cubenode=$order(plist("")) + If cubenode=""{ + Do WriteLog("

There are no cubes in this namespace

") + } Else { + Use LogFile + Do WriteLog("",2) + Do WriteLog("",4) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",6) + Set storageList="" + Set dataConnectorList="" + Set abstractcount = 0 + Set versionedcount = 0 + For { + Quit:cubenode="" //Do the work to get info and write out the table + Set cubename=$list(plist(cubenode),1) + Try { + Set versionedCube = ##class(%DeepSee.CubeVersion.Utils).%GetVersionedCubeName(cubename) + Set isVersioned = ##class(%DeepSee.CubeVersion.Utils).%IsVersion(versionedCube) + } Catch { + Set versionedCube = cubename + Set isVersioned = 0 + } + If ##class(%DeepSee.Utils).%IsCubeAbstract(cubenode){ //cube is abstract + //Don't run if Health insight because there are too many abstract cubes + Set:('isInsight) abstractList($I(abstractcount)) = cubenode + } ElseIf isVersioned { + Set versionedList($I(versionedcount)) = versionedCube + } ElseIf (cubename'="") { + Do WriteLog("",6) + Do WriteLog("",8) //cubename + Set cubecaption=##class(%DeepSee.Utils).%GetCubeCaption(cubename) + Do WriteLog("",8) + Set cubeclass=##class(%DeepSee.Utils).%GetCubeClass(cubename) //cube class + Set lastmod=$zdt($LG(plist(cubenode),3),3) //last cube compile + Set type=$LG(plist(cubenode),4) //subject area or cube? + Set sourceClass = $$GetSourceClass(cubenode,type) + Do WriteLog("",8) //writes sourceClass + Do WriteLog("",8) + Write !,?8,"" //RelatedCubes + Do WriteLog("",6) + } + Set cubenode=$order(plist(cubenode)) + } + Do WriteLog("",4) + Do WriteLog("
Cube NameDisplay NameSource ClassCube ClassRelated Cubes
"_cubename_""_cubecaption_""_sourceClass_""_cubeclass_"" Do GetRelationships(cubenode) Write "
",2) + //Write out list of special cubes: versioned, abstract, with SQL Storage, based on Data Connectors + Do WriteHeader4("Versioned Cubes",2) + If versionedcount { + Set ind = $O(versionedList("")) + While ind { + Do WriteLog("

"_versionedList(ind)_"

",2) + Set ind = $O(versionedList(ind)) + } + } + Do WriteHeader4("Abstract Cubes",2) + If abstractcount { + Set ind = $O(abstractList("")) + While ind { + Do WriteLog("

"_abstractList(ind)_"

",2) + Set ind = $O(abstractList(ind)) + } + } + Do WriteHeader4("Cubes with Source Classes Based on SQL Storage",2) + Set ptr=0 + If ($D(storageList) && (storageList'="")){ + While $LISTNEXT(storageList,ptr,class){ + Do WriteLog("

"_class_"

",2) + } + } + Do WriteHeader4("Cubes Based on Data Connectors",2) + If $D(dataConnectorList){ + Set ptr=0 + While $LISTNEXT(dataConnectorList,ptr,class){ + Do WriteLog("

"_class_"

",2) + } + } + Do WriteHeader4("Build Order for Related Cubes",2) + Do ##class(%DeepSee.CubeManager.Utils).GetCubeGroups(.groups) + Set relatedCubesExist = 0 + //Invert this array from groups(group,cube)=order to groupOrderCube(group,order)=cube + Set group = $O(groups("")) + While (group'="") { + Set cube = $O(groups(group,"")) + While (cube'="") { + //NB: order can be "" + Set order = $S(groups(group,cube)'="":groups(group,cube),1:"-") + Set:('relatedCubesExist && (order > 1)) relatedCubesExist = 1 + Set groupOrderCube(group,order) = cube + Set cube = $O(groups(group,cube)) + } + Set group = $O(groups(group)) + } + //Print a table with build order for cubes with relationships + If relatedCubesExist { + Do WriteLog("",2) + Do WriteLog("",4) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",6) + Set group = $O(groupOrderCube("")) + While (group'="") { + Set last = $O(groupOrderCube(group,""),-1) + If (last=1) { + Set group = $O(groupOrderCube(group)) + } Else { + Set order = $O(groupOrderCube(group,"")) + While (order'="") { + Set cube = groupOrderCube(group,order) + Do WriteLog("",6) //background-color: #ccc; + Do WriteLog("",10) + Do WriteLog("",10) + Do WriteLog("",10) + Do WriteLog("",6) + Set order = $O(groupOrderCube(group,order)) + } + Set group = $O(groupOrderCube(group)) + } + } + Do WriteLog("",4) + Do WriteLog("
Cube NameCube GroupOrder
"_cube_""_group_""_order_"
",2) + } Else { + Do WriteLog("No related cubes",4) + } + } + Do WriteLog("
") + } catch exc { + Use PDev + zw exc + } + ZN "%SYS" + Quit + +LogBuildSynchSection + Try { + Do WriteUpdate("Getting information on Build/Synch") + Do:tracking WriteTrack("buildsynch","Getting information on Build/Synch","") + Do WriteLog("
",2) + Do WriteParagraph("buildsynchlist","Cube Build/Synch") + Use PDev + ZN namespace + Do ##class(%DeepSee.Utils).%GetCubeList(.plist) + Set cubenode=$order(plist("")) + If cubenode=""{ + Use LogFile + Do WriteLog("

There are no cubes in this namespace

",4) + Do WriteLog("
",2) + Use PDev + Quit + } Else { + If ##class(%DeepSee.CubeManager.Utils).GetActiveRegistry()=""{ + Do WriteLog("

No active registry so Build Time and Build Rate will not be populated.

",4) + Do WriteLog("") + } Else { + Do WriteLog("

BuildTime, BuildRate, Build Errors show no values when the cube has not been built from Cube Manager.

",4) + } + //Get the latest DSTIME + //DTB422 moved ^DeepSee.Cubes to ^DeepSee.Update + If ($D(^DeepSee.Update)#10) { //1 (only top node) or 11 (top node and descendants) + Set DSTIME = ^DeepSee.Update + Do WriteLog("

DSTIME from ^DeepSee.Update is "_DSTIME_"

",4) + } ElseIf ($D(^OBJ.DSTIME)#10) { + Set DSTIME = ^OBJ.DSTIME + Do WriteLog("

DSTIME from ^OBJ.DSTIME is "_DSTIME_"

",4) + } Else { + Set lastDataUpdate = 0 + Set dstime = "" + Do WriteLog("

Could not find DSTIME

",4) + } + Do WriteLog("",4) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",10) + Do WriteLog("",10) + Do WriteLog("",10) + Do WriteLog("",10) + Do WriteLog("",10) + Do WriteLog("",10) + Do WriteLog("",10) + Do WriteLog("",10) + Do WriteLog("",10) + Do WriteLog("",10) + Do WriteLog("",10) + //Do WriteLog("",10) + Do WriteLog("",8) + //Cube group and build order + //Invert this array from groups(group,cube)=order to cubeGroupOrder(cube)=$LB(group,order) + Do ##class(%DeepSee.CubeManager.Utils).GetCubeGroups(.groups) + Set group = $O(groups("")) + While (group'="") { + Set cube = $O(groups(group,"")) + While (cube'="") { + //NB: order can be "" and cause errors + Set order = $S(groups(group,cube)'="":groups(group,cube),1:"-") + Set cubeGroupOrder(cube) = $LB(group,order) + Set cube = $O(groups(group,cube)) + } + Set group = $O(groups(group)) + } + Set storageList="" + Set dataConnectorList="" + Set abstractcount = 0 + For { + Quit:cubenode="" //Do the work to get info and write out the table + Set cubename=$list(plist(cubenode),1) + If (cubename'="" && '##class(%DeepSee.Utils).%IsCubeAbstract(cubenode)) { //if cube is not abstract + Do WriteLog("",8) + Do WriteLog("",10) //cubename + + + + + + /// Keep an eye on this. Does it perform well? + // COUNT(*) - Check Extent Size. + Set cube = $zu(28,cubename,5) + Set type = $LG(plist(cube),4) + Set sourceclass = $$GetSourceClass(cube,type) + Set sqlclass = ##class(%DeepSee.Utils).%GetSQLTableName(sourceclass) + Set NewExtentSize = ##Class(%SQL.Manager.Catalog).GetCalcTableExtentSize($P(sqlclass,".",1), $P(sqlclass,".",2)) + // First exclude abstract cubes and data connectors + If (sqlclass="Not available")||('##class(%SYSTEM.SQL).TableExists(sqlclass)) { + Do WriteLog("",10) + } ElseIf NewExtentSize>=200000 { + Do WriteLog("",8) + } ElseIf (NewExtentSize<10000) { + Do WriteUpdate("Getting COUNT(*) from source class of "_cube_". ExtentSize="_NewExtentSize) + Set countstar=$$GetCountStar(sqlclass) + Do WriteLog("",8) + } Else { + // Check if bitmap or bitmap extent index. + Set tRS=##class(%ResultSet).%New("%SQL.Manager.Catalog:Indices") + Set tSC = tRS.Execute($P(sqlclass,".",1),$P(sqlclass,".",2)) + //SKIP Quit:$$$ISERR(tSC) + Set hasBitmap= 0 + For { + Quit:'rs.Next() + Set tType = rs.Get("TYPE") + Set:$E(tType,1,6)="Bitmap" hasBitmap=1 + } + If hasBitmap { + Do WriteUpdate("Getting COUNT(*) from source class of "_cube_". ExtentSize="_NewExtentSize_", Bitmap index found") + Set countstar=$$GetCountStar(sqlclass) + Do WriteLog("",10) + } Else { + Do WriteLog("",8) + } + } + + + + + + Set lastmod=$zdt($LG(plist(cubenode),3),3) //last cube compile + Set facts=##class(%DeepSee.Utils).%GetCubeFactCount(cubename) //number of facts + //DTB422 moved ^DeepSee.Cubes to ^DeepSee.Update + If ($D(^DeepSee.Cubes("cubes",cubenode,"lastDataUpdate"))=1) { + Set lastDataUpdate = ^DeepSee.Cubes("cubes",cubenode,"lastDataUpdate") + Set dstime = $G(^DeepSee.Cubes("cubes",cubenode,"dstime"),"") + } ElseIf ($D(^DeepSee.Update("cubes",cubenode,"lastDataUpdate"))=1) { + Set lastDataUpdate = ^DeepSee.Update("cubes",cubenode,"lastDataUpdate") + Set dstime = $G(^DeepSee.Update("cubes",cubenode,"dstime"),"") + } Else { + Set lastDataUpdate = 0 + Set dstime = "" + } + If (lastDataUpdate'=0){ + Set lastSync=$zdt(lastDataUpdate,3) //Last cube sync from cube global + If lastSync="1840-12-31"{ + Set lastSync=" " + } Else{ + Set syncdate=$p(lastSync," ",1) + Set synctime=$p(lastSync," ",2) + Set lastSync=syncdate_" "_synctime + } + } Else { + Set lastSync="" + } + Set buildtime=$$GetBuildTime(cubename) + Do WriteLog("",10) + If buildtime=""{ + Do WriteLog("",10) + } Else { + Do WriteLog("",10) + } + Try { + If ((buildtime="") || (facts=0)) { + Set rate="" + } Else { + Set rate=$FNUMBER(facts/buildtime,",",2) + } + } Catch { + Set rate="" + } + Do WriteLog("",10) + Set builderrors = $G(^DeepSee.BuildErrors($ZCONVERT(cubename,"U")),"") + If (builderrors="") { + Do WriteLog("",10) + } Else { + Do WriteLog("",10) + } + Do WriteLog("",10) + Do WriteLog("",10) + Do WriteLog("",10) //LastUpdate = Last time cube was synced or built, "" if not done in Cube Manager + //Cube group and order + If $D(cubeGroupOrder(cubenode)) { + Set group = $LG(cubeGroupOrder(cubenode),1) + Set order = $LG(cubeGroupOrder(cubenode),2) + } Else { + Set group = "" + Set order = "" + } + Do WriteLog("",10) + Do WriteLog("",10) + Do WriteLog("",8) + } ElseIf ##class(%DeepSee.Utils).%IsCubeAbstract(cubenode){ + //Don't run if Health insight because there are too many abstract cubes + Set:('isInsight) abstractList($I(abstractcount)) = cubenode + } + Set cubenode=$order(plist(cubenode)) + } + Do WriteLog("",6) + Do WriteLog("
Cube NameSource CountFact CountBuild Time [s]Build Rate [Facts/s]Build ErrorsDSTIMELast CompileLast Build/SynchCube GroupBuild OrderRelated Cubes
"_cubename_""_$FNUMBER(countstar,"O,")_""_$FNUMBER(countstar,"O,")_""_$FNUMBER(facts,"O,")_""_$FNUMBER(buildtime,"O,")_""_rate_""_$FNUMBER(builderrors,"O,")_""_dstime_""_lastmod_""_lastSync_""_group_""_order_"
",4) + } + //Build Errors section + Do WriteHeader4("Build Errors",2,"From the ^DeepSee.BuildErrors global") + Set tCube = $O(^DeepSee.BuildErrors("")) + Set errs = 0 + While (tCube'="") { + If (^DeepSee.BuildErrors(tCube)) { + Set errs(tCube) = ^DeepSee.BuildErrors(tCube) + Set errs = errs + errs(tCube) + } + Set tCube = $O(^DeepSee.BuildErrors(tCube)) + } + If (errs) { + Set pre="title=""Build errors are logged in the ^DeepSee.BuildErrors global."">" + Set alert = "Alert: "_$FNUMBER(errs,"O,")_" build error(s) found" + Set alerts($I(alerts)) = pre_alert + Do WriteLog("

",2) + Set tCube = $O(errs("")) + While (tCube'="") { + Do WriteLog("

"_$FNUMBER(errs(tCube),"O,")_" build error(s) for '"_tCube_"'

",2) + Set tCube = $O(errs(tCube)) + } + } Else { + Do WriteLog("

No build errors

",2) + } + Do WriteLog("
") + } catch exc { + Use PDev + zw exc + } + ZN "%SYS" + Quit + + +LogCubeRegistry + Do WriteLog("
",2) + Do WriteParagraph("cuberegistry","Cube Registry") + ZN namespace + Set registry=##class(%DeepSee.CubeManager.Utils).GetActiveRegistry() + If registry=""{ + Do WriteLog("

No cube registry defined in this namespace

",2) + } Else{ + Do WriteLog("

Cube Registry storage class: "_registry_"

",2) + Set rs=##class(%ResultSet).%New("%DeepSee.CubeManager.RegistryMap:RegistryMapTableView") + Do rs.Execute() + Do WriteLog("",2) + Do WriteLog("",4) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",6) + For { + Quit:'rs.Next() + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",6) + } + + Do WriteLog("",4) + Do WriteLog("
Cube NameGroup NameRegisteredExcludeGroup Build OrderUpdate PlanSupports SynchronizeBuild EverySynch Every
"_rs.Get("CubeKey")_""_rs.Get("MgmtGroup")_""_rs.Get("IsRegistered")_""_rs.Get("Disabled")_""_rs.Get("CustomBuildOrder")_""_rs.Get("UpdatePlan")_""_rs.Get("DSTimeEnabled")_""_rs.Get("BuildEvery")_""_rs.Get("SynchEvery")_"
",2) + Do WriteLog("
",2) + } + Do WriteLog("
") + ZN "%SYS" + Quit + +LogDetailedCubeInfo + Do WriteLog("
") + Do WriteParagraph("cubeinfo","Cube Info") + Set cubeListLength=$ll(cubeList) + For i=1:1:cubeListLength{ + Set cube=$LG(cubeList,i) + If cube'=""{ + Do WriteLog(""_cube_"",2) + Do WriteLog("
",2) + } + } + Do WriteLog("
") + For cubeind=1:1:cubeListLength { + Set cube=$LG(cubeList,cubeind) + //Do:cube'="" LogCubeDetails(namespace,cube,PDev,LogFile) //PDev eg "/dev/pts/5" + If cube'="" { + ZN namespace + Do WriteLog("
") + Do LogCubeInfo + Do LogCubeDimensions + Do LogOtherCubeElements + Do WriteLog("
") + Do:tracking WriteTrack("cube","Detailed information collected",cube) + } + } + Quit + +LogCubeInfo + //New (namespace,LogFile,PDev,cube) + Do WriteUpdate("Getting detailed cube information for "_cube) + Do:tracking WriteTrack("cube","Build/Synch",cube) + Use LogFile + ZN namespace + Try { + Do WriteLog("
",2) + Do WriteLog("",2) + Do WriteLog("

Cube Info for "_cube_"

",2) + Set cubeclass=##class(%DeepSee.Utils).%GetCubeClass(cube) + Set factclass=##class(%DeepSee.Utils).%GetCubeFactClass(cube) + Set cubecaption=##class(%DeepSee.Utils).%GetCubeCaption(cube) + Set factcount=##class(%DeepSee.Utils).%GetCubeFactCount(cube) + Set moddate=$zdt(##class(%DeepSee.Utils).%GetCubeModifiedDate(cube)) + //Get the cube type + Set cubetype="" + Set:##class(%DeepSee.Utils).%IsCubeCompound(cube,.joinlist) cubetype="Compound" + Set:##class(%DeepSee.Utils).%IsCubeAbstract(cube) cubetype="Abstract" + Set base=##class(%DeepSee.Utils).%GetBaseCube(cube) + Set:((base'="") && (cubetype="")) cubetype="Subject Area" + //Start logging cube info + Do WriteLog("",2) + Do WriteLog("",4) + //Check versioned cube + Try { + Set versionedcube = ##class(%DeepSee.CubeVersion.Utils).%GetVersionedCubeName(cube,.vn) + Set isversioned = ##class(%DeepSee.CubeVersion.Utils).%IsVersion(versionedcube) + } Catch { + Set versionedcube = cube + Set isversioned = 0 + } + If isversioned { + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + } + //Continue + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + If isversioned { + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + //Get all compiled versions + Kill tList + Set tVersionNo = $O(^DeepSee.Cubes("versionIndex","versions",cube,"")) + While (tVersionNo'="") { + Set tVers = ##class(%DeepSee.CubeVersion.Utils).%GetVersionedCubeName(cube,tVersionNo) + Set tStatus = ##class(%DeepSee.CubeVersion.Utils).%GetCubeVersionStatus(cube,tVersionNo) + //Skip when tVersionNo is not a version and instead it marks "activeVersion", or "pendingVersion" + Set:tVers'="" tList(tVers) = tStatus + Set tVersionNo = $O(^DeepSee.Cubes("versionIndex","versions",cube,tVersionNo)) + } + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + } + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + //DSTIME and DSINTERVAL + If (base="")&&(cubetype="") { + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + } + //Cube Registry + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + + //Build errors + If ($D(^DeepSee.BuildErrors(cube)) && ^DeepSee.BuildErrors(cube)) { + Do WriteLog("",4) + Do WriteLog("
",8) + Do WriteLog("

Versioned Cube Name

",10) + Do WriteLog("

"_versionedcube_"

",10) + Do WriteLog("
",8) + Do WriteLog("

Cube Display Name

",10) + Do WriteLog("

"_cubecaption_"

",10) + Do WriteLog("
",8) + Do WriteLog("

Cube Type

",10) + Do:(cubetype="Subject Area") WriteLog("

Subject Area based on "_base_" cube

",10) + Do:(cubetype="Compound") WriteLog("

Compound Cube based on:

",10) + Do:(cubetype="Compound") WriteLog("

"_joinlist_"

",10) + Do:(cubetype="Abstract") WriteLog("

Abstract Cube

",10) + If (cubetype="") Do WriteLog("

Not a subject area, abstract, or a compound cube

",10) + Do WriteLog("
",8) + Do WriteLog("

Subject Area Class

",10) + Do WriteLog("

"_cubeclass_"

",10) + Do WriteLog("
",8) + Do WriteLog("

Inherits from

",10) + Set model = ##class(%DeepSee.Utils).%GetModel(cube) + Set inheritsfrom = "" + Set:(model'="") inheritsfrom = ##class(%DeepSee.Utils).%GetModel(cube).inheritsFrom + Do WriteLog("

"_inheritsfrom_"

",10) + Do WriteLog("
",8) + Do WriteLog("

Resource

",10) + Do WriteLog("

"_$G(^DeepSee.Cubes("cubes",cube,"resource"))_"

",10) + Do WriteLog("
",8) + Do WriteLog("

Source Class

",10) + //Get the source class from override or from %GetCubeList, then log it + If $D(^DeepSee.Overrides(cube,"SOURCECLASS")) { + Set sourceclass = ^DeepSee.Overrides(cube,"SOURCECLASS") + Do WriteLog("

"_sourceclass_" (from ^DeepSee.Overrides)

",10) + } Else { + Do ##class(%DeepSee.Utils).%GetCubeList(.plist) + Set type = $LG(plist(cube),4) + Set sourceclass = $$GetSourceClass(cube,type) + If ((cubetype="Subject Area")||(cubetype="Compound")) { + Do WriteLog("

Subject Area based on "_sourceclass_"

",10) + } Else { + Do WriteLog("

"_sourceclass_"

",10) + } + } + Do WriteLog("
",8) + //Get the SQL table name + Do WriteLog("

SQL Table Name

",10) + //NB: if sourceclass is invalid %GetSQLTableName returns the same string, possibly with _ instead of . + Set sqlclass = ##class(%DeepSee.Utils).%GetSQLTableName(sourceclass) + If (sqlclass="")||('##class(%SYSTEM.SQL).TableExists(sqlclass)) { + Set sqlclass="Not available" //Often in abstract cubes + } + If ((cubetype="Subject Area")||(cubetype="Compound")) { + Do WriteLog("

Subject Area based on "_sqlclass_"

",10) + } Else { + Do WriteLog("

"_sqlclass_"

",10) + } + Do WriteLog("
",8) + Do WriteLog("

Fact Class

",10) + Do WriteLog("

"_factclass_"

",10) + Do WriteLog("
",8) + Do WriteLog("

Deprecated Versions

",10) + Do ##class(%DeepSee.CubeVersion.Utils).%GetDeprecatedVersionList(cube,.tList) + Set tInd=$O(tList("")) + While (tInd'="") { + Do WriteLog("

"_tInd_"

",10) + Set tInd=$O(tList(tInd)) + } + Do WriteLog("
",8) + Do WriteLog("

Compiled Versions

",10) + Set tInd=$O(tList("")) + While (tInd'="") { + Do WriteLog("

"_tInd_" - "_$S(tList(tInd)="":"unknown",1:tList(tInd))_"

",10) + Set tInd=$O(tList(tInd)) + } + Do WriteLog("
",8) + //Row count on source. It might take some time (even 150 seconds on 100M facts) + Do WriteLog("

Source Count

",10) + //Check the following for abstract cubes and data connectors + If isTrak { //I noticed at a Trak site that COUNT(*) is slow. + Do WriteLog("

Not shown for Trak

",10) + } ElseIf (sqlclass="Not available")||('##class(%SYSTEM.SQL).TableExists(sqlclass)) { + Do WriteLog("

Not available

",10) + } Else { + Set SourceFactCount=$$GetCountStar(sqlclass) + Do WriteLog("

"_$FNUMBER(SourceFactCount,"O,")_"

",10) + } + Do WriteLog("
",8) + Do WriteLog("

Fact Count

",10) + Do WriteLog("

"_$FNUMBER(factcount,"O,")_"

",10) + Do WriteLog("
",8) + Do WriteLog("

Build Restriction

",10) + If base="" { + //Log buildRestriction property in cubes + Set tSC = $zobjclassmethod(cubeclass,"%GetSourceInfo",.tSourceInfo) + Set buildRestriction = $G(tSourceInfo("buildRestriction")) + If buildRestriction="" { + Do WriteLog("

No build restriction

",10) + } Else { + Do WriteLog("

Build restriction: "_$$encode(buildRestriction)_"

",10) + } + //Log maxFacts property in cubes + Set maxFacts = $G(tSourceInfo("maxFacts")) + If maxFacts="" { + Do WriteLog("

maxFacts property not found in subject area class

",10) + } Else { + Do WriteLog("

maxFacts = "_$FNUMBER(maxFacts,"O,")_"

",10) + } + } Else { + //Log filterspec property in subject areas (not cubes) + //NB $zobjclassmethod(cubeclass,"%GetFilterSpec") would also return the result from %OnGetFilterSpec + Set filterspec = $G(^DeepSee.Cubes("cubes",cube,"filterSpec")) + Set:(filterspec="") filterspec = "filterspec property not defined" + Do WriteLog("

filterSpec: "_filterspec_"

",10) + } + Set method = ##class(%Dictionary.CompiledMethod).%OpenId(cubeclass_"||%OnProcessFact") + If ((method="")||(method.Origin="%DeepSee.CubeDefinition")) { + Do WriteLog("

%OnProcessFact method not found in subject area class

",10) + } ElseIf (method.Origin=cubeclass) { + Do WriteLog("

%OnProcessFact method defined in subject area class

",10) + } + Set method = ##class(%Dictionary.CompiledMethod).%OpenId(cubeclass_"||%OnGetFilterSpec") + If ((method="")||(method.Origin="%DeepSee.CubeDefinition")||(method.Origin="%DeepSee.SubjectArea")) { + //NB: checking (method="") might be overkill + Do WriteLog("

%OnGetFilterSpec method not found in subject area class

",10) + } ElseIf (method.Origin=cubeclass) { + Do WriteLog("

%OnGetFilterSpec method defined in subject area class

",10) + } + Do WriteLog("
",8) + Do WriteLog("

Last Modified

",10) + Do WriteLog("

"_$ZDT($ZDTH(moddate),3)_"

",10) + Do WriteLog("
",8) + Do WriteLog("

DSTIME, DSINTERVAL

",10) + Set dstime = $G(tSourceInfo("dstime")) + If dstime="" { + Do WriteLog("

DSTIME property not found in subject area class

",10) + } Else { + Do WriteLog("

DSTIME = "_dstime_"

",10) + Set dsinterval = $G(tSourceInfo("dsinterval")) + If dsinterval="" { + Do WriteLog("

DSINTERVAL not specified

",10) + } Else { + Do WriteLog("

DSINTERVAL = "_dsinterval_"

",10) + } + } + Do WriteLog("
",8) + Do WriteUpdate("Getting detailed cube information for "_cube_": cube registry") + Do:tracking WriteTrack("cube","Cube Registry",cube) + Do WriteLog("

Cube Registry

",10) + Set rs = ##class(%ResultSet).%New("%DeepSee.CubeManager.RegistryMap:RegistryMapTableView") + Set registered = "" + Set state = "" + Do rs.Execute(cube) + While (rs.Next()) { + If (cube=rs.Get("CubeKey")){ + Set registered = rs.Get("IsRegistered") + If (registered="No") { + Set registered = $S(registered="Yes":"registered",registered="No":"not registered",1:"unknown") + } ElseIf (registered="Yes") { + Set state = rs.Get("Disabled") + Set state = $S(state="Yes":"disabled",state="No":"enabled",1:"unknown") + } + } + } + If (registered="not registered") { + Do WriteLog("

Cube is "_registered_" in Cube Manager

",10) + } Else { + If (state="enabled") { + Set msgsynch=$$GetLastBuild("Synch",cube) //Get last synch + Set msgbuild=$$GetLastBuild("Build",cube) //Get last build + Set msgupdate=$$GetLastBuild("Update",cube) //Get last update + Set msgrepair=$$GetLastBuild("Repair",cube) //Get last repair + Do WriteLog("

Cube is "_state_" in Cube Manager. Most Recent events:

",10) + Do WriteLog("

Synch event: "_msgsynch_"

",10) + Do WriteLog("

Build event: "_msgbuild_"

",10) + Do WriteLog("

Registry Update event: "_msgupdate_"

",10) + Do WriteLog("

Repair event: "_msgrepair_"

",10) + //Do alertInitialBuildCubeManager(cube,msgrepair,msgbuild,.alerts) + } Else { + Do WriteLog("

Cube is "_state_" in Cube Manager

",10) + } + } + Do WriteLog("
",2) + Do WriteLog("

Build Errors

",2) + If ($D(^DeepSee.BuildErrors(cube)) && ^DeepSee.BuildErrors(cube) <4) { + Do WriteLog("
") + } Else { + Do WriteLog("
") + } + Do WriteLog("
",10)
+			Set totCount = ^DeepSee.BuildErrors(cube)
+			Set tCount = 0
+			Set k = $O(^DeepSee.BuildErrors(cube,""))
+			While (k'="") {
+				Set tCount = tCount + 1
+				Set tSC = $G(^DeepSee.BuildErrors(cube,k))
+				Write $J($FNUMBER(tCount,"O,"),5),$J("",3),"Source ID: ",k
+				Write !,?8,$System.Status.GetErrorText(tSC),!!
+				If (tCount>1000) {
+					Write !,?0,"... skipping build errors ..."
+					Write !
+					Write !
+					Quit
+				}
+				Set k = $O(^DeepSee.BuildErrors(cube,k))
+			}
+			Write $FNUMBER(totCount,"O,")," build error(s) for '",cube,"'"
+			Do WriteLog("
",10) + Do WriteLog("
") + } Else { + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("

Build Errors

",4) + Do WriteLog("

",10) + Do ##class(%DeepSee.Utils).%PrintBuildErrors(cube) + Write ?10,"

" + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",4) + Do WriteLog("",2) + } + } Catch(ex) { + Set tSC = ex.AsStatus() + Do $System.Status.DisplayError(tSC) + Do:tracking WriteTrack("warning","","LogCubeInfo",$System.Status.GetErrorText(tSC)) + } + ZN "%SYS" + Quit + +LogCubeDimensions + Do WriteUpdate("Getting detailed cube information for "_cube_": get dimension list") + Do:tracking WriteTrack("cube","Dimension list",cube) + ZN namespace + Do WriteLog("
",2) + Do WriteLog("",2) + Do WriteLog("

Dimensions for "_cube_"

",2) + If ##class(%DeepSee.Utils).%IsCubeAbstract(cube) { + Do WriteLog("

No dimensions because the cube is abstract

",2) + Quit + } + Do WriteLog("

Dimension List

",2) + Set st=##class(%DeepSee.Utils).%GetDimensionList(cube,.dimensionlist,1) + Do WriteLog("",2) + Do WriteLog("",4) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Set DimNo=$O(dimensionlist(-1)) //skip Calculated Dimensions + Set oldHierNo=0 + Kill timeLevels + For { + Quit:DimNo="" + Set HierNo=$O(dimensionlist(DimNo,"")) + For { + If HierNo="" { + Set oldHierNo=0 + Quit + } + Set LevelNo=$O(dimensionlist(DimNo,HierNo,"")) + For { + Quit:LevelNo="" + Set type=$LG(dimensionlist(DimNo,HierNo,LevelNo),1) + If (HierNo=0) { //Dimension. + //In this case 4th item "type" is actually the caption for all level + Do WriteLog("",6) + Do WriteLog("",8) //DimName + If ($LG(dimensionlist(DimNo,HierNo,LevelNo),1)="r") { //relationships + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + } + + If ((type="d") && ($LG(dimensionlist(DimNo,HierNo,LevelNo),4)'="")) { + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) //Skip DimName column + } + } + If (HierNo'=0){ + If type="all" { + //Skip the all level because it was already shown next to the dimension + } ElseIf ((LevelNo=0) && (DimNo'=0)) { + Set newHier=0 + If (oldHierNo && (HierNo'=oldHierNo)) { //Maybe the logic could be simpler but this works + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + } + Do WriteLog("",8) //HierName + } ElseIf ((LevelNo=0) && (DimNo=0)){ //Measures section + If HierNo>1 { + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + } + Do WriteLog("",8) //MeasName + Do WriteLog("",8) + Do WriteLog("",8) + } ElseIf (DimNo'=0) { + If $E($LG(^DeepSee.Cubes("cubes",cube,"mbr#",DimNo,HierNo,LevelNo),6),0,14)="%DeepSee.Time." { + Set temp=^DeepSee.Cubes("cubes",cube,"mbr#",DimNo,HierNo,LevelNo) + Set timeLevels(DimNo,HierNo,LevelNo)=$LB($LG(temp,6),cube,$LG(temp,2),$LG(temp,3),$LG(temp,4)) + } + If newHier { + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",8) + } + Do WriteLog("",8) //LevelName + Set type=$S(type="all":"[All level a]",1:"") + Do WriteLog("",8) //type + Set newHier=1 + } + } + Set LevelNo=$O(dimensionlist(DimNo,HierNo,LevelNo)) + } + Set oldHierNo=HierNo + Set HierNo=$O(dimensionlist(DimNo,HierNo)) + } + Set DimNo=$O(dimensionlist(DimNo)) + Do WriteLog("",6) + } + Do WriteLog("",4) + Do WriteLog("
DimensionHierarchy LevelType
"_$LG(dimensionlist(DimNo,HierNo,LevelNo),2)_""_$LG(dimensionlist(DimNo,HierNo,LevelNo),4)_"[All level]
"_$LG(dimensionlist(DimNo,HierNo,LevelNo),3)_"
"_$LG(dimensionlist(DimNo,HierNo,LevelNo),3)_"
"_$LG(dimensionlist(DimNo,HierNo,LevelNo),4)_""_type_"
",2) + //Alert if incompatible time levels are found + Do alertTimeLevels(.timeLevels,.alerts) + //Show calculated members in ^DeepSee.CalcMbrs + Do WriteLog("

Calculated Members

",2) + If $D(^DeepSee.CalcMbrs(cube)) { + Do WriteLog("",2) + Do WriteLog("",4) + Do WriteLog("",6) + Do PrintGlobal(namespace,"^DeepSee.CalcMbrs("""_cube_""")",10) + Do WriteLog("",6) + Do WriteLog("",4) + Do WriteLog("
",2) + } Else { + Do WriteLog("

No calculated members found for "_cube_"

",2) + } + //Detailed cube information + Do WriteUpdate("Getting detailed cube information for "_cube_": %Analyze") + Do:tracking WriteTrack("cube","%Analyze",cube) + Do WriteLog("

Analyze

",2) + Do WriteLog("",2) + Do WriteLog("",4) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",4) + Do WriteLog("
",8) + Do WriteLog("
",10)
+	//Execute %Analyze but skip it if indices take too long
+	Try {
+		Set dirindices=##class(%SYS.Namespace).GetGlobalDest(namespace,"DeepSee.Index")
+		Do ##class(%Library.GlobalEdit).GetGlobalSizeBySubscript($P(dirindices,"^",2),"DeepSee.Index("""_cube_""")","",.sizeindex) 
+		Set dirfacts=##class(%SYS.Namespace).GetGlobalDest(namespace,"DeepSee.Fact")
+ 		Do ##class(%Library.GlobalEdit).GetGlobalSizeBySubscript($P(dirfacts,"^",2),"DeepSee.Fact("""_$zu(28,factclass,5)_""")","",.sizefacts)
+		Set flag="c"
+		Set:(sizeindex<500) flag="i"_flag
+		If (flag'="c") {
+			//See if analyzing facts is quick
+			Set:(sizefacts<300) flag="f"_flag
+			Do WriteLog("Do ##class(%DeepSee.Utils).%Analyze("""_cube_""","""_flag_""",0)")
+			Do ##class(%DeepSee.Utils).%Analyze(cube,flag,0)
+		} Else {
+			Set msg="%Analyze was skipped because of the sizes of ^DeepSee.Fact or ^DeepSee.Index global ("_
+					sizefacts_" and "_sizeindex_", respectively). Consider to run the following command: "
+			Set msg2="Do ##class(%DeepSee.Utils).%Analyze("""_cube_""",""fci"",0)"
+			Do WriteLog(msg)
+			Do WriteLog(msg2)
+			Do:tracking WriteTrack("warning","",cube,msg_msg2)
+		}
+		Do WriteLog("")
+		Do WriteLog("")
+		Do WriteLog("")
+	} Catch(ex) {
+		Set tSC = ex.AsStatus()
+		Do WriteLog(tSC)
+	}
+	// Translate the filed names in %Analyze to actual specs
+	Do WriteUpdate("Getting detailed cube information for "_cube_": FieldNameToSpec")
+	Do:tracking WriteTrack("cube","FieldNameToSpec",cube)
+	Write "FieldNameToSpec("""_cube_""")",!
+	Do FieldNameToSpec(cube)
+	Do WriteLog("")
+	Do WriteLog("")
+	Do WriteLog("")
+	Do WriteUpdate("Getting detailed cube information for "_cube_": %AnalyzeMissing")
+	Do:tracking WriteTrack("cube","%AnalyzeMissing",cube)
+	Write "Do ##class(%DeepSee.Utils).%AnalyzeMissing(""",cube,""")",!
+	Do ##class(%DeepSee.Utils).%AnalyzeMissing(cube)
+	Do WriteLog("
",10) + Do WriteLog("
",2) + Do WriteLog("") + ZN "%SYS" + Quit + +LogOtherCubeElements + Do WriteUpdate("Getting detailed cube information for "_cube_": other cube elements") + Do:tracking WriteTrack("cube","Other cube elements",cube) + ZN namespace + Do WriteLog("
",2) + Do WriteLog("",2) + Do WriteLog("

Other Elements for "_cube_"

",2) + If ##class(%DeepSee.Utils).%IsCubeAbstract(cube) { + Do WriteLog("

Not available because the cube is abstract

",0) + ZN "%SYS" + Quit + } + Do ##class(%DeepSee.Utils).%GetPivotVariables(cube,.pivotvars) + Do ##class(%DeepSee.Utils).%GetCubeListingFields(cube,.listingfields) + Do ##class(%DeepSee.Utils).%GetCubeListings(cube,.listings) + Set model = ##class(%DeepSee.Utils).%GetModel(cube) + If model="" { + Set defaultListingName = "" + } Else { + Set defaultListingName = model.defaultListing + } + /// Pivot Variables + Do WriteLog("

Pivot Variables

",2) + If $D(pivotvars){ + Do WriteLog("",2) + Do WriteLog("",4) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + For ii=1:1:pivotvars{ + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",8) //Description + Do WriteLog("",8) //Default Value + Do WriteLog("",8) //Type + Do WriteLog("",6) + } + Do WriteLog("",4) + Do WriteLog("
NameDescriptionDefault ValueType
"_$LG(pivotvars(ii),1)_""_$LG(pivotvars(ii),2)_""_$LG(pivotvars(ii),3)_""_$LG(pivotvars(ii),4)_"
",2) + } + /// Named sets + Do WriteLog("

Named Sets

",2) + Do WriteLog("") + Merge namedsets = ^DeepSee.Cubes("cubes",cube,"namedSets") + If $D(namedsets){ + Do WriteLog("",2) + Do WriteLog("",4) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Set ii = $O(namedsets("")) + While ii'="" { + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",8) //Set Expression + Do WriteLog("",6) + Set ii = $O(namedsets(ii)) + } + Do WriteLog("",4) + Do WriteLog("
NameSet Expression
"_$LG(namedsets(ii),1)_""_$LG(namedsets(ii),2)_"
",2) + } + //Listing fields + Do WriteLog("

Listing Fields

",2) + If $D(listingfields){ + Do WriteLog("") + Do WriteLog("",2) + Do WriteLog("",4) + Do WriteLog("",6) + Do WriteLog("",4) + Set tIndex = $O(listingfields("")) + While tIndex'="" { + Do WriteLog("",4) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",4) + Set tIndex = $O(listingfields(tIndex)) + } + Do WriteLog("",2) + Do WriteLog("
NameField ExpressionResourceDescription
"_$LG(listingfields(tIndex),1)_""_$LG(listingfields(tIndex),2)_""_$G(^DeepSee.Cubes("cubes",cube,"listingFields",$LG(listingfields(tIndex),1),"resource"))_""_$LG(listingfields(tIndex),3)_"
") + Do WriteLog("") + } + //Listings + Do WriteLog("

Listings

",2) + If $D(listings){ + Do WriteLog("",2) + Do WriteLog("",4) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",6) + //Write fields of listing nicely + Set listing=$O(listings("")) + While listing'="" { + //$$$CUSTOM just marks there are listing fields + If listing="$$$CUSTOM" { + Set listing=$O(listings(listing)) + Continue + } + Do WriteLog("",6) + Do WriteLog("",8) + Set fieldString=$LG(listings(listing),2) + Set listingSource=$LG(listings(listing),5) //Listing source + //Resource + Set resource = "" + Set:(listingSource="cube") resource = $G(^DeepSee.Cubes("cubes",cube,"listing",listing,"resource")) + Set:(listingSource="listingGroup") resource = $G(^DeepSee.ListingGroups("cubes",cube,"listing",listing,"resource")) + Set listingSource=$S(listingSource="listingGroup":"Listing Group",listingSource="cube":"Cube",1:listingSource) + //Custom SQL listing vs normal listing with fields + If (fieldString="") { + Do WriteLog("",8) //FieldName + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",6) + //Split listing expression on multiple lines on SQL keywords: FROM, WHERE + //Split an write FROM part + Set listingExpr = $G(^DeepSee.Cubes("cubes",cube,"listing",listing,"sql")) + Set tInd = $FIND($ZCONVERT(listingExpr,"U")," FROM ") + Set stub = $E(listingExpr,0,tInd-6) + Set listingExpr = $E(listingExpr,tInd-5,*) + If tInd { + Do WriteLog("",6) + Do WriteLog("",8) //Skip Listing Name columns + Do WriteLog("",8) + Do WriteLog("",8) //Skip Listing Name column + Do WriteLog("",8) //Skip Listing Name column + Do WriteLog("",6) + } + //Split an write WHERE part + Set tInd = $FIND($ZCONVERT(listingExpr,"U")," WHERE ") + Set stub = $E(listingExpr,0,tInd-7) + Set listingExpr = $E(listingExpr,tInd-6,*) + If tInd { + Do WriteLog("",6) + Do WriteLog("",8) //Skip Listing Name column + Do WriteLog("",8) + Do WriteLog("",8) //Skip Listing Name column + Do WriteLog("",8) //Skip Listing Name column + Do WriteLog("",6) + } + //Write all that is left + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) //Skip Listing Name column + Do WriteLog("",8) //Skip Listing Name column + Do WriteLog("",6) + } Else { //Normal listings + //Print the list fields (the source properties) separately in the second column + Set fieldList=$LFS(fieldString,",") + //Place the first fieldList in the same line + Set tInd=0 + Do WriteLog("",8) //Skip first field column + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",6) + //Do WriteLog("",6) + //Write one field per row + Set field=$LG(fieldList,$I(tInd)) + While field'="" { + //Try to parse $$$TEXT[] in listings correctly + If ($FIND($ZCONVERT(field,"U"),"$$$TEXT[") && '$FIND(field,"]")) { //Typical of Health Insight + Set field=field_","_$LG(fieldList,$I(tInd)) + } + //Health Insight has often NVL() || NVL() in listings + If ($E($ZCONVERT(field,"U"),1,5)["NVL(") { + Set field=field_","_$LG(fieldList,$I(tInd)) + While ($L(field)<1000) { //Stop in case things go wrong + Set fieldafter=$LG(fieldList,tInd+1) + If (($E(fieldafter)="'") || ($E(fieldafter)=")")) { + Set field=field_","_fieldafter + Set tInd=tInd+1 + } Else { + Quit + } + } + } + /*//I don't think field can start with single quote but that happens when using eg NVL() + If (($E(field)="'") || ($E(field,2)="'")) { + Set field=field_$LG(fieldList,$I(tInd)) + }*/ + Do WriteLog("",6) + Do WriteLog("",8) //Nothing in the first column + Do WriteLog("",8) + Do WriteLog("",8) //Nothing in the 3rd column (Source) + Do WriteLog("",8) //Nothing in the 4th column (Resource) + Do WriteLog("",6) + Set field=$LG(fieldList,$I(tInd)) + } + } + Set listing=$O(listings(listing)) + } + Do WriteLog("",4) + Do WriteLog("
Listing NameFieldsSourceResource
"_listing_$S((listing=defaultListingName):" (default)",1:"")_"*No Fields - Custom SQL Listing*"_listingSource_""_resource_"
"_stub_"
"_stub_"
"_listingExpr_"
"_listingSource_""_resource_"
"_field_"
",2) + } Else{ + Do WriteLog("No detail listings defined in this cube") + } + ZN "%SYS" + Quit + +LogQuerylog + //Get last N queries run by each user, where N can be secretly chosen from the prompt instead of Y/N + + Do WriteUpdate("Getting Query Log, DeepSee logs, and cconsole.log") + Do:tracking WriteTrack("getlogs","Getting Query Log, DeepSee logs, and cconsole.log","") + Do WriteLog("
") + Do WriteParagraph("querylog","Query Log") + Do WriteLog("

▸ Expand

",2) + Do WriteLog("
",2) + ZN namespace + Do:($D(^DeepSee.QueryLog)<10) WriteLog("

Query log global not found

",2) + Quit:($D(^DeepSee.QueryLog)<10) + //Get usercount in ^DeepSee.QueryLog + Set user=$O(^DeepSee.QueryLog("")) + Set usercount=0 + While (user'="") { + Set userqueries(user)=$G(^DeepSee.QueryLog(user)) + Set usercount=$I(usercount) + Set user=$O(^DeepSee.QueryLog(user)) + } + //Show table with number of queries run by users + Do WriteHeader4("Users running MDX queries",2) + //Do WriteLog("

Number of users = "_usercount_"

") + If $D(userqueries) { + Do WriteLog("",2) + Do WriteLog("",4) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",6) + Set u = $O(userqueries("")) + While (u'="") { + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",6) + Set u = $O(userqueries(u)) + } + Do WriteLog("",4) + Do WriteLog("
User ("_usercount_" total) Queries run
"_u_""_userqueries(u)_"
",2) + } + //Show table with the most run queries, 5 by default unless the user used the secret option on prompt + Set numqueries = 5 + Set:(getLogs>1) numqueries = getLogs + Do WriteHeader4("Most run queries",2) + Do MostRunQueries(numqueries) + //Last Query subsection + Do WriteHeader4("Last query",2) + Do WriteLog("
",2)
+	Set lastquery=$g(^[namespace]DeepSee.LastQuery)		//Display last query
+	If lastquery'=""{		
+		Do WriteLog(lastquery,0)
+		Use PDev
+	}
+	Do WriteLog("
",2) + //Subsection with 5 last queries for each user + Do WriteHeader4("MDX queries by user",2) + //Show the last 5 queries by default unless the user used the secret option on prompt + Do lastNQueries(numqueries) + Do WriteLog("
",2) //Close Expand/Collapse div + Do WriteLog("") + Use PDev + Quit + +LogDeepSeelog + //Processes DeepSee Log file + Try { + New x + Set DSFile=$zu(12)_"DeepSeeTasks_"_namespace_".log" + Do WriteLog("
") + Do WriteParagraph("dslog","DeepSee Logs") + Do WriteLog("

▸ Expand

",2) + //Do WriteLog("
") + Do WriteLog("
",2) + Do WriteLog("
",4)
+		Do WriteLog("DeepSee Logs File "_DSFile_":"),WriteLog("")
+		Open DSFile:"R":FileOpenTimeOut
+		If '$Test Do  Quit
+		.	Do WriteLog("Error: could not open DeepSee Logs File "_DSFile)
+		.	Use LogFile 
+		.	Do WriteLog("
",4) + . Do WriteLog("
",2) + . Do WriteLog("
",0) + . Use PDev + . Quit + //Read timeout added to prevent the case where neither error nor $ZEOF terminate the loop + For Use DSFile Read x:FileReadTimeOut Set ZEOF=$ZEof Use PDev Quit:'$Test!(ZEOF) Use LogFile Write x,CRLF Use PDev + Close DSFile + Use LogFile + Do WriteLog("",4) + Do WriteLog("
",2) + Do WriteLog("") + Use PDev + } Catch(ex) { + Set tSC = ex.AsStatus() + Close DSFile + Use LogFile + Do WriteLog("",4) + Do WriteLog("",2) + Do WriteLog("") + Use PDev + } + Quit + +LogCPF + Try { + //Processes Cache configuration file (usually Cache.cpf) + New x + Do WriteLog("
") + Do WriteParagraph("cpf","cache.cpf file") + Use PDev + Do WriteLog("") + Do WriteLog("

▸ Expand

",2) + //Do WriteLog("
") + Do WriteLog("
",2) + Do WriteLog("

Caché Configuration File "_ConfigFile_":"_"

",4) + Do WriteLog("
",4)
+		Open ConfigFile:"R":FileOpenTimeOut
+		If '$Test Do  Quit
+		.	Do WriteLog("Error: could not open Caché Configuration File "_ConfigFile)
+		.	Do WriteLog("
") + . Do WriteLog("
") + . Use PDev + . Quit + //Read timeout added to prevent the case where neither error nor $ZEOF terminate the loop + Set MapCount=1 + Set NsCount=1 + For { + Use ConfigFile Read x:FileReadTimeOut + If $p(x,".",1)="[Map" { //Grab namespace we are mapping from + Set NsMap(NsCount) = x + Set NsCount = $I(NsCount) + } + If x["OBJ.DSTIME" { //Grab OBJ.DSTIME mapping + Set DSTimeMap(NsCount)=x + } + If $p(x,".",1)="Global_DeepSee" { //Create array of DeepSee.* global mappings within this namespace + Set DeepSeeMap(NsCount,MapCount) = x + Set MapCount = $I(MapCount) + } + Set ZEOF=$ZEof + Use PDev + Quit:'$Test!(ZEOF) + Use LogFile + Write x,CRLF + Use PDev + } + Close ConfigFile + For i=1:1:NsCount{ + Write NsMap(i),! + Set NumMaps=$O(DeepSeeMap(i,""),-1) + For k=1:1:NumMaps{ + Write DeepSeeMap(i,k),! + If k=NumMaps Write ! + } + } + Use LogFile + Do WriteLog("",4) + Do WriteLog("
",2) + Do WriteLog("
") + Use PDev + } Catch(ex) { + Set tSC = ex.AsStatus() + Close ConfigFile + Use LogFile + Do WriteLog("",4) + Do WriteLog("",2) + Do WriteLog("") + Use PDev + } + Quit + +LogCConsole + Try { + //Processes cconsole.log + New cconsoleFile,cconsoleSize,x + Do WriteLog("
") + Do WriteParagraph("cconsole","cconsole.log") + Do WriteLog("

▸ Expand

",2) + Do WriteLog("
",2) + Do WriteLog("
",4)
+		Use PDev
+		If $Data(NoRun("cconsole")) Do  Quit
+		.	Do WriteLog(""),WriteLog("cconsole.log information inhibited by User.")
+		.	Do WriteLog("
",4) + . Do WriteLog("
",2) + . Do WriteLog("
") + . Use PDev + + If OS?1"Win".e!(OS="UNIX"){ + Set cconsoleFile=MgrDir_DirDelim_"cconsole.log" + } Else { + Set:(OS="VMS") cconsoleFile=MgrDir_"CCONSOLE.LOG" + } + Set cconsoleSize=$ZUtil(140,1,cconsoleFile) + If 'cconsoleSize Do Quit + . Do WriteLog("File "_cconsoleFile_" is zero bytes long.") + . Do WriteLog("",4) + . Do WriteLog("",2) + . Do WriteLog("") + . Use PDev + . Quit + //Only put the last 8mb in the file + If cconsoleSize>(8388608 /* 8mb */) { + Set SkipSize=cconsoleSize-8388608 + Do WriteLog("File "_cconsoleFile_" is too large, skipping first "_SkipSize_" bytes",2) + } Else { + Set SkipSize=0 + } + Do CopyToLog(cconsoleFile,"Caché cconsole.log",SkipSize) + } Catch(ex) { + Set tSC = ex.AsStatus() + Do WriteLog("Error in logging the cconsole.log file") + } + Do WriteLog("",4) + Do WriteLog("",2) + Do WriteLog("") + Use PDev + Quit + +LogMappings + Do WriteLog("
") + Do WriteParagraph("Mappings","Mappings") + ZN "%SYS" + Try { + Set rs=##class(%ResultSet).%New("Config.MapGlobals:List") + Do rs.Execute(namespace) + Set next=rs.Next() + If ('next) { + Do WriteLog("

No mappings for the "_namespace_" namespace

",2) + Do WriteLog("
") + Return + } + Do rs.Execute(namespace) + Do WriteLog("",2) + Do WriteLog("",4) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",6) + For { + Quit:'rs.Next() + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",6) + } + Do WriteLog("",4) + Do WriteLog("
GlobalDatabase
"_rs.Get("Name")_""_rs.Get("Database")_"
",2) + Do WriteLog("
",2) + } Catch(ex) { + Set tSC = ex.AsStatus() + } + Do WriteLog("") + ZN "%SYS" + Quit + +LogDataBases + Try { + Do WriteUpdate("Getting local databases information") + Do:tracking WriteTrack("databases","Getting local databases information","") + //CKEY^%SYS.LICENSE + Do WriteLog("
") + Do WriteParagraph("LocalDB","Local Databases") + Do WriteLog("
",2) + ZN "%SYS" + Set Maj=##class(%SYSTEM.Version).GetMajor() + If Maj<2009 { + Set result=##class(%Library.ResultSet).%New("Config.DataStorage:LocalDatabaseList") + } Else { + Set result=##class(%Library.ResultSet).%New("Config.Databases:LocalDatabaseList") + } + Set tSC = result.Execute() + If ('tSC) { + Do $System.Status.DisplayError(tSC) + Do:tracking WriteTrack("warning","","LogDataBases",$System.Status.GetErrorText(tSC)) + Quit + } + Do WriteLog("",2) + Do WriteLog("",4) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",6) + While result.Next(.tSC) { + If ('tSC) Quit + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Set db=##class(SYS.Database).%OpenId(result.Data("Directory")) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",6) + } + If ('tSC) { + Do $System.Status.DisplayError(tSC) + Do:tracking WriteTrack("warning","","LogDataBases",$System.Status.GetErrorText(tSC)) + Quit + } + Do WriteLog("",4) + Do WriteLog("
DatabaseDirectorySize [MB]Block Size [KB]StatusResourceEncryptedJournal
"_result.Data("Name")_""_result.Data("Directory")_""_$FNUMBER(result.Data("Size in MB"),",",0)_""_$FNUMBER(db.BlockSize/1024,",",0)_""_result.Data("Status")_""_result.Data("Resource")_""_result.Data("Encrypted")_""_result.Data("Journal")_"
",2) + } Catch(ex) { + Set tSC = ex.AsStatus() + Do $System.Status.DisplayError(tSC) + Do:tracking WriteTrack("warning","","LogDataBases",$System.Status.GetErrorText(tSC)) + } + Do WriteLog("
") + Quit $$$OK + +LogTasks + Try { + Do WriteUpdate("Getting background tasks information") + Do:tracking WriteTrack("tasks","Getting background tasks information","") + Do WriteLog("
") + Do WriteParagraph("Taskschedule","Task schedule") + Use LogFile + ZN "%SYS" + Set rs = ##class(%ResultSet).%New("%SYS.Task:TaskListFilter") + Set:(rs="") rs = ##class(%ResultSet).%New("%SYS.Task:TaskList") //Old versions + Do rs.Execute() + Do WriteLog("",2) + Do WriteLog("",4) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",6) + While (rs.Next()) { + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + + Do WriteLog("",6) + } + } Catch { + //Do WriteLog("
Task NameTask TypeNamespaceDescriptionIDSuspendedLast FinishedNextScheduled
"_rs.%Get("Task Name")_""_rs.%Get("Task Type")_""_rs.%Get("Namespace")_""_rs.%Get("Description")_""_rs.%Get("ID")_""_rs.%Get("Suspended")_""_rs.%Get("Last Finished")_""_rs.%Get("Next Scheduled")_"
") + Do WriteLog("

An error occurred

",2) + } + Do WriteLog("",4) + Do WriteLog("",2) + Do WriteLog("
") + Quit + +LogJournal + Do WriteUpdate("Getting journaling information") + Do:tracking WriteTrack("journal","Getting journaling information","") + Do WriteLog("
") + Do WriteParagraph("Journaling","Journaling",2) + ZN "%SYS" + Try{ + Set pdir = ##class(%SYS.Journal.System).GetPrimaryDirectory(.st) + Set altdir = ##class(%SYS.Journal.System).GetAlternateDirectory(.st) + Set freesp = ##class(%SYS.Journal.System).GetFreeSpace() + Set stateString = ##class(%SYS.Journal.System).GetStateString() + Set filen=1 + Set FileName = ##class(%SYS.Journal.System).GetCurrentFileName() + While FileName'="" { + Set FileSize=$zu(140,1,FileName) + i (FileSize<0)||($ZU(78,22,FileName)'=1) s Row="Filename" Quit + Set $li(Row(filen),1)=FileName + Set $li(Row(filen),2)=FileSize + Set $li(Row(filen),3)=$zdt($zdth($p($zu(78,22,FileName,4),",",2),-2),3) + Set $li(Row(filen),4)=4 //..TranslateReason($P($zu(78,22,FileName,1),",",3)) + Do ##class(%SYS.Journal.File).GetPrev(FileName,.FileName) + Set filen=filen+1 + } + ZN namespace + Use LogFile + Do WriteLog("",2) + Do WriteLog("",4) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",6) + Do WriteLog("",4) + Do WriteLog("
",8) + Do WriteHeader4("Primary Directory",10) + Do WriteLog("

"_pdir_"

",10) + Do WriteLog("
",8) + Do WriteHeader4("Alternative Directory",10) + Do WriteLog("

"_altdir_"

",10) + Do WriteLog("
",8) + Do WriteHeader4("Free Space",10) + Do WriteLog("

"_$FNUMBER(freesp/1024/1024,",",0)_" MB

",10) + Do WriteLog("
",8) + Do WriteHeader4("State",10) + Do WriteLog("

"_stateString_"

",10) + Do WriteLog("
",2) + If $D(Row(1)) { + Do WriteHeader4("Journal Files",2) + Do WriteLog("",2) + Do WriteLog("",4) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",6) + Set filen=1 + While $D(Row(filen)) { + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Set a=$LG(Row(filen),6) + Set reas=$S(a=-1:"",a=0:"unspecified",a=1:"by user",a=2:"file size limit reached",a=3:"to retry failed I/O", + a=4:"by backup",a=5:"by restore",a=6:"by task manager",a=7:"to activate journal changes", + a=8:"to reenable journaling",a=9:"by mirror startup",a=10:"by mirror shutdown",a=11:"mirror database removed",1:"Unknown") + Do WriteLog("",8) + Do WriteLog("",6) + Set filen=filen+1 + } + Do WriteLog("",4) + Do WriteLog("
NameSize in KBCreation TimeReason
"_$LG(Row(filen),1)_""_$FNUMBER($LG(Row(filen),2)/1024,",",0)_""_$LG(Row(filen),3)_""_reas_"
",2) + } + } Catch { + Do WriteLog("

An error occurred

",2) + } + Do WriteLog("
") + Quit + +LogAlerts + Try { + Do WriteLog("
") + Do WriteParagraph("Alerts","Alerts") + If $D(alerts)>9 { //alerts is an array + Do WriteLog("

The following alerts were raised on this system. Please find more details above

",2) + Set i = $O(alerts("")) + While (i'="") { + Do WriteLog("

",2) + Set i = $O(alerts(i)) + } + } Else { + Do WriteLog("

No alerts"_"

",2) + } + } Catch(ex) { + Set tSC = ex.AsStatus() + Do WriteLog("

Error: "_tSC_"

",2) + } + Do WriteLog("
") + Quit + +LogTrailer + //Records a Trailer record to LogFile + Do WriteParagraph("end","End of DeepSeeButtons") + Do WriteLog("

"_ConfigName_" on Machine """_HostName_"""

") + Do WriteLog("") //End
+ Use PDev + Quit + +LogSidePanel(cubeList,getLogs,numalerts) + Do WriteLog("
") + Do WriteLog("×",2) + Do WriteLog("DeepSee Setup",2) + If (isInsight || isTrak) { + //Set nOverrides=$$CountNodes(namespace,"^DeepSee.Overrides") + Do:(nOverrides>=10) WriteLog("DeepSee Overrides",2) + } + Do WriteLog("Server Details",2) + Do WriteLog("Cubes",2) + Do WriteLog("Build/Synch",2) + Do WriteLog("Cube Registry",2) + If (($D(cubeList)'=0) && (cubeList'="")) { + Do WriteLog("Cube Info",2) + Set cubeListLength=$ll(cubeList) + For i=1:1:cubeListLength{ + Set cube=$LG(cubeList,i) + Do:cube'="" WriteLog(""_cube_"",2) + } + } + If getLogs{ + Do WriteLog("Query Log",2) + Do WriteLog("DeepSee Logs",2) + } + Do WriteLog("cache.cpf",2) + Do:getLogs WriteLog("cconsole.log",2) + Do WriteLog("Mappings",2) + Do WriteLog("Local Databases",2) + Do WriteLog("Task Schedule",2) + Do WriteLog("Journaling",2) + Set colorclass=$S(numalerts: "red",1:"") + Do WriteLog("Alerts ("_numalerts_")",2) + Do WriteLog("
") + Quit + +LogCloseBody + Do WriteLog("") + Do WriteLog("") + Do WriteUpdate("DeepSeeButtons report saved to "_LogFile) + Do:tracking WriteTrack("save","DeepSeeButtons report saved to ",LogFile) + Do WriteUpdate("Done") + Do:tracking WriteTrack("complete","Complete","") + Quit + + +/// More helper functions for the Log* functions above +ValidateNamespace(namespace) [namespace]{ + Set namespace=$ZCONVERT(namespace, "U") + Try { + ZN namespace + return namespace + } Catch ex { + Write !,namespace," is invalid. Please enter a valid namespace." + Set namespace="" + Return namespace + } +} + +Init() + //Sets routine-wide variables + New i,LogFilePrefix,v,x + Set PDev=$Principal + Set CRLF=$Char(13,10) + Set CmdOpenTimeOut=60 + Set CmdReadTimeOut=30 + Set FileOpenTimeOut=5 + Set FileReadTimeOut=30 + Set CacheVerStr=$ZVersion + Set CacheVerNumber=$System.Version.GetNumber() + Set HostName=$ZUtil(54,0) + Set CacheDir="" + + Set IPAddr="unknown" + Set FullHostName="unknown" + Try { + //$zversion(0) is a bit string that informs what features are enabled in cache'. + //It can fail behind a firewalls + #define USEIPV6 $zbitget($zversion(0)_$c(0,0,0,0),42) + #define HostNameToIPText(%h,%f) $s($$$USEIPV6:$SYSTEM.INetInfo.HostNameToAddr(%h,%f),1:$p($ZU(54,13,%h),",",1)) + #define IPTextToBinary(%ip) $s($$$USEIPV6:$SYSTEM.INetInfo.TextAddrToBinary(%ip),1:$ZU(54,1,%ip)) + #define IPBinaryToHostName(%ip) $s($$$USEIPV6:$SYSTEM.INetInfo.AddrToHostName(%ip),1:$p($ZU(54,14,%ip),",",2)) + #define IPTextToHostName(%ip) $$$IPBinaryToHostName($$$IPTextToBinary(%ip)) + Set IPAddr=$$$HostNameToIPText(HostName,0) + Set FullHostName=$$$IPTextToHostName(IPAddr) + } Catch(ex) { + Set tSC = ex.AsStatus() + Set FullHostName="Unknown" + Set IPAddr="unknown (due to "_$System.Status.GetErrorText(tSC)_")" + } + Set MgrDir=$ZUtil(12) + Set MgrNsp=$$ST() + Set CurDir=$ZUtil(12,"") + Set CurNsp=$ZUtil(5) + Set x=$ZUtil(86),ConfigFile=$Piece(x,"*",1),ConfigName=$Piece(x,"*",2) + Set CurUser=$ZUtil(67,11,$Job) + Set CustomerName=$System.License.KeyCustomerName() + Set OrderNumber=$System.License.KeyOrderNumber() + //Equivalent to $System.Version.GetCompBuildOS() + //Get if Trak or HealthInsight + Set isInsight=$$isHealthInsight(namespace) //Determine if this is a Health Insight namespace (1 if yes) + Set isTrak=$$isTrak(namespace) //Determine if this is a Health Insight namespace (1 if yes) + Set nOverrides = "" + Set:(isInsight || isTrak) nOverrides=$$CountNodes(namespace,"^DeepSee.Overrides") + Set v=$ZVersion,v=$ZConvert(v,"l") + If v["windows" Set OS="WinNT" //Windows NT, 2000, XP or 2003 Server + Else If v["unix" Set OS="UNIX" + Else If v["openvms" Set OS="VMS" + Else Set OS="*** Unrecognized OS ***" + If OS?1"***".e Quit + If (OS?1"Win".e) { + Set DirDelim="\" + Set NullDev="//./nul" + Do SetDirs + Set KeyFile=MgrDir_DirDelim_"Cache.key" + Set BinDir=CacheDir_DirDelim_"Bin" + } ElseIf (OS="UNIX") { + Set DirDelim="/" + Set NullDev="/dev/null/" + Do SetDirs + Set KeyFile=MgrDir_DirDelim_"cache.key" + Set BinDir=CacheDir_DirDelim_"bin" + } ElseIf (OS="VMS") { + Set DirDelim="." + Set NullDev="NL:" + Do SetDirs + Set KeyFile=MgrDir_"CACHE.KEY" + Set i=$Find(MgrDir,".MGR") + Set BinDir=$Extract(MgrDir,1,i-$Length(".MGR")-1)_".BIN"_$Extract(MgrDir,i,*) + } + Quit + +InitLogFile() + Set LogFilePrefix="" + Set FileOpenTimeOut=5 + Set CustomerName=$System.License.KeyCustomerName() + If CustomerName'="" Set LogFilePrefix="DeepSeeButtons_"_$Piece(CustomerName," ",1)_"_" + If LogFilePrefix'="",LogFilePrefix?1a.an,$Length(LogFilePrefix)<20 + Set:LogFile="" LogFile=$$NewFile(LogFilePrefix,"html") + Quit LogFile + +ST() + //Sets the Manager's Namespace (also hardcoded in %ST) + ZN "%SYS" + New + Do ^ST + Set MgrNsp=%ST("MGRNSP") + Quit MgrNsp + +DialogCubes(namespace) { + Set cubeString="" + ZN namespace + Do ##class(%DeepSee.Utils).%GetCubeList(.cubeList,,1) + If '$D(cubeList){ + Write !,"There are no cubes in this namespace!" + Set cubeList="" + Quit cubeList + } + Do { + Set cube="" + Write !,"Give cube name for detailed cube info or press enter to continue: " + Read cube + Set:cube="?" cube=$$ListCubes() + If (cube="")||(cube="QUIT")||(cube="Q") { + Quit + } ElseIf (cube'="") { + If ($LISTFIND($LISTFROMSTRING(cubeString),$ZCONVERT(cube,"t"))'=0) { + Write !,"Cube already selected" + Set cube="" + } ElseIf (cube="ALL") { //problem: it asks again + Set cubeString=$$GetAllCubes(namespace) + Set cube="QUIT" //prob useless + Quit + } ElseIf ##class(%DeepSee.Utils).%CubeExists(cube,.status)'=1 { + Write !,cube," is an invalid cube selection: " + Write !,"Enter '?' to see list of cubes in the "_namespace_" namespace",! + //Set cube="" + } Else { + Set cube=$ZCONVERT(cube,"t") //Make cube name uppercase to normalize names + Set cubeString=cubeString_","_cube + } + } + } While (cube'="")&&(cube'="QUIT")&&(cube'="Q") + Set:$E(cubeString,0,1)="," cubeString=$p(cubeString,",",2,*) //Eliminate leading comma + Set cubeSelection=$LFS(cubeString,",") //Create list + ZN "%SYS" + Quit cubeSelection +} + +GetAllCubes(namespace) + Set cubeString="" + ZN namespace + Do ##class(%DeepSee.Utils).%GetCubeList(.cubeList,,1) + Set cubeString="" + + Set cubetmp=$Order(cubeList("")) + While (cubetmp'="") { + Set cubeString=cubeString_","_cubetmp + Set cubetmp=$Order(cubeList(cubetmp)) + } + + Set cubeString=$P(cubeString,",",2,*) + ZN "%SYS" + Quit cubeString + +VerifyInputCubes(cubeList,namespace,tracking=0){ + Set len=$LISTLENGTH(cubeList) + For i=1:1:len{ + Set cube=$LG(cubeList,i) + Set cube=$ZCONVERT(cube, "U") + ZN namespace + If ##class(%DeepSee.Utils).%CubeExists(cube,.status)'=1 { + Write !!, cube_": invalid cube selection. It will not be included in the report" + //Do $system.OBJ.DisplayError(status) + Do:tracking WriteTrack("warning","",cube,"invalid cube selection. It was not included in the report") + Set cube="" + } + Set $LIST(cubeList,i)=cube //Change element in list to uppercase version (or null if it didn't exist) + } + ZN "%SYS" + Quit cubeList +} + +SetDirs + //Sets Cache Installation Directory + New i,Dev,Dir + If OS?1"Win".e!(OS="UNIX") Do + . If $Extract(MgrDir,$Length(MgrDir))=DirDelim Set MgrDir=$Extract(MgrDir,1,$Length(MgrDir)-1) //Remove trailing \ or / + . If $Extract(CurDir,$Length(CurDir))=DirDelim Set CurDir=$Extract(CurDir,1,$Length(CurDir)-1) //Remove trailing \ or / + . Quit + Else If OS="VMS" Do + . Set MgrDir=$$VMSCanonize(MgrDir) + . Set CurDir=$$VMSCanonize(CurDir) + . Quit + If OS?1"Win".e!(OS="UNIX") Set i=$Length(MgrDir,DirDelim)-1,CacheDir=$Piece(MgrDir,DirDelim,1,i) + Else If OS="VMS" Do + . Set Dev=$Piece(MgrDir,":",1),Dir=$Piece(MgrDir,":",2,$$$MaxPieceNum) + . If $Extract(Dir,1)="[" Set Dir=$Extract(Dir,2,*) + . If $Extract(Dir,$Length(Dir))="]" Set Dir=$Extract(Dir,1,$Length(Dir)-1) + . Set Dir=$Piece(Dir,".",1,$Length(Dir,".")-1) + . Set Dir="["_Dir_"]" + . Set CacheDir=Dev_":"_Dir + . Quit + Quit + +ListCubes(){ + Do ##class(%DeepSee.Utils).%GetCubeList(.cubeList,,1) + Write !, "Cubes in this namespace: ",!! + Set cubetmp="" + + Set cubetmp=$order(cubeList("")) + While (cubetmp'="") { + Write cubetmp,! + Set cubetmp=$order(cubeList(cubetmp)) + } + Write "ALL",! + Write !, "Give cube name for detailed cube info or press enter to continue: " + Read cube + + Quit cube //returns "" if no cube number entered +} + +LongName(x) + New (OS,x) + Set x=$Get(x,"") + If OS="VMS" Quit x + Set Space=$Char(32),Quote=$Char(34) + If x[Space Set x=Quote_x_Quote + Quit x + +VMSCanonize(Dir) + New (Dir) + Set Dev=$Piece(Dir,":",1),Dir=$Piece(Dir,":",2,$$$MaxPieceNum) + Set Dir=$Translate(Dir,"<","[") //Replace < by [ + Set Dir=$Translate(Dir,">","]") //Replace > by ] + Set i=$Length(Dir,"[")-1 + If i>1 Do //Directory format is [DIR.][SUBDIR]... + . If $Extract(Dir,1)="[" Set Dir=$Extract(Dir,2,*) + . If $Extract(Dir,$Length(Dir))="]" Set Dir=$Extract(Dir,1,$Length(Dir)-1) + . For Quit:$Piece(Dir,"[",2)="" Set Dir=$Piece(Dir,"[",1)_$Piece(Dir,"[",2,$$$MaxPieceNum) + . For Quit:$Piece(Dir,"]",2)="" Set Dir=$Piece(Dir,"]",1)_$Piece(Dir,"]",2,$$$MaxPieceNum) + . Set Dir="["_Dir_"]" + . Quit + Set Dir=Dev_":"_Dir + Quit Dir + +WriteLastStartup + Try { + Set timein=$ZHorolog\1, now=$Horolog + Set timeup=timein + Set days=timeup\86400 + Set timeup=timeup-(days*86400) + Set hours=timeup\3600 + Set timeup=timeup-(hours*3600) + Set minutes=timeup\60 + Set timeup=timeup-(minutes*60) + Set seconds=timeup + Set today=+now + Set secs=$Piece(now,",",2) + Set now=(today*86400)+secs + Set then=now-timein + Set odays=then\86400 + Set osecs=then-(odays*86400) + Set oh=odays_","_osecs + Do WriteLog("

"_$ZDATETIME(oh,3)_". As of this report Caché has been up for "_days_" days "_hours_" hours "_minutes_" minutes "_seconds_" seconds"_"

",8) + } Catch(ex) { + Set tSC = ex.AsStatus() + Do WriteLog($System.Status.GetErrorText(tSC),10) + Do:tracking WriteTrack("warning","","WriteLastStartup",$System.Status.GetErrorText(tSC)) + } + Quit + +isHealthInsight(namespace){ + Try{ + ZN namespace + Set HealthShare=##class(%SYSTEM.License).GetFeature(12) //Look in license for HealthShare Foundation + ZN "%SYS" + Return HealthShare + } Catch { + ZN "%SYS" + Return 0 //Method did not work so return 0 + } +} + +isTrak(namespace){ + Try{ + ZN namespace + Set BitTrakCare = ##class(%SYSTEM.License).GetFeature(6) //BitTrakCare + ZN "%SYS" + Return BitTrakCare + } Catch { + ZN "%SYS" + Return 0 //Method did not work so return 0 + } +} + +NLS + Try { + New LocCur,LocDesc,LocSrc,oLoc + Do WriteHeader4("Current Locale",8) + ZN "%SYS" + Set oLoc=##class(Config.NLS.Locales).OpenCurrent() + If oLoc="" Set LocCur="Unknown",LocDesc="Unknown" + Else Set LocCur=oLoc.Name,LocDesc=oLoc.Description + Set LocSrc=$$ComputeFullDBDir^%SYS.API("Locale") + Do WriteLog("

"_LocCur_" ("_LocDesc_")

",8) + } Catch(ex) { + Set tSC = ex.AsStatus() + Do WriteLog($System.Status.GetErrorText(tSC),10) + Do:tracking WriteTrack("warning","","NLS",$System.Status.GetErrorText(tSC)) + } + Quit + +OSVer + //This is almost the same as the OSVer function in ^Buttons + Try { + //Add the OS version to LogFile + New Cmd,uname + Do WriteHeader4("Operating System Version",8) + Do WriteLog("

",8) + If OS?1"Win".e Set Cmd="Ver" + If OS="UNIX" Set Cmd="uname -a" + If OS="VMS" Set Cmd="WRITE SYS$OUTPUT ""OpenVMS "",F$GETSYI(""VERSION"")" + Do ExternalCmd(Cmd) + //Do ExternalCmd^Buttons(Cmd) + If OS="UNIX" Set uname=$$uname() + If ($D(uname) && (uname?1"AIX".e)) { + Do WriteLog(" -- ",8) + Do ExternalCmd("lsattr -El proc0") + //Do ExternalCmd^Buttons("lsattr -El proc0") + } + } Catch(ex) { + Set tSC = ex.AsStatus() + Do WriteLog($System.Status.GetErrorText(tSC),10) + Do:tracking WriteTrack("warning","","OSVer",$System.Status.GetErrorText(tSC)) + } + Do WriteLog("

",8) + Quit + +uname() + New (CmdOpenTimeOut,CmdReadTimeOut,PDev) + Set Cmd="uname -s" + Open Cmd:"RQ":CmdOpenTimeOut + If '$Test Quit "" + Try { + Use Cmd Read uname:CmdReadTimeOut Use PDev + } Catch(ex) { + Set tSC = ex.AsStatus() + } + Close Cmd + Quit uname + +RAM + Do WriteHeader4("RAM",8) + //First refresh CPU info + Do $ZU(204,0) + Do WriteLog("

Model: "_$ZU(204,2)_"

",8) + Do WriteLog("

Chips: "_$ZU(204,6)_"

",8) + Do WriteLog("

Cores: "_$ZU(204,5)_"

",8) + Do WriteLog("

Threads: "_$ZU(204,4)_"

",8) + Do WriteLog("

Frequency: "_$ZU(204,11)_" MHz

",8) + Set temp = $ZU(190,18) + Do WriteLog("

Total physical memory: "_$FNUMBER($P(temp,",",1)/1024,",",0)_" MB

",8) + Do WriteLog("

Free physical memory: "_$FNUMBER($P(temp,",",2)/1024,",",0)_" MB

",8) + Do WriteLog("

Total paging/swap space: "_$FNUMBER($P(temp,",",3)/1024,",",0)_" MB

",8) + Do WriteLog("

Free paging/swap space: "_$FNUMBER($P(temp,",",4)/1024,",",0)_" MB

",8) + Do WriteLog("",8) + Quit + +DiskSpace + Do WriteHeader4("Disk space",8) + Do ##class(%File).DriveListExecute(.drivelist) + For { + Set st=##class(%File).DriveListFetch(.drivelist,.drive,.AtEnd) + Set drive = $LG(drive) + Do ##class(%Library.File).GetDirectorySpace(drive,.free,.total,1) + Do WriteLog("

Total space in """_drive_""" drive: "_$FNUMBER(total,",",0)_" MB

",8) + Do WriteLog("

Free space in """_drive_""" drive: "_$FNUMBER(free,",",0)_" MB

",8) + Quit:AtEnd + } + Quit + +CountNodes(namespace,g){ + ZN namespace + Return:'$D(@g) 0 + For count=$D(@g)#10:1 Set g=$Query(@g) Quit:g="" + Return count +} + +GetLastBuild(CubeEvent,cubename) [cubename,CubeEvent,cubekey,cubeevent,totaltime,cubesize,finishtime,factsupdated,SQLCODE] { + new cubekey,totaltime,cubesize,finishtime,factsupdated,SQLCODE + + Set sql ="SELECT TOP 1 CubeKey,TotalTime,CubeSize,FinishTime,FactsUpdated " _ + "FROM %DeepSee_CubeManager.CubeEvent " _ + "WHERE CubeEvent='"_CubeEvent_"' "_ + $S($D(cubename):"AND CubeKey='"_cubename_"' ",1:"") _ + "ORDER BY FinishTime DESC" + Set rs = ##class(%SQL.Statement).%ExecDirect(.S,sql) + + Set SQLCODE="" + If rs.%Next() { + Set cubekey = rs.%Get("CubeKey") + Set totaltime = rs.%Get("TotalTime") + Set cubesize = rs.%Get("CubeSize") + Set finishtime = rs.%Get("FinishTime") + Set factsupdated = rs.%Get("FactsUpdated") + Set SQLCODE = rs.%SQLCODE + } + + IF SQLCODE=0 { + If CubeEvent="Synch"{ + Set string=$FNUMBER(factsupdated,"O,")_" facts synched on "_finishtime_" in "_totaltime_" seconds" + } ElseIf CubeEvent="Build"{ + Set string=$FNUMBER(cubesize,"O,")_" facts built on "_finishtime_" in "_totaltime_" seconds" + } ElseIf CubeEvent="Update"{ + Set string="on "_finishtime + } ElseIf CubeEvent="Repair"{ + Set string=$FNUMBER(cubesize,"O,")_" facts built on "_finishtime_" in "_totaltime_" seconds" + } Else { + Set string=CubeEvent_" event on "_finishtime_" in "_totaltime + } + Set:'$D(cubename) string = string_" for the "_cubekey_" cube" + } ElseIf SQLCODE=100 { + Set string = "Not found" + } Else { + Set string = "SQL Error code: "_SQLCODE + } + Quit string +} + +GetRelationships(cube){ + Quit:##class(%DeepSee.Utils).%IsCubeCompound(cube) //Can't have a related, compound cube + Set status=##class(%DeepSee.Utils).%GetDimensionList(cube,.dimlist) + Set nodenum=$O(dimlist(""),-1) //Get last node in dimlist + Set count=0 + If status=1 { + For { + If $LG(dimlist(nodenum,0,0),1)="r"{ //If dimension is a relationship... + Set count=count+1 //increment count + Set dimname=$LG(dimlist(nodenum,0,0),2) //Get name of relationship + Set relationships(count)=##class(%DeepSee.Utils).%GetRelatedCube(cube,dimname) //Related cube name + } + Quit:nodenum=0 //If no dimensions defined, first node will be 0 + Set nodenum=$O(dimlist(nodenum),-1) + Quit:$LG(dimlist(nodenum,0,0),1)'="r" + } + If count=0 { + Write " " + } Else { + For i=1:1:count { + If $g(relationships(i),"null")'="null" { + Write relationships(i) + Write:(i'=count) ", " + } + } + } + } + Quit +} + +GetSourceClass(cube,type)[storageList, dataConnectorList]{ + Try { + Set sourceClass="" + If type="cube" { + Set cubeObj=##class(%DeepSee.Utils).%GetModel(cube) + If cubeObj=""{ + Set sourceClass = "Subject area class not compiled" + Quit + } + Set sourceClass=cubeObj.sourceClass //Source Class name + If sourceClass=""&&isInsight{ + Set sourceClass=^DeepSee.Overrides(cube,"SOURCECLASS") //Source class isn't part of cube object + } + Set classObj=##class(%Dictionary.CompiledClass).%OpenId(sourceClass) + Set storage=classObj.StorageStrategy + + Set super=classObj.Super + + If storage["SQLStorage"{ + Set $LIST(storageList,*+1)=cube + } + If super["%DeepSee.DataConnector"{ + Set $LIST(dataConnectorList,*+1)=cube + } + } ElseIf type="subjectArea" { + Set basecube=##class(%DeepSee.Utils).%GetBaseCube(cube) + Do ##class(%DeepSee.Utils).%GetCubeList(.plist) + Set typebasecube = $LG(plist(basecube),4) + Set sourceClass = $$GetSourceClass(basecube,typebasecube) + } Else { + Set sourceClass="Not available" + } + } catch { + Set sourceClass = "Not available" + } + Quit sourceClass +} + +GetCountStar(sqlclass){ + Try { + Set FactCount="" + Set SQLQuery="SELECT COUNT(*) As FactCount FROM "_sqlclass + Set tStatement = ##class(%SQL.Statement).%New() + Set st = tStatement.%Prepare(SQLQuery) + If 'st { + Set FactCount = $System.Status.DisplayError(st) + Quit + } + Set rset = tStatement.%Execute() + If (rset.%SQLCODE < 0) { + Set FactCount = rset.%Message + Quit + } + Do rset.%Next() + Set FactCount = rset.FactCount + } Catch(ex) { + Set FactCount = ex.AsStatus() + Do $System.Status.DisplayError(tSC) + } + Quit FactCount +} + +GetDeepSeeAuditCode + Kill auditcode,querycode + Do WriteHeader4("Audit",8) + Try { + If $D(^[namespace]DeepSee.AuditCode){ + Set auditcode=$g(^[namespace]DeepSee.AuditCode) + Do WriteLog("

DeepSee.AuditCode: "_auditcode_"

",8) + } Else{ + Do WriteLog("

^DeepSee.AuditCode is undefined

",8) + } + If $D(^[namespace]DeepSee.AuditQueryCode){ + Set querycode=$g(^[namespace]DeepSee.AuditQueryCode) + Do WriteLog("

DeepSee.AuditQueryCode: "_querycode_"

",8) + } Else{ + Do WriteLog("

^DeepSee.AuditQueryCode is undefined

",8) + } + } Catch { + Write "Not Available" + } + Quit + +GetBuildTime(cube) + [time,cube] PUBLIC{ + new time + Set cube=$zconvert(cube,"u") + + Set sql ="SELECT TotalTime FROM %DeepSee_CubeManager.CubeEvent where cubekey='" _ + cube _ "' and cubeevent='Build' order by finishtime desc" + Set rs = ##class(%SQL.Statement).%ExecDirect(.S,sql) + + If rs.%Next() { + Quit rs.%Get("TotalTime") + } Else{ + Quit "" + } +} + +FieldNameToSpec(pCubeName) { + Set tSC = $$$OK + Q:pCubeName="" + Try { + Set tCube = $G(^DeepSee.Cubes("cubes",$zu(28,pCubeName,5),"indexName"),$zu(28,pCubeName,5)) + //Loop over indD,indH,indL in ^DeepSee.Cubes("cubes",tCube,"mbr#",indD,indH,indL) + Set indD = $O(^DeepSee.Cubes("cubes",tCube,"mbr#","")) + While (indD '= "") { + Set indH = $O(^DeepSee.Cubes("cubes",tCube,"mbr#",indD,"")) + While (indH '= "") { + Set indL = $O(^DeepSee.Cubes("cubes",tCube,"mbr#",indD,indH,"")) + While (indL '= "") { + Set list = ^DeepSee.Cubes("cubes",tCube,"mbr#",indD,indH,indL) + Set type = $LG(list,1) + Set tIndex = $LG(list,5) + If ((tIndex'="") && ((type="l") || (type="m") || (type="r"))) { + Set tIndexName = $S($E(tIndex)="M":$G(^DeepSee.Cubes("cubes",tCube,"msr#",tIndex),tIndex), + 1:$G(^DeepSee.Cubes("cubes",tCube,"fact#",tIndex),tIndex)) + If ($D(^DeepSee.Cubes("cubes",tCube,"fact","prop",tIndexName,"alias"))) { + Set tIndexName = ^DeepSee.Cubes("cubes",tCube,"fact","prop",tIndexName,"alias") + } + If ((type="l") && (tIndexName'="") && (tIndex>1)) { //Also skipping %Search with tIndex=1 + Set dimname = $LG(list,2) + Set hiername = $LG(list,3) + Set levelname = $LG(list,4) + Set fieldname2spec(tIndexName) = "["_dimname_"].["_hiername_"].["_levelname_"]" + Write !,?4,tIndexName,?41," ",fieldname2spec(tIndexName) + } ElseIf ((type="m") && (tIndex'="")) { //e.g. COUNT has no tIndex + Set dimname = $LG(list,2) //this is always "Measures" + Set measname = $LG(list,3) + If '$D(fieldname2spec(tIndexName)) { + Set fieldname2spec(tIndexName) = "["_dimname_"].["_measname_"]" + } Else { + Set fieldname2spec(tIndexName) = fieldname2spec(tIndexName)_", ["_dimname_"].["_measname_"]" + } + Set fieldname2spec(tIndexName) = "["_dimname_"].["_measname_"]" + Write !,?4,tIndexName,?41," ",fieldname2spec(tIndexName) + } ElseIf (type="r") { + Set dimname = $LG(list,2) + Set fieldname2spec(tIndexName) = "["_dimname_"]" + Write !,?4,tIndexName,?41," ",fieldname2spec(tIndexName) + } + } + Set indL = $O(^DeepSee.Cubes("cubes",tCube,"mbr#",indD,indH,indL)) + } + Set indH = $O(^DeepSee.Cubes("cubes",tCube,"mbr#",indD,indH)) + } + Set indD = $O(^DeepSee.Cubes("cubes",tCube,"mbr#",indD)) + } + Set tSC = $$$OK + } + Catch(ex) { + Set tSC = ex.AsStatus() + } +} + +MostRunQueries(numqueries) + //Show table with the most run queries + //Use $ZCRC(,7) to hash an MDX query, then create two arrays: + // queryarr(hashed MDX query) = frequency + // crcarr(hashed MDX query) = MDX query + Set u = "" + Set i = "" + For { + Set u = $O(^DeepSee.QueryLog(u)) + Quit:u="" + For { + Set i = $O(^DeepSee.QueryLog(u,i)) + Quit:i="" + //Strip some patterns from MDX queries + Set strippedquery = $ZSTRIP(^DeepSee.QueryLog(u,i),"*C") //strip control characters + Set strippedquery = $REPLACE(strippedquery,", ",",") //replace ", " + Set strippedquery = $ZSTRIP(strippedquery,"<=>W") //strip leading, trailing, and repeating white spaces + Set crc = $ZCRC(strippedquery,7) + If $D(queryarr(crc)) { + Set queryarr(crc) = $I(queryarr(crc)) + } Else { + Set queryarr(crc) = 1 + Set crcarr(crc) = strippedquery + } + } + } + //Reverse the queryarr array to get frequencies handy: + // freqarr(frequency, hashed MDX query) = MDX query + Set c = "" + For { + Set c = $O(queryarr(c)) + Quit:c="" + Set f = queryarr(c) + Set freqarr(f,c) = crcarr(c) + } + //Print + Do WriteLog("",2) + Do WriteLog("",4) + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",6) + Set freq = "" + For n = 1:1:numqueries { + Set freq = $O(freqarr(freq),-1) + Quit:freq="" + Do WriteLog("",6) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",8) + Do WriteLog("",6) + } + Do WriteLog("",4) + Do WriteLog("
#FrequencyQuery
"_n_""_freq_"",8) + Set hashed="" + Set counter = 0 + For { + Set hashed=$O(freqarr(freq,hashed)) + Quit:hashed="" + Do:counter=7 WriteLog("

...

",10) //Show up to 6 queries per frequency + Quit:counter=7 + Set query = freqarr(freq,hashed) + Do WriteLog("

"_$$encode(query)_"

",10) + Set counter= $I(counter) + } + Do WriteLog("
",2) + Quit + +lastNQueries(numqueries) + Do WriteLog("
",4)
+	Set username=""
+	For k=1:1 {
+		Set numqueriesuser = numqueries
+		Set username=$O(^DeepSee.QueryLog(username),1)
+		If username="" Quit
+		Set totqueries=$O(^DeepSee.QueryLog(username,""),-1)
+		Set:totqueriestotqueries				//User has fewer than 5 queries
+			Set counter=$O(^DeepSee.QueryLog(username,counter),-1)
+			Set query=$Get(^DeepSee.QueryLog(username,counter))
+			If query'=""{
+				Do WriteLog( i_") "_$$encode(query),0)
+			}
+		}
+	}
+	Do WriteLog("
",2) + Quit + +encode(string) { + Quit $ZCVT(string,"O","HTML") +} + +/// Alerts +alertRoutineSize(RoutineSize,alerts) { + Try { + If (RoutineSize=0) { + Set pre="title=""Routine buffers have the default ''0'' value and might need customization"">" + Set alert = "Alert: Routine buffers have not been customized" + Set alerts($I(alerts)) = pre_alert + Do WriteLog("

",8) + } + Set tSC = 1 + } Catch (ex) { + Set tSC = ex.AsStatus() + Do $System.Status.DisplayError(tSC) + } + Quit tSC +} + +alertGlobalKSize(GlobalKSize,alerts) { + Try { + If (GlobalKSize="0,0,0,0,0,0") { + Set pre="title=""Global buffers have the default ''0,0,0,0,0,0'' values and might need customization"">" + Set alert = "Alert: Global buffers have not been customized" + Set alerts($I(alerts)) = pre_alert + Do WriteLog("

",8) + } + Set tSC = 1 + } Catch (ex) { + Set tSC = ex.AsStatus() + Do $System.Status.DisplayError(tSC) + } + Quit tSC +} + +alertDStimeRW(DSTimeMapFrom,alerts) { + Try { + ZN "%SYS" + //Check if DB is Read-Write + Set sc = ##class(Config.Databases).Get(DSTimeMapFrom, .prop) + //If a remote DB is used we do not know + If prop("Server")'="" { + Set db=##Class(SYS.Database).%OpenId(prop("Directory")) + Set readonly = db.ReadOnly + If readonly { + Set pre="title=""In Caché versions including DevChange DTB422 ^OBJ.DSTIME and ^DeepSee.Update should be mapped to a Read-Write database"">" + Set alert = "Alert: ^OBJ.DSTIME and/or ^DeepSee.Update are stored in the "_DSTimeMapFrom_" database, which should be Read-Write" + Set alerts($I(alerts)) = pre_alert + Do WriteLog("

",8) + } + } + Set tSC = 1 + } Catch (ex) { + Set tSC = ex.AsStatus() + Do $System.Status.DisplayError(tSC) + } + Quit tSC +} + +alertCacheMappings(ns,alerts) { + Try { + //Check if ^DeepSee.Cache.Results, .Axis, .Cells end up in a journaled DB + ZN "%SYS" + Set tSC = $$$OK + Set DSCacheGlobals = $LB("DeepSee.Cache.Results","DeepSee.Cache.Axis","DeepSee.Cache.Cells") + While 1 { + Set cacheGlob=$LG(DSCacheGlobals,$I(i)) + Quit:(cacheGlob="") + Set sysdir=##class(%SYS.Namespace).GetGlobalDest(ns,cacheGlob) + //sysdir is system^directory, but only the directory is needed for the following call + Set DB=##class(SYS.Database).%OpenId($P(sysdir,"^",2)) + If (DB.GlobalJournalState = 3) { + Do ##Class(Config.Databases).DatabasesByDirectory($P(sysdir,"^",1),$P(sysdir,"^",2),.listDB) + Set DBname=$LISTTOSTRING(listDB,",") //In general I would expect one DB but there could be more + Set pre="title=""Journaling the DeepSee cache leads to problems with disk size and query performance"">" + Set alert = "Alert: The DeepSee cache stored in the "_DBname_" database is journaled" + Set alerts($I(alerts)) = pre_alert + Do WriteLog("

",8) + Quit + } + } + } Catch (ex) { + Set tSC = ex.AsStatus() + Do WriteLog("

",8) + } + Quit tSC +} + +alertJoinIndexMappings(ns,alerts) { + Try { + //Check if ^DeepSee.JoinIndex ends up in a journaled DB. + //It should go with the cache but it is less bad than journaling ^DeepSee.Cache* globals. + //For this reason I keep this alert separate from alertCacheMappings + ZN "%SYS" + Set tSC = $$$OK + Set cacheGlob = "DeepSee.JoinIndex" + Set sysdir=##class(%SYS.Namespace).GetGlobalDest(ns,cacheGlob) + //sysdir is system^directory, but only the directory is needed for the following call + Set DB=##class(SYS.Database).%OpenId($P(sysdir,"^",2)) + If (DB.GlobalJournalState = 3) { + Do ##Class(Config.Databases).DatabasesByDirectory($P(sysdir,"^",1),$P(sysdir,"^",2),.listDB) + Set DBname=$LISTTOSTRING(listDB,",") //In general I would expect one DB but there could be more + Set pre="title=""We suggest mapping the ^DeepSee.JoinIndex global together with the DeepSee cache to an unjournaled database"">" + Set alert = "Alert: The ^DeepSee.JoinIndex global stored in the "_DBname_" database is journaled" + Set alerts($I(alerts)) = pre_alert + Do WriteLog("

",8) + } + } Catch (ex) { + Set tSC = ex.AsStatus() + Do WriteLog("

",8) + } + Quit tSC +} + +alertInitialBuildCubeManager(cube,msgrepair,msgbuild,alerts) { + Try { + Set alert="" + Set pre="title=""Before you synchronize cubes from the Cube Manager, it is necessary to build the cubes at least once from the Cube Manager."">" + If ((msgrepair="Not found") && (msgbuild="Not found")) { + Set alert = "Alert: there is no record for the initial build of "_cube_" from Cube Manager. Check if the cube is updating" + Set alerts($I(alerts)) = pre_alert + } + Set tSC = 1 + } Catch(ex) { + Set tSC = ex.AsStatus() + Set alert = tSC + Set alerts($I(alerts)) = alert + } + Do WriteLog("

",8) +} + +alertTimeLevels(timeLevels,alerts) { + Try { + Set throwalert=0 + Set DimNo=$O(timeLevels("")) + For { + Quit:DimNo="" + Set HierNo=$O(timeLevels(DimNo,"")) + For { + Quit:HierNo="" + + Set typeparent = "" + Set levelparent = "" + + Set LevelNo=$O(timeLevels(DimNo,HierNo,"")) + For { + Quit:LevelNo="" + Set levelType = $LG(timeLevels(DimNo,HierNo,LevelNo),1) + + Set type = $S(levelType="%DeepSee.Time.Decade":"normal", + levelType="%DeepSee.Time.Year":"normal", + levelType="%DeepSee.Time.QuarterYear":"normal", + levelType="%DeepSee.Time.MonthYear":"normal", + levelType="%DeepSee.Time.DayMonthYear":"normal", + levelType="%DeepSee.Time.WeekYear":"normal", + levelType="%DeepSee.Time.WeekNumber":"week", + levelType="%DeepSee.Time.QuarterNumber":"normal", + levelType="%DeepSee.Time.MonthNumber":"normal", + levelType="%DeepSee.Time.DayNumber":"normal", + levelType="%DeepSee.Time.DayOfWeek":"normal", + levelType="%DeepSee.Time.HourNumber":"time", + levelType="%DeepSee.Time.MinuteNumber":"time", + 1:"custom") + Set level = $S(levelType="%DeepSee.Time.Decade":9, + levelType="%DeepSee.Time.Year":8, + levelType="%DeepSee.Time.QuarterYear":7, + levelType="%DeepSee.Time.MonthYear":6, + levelType="%DeepSee.Time.DayMonthYear":3, + levelType="%DeepSee.Time.WeekYear":5, + levelType="%DeepSee.Time.WeekNumber":4, + levelType="%DeepSee.Time.QuarterNumber":7, + levelType="%DeepSee.Time.MonthNumber":6, + levelType="%DeepSee.Time.DayNumber":3, + levelType="%DeepSee.Time.DayOfWeek":3, + levelType="%DeepSee.Time.HourNumber":2, + levelType="%DeepSee.Time.MinuteNumber":1, + 1:"custom") + + //Start by excluding the custom time dimensions. + If (type="custom") || (typeparent="custom") { + //Custom time levels. Good to go + } ElseIf (typeparent = "") || (levelparent="") { + //Top level. Good to go + } ElseIf (level>levelparent) { + Set throwalert = 1 + } ElseIf (type'=typeparent) { + //Check when mixing different types. The previous check took care of several wrong cases + //Hours and Minutes are incompatible with anything else + If (type="time") || (typeparent="time") { + Set throwalert = 1 + } ElseIf (typeparent="normal") && (type="week") { + //WeekNumber is under a "normal" level such as Year. WeekYear is ok + If (level'=4) { + Set throwalert = 1 + } + } ElseIf (typeparent="week") { + //This is fine because type="time" bigger level numbers were caught before. Days are fine + } ElseIf (typeparent="other") { + //I assume abstract/custom time functions are ok + } + } + If throwalert=1 { + Set tl = timeLevels(DimNo,HierNo,LevelNo) + Set pre="title=""Placing certain time levels such as Year of Month in the same hierarchy as a week level will lead to unexpected results"">" + Set alert = "The "_$LG(tl,3)_"."_$LG(tl,4)_"."_$LG(tl,5)_" level in the "_$LG(tl,2)_ + " cube using the "_$LG(tl,1)_" time function is incompatible with other time levels in the same hierarchy" + Set alerts($I(alerts)) = pre_alert + Do WriteLog("

",0) + Set throwalert=0 + //Advance to next hierarchy, right? + Quit + } + + Set typeparent = type + Set levelparent = level + Set LevelNo=$O(timeLevels(DimNo,HierNo,LevelNo)) + } + Set HierNo=$O(timeLevels(DimNo,HierNo)) + } + Set DimNo=$O(timeLevels(DimNo)) + } + Set tSC = 1 + } Catch (ex) { + Set tSC = ex.AsStatus() + } + Quit tSC +} + + +/// Write, I/O, etc helper functions +WriteLog(string,spaces) + //Adds a record to LogFile + If string?1"***".e Quit + Use LogFile + If '$D(spaces) Set spaces=0 + Write !,?spaces,string + Quit + +WriteParagraph(name,title,flag) + If '$D(flag) Set flag = 1 + Do:flag WriteLog("


",2) + Do WriteLog("",2) + Do WriteLog("

"_title_"

",2) + Quit + +WriteHeader4(header,spaces,title) + Use LogFile + If '$D(spaces) Set spaces=0 + If '$D(title) Set title="" + Do WriteLog(""_header_"",spaces) + Quit + +WriteUpdate(msg) + New (msg, PDev, LogFile, tracking) + Use PDev + Write $C(13,27)_"[0J"_msg + Use LogFile + Quit + +WriteTrack(phase,mgs="",details="",errors="") + ZN namespace + Set tStep = $Case(phase,"setup":1,"cubelog":2,"buildsynch":3,"cube":4,"getlogs":5,"databases":6,"tasks":7,"journal":8,"save":9,"warning":10,"complete":12,"error":13,:11) + Set ^IRIS.Temp.DeepSeeButtonsTrack(+$J,tStep)=$LB(phase,mgs,details,errors) + //If logging detail info on cubes or a warning, create a third node in the global + Set:phase="cube" ^IRIS.Temp.DeepSeeButtonsTrack(+$J,tStep,details)=$LB(phase,mgs,details,errors) + Set:phase="warning" ^IRIS.Temp.DeepSeeButtonsTrack(+$J,tStep,details)=$LB(phase,mgs,details,errors) + +WriteAdhocPatch + Try { + Set patchvar=$Order(^%qPatch("")) + While (patchvar'=""){ + Set data=^%qPatch(patchvar) + Set patchvar2=$Order(^%qPatch(patchvar)) + Do WriteLog("

Adhoc: "_$list(data)_"

",8) + Do WriteLog("

Description: "_$list(data,2)_"

",8) + Do WriteLog("

Created at: "_$list(data,5)_"

",8) + Do WriteLog("

Created on $zv: "_$piece($list(data,6),")",1,2)_")"_"

",8) + Do WriteLog("

Applied on: "_$list(data,7)_"

",8) + Do WriteLog("

Applied by: "_$list(data,8)_"

",8) + Do WriteLog("") + Set patchvar=$Order(^%qPatch(patchvar)) + } + } Catch(ex) { + //Set tSC = ex.AsStatus() + Do WriteLog("

An error occurred

",8) + } + Quit + +PrintGlobal(namespace,glob,spaces){ + ZN namespace + Quit:'$D(@glob) + Quit:glob="" + Set:$D(spaces) spaces = 0 + Set queryary=$QUERY(@glob@("")) + Set res=@queryary + Set quote="" + Set:'(res=+res) quote="""" + If $ListValid(res) { + //This seems to provide good formatting for ^DeepSee.CalcMbrs + Set res = "$lb("""_$REPLACE($LISTTOSTRING(res,"@"),"""","""""")_""")" + Set res = $REPLACE(res,"@",""",""") + Set quote="" + } + Do WriteLog("

"_queryary_" = "_quote_res_quote_"

",spaces) + For { + Set queryary=$QUERY(@queryary) + Quit:queryary="" + Set res=@queryary + Set quote="" + Set:'(res=+res) quote="""" + Do WriteLog("

"_queryary_" = "_quote_res_quote_"

",spaces) + } +} + +NewFile(LogFilePrefix,LogFileSuffix) + //Creates a new file with Date and Time added to the filename and opens it for Reading and Writing + //File Name can be either "Cache" or "cstat" + New Date,Dir,NewFile,Time + Set:LogFileSuffix="" LogFileSuffix="html" + Set Date=$TRANSLATE($ZD($H,3),"-","") + Set Time=$TRANSLATE($ZT($H,2),":","") + If (OS?1"Win".e) { + Set LogFileSuffix=$ZConvert(LogFileSuffix,"l") + } ElseIf (OS="UNIX") { + Set LogFileSuffix=$ZConvert(LogFileSuffix,"l") + } ElseIf (OS="VMS") { + Set LogFileSuffix=$ZConvert(LogFileSuffix,"U") + } + Set Dir=MgrDir + Set LogDirectory=$Get(LogDirectory,"") + Set:LogDirectory'="" Dir=LogDirectory + If (OS?1"Win".e) { + Set NewFile=Dir_DirDelim_LogFilePrefix_Date_"_"_Time_"."_LogFileSuffix + } ElseIf (OS="UNIX") { + Set NewFile=Dir_DirDelim_LogFilePrefix_Date_"_"_Time_"."_LogFileSuffix + } ElseIf (OS="VMS") { + Set NewFile=Dir_$ZConvert(LogFilePrefix,"U")_Date_Time_"."_LogFileSuffix_";" + } + // Open NewFile:"RWNSK\UTF8\":FileOpenTimeOut + // If '$Test Quit "" + Quit NewFile + +ExternalCmd(Command) + //Executes an external program and adds its output to LogFile + //Requires the full specification of the Exe file + New PDev,x + Set PDev=$Principal + If OS="UNIX" Do ExtCmdPipe + If OS?1"Win".e!(OS="VMS") Do ExtCmdFile + Use PDev + Quit + +ExtCmdPipe + //Executing an OS command through a pipe works on UNIX + //It should also work on 32-bit Windows (NT, 2000 and XP), but I found inconsistent behavior on these platforms + Open Command:"RQ":CmdOpenTimeOut + If '$Test Quit + Try { + //Read timeout added to prevent the case where neither error nor $ZEOF terminate the loop + For Use Command Read x:CmdReadTimeOut Set ZEOF=$ZEof Use PDev Quit:'$Test!(ZEOF) If x'="" Do WriteLog($ZConvert(x,"O","HTML")) + Close Command + } Catch(ex) { + Set tSC = ex.AsStatus() + Close Command + } + Quit + +ExtCmdFile + //Only to be executed when OS is Windows or VMS, when either pipes don't work or behave inconsistently + New Date,File,Time + Set Date=$TRANSLATE($ZD($H,3),"-","") + Set Time=$TRANSLATE($ZT($H,2),":","") + If OS?1"Win".e Do + . Set File=MgrDir_DirDelim_Date_Time_".$$$" + . Set Command=$Char(34)_Command_" > "_$$LongName(File)_$Char(34) //Cache will call "Cmd /c", which requires quotes surrounding the command + . Quit + Else If OS="VMS" Set File=MgrDir_Date_Time_".$$$" + If OS?1"Win".e Set x=$ZF(-1,Command) + Else If OS="VMS" Set x=$ZF(-1,Command,File) + Set $ZTrap="ExitCmdNoFile" + Open File:"R":FileOpenTimeOut + If '$Test Do WriteLog("Error: could not open file "_File) Quit + Set $ZTrap="ExitCmdFileEOF" + //Read timeout added to prevent the case where neither error nor $ZEOF terminate the loop + For { + Use File + Read x:FileReadTimeOut + Set ZEOF=$ZEof + Use PDev + Quit:'$Test!(ZEOF) + If x'="" Do WriteLog($ZConvert(x,"O","HTML")) + } + Set $ZTrap="" + Set $ZError="" + Close File + If OS="VMS" Do + . If $Extract(File,$Length(File))'=";" Set File=File_";" + . Set File=File_"*" + . Quit + Set x=$ZUtil(140,5,File) //Delete temporary scratch file + Quit +ExitCmdFileEOF + Set $ZTrap="" + Set $ZError="" + Close File + If OS="VMS" Do + . If $Extract(File,$Length(File))'=";" Set File=File_";" + . Set File=File_"*" + . Quit + Set x=$ZUtil(140,5,File) //Delete temporary scratch file + Quit + +ExitCmdNoFile + Set $ZTrap="" + Set $ZError="" + Quit + +CopyToLog(InputFile,Caption,SkipSize=0) + //Appends a file to LogFile. Used for cconsole.log + //InputFile can be cconsole.log, the generated cstat output file, inuse.dmp or dumpkeys.txt + //SkipSize - Skip the first x number of bytes in the file to reduce size. Used by cconsole.log + //to keep it a reasonable size + New %DAT,%TIM,x + Do INT^%D,INT^%T + Do WriteLog(Caption_" on "_%DAT_" at "_%TIM_":"),WriteLog("") + Try { + Open InputFile:"R":FileOpenTimeOut + If '$Test Do WriteLog("File "_InputFile_" does not exist") Do WriteLog("") Use PDev Quit + //Read timeout added to prevent the case where neither error nor $ZEOF terminate the loop + If SkipSize>0 Do WriteLog("File "_InputFile_" is too large, skipping first "_SkipSize_" bytes"),WriteLog("") + Set Size=0 + For { + Use InputFile + Read x:FileReadTimeOut + Set ZEOF=$ZEof + Use PDev + Quit:'$Test!(ZEOF) + Set Size=Size+$l(x) + Continue:SkipSize>Size + Use LogFile + Write $zconvert(x,"O","HTML"),CRLF + Use PDev + } + } Catch(ex) { + Set tSC = ex.AsStatus() + } + Close InputFile + Quit +