KMPSTMRT ;SP/JML - Collect Cache Metrics for the VistA Storage Monitor ;2/1/2023
;;4.0;CAPACITY MANAGEMENT;**1,2,3,4**;3/1/2018;Build 36
;
; Reference to KMPVVSTM^%ZOSVKSD in ICR #6342
; Reference to $$HTFM^XLFDT in ICR #10103
; Reference to GETENV^%ZOSV, EC^%ZOSV and LGR^%ZOSV in ICR #10097
; Reference to $ESTACK, $ETRAP, ^%ZTER and UNWIND^%ZTER in ICR #1621
;
RUN ;
N $ESTACK,$ETRAP S $ETRAP="D ^%ZTER Q"
I $$GETVAL^KMPVCCFG("VSTM","ONOFF",8969,"I") D RU^%ZOSVKR("KMP VSTM COLLECTOR")
N B,KMPBPM,KMPBS,KMPCSMB,KMPDATE,KMPDB,KMPDFS,KMPDIR,KMPDISK,KMPDNUM,KMPDSTR,KMPES,KMPFB,KMPFSMB,KMPINST
N KMPISD,KMPMSMB,KMPNDTYP,KMPSC,KMPSTAT,KMPSTR,KMPTI,KMPVDATA,KMPVDIR,KMPVLN,KMPVNODE,KMPVSINF,Y,X
N KMPDATA,KMPDST,KMPETSO,KMPFMDAY,KMPTIMES,KMPUTCE,KMPUTCO,KMPRUN,KMPCDATE
; ALWAYS - verify data is not building past configured number of days - if so for any reason, delete it
D PURGEDLY^KMPVCBG("VSTM")
; Quit if monitor is not turned on
I $$GETVAL^KMPVCCFG("VSTM","ONOFF",8969)'="ON" D Q
.I $$GETVAL^KMPVCCFG("VSTM","ONOFF",8969,"I") D RU^%ZOSVKR("KMP VSTM COLLECTOR")
; Check environment, quit if test and test systems not allowed
I $$PROD^KMPVCCFG()'="prod",$$GETVAL^KMPVCCFG("VSTM","ALLOW TEST SYSTEM",8969,"I")'=1 Q
; Only run if 1st or 3rd Saturday of the month
S KMPRUN=0
S (X,KMPFMDAY)=+$$HTFM^XLFDT($H,1) ;supported by ICR #10103
D DW^%DTC
I Y=6 D
.S KMPDNUM=$SYSTEM.SQL.DAYOFMONTH(+$H)
.I KMPDNUM<8 S KMPRUN="01"
.I (KMPDNUM>14)&(KMPDNUM<22) S KMPRUN="15"
; SET KMPTEST=1 TO RUN TEST ON DAYS OTHER THAN THE 1ST OR 15TH DAY OF MONTH
I $G(KMPTEST) S KMPRUN=$E(KMPFMDAY,6,7) K KMPTEST
I KMPRUN D
.S KMPVSINF=$$SITEINFO^KMPVCCFG()
.S KMPSC=$P(KMPVSINF,"^",5),B="|"
.D GETENV^%ZOSV S KMPVNODE=$P(Y,U,3)_":"_$P($P(Y,U,4),":",2) ;supported by ICR #10097
.S KMPINST=$P(KMPVNODE,":",2),KMPNDTYP=$$NODETYPE^KMPUTLW(KMPINST)
.; S KMPFMDAY To either the 1st or 15th regardless of actual day to make queries consistent
.S KMPTIMES=$$TSTAMP^KMPUTLW($E(KMPFMDAY,1,5)_KMPRUN,"FILEMAN",1) ; yyy-mm-dd hh:mm:ssZts
.S KMPCDATE=$P($$TSTAMP^KMPUTLW(KMPFMDAY,"FILEMAN",1)," ")
.S KMPETSO=$P(KMPTIMES,"^")
.S KMPUTCO=$P(KMPTIMES,"^",2)
.S KMPUTCE=$P(KMPTIMES,"^",3)
.S KMPDST=$P(KMPTIMES,"^",4)
.D KMPVVSTM^%ZOSVKSD(.KMPVDATA) ;supported by ICR #6342
.D STORAGE
.D ZERONODE
.D GLOBALS
I $$GETVAL^KMPVCCFG("VSTM","ONOFF",8969,"I") D RU^%ZOSVKR("KMP VSTM COLLECTOR END")
Q
;
STORAGE ;
S KMPVDIR="",KMPVLN=1
F S KMPVDIR=$O(KMPVDATA(KMPVDIR)) Q:KMPVDIR="" D
.D GETDB(KMPVDIR,.KMPRES)
.S KMPDB=KMPRES("DB"),KMPDISK=KMPRES("DISK"),KMPDIR=KMPRES("DIR")
.S KMPDATA=$G(KMPVDATA(KMPVDIR))
.;MaxSize(MB)^Current Size(MB)^Block Size(int)^Bocks per Map(int)^Free space(MB)^Free Space(int-Blocks)^System Dir(bool)^Expansion size^FreeSpace
.S KMPMSMB=$$CALC($P(KMPDATA,"^",1)),KMPCSMB=$$CALC($P(KMPDATA,"^",2)),KMPBS=$P(KMPDATA,"^",3)
.S KMPBPM=$P(KMPDATA,"^",4),KMPFSMB=$$CALC($P(KMPDATA,"^",5)),KMPFB=$P(KMPDATA,"^",6)
.S KMPISD=$P(KMPDATA,"^",7),KMPES=$$CALC($P(KMPDATA,"^",8)),KMPDFS=$$CALC($P(KMPDATA,"^",9))
.S KMPDSTR=KMPDB_B_KMPDISK_B_KMPDIR_B_KMPMSMB_B_KMPCSMB_B_KMPBS_B_KMPBPM_B_KMPFSMB_B_KMPFB_B_KMPISD_B_KMPES_B_KMPDFS
.S ^KMPTMP("KMPV","VSTM","TRANSMIT","STORAGE",$J,KMPVLN)=KMPDSTR,KMPVLN=KMPVLN+1
Q:'$D(^KMPTMP("KMPV","VSTM","TRANSMIT","STORAGE",$J))
; package data into JSON object and send
N KMPDARR,KMPJMSG,KMPJSON
S KMPJSON=##class(%DynamicObject).%New()
S KMPJSON.Function="VSTM-STORAGE"
D SITE^KMPUTLW(KMPJSON)
S KMPJMSG=##class(%DynamicObject).%New()
S KMPJMSG.Timestamp=KMPETSO,KMPJMSG.UtcOdbc=KMPUTCO
S KMPJMSG.UtcEpoch=KMPUTCE,KMPJMSG.IsDst=KMPDST
S KMPJMSG.CollectDate=KMPCDATE
S KMPJMSG.Node=$P(KMPVNODE,":"),KMPJMSG.NodeType=KMPNDTYP
S KMPJMSG.Instance=KMPINST,KMPJMSG.Date=$$SHORTDAT^KMPUTLW($H,"HOROLOG")
S KMPJSON.MessageData=KMPJMSG
S KMPDARR=##class(%DynamicArray).%New()
S KMPTI=""
F S KMPTI=$O(^KMPTMP("KMPV","VSTM","TRANSMIT","STORAGE",$J,KMPTI)) Q:KMPTI="" D
.S KMPDATA=$G(^KMPTMP("KMPV","VSTM","TRANSMIT","STORAGE",$J,KMPTI))
.D KMPDARR.%Push(KMPDATA)
S KMPJSON.Details=KMPDARR
S KMPSTAT=$$POST^KMPUTLW(KMPJSON,"/storage",,"VSTM")
I +KMPSTAT'=200 S KMPSTAT=$$POST^KMPUTLW(KMPJSON,"/storage",,"VSTM")
S ^XTMP("KMP "_KMPFMDAY,"VSTM-STORAGE","HTTP",KMPVNODE,$P($H,",",2))=KMPSTAT
K ^KMPTMP("KMPV","VSTM","TRANSMIT","STORAGE",$J)
I +KMPSTAT'=200 S KMPLOC="/storage" D SETRETRY
Q
;
ZERONODE ;
D ZERO^KMPTASK()
Q:'$D(^KMPTMP("KMPV","VSTM","TRANSMIT","ZERO",$J))
; package data into JSON object and send
N KMPDARR,KMPJMSG,KMPJSON
S KMPJSON=##class(%DynamicObject).%New()
S KMPJSON.Function="VSTM-ZERONODE"
D SITE^KMPUTLW(KMPJSON)
S KMPJMSG=##class(%DynamicObject).%New()
S KMPJMSG.Timestamp=KMPETSO,KMPJMSG.UtcOdbc=KMPUTCO
S KMPJMSG.UtcEpoch=KMPUTCE,KMPJMSG.IsDst=KMPDST
S KMPJMSG.CollectDate=KMPCDATE
S KMPJMSG.Node=$P(KMPVNODE,":"),KMPJMSG.NodeType=KMPNDTYP
S KMPJMSG.Instance=KMPINST,KMPJMSG.Date=$$SHORTDAT^KMPUTLW($H,"HOROLOG")
S KMPJSON.MessageData=KMPJMSG
S KMPDARR=##class(%DynamicArray).%New()
S KMPTI=""
F S KMPTI=$O(^KMPTMP("KMPV","VSTM","TRANSMIT","ZERO",$J,KMPTI)) Q:KMPTI="" D
.S KMPDATA=$G(^KMPTMP("KMPV","VSTM","TRANSMIT","ZERO",$J,KMPTI))
.D KMPDARR.%Push(KMPDATA)
S KMPJSON.Details=KMPDARR
S KMPSTAT=$$POST^KMPUTLW(KMPJSON,"/zeronode",1,"VSTM")
I +KMPSTAT'=200 S KMPSTAT=$$POST^KMPUTLW(KMPJSON,"/zeronode",1,"VSTM")
S ^XTMP("KMP "_KMPFMDAY,"VSTM-ZERONODE","HTTP",KMPVNODE,$P($H,",",2))=KMPSTAT
K ^KMPTMP("KMPV","VSTM","TRANSMIT","ZERO",$J)
I +KMPSTAT'=200 S KMPLOC="/zeronode" D SETRETRY
Q
;
GLOBALS ;
S KMPVDIR="",KMPVLN=1
D GLOSTATS^KMPTASK(.KMPVDATA)
Q:'$D(^KMPTMP("KMPV","VSTM","TRANSMIT","GLOBALS",$J))
; package data into JSON object and send
N KMPDARR,KMPJMSG,KMPJSON
S KMPJSON=##class(%DynamicObject).%New()
S KMPJSON.Function="VSTM-GLOBALS"
D SITE^KMPUTLW(KMPJSON)
S KMPJMSG=##class(%DynamicObject).%New()
S KMPJMSG.Timestamp=KMPETSO,KMPJMSG.UtcOdbc=KMPUTCO
S KMPJMSG.UtcEpoch=KMPUTCE,KMPJMSG.IsDst=KMPDST
S KMPJMSG.CollectDate=KMPCDATE
S KMPJMSG.Node=$P(KMPVNODE,":"),KMPJMSG.NodeType=KMPNDTYP
S KMPJMSG.Instance=KMPINST,KMPJMSG.Date=$$SHORTDAT^KMPUTLW($H,"HOROLOG")
S KMPJSON.MessageData=KMPJMSG
S KMPDARR=##class(%DynamicArray).%New()
S KMPTI=""
F S KMPTI=$O(^KMPTMP("KMPV","VSTM","TRANSMIT","GLOBALS",$J,KMPTI)) Q:KMPTI="" D
.S KMPDATA=$G(^KMPTMP("KMPV","VSTM","TRANSMIT","GLOBALS",$J,KMPTI))
.D KMPDARR.%Push(KMPDATA)
S KMPJSON.Details=KMPDARR
S KMPSTAT=$$POST^KMPUTLW(KMPJSON,"/globals",1,"VSTM")
I +KMPSTAT'=200 S KMPSTAT=$$POST^KMPUTLW(KMPJSON,"/globals",1,"VSTM")
S ^XTMP("KMP "_KMPFMDAY,"VSTM-GLOBALS","HTTP",KMPVNODE,$P($H,",",2))=KMPSTAT
K ^KMPTMP("KMPV","VSTM","TRANSMIT","GLOBALS",$J)
I +KMPSTAT'=200 S KMPLOC="/globals" D SETRETRY
Q
;
CALC(KMPVAL) ; Convert to MB if units specified in value, round to 3 decimal places
I KMPVAL="Unlimited" Q 0 ; maximum can be "Unlimited"
I KMPVAL["MB" Q $NUM(+KMPVAL*1,3)
I KMPVAL["GB" Q $NUM(+KMPVAL*1024,3)
Q $NUM(KMPVAL,3)
;
GETDB(DBSTR,KMPRES) ;
N KMPSTYP
I DBSTR["$" S KMPSTYP="VMS"
I DBSTR["/" S KMPSTYP="UNIX"
I DBSTR["\" S KMPSTYP="NT"
I KMPSTYP="UNIX" D Q
.S KMPRES("DISK")=""
.S KMPRES("DIR")=DBSTR
.S KMPRES("DB")=$P(DBSTR,"/",$L(DBSTR,"/")-1)
I KMPSTYP="VMS" D Q
.S KMPRES("DISK")=$P(DBSTR,":")
.S KMPRES("DIR")=$P(DBSTR,":",2)
.S KMPRES("DB")=$P($P(KMPRES("DIR"),".",$L(KMPRES("DIR"),".")),"]")
I KMPSTYP="NT" D Q
.S KMPRES("DISK")=$P(DBSTR,"\")
.S KMPRES("DIR")=$P(DBSTR,":",2)
.S KMPRES("DB")=$P(DBSTR,"\",$L(DBSTR,"\")-1)
E D
.S KMPRES("DISK")=""
.S KMPRES("DIR")=""
.S KMPRES("DB")=DBSTR
Q
;
SETRETRY ;
N KMPTEXT
S KMPTEXT("SUBJECT")="VSM FAILED SEND: VSTM at "_KMPJSON.Site.SiteCode
S KMPTEXT(1)="Status Code: "_+KMPSTAT
S KMPTEXT(2)="Status Text: "_$P(KMPSTAT,"^",2)
S KMPTEXT(3)="Response Time: "_$P(KMPSTAT,"^",3)
S KMPTEXT(4)="Endpoint: "_KMPLOC
S KMPTEXT(4)="Node: "_KMPVNODE
D INFOMSG^KMPUTLW(.KMPTEXT)
S ^KMPTMP("KMPV","VSTM","RETRY",KMPVNODE,+$H,KMPLOC,$H)=KMPJSON.%ToJSON()
Q
;
RETRY ; retry failed POSTS
N KMPDAY,KMPI,KMPJSON,KMPSTAT,KMPLOC,KMPVNODE,Y
;
D GETENV^%ZOSV S KMPVNODE=$P(Y,"^",3)_":"_$P($P(Y,"^",4),":",2) ;supported by ICR #10097
S KMPDAY=""
F S KMPDAY=$O(^KMPTMP("KMPV","VSTM","RETRY",KMPVNODE,KMPDAY)) Q:KMPDAY="" D
.S KMPLOC=""
.F S KMPLOC=$O(^KMPTMP("KMPV","VSTM","RETRY",KMPVNODE,KMPDAY,KMPLOC)) Q:KMPLOC="" D
..S KMPI=""
..F S KMPI=$O(^KMPTMP("KMPV","VSTM","RETRY",KMPVNODE,KMPDAY,KMPLOC,KMPI)) Q:KMPI="" D
...S KMPJSON=$G(^KMPTMP("KMPV","VSTM","RETRY",KMPVNODE,KMPDAY,KMPLOC,KMPI))
...S KMPSTAT=$$POST^KMPUTLW({}.%FromJSON(KMPJSON),KMPLOC,1,"VSTM")
...I +KMPSTAT=200 K ^KMPTMP("KMPV","VSTM","RETRY",KMPVNODE,KMPDAY,KMPLOC,KMPI)
...H $R(10)
Q
--- Routine Detail --- with STRUCTURED ROUTINE LISTING ---[H[J[2J[HKMPSTMRT 8885 printed Dec 13, 2024@01:41:51 Page 2
KMPSTMRT ;SP/JML - Collect Cache Metrics for the VistA Storage Monitor ;2/1/2023
+1 ;;4.0;CAPACITY MANAGEMENT;**1,2,3,4**;3/1/2018;Build 36
+2 ;
+3 ; Reference to KMPVVSTM^%ZOSVKSD in ICR #6342
+4 ; Reference to $$HTFM^XLFDT in ICR #10103
+5 ; Reference to GETENV^%ZOSV, EC^%ZOSV and LGR^%ZOSV in ICR #10097
+6 ; Reference to $ESTACK, $ETRAP, ^%ZTER and UNWIND^%ZTER in ICR #1621
+7 ;
RUN ;
+1 NEW $ESTACK,$ETRAP
SET $ETRAP="D ^%ZTER Q"
+2 IF $$GETVAL^KMPVCCFG("VSTM","ONOFF",8969,"I")
DO RU^%ZOSVKR("KMP VSTM COLLECTOR")
+3 NEW B,KMPBPM,KMPBS,KMPCSMB,KMPDATE,KMPDB,KMPDFS,KMPDIR,KMPDISK,KMPDNUM,KMPDSTR,KMPES,KMPFB,KMPFSMB,KMPINST
+4 NEW KMPISD,KMPMSMB,KMPNDTYP,KMPSC,KMPSTAT,KMPSTR,KMPTI,KMPVDATA,KMPVDIR,KMPVLN,KMPVNODE,KMPVSINF,Y,X
+5 NEW KMPDATA,KMPDST,KMPETSO,KMPFMDAY,KMPTIMES,KMPUTCE,KMPUTCO,KMPRUN,KMPCDATE
+6 ; ALWAYS - verify data is not building past configured number of days - if so for any reason, delete it
+7 DO PURGEDLY^KMPVCBG("VSTM")
+8 ; Quit if monitor is not turned on
+9 IF $$GETVAL^KMPVCCFG("VSTM","ONOFF",8969)'="ON"
Begin DoDot:1
+10 IF $$GETVAL^KMPVCCFG("VSTM","ONOFF",8969,"I")
DO RU^%ZOSVKR("KMP VSTM COLLECTOR")
End DoDot:1
QUIT
+11 ; Check environment, quit if test and test systems not allowed
+12 IF $$PROD^KMPVCCFG()'="prod"
IF $$GETVAL^KMPVCCFG("VSTM","ALLOW TEST SYSTEM",8969,"I")'=1
QUIT
+13 ; Only run if 1st or 3rd Saturday of the month
+14 SET KMPRUN=0
+15 ;supported by ICR #10103
SET (X,KMPFMDAY)=+$$HTFM^XLFDT($HOROLOG,1)
+16 DO DW^%DTC
+17 IF Y=6
Begin DoDot:1
+18 SET KMPDNUM=$SYSTEM.SQL.DAYOFMONTH(+$HOROLOG)
+19 IF KMPDNUM<8
SET KMPRUN="01"
+20 IF (KMPDNUM>14)&(KMPDNUM<22)
SET KMPRUN="15"
End DoDot:1
+21 ; SET KMPTEST=1 TO RUN TEST ON DAYS OTHER THAN THE 1ST OR 15TH DAY OF MONTH
+22 IF $GET(KMPTEST)
SET KMPRUN=$EXTRACT(KMPFMDAY,6,7)
KILL KMPTEST
+23 IF KMPRUN
Begin DoDot:1
+24 SET KMPVSINF=$$SITEINFO^KMPVCCFG()
+25 SET KMPSC=$PIECE(KMPVSINF,"^",5)
SET B="|"
+26 ;supported by ICR #10097
DO GETENV^%ZOSV
SET KMPVNODE=$PIECE(Y,U,3)_":"_$PIECE($PIECE(Y,U,4),":",2)
+27 SET KMPINST=$PIECE(KMPVNODE,":",2)
SET KMPNDTYP=$$NODETYPE^KMPUTLW(KMPINST)
+28 ; S KMPFMDAY To either the 1st or 15th regardless of actual day to make queries consistent
+29 ; yyy-mm-dd hh:mm:ssZts
SET KMPTIMES=$$TSTAMP^KMPUTLW($EXTRACT(KMPFMDAY,1,5)_KMPRUN,"FILEMAN",1)
+30 SET KMPCDATE=$PIECE($$TSTAMP^KMPUTLW(KMPFMDAY,"FILEMAN",1)," ")
+31 SET KMPETSO=$PIECE(KMPTIMES,"^")
+32 SET KMPUTCO=$PIECE(KMPTIMES,"^",2)
+33 SET KMPUTCE=$PIECE(KMPTIMES,"^",3)
+34 SET KMPDST=$PIECE(KMPTIMES,"^",4)
+35 ;supported by ICR #6342
DO KMPVVSTM^%ZOSVKSD(.KMPVDATA)
+36 DO STORAGE
+37 DO ZERONODE
+38 DO GLOBALS
End DoDot:1
+39 IF $$GETVAL^KMPVCCFG("VSTM","ONOFF",8969,"I")
DO RU^%ZOSVKR("KMP VSTM COLLECTOR END")
+40 QUIT
+41 ;
STORAGE ;
+1 SET KMPVDIR=""
SET KMPVLN=1
+2 FOR
SET KMPVDIR=$ORDER(KMPVDATA(KMPVDIR))
if KMPVDIR=""
QUIT
Begin DoDot:1
+3 DO GETDB(KMPVDIR,.KMPRES)
+4 SET KMPDB=KMPRES("DB")
SET KMPDISK=KMPRES("DISK")
SET KMPDIR=KMPRES("DIR")
+5 SET KMPDATA=$GET(KMPVDATA(KMPVDIR))
+6 ;MaxSize(MB)^Current Size(MB)^Block Size(int)^Bocks per Map(int)^Free space(MB)^Free Space(int-Blocks)^System Dir(bool)^Expansion size^FreeSpace
+7 SET KMPMSMB=$$CALC($PIECE(KMPDATA,"^",1))
SET KMPCSMB=$$CALC($PIECE(KMPDATA,"^",2))
SET KMPBS=$PIECE(KMPDATA,"^",3)
+8 SET KMPBPM=$PIECE(KMPDATA,"^",4)
SET KMPFSMB=$$CALC($PIECE(KMPDATA,"^",5))
SET KMPFB=$PIECE(KMPDATA,"^",6)
+9 SET KMPISD=$PIECE(KMPDATA,"^",7)
SET KMPES=$$CALC($PIECE(KMPDATA,"^",8))
SET KMPDFS=$$CALC($PIECE(KMPDATA,"^",9))
+10 SET KMPDSTR=KMPDB_B_KMPDISK_B_KMPDIR_B_KMPMSMB_B_KMPCSMB_B_KMPBS_B_KMPBPM_B_KMPFSMB_B_KMPFB_B_KMPISD_B_KMPES_B_KMPDFS
+11 SET ^KMPTMP("KMPV","VSTM","TRANSMIT","STORAGE",$JOB,KMPVLN)=KMPDSTR
SET KMPVLN=KMPVLN+1
End DoDot:1
+12 if '$DATA(^KMPTMP("KMPV","VSTM","TRANSMIT","STORAGE",$JOB))
QUIT
+13 ; package data into JSON object and send
+14 NEW KMPDARR,KMPJMSG,KMPJSON
+15 SET KMPJSON=##class(%DynamicObject).%New()
+16 SET KMPJSON.Function="VSTM-STORAGE"
+17 DO SITE^KMPUTLW(KMPJSON)
+18 SET KMPJMSG=##class(%DynamicObject).%New()
+19 SET KMPJMSG.Timestamp=KMPETSO
SET KMPJMSG.UtcOdbc=KMPUTCO
+20 SET KMPJMSG.UtcEpoch=KMPUTCE
SET KMPJMSG.IsDst=KMPDST
+21 SET KMPJMSG.CollectDate=KMPCDATE
+22 SET KMPJMSG.Node=$PIECE(KMPVNODE,":")
SET KMPJMSG.NodeType=KMPNDTYP
+23 SET KMPJMSG.Instance=KMPINST
SET KMPJMSG.Date=$$SHORTDAT^KMPUTLW($HOROLOG,"HOROLOG")
+24 SET KMPJSON.MessageData=KMPJMSG
+25 SET KMPDARR=##class(%DynamicArray).%New()
+26 SET KMPTI=""
+27 FOR
SET KMPTI=$ORDER(^KMPTMP("KMPV","VSTM","TRANSMIT","STORAGE",$JOB,KMPTI))
if KMPTI=""
QUIT
Begin DoDot:1
+28 SET KMPDATA=$GET(^KMPTMP("KMPV","VSTM","TRANSMIT","STORAGE",$JOB,KMPTI))
+29 DO KMPDARR.%Push(KMPDATA)
End DoDot:1
+30 SET KMPJSON.Details=KMPDARR
+31 SET KMPSTAT=$$POST^KMPUTLW(KMPJSON,"/storage",,"VSTM")
+32 IF +KMPSTAT'=200
SET KMPSTAT=$$POST^KMPUTLW(KMPJSON,"/storage",,"VSTM")
+33 SET ^XTMP("KMP "_KMPFMDAY,"VSTM-STORAGE","HTTP",KMPVNODE,$PIECE($HOROLOG,",",2))=KMPSTAT
+34 KILL ^KMPTMP("KMPV","VSTM","TRANSMIT","STORAGE",$JOB)
+35 IF +KMPSTAT'=200
SET KMPLOC="/storage"
DO SETRETRY
+36 QUIT
+37 ;
ZERONODE ;
+1 DO ZERO^KMPTASK()
+2 if '$DATA(^KMPTMP("KMPV","VSTM","TRANSMIT","ZERO",$JOB))
QUIT
+3 ; package data into JSON object and send
+4 NEW KMPDARR,KMPJMSG,KMPJSON
+5 SET KMPJSON=##class(%DynamicObject).%New()
+6 SET KMPJSON.Function="VSTM-ZERONODE"
+7 DO SITE^KMPUTLW(KMPJSON)
+8 SET KMPJMSG=##class(%DynamicObject).%New()
+9 SET KMPJMSG.Timestamp=KMPETSO
SET KMPJMSG.UtcOdbc=KMPUTCO
+10 SET KMPJMSG.UtcEpoch=KMPUTCE
SET KMPJMSG.IsDst=KMPDST
+11 SET KMPJMSG.CollectDate=KMPCDATE
+12 SET KMPJMSG.Node=$PIECE(KMPVNODE,":")
SET KMPJMSG.NodeType=KMPNDTYP
+13 SET KMPJMSG.Instance=KMPINST
SET KMPJMSG.Date=$$SHORTDAT^KMPUTLW($HOROLOG,"HOROLOG")
+14 SET KMPJSON.MessageData=KMPJMSG
+15 SET KMPDARR=##class(%DynamicArray).%New()
+16 SET KMPTI=""
+17 FOR
SET KMPTI=$ORDER(^KMPTMP("KMPV","VSTM","TRANSMIT","ZERO",$JOB,KMPTI))
if KMPTI=""
QUIT
Begin DoDot:1
+18 SET KMPDATA=$GET(^KMPTMP("KMPV","VSTM","TRANSMIT","ZERO",$JOB,KMPTI))
+19 DO KMPDARR.%Push(KMPDATA)
End DoDot:1
+20 SET KMPJSON.Details=KMPDARR
+21 SET KMPSTAT=$$POST^KMPUTLW(KMPJSON,"/zeronode",1,"VSTM")
+22 IF +KMPSTAT'=200
SET KMPSTAT=$$POST^KMPUTLW(KMPJSON,"/zeronode",1,"VSTM")
+23 SET ^XTMP("KMP "_KMPFMDAY,"VSTM-ZERONODE","HTTP",KMPVNODE,$PIECE($HOROLOG,",",2))=KMPSTAT
+24 KILL ^KMPTMP("KMPV","VSTM","TRANSMIT","ZERO",$JOB)
+25 IF +KMPSTAT'=200
SET KMPLOC="/zeronode"
DO SETRETRY
+26 QUIT
+27 ;
GLOBALS ;
+1 SET KMPVDIR=""
SET KMPVLN=1
+2 DO GLOSTATS^KMPTASK(.KMPVDATA)
+3 if '$DATA(^KMPTMP("KMPV","VSTM","TRANSMIT","GLOBALS",$JOB))
QUIT
+4 ; package data into JSON object and send
+5 NEW KMPDARR,KMPJMSG,KMPJSON
+6 SET KMPJSON=##class(%DynamicObject).%New()
+7 SET KMPJSON.Function="VSTM-GLOBALS"
+8 DO SITE^KMPUTLW(KMPJSON)
+9 SET KMPJMSG=##class(%DynamicObject).%New()
+10 SET KMPJMSG.Timestamp=KMPETSO
SET KMPJMSG.UtcOdbc=KMPUTCO
+11 SET KMPJMSG.UtcEpoch=KMPUTCE
SET KMPJMSG.IsDst=KMPDST
+12 SET KMPJMSG.CollectDate=KMPCDATE
+13 SET KMPJMSG.Node=$PIECE(KMPVNODE,":")
SET KMPJMSG.NodeType=KMPNDTYP
+14 SET KMPJMSG.Instance=KMPINST
SET KMPJMSG.Date=$$SHORTDAT^KMPUTLW($HOROLOG,"HOROLOG")
+15 SET KMPJSON.MessageData=KMPJMSG
+16 SET KMPDARR=##class(%DynamicArray).%New()
+17 SET KMPTI=""
+18 FOR
SET KMPTI=$ORDER(^KMPTMP("KMPV","VSTM","TRANSMIT","GLOBALS",$JOB,KMPTI))
if KMPTI=""
QUIT
Begin DoDot:1
+19 SET KMPDATA=$GET(^KMPTMP("KMPV","VSTM","TRANSMIT","GLOBALS",$JOB,KMPTI))
+20 DO KMPDARR.%Push(KMPDATA)
End DoDot:1
+21 SET KMPJSON.Details=KMPDARR
+22 SET KMPSTAT=$$POST^KMPUTLW(KMPJSON,"/globals",1,"VSTM")
+23 IF +KMPSTAT'=200
SET KMPSTAT=$$POST^KMPUTLW(KMPJSON,"/globals",1,"VSTM")
+24 SET ^XTMP("KMP "_KMPFMDAY,"VSTM-GLOBALS","HTTP",KMPVNODE,$PIECE($HOROLOG,",",2))=KMPSTAT
+25 KILL ^KMPTMP("KMPV","VSTM","TRANSMIT","GLOBALS",$JOB)
+26 IF +KMPSTAT'=200
SET KMPLOC="/globals"
DO SETRETRY
+27 QUIT
+28 ;
CALC(KMPVAL) ; Convert to MB if units specified in value, round to 3 decimal places
+1 ; maximum can be "Unlimited"
IF KMPVAL="Unlimited"
QUIT 0
+2 IF KMPVAL["MB"