Performance Metrics
Performance metrics are available in KCML 07.16.00.23055 or later for AIX 7 and Linux 2.6 (or later) and are depedent on the KCML Message Queue Support library, kmsgq.so.
KCML has been instrumented to produce statistics on the performance of the application code. Statistics include processor utilization, memory usage and disk I/O, see List of Performance Metrics.
The statistics are sent, via kmsgq.so to a RabbitMQ server cluster where they can be processed, for example by populating an InfluxDB database. To reduce the impact of performance metrics it is advisable to have a fast network connection between the application server and the RabbitMQ server.
Each performance metric can be individually enabled by calling 'KCML_PerfMetric_Set() passing in one of the built-in KCML_PERFMETRIC_ flags. In KCML 7.16, or later, these flags are members of a KCML_PERFMETRICS enumeration. A performance metric can either be enabled for an individual partition or globally, for all partitions, by passing in a partition number of zero. A performance metric will be sent if its flag has been set either at a partition or global level. These flags are stored in same shared memory area as $PSTAT which must have been created by a KCML, or its utilities, that support performance metrics and with an extended $PSTAT configured.
REM Enable kcml.kdb.open on this partition 'KCML_PerfMetric_Set(_KCML_PERFMETRIC_KCML_KDB_OPEN, #PART, sToken$)
REM Enable kcml.session.start on all partitions 'KCML_PerfMetric_Set(_KCML_PERFMETRIC_KCML_SESSION_START, 0, sToken$)
Calling 'KCML_PerfMetric_Clear() will unset the flag, either for the specified partition or for all partitions.
The optional sToken$ parameter is intended for use on customer systems where only certain processes are expected to change the state of performance metrics.
See: Access Control
Applications can check what performance metrics are enabled by calling 'KCML_PerfMetric_Get(). This will return an array of KCML_PerfMetricRec records which contains the performance metrics name, its flag value and its state, ie enabled or disabled.
00010 REM Display global performance metrics : DIM a$(0)_kcml_perfmetricrec : DIM rc AS bool : DIM nCount AS Integer : DIM i AS Integer : DIM state$8 : rc = 'kcml_perfmetric_get(BYREF a$(),0) : IF (rc) : nCount = DIM(a$(),1) : FOR i = 1 TO nCount : state$ = (FLD(a$(i).kcml_perfmetric_enabled) ? "on" : "off") : PRINT FLD(a$(i).kcml_perfmetric_name$);" = ";FLD(a$(i).kcml_perfmetric_flag);" = ";state$ : NEXT i : ELSE : REM $PSTAT not large enough. Most likely created by an older version of KCML. : PRINT "Performance metrics not available" : END IF : $END
Running the above example should display the state of each performance metric.
By default the collection of performance metrics is disabled. To enable performance metrics the location, and credentials, to the RabbitMQ server and a named queue must be specified in /etc/kcml/msgq.conf. Systems that have been executed as a Connection Manager Service may also define their own configuration in /etc/kcml/msgq.$SERVICE.conf. If /etc/kcml/msgq.$SERVICE.conf does not exist then the configuration will be loaded from /etc/kcml/msgq.conf.
See KCML Message Queue Support library: Configuration.
Next configure KCML to use that queue for performance metrics by adding the following to msgq.conf
[perfmetric] queue=myQueue
The [perfmetric] section can also have the following optional settings:-
mem=1024 logperiod=30 iotimerfreq=1000 decltimerfreq=50 maxdupidx=20000 lockwaitalert=5 maxtranstime=4 x509warndays=100
The mem setting will cause kcml.mem.delta to be reported for every allocation that exceeds the specified size, in kilobytes.
The logperiod value specifies the frequency, in seconds, that periodically logged metrics such as kcml.kdb.io & kcml.declare.total are reported.
Increasing the following key values of the [perfmetric] section can be used to reduce the overhead of determining how long ago the last periodic metrics were sent.
Metric | Key | Default value | Description |
---|---|---|---|
kcml.kdb.io | iotimerfreq | 100 | Number of I/O operations between checking the last time kcml.kdb.io was sent |
kcml.declare.total | decltimerfreq | 25 | Number of $DECLARE calls executed between checking the last time kcml.declare.total was sent |
For example the above configuration will only check every 1000 read/write operations and every 50th $DECLARE call.
The maxdupidx value controls the sensitivity of the kcml.kdb.dupidxio metric. By default KCML will report this metric if 100000 index blocks are scanned when searching a table with duplicate indices. The above example lowers this limit to 20000 index blocks.
The lockwaitalert value sets the timeout, in seconds, for kcml.native.lock - if $OPEN takes longer than that time to obtain the lock then the kcml.native.lock metric will be sent. The default, if no lockwaitalert value is set, is 2 seconds.
The maxtranstime value set the threshold, in seconds, over which the life-time of a transaction will be reported by the kcml.kdb.transtime & kcml.sql.opttranstime metrics. The default value is 2 seconds.
The x509warndays setting sets the number of days before certificate expiry that the kcml.x509.expiry metric will be sent. The default is 30.
By default all performance metrics are not enabled. However performance metrics can be enabled, for all partitions, when $PSTAT is created by specifying them in the [perfmetric] section of msgq.conf:-
# Send performance metrics to myQueue and always enable kcml.session.start and kcml.session.lic [perfmetric] queue=myQueue kcml.session.start=1 kcml.session.lic=1
Text-string|YYYY-MM-DDThh:mm:ssZ<crlf>
A SHA-256 message digest signature is then calculated, using a private key, and then appended after being base-64 encoded:-
Text-string|YYYY-MM-DD hh:mm:ss<crlf> signature=xxxxx...
Where xxxxx... is the base-64 encoded signature.
The public key is then extracted from the private key and then added to the [perfmetric] section of /etc/kcml/msgq.conf:-
# Enforce security for 'KCML_PerfMetric_Set() and 'KCML_PerfMetric_Clear() [perfmetric] queue=myQueue pubkey=zzzzz...
Where zzzzz... is the base-64 encoded public key.
When 'KCML_PerfMetric_Set() & 'KCML_PerfMetric_Clear() are called they inspect the timestamp and check that it is within 5 minutes of the current time.
If the timestamp is outside of that margin the functions will fail and return a value of _KCML_PERFMETRIC_TOKENEXPIRED.
The default margin can be changed by specifying the tokentimestampmargin value, in seconds, in the [perfmetric] section on /etc/kcml/msgq.conf
# Enforce security for 'KCML_PerfMetric_Set() and 'KCML_PerfMetric_Clear() # Increase timestamp margin to 10 minutes. [perfmetric] queue=myQueue pubkey=zzzzz... tokentimestampmargin=600
The signature will then be verified using the public key that was added to /etc/kcml/msgq.conf, if no pubkey value was added to /etc/kcml/msgq.conf then _KCML_PERFMETRIC_NOPUBKEY will be returned. If the signature is valid then the state of the perfmance metric will be changed, othwise a value of _KCML_PERFMETRIC_VERIFYFAILURE will be returned.
The KCML process that calls 'KCML_PerfMetric_Set() & 'KCML_PerfMetric_Clear() should not have access to the private key, ie to avoid the possibility bypassing the security by using self-signed tokens. Typically the token, and its signature, would be constructed on a different machine and then passed to a SOAP server, that verifies the signature using the public key, when it calls 'KCML_PerfMetric_Set() & 'KCML_PerfMetric_Clear().
However on internal development systems such security may not be required and can be disabled by adding the suppressverify key to the [perfmetric] section of /etc/kcml/msgq.conf :-
# Disable security for 'KCML_PerfMetric_Set() and 'KCML_PerfMetric_Clear() [perfmetric] queue=myQueue suppressverify=1
In this case the sToken$ parameter can be omitted or passed an empty string.
Messages are plain text and begin with a name of the form kcml.perf.metric. Then a common set of comma-separated key=value pair identifiers are included.
Example | Description |
---|---|
host="MachineName" | The application server's node name |
user="UserName" | Owner of the process |
pid=12345 | Process ID |
uuid="...." | Univerally unique identifier |
ts=1484752401428527 | Timestamp. Number of microseconds since epoch |
exe="kcml" | Executable program name. Typically kcml but can be kiodbc or kwebserv. |
service="AppName" | Application's service name in kconf.xml |
part=345 | Partition number, #PART. |
This set of values is also included with application performance metrics sent using 'KCML_PerfMetric_Send().
Each performance metric then appends one or more, comma separated, key=value pairs.
For example, kcml.load.prog
kcml.load.prog,host="centos6.kcml.com",user="fred",pid=6481,uuid="884a1fc0-65f9-4a53-9d8e-875172abf5b6",ts=1488216010824575,exe="kcml",service="MyApp",part=1015,file="/user1/src/myapp/sw/progs/main.src",loadtime=2545
Below is a list of performance metrics with the common set of key=value pairs omitted for clarity.
All time values are in micro-seconds, unless otherwise stated.
Hover the mouse pointer over each statistic for a description.
Note that not all constants have unique value as some metrics are enabled in pairs, for example kcml.session.start & kcml.session.end.
Metric | Constant Name | Constant Value | Description | Send Condition | Example |
---|---|---|---|---|---|
kcml.clnt.roundtriptime | _KCML_PERFMETRIC_KCML_CLNT_ROUNDTRIPTIME | 1 | A measure of network latency. Round-trip time, in microseconds, from the server to the client and back. | Form.Open() | kcml.clnt.roundtriptime,rtt=usec |
kcml.clnt.payload | _KCML_PERFMETRIC_KCML_CLNT_PAYLOAD | 2 | Client network payload required to display a form. It is a total of all the data sent up until the form's Show() event. | Form.Terminate() | kcml.clnt.payload,prog=string,form=string,cached=bool,shown=bool,size=count |
kcml.cpu.usage | _KCML_PERFMETRIC_KCML_CPU_USAGE | 3 | Total amount of processor time the partition has used | Program LOAD, SOAP server method calls & $END. Periodically from KDB/KISAM I/O operations, form events, $BREAK, $IF & 'KCML_poll() | kcml.cpu.usage,usertime=usec,systime=usec |
kcml.declare.call | _KCML_PERFMETRIC_KCML_DECLARE_CALL | 4 | Record of a $DECLARE call. The number of bytes sent and received is only applicable to client-side $DECLARE calls, where svr is 0 | $DECLARE | kcml.declare.call,lib=string,fn=string,svr=bool,time=usec,writebytes=count,readbytes=count |
kcml.declare.total | _KCML_PERFMETRIC_KCML_DECLARE_TOTAL | 39 | Summary of $DECLARE calls | Program LOAD, $END & periodically from $DECLARE | kcml.declare.total,count=num,writebytes=num,readbytes=num,server=num,client=num |
kcml.env.get | _KCML_PERFMETRIC_KCML_ENV_GET | 5 | Get environment value | val$=ENV(varName$) | kcml.env.get,name=string,time=usec,stack=string |
kcml.env.set | _KCML_PERFMETRIC_KCML_ENV_SET | 6 | Set environment value | ENV(varName$)=newValue$ | kcml.env.set,name=string,time=usec,stack=string |
kcml.env.total | _KCML_PERFMETRIC_KCML_ENV_TOTAL | 53 | Total number of ENV() statements | Program LOAD, SOAP server method calls & $END. Periodically from KDB/KISAM I/O operations, form events, $BREAK, $IF & 'KCML_poll() | kcml.env.total,set=count,get=count |
kcml.form.open | _KCML_PERFMETRIC_KCML_FORM_OPEN | 7 | Form open | Form.Open() | kcml.form.open,prog=string,form=string |
kcml.form.idle | _KCML_PERFMETRIC_KCML_FORM_IDLE | 8 | Record of a form's Idle() event executing | Form.Idle() | kcml.form.idle,prog=string,form=string,timer=msec |
kcml.kdb.open | _KCML_PERFMETRIC_KCML_KDB_OPEN | 9 | Database open table | KI_OPEN & KI_CREATE | kcml.kdb.open,table=string,handle=num,chandle=num,mode=string,time=usec |
kcml.kdb.close | _KCML_PERFMETRIC_KCML_KDB_CLOSE | 9 | Database close table | KI_CLOSE | kcml.kdb.close,table=string,handle=num,chandle=num |
kcml.kdb.connect | _KCML_PERFMETRIC_KCML_KDB_CONNECT | 12 | Database connect | KI_CONNECT | kcml.kdb.connect,time=usec,type=string,handle=num,dsn=string |
kcml.kdb.disconnect | _KCML_PERFMETRIC_KCML_KDB_DISCONNECT | 12 | Database disconnect | KI_DISCONNECT | kcml.kdb.disconnect,handle=num |
kcml.kdb.io | _KCML_PERFMETRIC_KCML_KDB_IO | 11 | Database I/O | Sent periodically during any read/write operation on KISAM/KDB tables & KI_CLOSE | kcml.kdb.io,table=string,handle=num,chandle=num,nread=count,readbytes=count,readtime=usec,nwrite=count,writebytes=count,writetime=usec,nreadidx=count,readbytesidx=count,readtimeidx=usec,nwriteidx=count,writebytesidx=count,writetimeidx=usec,nreaddata=count,readbytesdata=count,readtimedata=usec,nwritedata=count,writebytesdata=count,writetimedata=usec,mode=char |
kcml.kdb.error | _KCML_PERFMETRIC_KCML_KDB_ERROR | 34 | Last database error | KI_ERROR_TEXT on a handle where a database call has failed | kcml.kdb.error,handle=num,chandle=num,errtext=string |
kcml.kdb.dupidxio | _KCML_PERFMETRIC_KCML_KDB_DUPIDXIO | 47 | Duplicate index I/O | Sent during database I/O when the maxdupidx threshold in /etc/kcml/msgq.conf has been exceeded | kcml.kdb.dupidxio,table=string,handle=num,chandle=num,keyval=hex,add=bool,reccnt=count,reclen=num,idxblocks=count,idxbytes=count |
kcml.kdb.transtime | _KCML_PERFMETRIC_KCML_KDB_TRANSTIME | 54 | Time taken to perform a transaction | Transaction commit | kcml.kdb.transtime,chandle=num,time=usec,retries=count,status=string,stack=string |
kcml.kdb.prepare | _KCML_PERFMETRIC_KCML_KDB_PREPARE | 58 | Preparation of SQL plan | Sent when an SQL plan is prepared using CALL KI_PREPARE or KI_SQL | kcml.kdb.prepare,plan=num,handle=num,chandle=num,errtext=string,sql=string,time=usec,columns=count,kfn=string |
kcml.kdb.execute | _KCML_PERFMETRIC_KCML_KDB_EXECUTE | 58 | Execution of SQL plan | Sent when an SQL plan is executed using CALL KI_EXECUTE or KI_SQL | kcml.kdb.execute,plan=num,handle=num,chandle=num,time=usec,reclen=num,errtext=string |
kcml.kdb.fetch | _KCML_PERFMETRIC_KCML_KDB_FETCH | 59 | Result-set fetch from a database | Sent in KI_CLOSE or periodically during CALL KI_FETCH or when kiodbc queries an Oracle/PostgreSQL database | kcml.kdb.fetch,plan=num,rows=count,time=usec |
kcml.kdb.wsopen | _KCML_PERFMETRIC_KCML_KDB_WSOPEN | 64 | Open or create a word search index | KI_WS_OPEN & KI_WS_CREATE | kcml.kdb.wsopen,table=string,mode=string,chandle=num,exhandle=num,idxhandle=num,noisefile=string,noisesize=num,time=usec,major=num,minor=num |
kcml.kdb.startio | _KCML_PERFMETRIC_KCML_KDB_STARTIO | 70 | KI_START io | KI_START | kcml.kdb.startio,table=string,handle=num,chandle=num,keyval=hex,reccnt=count,idxblocks=count,idxbytes=count |
kcml.mem.used | _KCML_PERFMETRIC_KCML_MEM_USED | 14 | Amount of memory used | Program LOAD & SOAP server method calls. Periodically from KDB/KISAM I/O operations, form events, $BREAK, $IF & 'KCML_poll() | kcml.mem.used,mem=kb |
kcml.mem.delta | _KCML_PERFMETRIC_KCML_MEM_DELTA | 15 | Change in memory used, sent when the change exceeds threshold as defined in msgq.conf | DIM, REDIM & NEW | kcml.mem.delta,mem=kb,stack=string |
kcml.mem.sym | _KCML_PERFMETRIC_KCML_MEM_SYM | 56 | Foreground symbol table statistics | Program LOAD, COM CLEAR & SOAP server method calls. Periodically from KDB/KISAM I/O operations, form events, $BREAK, $IF & 'KCML_poll() | kcml.mem.sym,size=num,total=num,com=num,const=num,defsub=num,obj=num |
kcml.mem.redim | _KCML_PERFMETRIC_KCML_MEM_REDIM | 63 | Number of times an array or string as been REDIMensioned | MAT REDIM | kcml.mem.redim,newsize=bytes,dim1=num,dim2=num,redimcnt=count,stack=string |
kcml.native.open | _KCML_PERFMETRIC_KCML_NATIVE_OPEN | 18 | Opening native files | OPEN #, $DEVICE, DATALOAD DC OPEN, DATASAVE DC OPEN | kcml.native.open,file=string,handle=num,mode=string,time=usec,device=string |
kcml.native.close | _KCML_PERFMETRIC_KCML_NATIVE_CLOSE | 18 | Close native file | CLOSE #, $CLOSE, $REWIND | kcml.native.close,file=string,handle=num,device=string |
kcml.native.io | _KCML_PERFMETRIC_KCML_NATIVE_IO | 16 | Native I/O | CLOSE # & periodically during READ #, WRITE #, PRINT, DATALOAD BA/BU and DATASAVE BA/BU | kcml.native.io,file=string,nread=count,readbytes=count,readtime=usec,nwrite=count,writebytes=count,writetime=usec,handle=num,device=string |
kcml.native.dir | _KCML_PERFMETRIC_KCML_NATIVE_DIR | 17 | Directory enumeration | KI_DIR, KI_DIR_LIST & 'KCML_Dir_List() | kcml.native.dir,path=string,files=count,dirs=count,readtime=usec |
kcml.native.lock | _KCML_PERFMETRIC_KCML_NATIVE_LOCK | 45 | Native file lock | $OPEN | kcml.native.lock,file=string,handle=num,device=string,waittime=num,locked=num,ownerpid=num,ownerpart=num,owneruuid=string |
kcml.session.start | _KCML_PERFMETRIC_KCML_SESSION_START | 22 | Start of a KCML session | Session startup and $RELEASE | kcml.session.start,client=string,ip=string,term=num,peerip=string,peerport=num,mac=string,rel=num,termtype=char,version=string,puuid=string,time=usec |
kcml.session.end | _KCML_PERFMETRIC_KCML_SESSION_END | 22 | End of a session | End of a session, $END | kcml.session.end,client=string,ip=string,term=num,peerip=string,peerport=num,mac=string,rel=num,termtype=char,status=num |
kcml.session.lic | _KCML_PERFMETRIC_KCML_SESSION_LIC | 30 | Session licence usage | Start and end of a foreground session | kcml.session.lic,total=num,used=num |
kcml.shell.cmd | _KCML_PERFMETRIC_KCML_SHELL_CMD | 21 | Shell command | SHELL | kcml.shell.cmd,result=num,exectime=usec,systime=usec,usertime=usec,ptty=bool,cmd=string |
kcml.tcp.open | _KCML_PERFMETRIC_KCML_TCP_OPEN | 19 | TCP/IP Socket open | OPEN #hSock ... "@" & SOAP client | kcml.tcp.open,address=string,port=num,time=usec,dnstime=usec,ssl=bool,tls_ver=string,error=string,handle=num,server=bool |
kcml.tcp.close | _KCML_PERFMETRIC_KCML_TCP_CLOSE | 19 | TCP Socket close | CLOSE #hSock | kcml.tcp.close,address=string,port=num,handle=num |
kcml.tcp.io | _KCML_PERFMETRIC_KCML_TCP_IO | 20 | TCP Socket transfers | SOAP client & server. Periodically sent during READ #hSock & WRITE #hSock | kcml.tcp.io,address=string,port=num,nrecv=count,recvbytes=count,recvtime=usec,nsend=count,sendbytes=count,sendtime=usec,handle=num |
kcml.udp.open | _KCML_PERFMETRIC_KCML_UDP_OPEN | 50 | UDP Socket open | OPEN #hSock ... "@" | kcml.udp.open,handle=num |
kcml.udp.close | _KCML_PERFMETRIC_KCML_UDP_CLOSE | 50 | UDP Socket close | CLOSE #hSock | kcml.udp.close,handle=num |
kcml.udp.recv | _KCML_PERFMETRIC_KCML_UDP_RECV | 51 | UDP Socket Read | READ #hSock | kcml.udp.recv,handle=num,address=string,port=num,recvbytes=count,recvtime=usec,nrecv=count |
kcml.udp.send | _KCML_PERFMETRIC_KCML_UDP_SEND | 51 | UDP Socket Write | WRITE #hSock | kcml.udp.send,handle=num,address=string,port=num,sendbytes=count,sendtime=usec,nsend=count |
kcml.soap.start | _KCML_PERFMETRIC_KCML_SOAP_START | 28 | SOAP server startup time | Start of a SOAP server when generating WSDL | kcml.soap.start,interface=string,wsdltime=usec,version=string,endpoint=string |
kcml.soap.call | _KCML_PERFMETRIC_KCML_SOAP_CALL | 29 | Detail of the execution of a SOAP server method | After execution of a SOAP server method | kcml.soap.call,interface=string,method=string,time=usec |
kcml.soap.lic | _KCML_PERFMETRIC_KCML_SOAP_LIC | 30 | SOAP licence usage | Start and end of SOAP server | kcml.soap.lic,total=num,used=num |
kcml.httpd.request | _KCML_PERFMETRIC_KCML_HTTPD_REQUEST | 46 | HTTP request | After a request to a HTTP server | kcml.httpd.request,interface=string,method=string,endpoint=string,time=usec,reqsize=count,respsize=count,status=string |
kcml.total.io | _KCML_PERFMETRIC_KCML_TOTAL_IO | 23 | Total file & network I/O | Program LOAD, SOAP server method calls & $END. Periodically from KDB/KISAM or native file I/O operations, form events, $BREAK, $IF & 'KCML_poll() | kcml.total.io,nread=count,readbytes=count,nwrite=count,writebytes=count,nreadkdb=count,readbyteskdb=count,nwritekdb=count,writebyteskdb=count,nreadnative=count,readbytesnative=count,nwritenative=count,writebytesnative=count,nreadtcp=count,readbytestcp=count,nwritetcp=count,writebytestcp=count,nreadudp=count,readbytesudp=count,nwriteudp=count,writebytesudp=count,readbyteskclient=count,writebyteskclient=count,cachedrows=count,nativehdlcnt=count,dbhdlcnt=count |
kcml.load.lib | _KCML_PERFMETRIC_KCML_LOAD_LIB | 26 | Library load I/O | LIBRARY ADD / MODULE ADD | kcml.load.lib,file=string,kar=string,size=count,loadtime=usec |
kcml.load.prog | _KCML_PERFMETRIC_KCML_LOAD_PROG | 27 | Program load I/O | LOAD program | kcml.load.prog,file=string,loadtime=usec |
kcml.global.load | _KCML_PERFMETRIC_KCML_GLOBAL_LOAD | 48 | Loading process global library | SELECT @PART | kcml.global.load,lib=string,size=num,globpart=num,globuuid=string |
kcml.global.lock | _KCML_PERFMETRIC_KCML_GLOBAL_LOCK | 49 | Locking of the global shared | @LOCK / @UNLOCK | kcml.global.lock,lock=bool,time=usec |
kcml.xml.open | _KCML_PERFMETRIC_KCML_XML_OPEN | 24 | XML_OPEN | XML_OPEN | kcml.xml.open,file=string,handle=num,size=bytes |
kcml.xml.parsebuffer | _KCML_PERFMETRIC_KCML_XML_PARSEBUFFER | 24 | Load XML via XML_PARSE_BUFFER | XML_PARSE_BUFFER | kcml.xml.parsebuffer,handle=num,size=bytes |
kcml.xml.next | _KCML_PERFMETRIC_KCML_XML_NEXT | 25 | Parse XML | First XML_NEXT call | kcml.xml.next,handle=num,mem=bytes,time=usec |
kcml.xml.close | _KCML_PERFMETRIC_KCML_XML_CLOSE | 24 | XML_CLOSE call | XML_CLOSE | kcml.xml.close,handle=num |
kcml.odbc.lic | _KCML_PERFMETRIC_KCML_ODBC_LIC | 43 | ODBC licence usage | Start up of kiodbc | kcml.odbc.lic,total=num,used=num,version=string |
kcml.odbc.start | _KCML_PERFMETRIC_KCML_ODBC_START | 22 | Start of an instance of the ODBC server | Start of an instance of the ODBC server | kcml.odbc.start,client=string |
kcml.odbc.end | _KCML_PERFMETRIC_KCML_ODBC_END | 22 | End of an instance of the ODBC server | End of an instance of the ODBC server | kcml.odbc.end,client=string,fetched=count,rows=count,status=num |
kcml.odbc.prepare | _KCML_PERFMETRIC_KCML_ODBC_PREPARE | 60 | Preparation of SQL plan | Sent when an SQL plan is prepared by kiodbc | kcml.odbc.prepare,plan=num,handle=num,chandle=num,err=num,sql=string,time=usec,columns=count |
kcml.odbc.execute | _KCML_PERFMETRIC_KCML_ODBC_EXECUTE | 60 | Execution of SQL plan | Sent when an SQL plan is executed by kiodbc | kcml.odbc.execute,plan=num,handle=num,chandle=num,time=usec,reclen=num,err=num |
kcml.odbc.error | _KCML_PERFMETRIC_KCML_ODBC_ERROR | 60 | Database error | Sent when kiodbc sends an error back to the driver | kcml.odbc.error,plan=num,errtext=string |
kcml.odbc.fetch | _KCML_PERFMETRIC_KCML_ODBC_FETCH | 61 | Result-set fetch | Sent periodically when the kiodbc server is sending a result set to the ODBC driver | kcml.odbc.fetch,plan=num,rows=count,fetched=count,time=usec |
kcml.sql.open | _KCML_PERFMETRIC_KCML_SQL_OPEN | 31 | Database open table | KI_OPEN | kcml.sql.open,table=string,handle=num,chandle=num,mode=string,time=usec |
kcml.sql.close | _KCML_PERFMETRIC_KCML_SQL_CLOSE | 31 | Database close table | KI_CLOSE | kcml.sql.close,table=string,handle=num,chandle=num |
kcml.sql.prepare | _KCML_PERFMETRIC_KCML_SQL_PREPARE | 32 | Preparation of SQL plan | Sent when an SQL plan is prepared on an Oracle database | kcml.sql.prepare,sthandle=num,handle=num,chandle=num,sql=string,time=usec,kfn=string,err=num,plan=num |
kcml.sql.execute | _KCML_PERFMETRIC_KCML_SQL_EXECUTE | 32 | Execution of SQL plan | Sent when an SQL plan is executed on an Oracle database | kcml.sql.execute,schandle=num,sthandle=num,handle=num,chandle=num,time=usec,err=num,plan=num |
kcml.sql.fetch | _KCML_PERFMETRIC_KCML_SQL_FETCH | 33 | Result-set fetch | Sent periodically during any read/write operation on an Oracle database table & KI_END or KI_CLOSE | kcml.sql.fetch,sthandle=num,handle=num,chandle=num,rows=count,time=usec,plan=num |
kcml.sql.lobread | _KCML_PERFMETRIC_KCML_SQL_LOBREAD | 33 | LOB read | Sent periodically during any read/write operation on an Oracle database table | kcml.sql.lobread,handle=num,chandle=num,schandle=num,size=num,time=usec |
kcml.sql.bindin | _KCML_PERFMETRIC_KCML_SQL_BINDIN | 38 | Binding of input parameters | Sent during & after the execution of the SQL plan on an Oracle database | kcml.sql.bindin,sthandle=num,handle=num,chandle=num,name=string,size=num,type=string,ind=num,fmt=string,value=string |
kcml.sql.transstart | _KCML_PERFMETRIC_KCML_SQL_TRANSSTART | 41 | Transaction start | Start of a transaction. Oracle databases only | kcml.sql.transstart,chandle=num,schandle=num,flags=num,err=num |
kcml.sql.transrollback | _KCML_PERFMETRIC_KCML_SQL_TRANSROLLBACK | 41 | Transaction rollback | Transaction rollback. Oracle databases only | kcml.sql.transrollback,chandle=num,schandle=num,time=usec,err=num |
kcml.sql.transcommit | _KCML_PERFMETRIC_KCML_SQL_TRANSCOMMIT | 41 | Transaction commit | Transaction commit. Oracle database only | kcml.sql.transcommit,chandle=num,schandle=num,time=usec,err=num |
kcml.sql.transdetach | _KCML_PERFMETRIC_KCML_SQL_TRANSDETACH | 41 | Transaction detach | Start of an autonomous transaction. Oracle databases only | kcml.sql.transdetach,chandle=num,schandle=num,flags=num,err=num |
kcml.sql.total | _KCML_PERFMETRIC_KCML_SQL_TOTAL | 35 | Total remote database load | Program LOAD, SOAP server method calls, form events & $END. Periodically from database or native file I/O operations, $BREAK, $IF & 'KCML_poll() | kcml.sql.total,prepcnt=num,execcnt=num,fetchcnt=num,lobrds=num,ptime=usec,etime=usec,ftime=usec,ltime=usec,hdlcnt=num,curscnt=num |
kcml.sql.error | _KCML_PERFMETRIC_KCML_SQL_ERROR | 40 | Database error | Lookup of an error caused by the failure of a database function call | kcml.sql.error,handle=num,chandle=num,err=num |
kcml.sql.handlealloc | _KCML_PERFMETRIC_KCML_SQL_HANDLEALLOC | 44 | Allocate handle | KI_OPEN, KI_PREPARE | kcml.sql.handlealloc,handle=num,chandle=num,sthandle=num |
kcml.sql.handlefree | _KCML_PERFMETRIC_KCML_SQL_HANDLEFREE | 44 | Free handle | KI_END, KI_CLOSE, LOAD & $SPACE | kcml.sql.handlefree,handle=num,chandle=num,sthandle=num |
kcml.sql.opttranstime | _KCML_PERFMETRIC_KCML_SQL_OPTTRANSTIME | 62 | Time taken to commit an optimistic transaction | User input, LOAD, $BREAK, $IF, KI_CLOSE | kcml.sql.opttranstime,chandle=num,time=usec,stack=string |
kcml.sql.ddl | _KCML_PERFMETRIC_KCML_SQL_DDL | 66 | DDL executed in DB | Any DDL executed in DB | kcml.sql.ddl,handle=num,chandle=num,sql=string,stack=string |
kcml.sql.tableddl | _KCML_PERFMETRIC_KCML_SQL_TABLEDDL | 67 | DDL executed in DB | Any table DDL executed in DB, CREATE TABLE, DROP TABLE, RENAME, ALTER TABLE | kcml.sql.tableddl,handle=num,chandle=num,sql=string,stack=string |
kcml.databridge.socketwrite | _KCML_PERFMETRIC_KCML_DATABRIDGE_SOCKETWRITE | 68 | Time taken to write to socket (milli-seconds) | Message written to kdatadaemon | kcml.databridge.socketwrite,time=num |
kcml.databridge.daemonmessage | _KCML_PERFMETRIC_KCML_DATABRIDGE_DAEMONMESSAGE | 69 | Message from DataBridge daemon | Error in kdatadaemon processing | kcml.databridge.daemonmessage,message=string |
kcml.cache.open | _KCML_PERFMETRIC_KCML_CACHE_OPEN | 9 | Table cache open | Opening of a cached table | kcml.cache.open,table=string,handle=num,chandle=num,size=num,time=usec |
kcml.cache.close | _KCML_PERFMETRIC_KCML_CACHE_CLOSE | 9 | Table cache close | Close of a cached table | kcml.cache.close,table=string,handle=num,chandle=num,time=usec,rows=count |
kcml.cache.refresh | _KCML_PERFMETRIC_KCML_CACHE_REFRESH | 36 | Database table caching | Cache file is rebuilt | kcml.cache.refresh,file=string,handle=num,chandle=num,size=num,time=usec |
kcml.cache.reject | _KCML_PERFMETRIC_KCML_CACHE_REJECT | 36 | Table cache rejection | Attempting to cache a table that is too large | kcml.cache.reject,table=string,handle=num,chandle=num |
kcml.cache.read | _KCML_PERFMETRIC_KCML_CACHE_READ | 55 | Table cache read | Sent periodically while reading from a cached table | kcml.cache.read,table=string,handle=num,chandle=num,rows=count |
kcml.lic.open | _KCML_PERFMETRIC_KCML_LIC_OPEN | 37 | Lookup of a [Section] and key=value from the application server's licence file | $LIC() | kcml.lic.open,file=string,section=string,key=string,value=string,time=usec,found=bool |
kcml.lic.client | _KCML_PERFMETRIC_KCML_LIC_CLIENT | 37 | Lookup of a [Section] and key=value from the client's licence file | $LIC() | kcml.lic.client,section=string,key=string,value=string,time=usec,found=bool |
kcml.proc.stacktrace | _KCML_PERFMETRIC_KCML_PROC_STACKTRACE | 42 | Program stack trace. The flag is temporary and is unset when the perfmetric metric is sent. | After execution of a statement that has been signalled with bkstat -K<part>:SIGUSR2:Stacktrace | kcml.proc.stacktrace,stack=string |
kcml.jclient.req | _KCML_PERFMETRIC_KCML_JCLIENT_REQ | 52 | Browser client request times | Sent periodically while processing requests from the browser client | kcml.jclient.req,network=usec,render=usec,wcm=usec,event=usec,resp=usec,sent=count,recv=count |
kcml.translate.form | _KCML_PERFMETRIC_KCML_TRANSLATE_FORM | 57 | Warning of missing translations in a DEFFORM | Form.Terminate() | kcml.translate.form,lang=num,form=string,prog=string,count=count |
kcml.translate.missing | _KCML_PERFMETRIC_KCML_TRANSLATE_MISSING | 57 | Warning of a missing translation in a chevron string | LOAD program & $END | kcml.translate.missing,lang=num,prog=string,line=num,stat=num,count=num |
kcml.translate.clipped | _KCML_PERFMETRIC_KCML_TRANSLATE_CLIPPED | 57 | Translated strings clipped on rendering in the client | Form.Open() | kcml.translate.clipped,form=string,ctrl=string,context=string,label=string,text=string,dpi=num,screenw=num,screenh=num,formw=num,formh=num,ctrlw=num,textw=num,extra=string |
kcml.x509.expiry | _KCML_PERFMETRIC_KCML_X509_EXPIRY | 65 | Warn of SSL certificate expiry | kcml.x509.expiry,type=string,validto=string,subject=string,san=string,issuer=string,path=string,daysremaining=num,selfsigned=num,peer=num |
The [perfmetric] section supports the following settings:-
Metric | Key | Default Value | Required | Description |
---|---|---|---|---|
kcml.declare.total | decltimerfreq | 25 | Optional | Number of $DECLARE calls between checking time of last send of kcml.declare.total |
kcml.kdb.dupidxio | maxdupidx | 100000 | Optional | Max number of index blocks we read while scanning for a dup idx, if we exceed that limit issue a kcml.kdb.dupidxio |
kcml.kdb.transtime | maxtranstime | 2 | Optional | If a transaction takes longer than this timeout (in seconds) then issue a kcml.kdb.transtime |
kcml.kdb.startio | maxstartio | 5000 | Optional | Max KI_START io |
kcml.mem.delta | mem | 65536 | Optional | Default threshold, in kilobytes, for kcml.mem.delta |
kcml.mem.redim | maxredim | 50 | Optional | Threshold of number of REDIMs on an array/string |
kcml.native.lock | lockwaitalert | 2 | Optional | If a lock takes longer than this timeout (in seconds) then issue a kcml.native.lock |
kcml.translate.missing | maxtranslatemissing | 2 | Optional | Max number of kcml.translate.missing metrics to report |
kcml.x509.expiry | x509warndays | 30 | Optional | How many days before we warn of X509 cert expiry |
pubkey | "" | Optional | Public key used to verify the security token | |
tokentimestampmargin | 300 | Optional | Maximum difference of the timestamp in the security token and the current time. | |
perfopenfile | FALSE | Optional | Flag to allow 'KCML_PerfMetric_OpenFile() to work with signatures | |
iotimerfreq | 100 | Optional | Number of I/O operations between checking the time between periodic metrics | |
logperiod | 600 | Optional | Number of seconds between reporting periodic metrics, such as kcml.kdb.io | |
suppressverify | FALSE | Optional | Flag to disable token verification on internal development systems | |
queue | "" | Required | Queue name for performance metrics |
Application code may also be instrumented. As all KCML internal performance metrics use microseconds it is also recommended to do the same. An application's metric name may be any string value except that is must not begin with "kcml".
The example below uses 'KCML_PerfTimer_Start() and 'KCML_PerfTimer_Stop() to measure how long a subroutime took to execute and then sends the statistics to the RabbitMQ server using 'KCML_PerfMetric_Send().
00010 'main() : $END : DEFSUB 'main() : LOCAL DIM rTimes$_kcml_perftimerrec : LOCAL DIM nTimerId AS integer : : REM Start a performance timer : ntimerid = 'KCML_PerfTimer_Start() : : REM call the code to be monitored : 'doSomeThing() : : REM Stop the performance timer : 'KCML_PerfTimer_Stop(ntimerid,BYREF rTimes$) : REM Report the statistic : 'KCML_PerfMetric_Send("","my.app.metric",$PRINTF("elapsed=%d,exectime=%d,usertime=%d,kerneltime=%d",FLD(rTimes$.KCML_PerfTimer_Elapsed),FLD(rTimes$.KCML_PerfTimer_Exec),FLD(rTimes$.KCML_PerfTimer_User),FLD(rTimes$.KCML_PerfTimer_Kernel))) : END SUB : : REM Fake up application processor and idle time : DEFSUB 'doSomeThing() : LOCAL DIM i AS integer : LOCAL DIM j AS integer : LOCAL DIM rc : LOCAL DIM a$0 : : FOR i = 1 TO 1000 : REM Fake up execution time : FOR j = 1 TO 1000 : REDIM a$ = $UPPER("quick brown fox") : NEXT j : REM Fake up idle time by pausing for 1 millisecond : rc = $IF,1 : NEXT i : END SUB
The final message sent via 'KCML_PerfMetric_Send() is the application's metric name followed by the common set of identifiers and then finally the list of statistics the application has measured.
For example, the above program may report the following to the message queue:-
my.app.metric,host="myserver",user="fred",pid=29583,uuid="e8bf5cba-183f-40c8-9e30-cf5674c9ee3f",ts=1490374670046022,exe="kcml",part=2048,elapsed=2372010,exectime=160416,usertime=163000,kerneltime=19000
The 07.22 version of kiodbc will also produce performance metrics in the same way as KCML. As kiodbc processes tend to be short-lived & they are not interactive there is little opportunity to enable additional metrics on a running process. It may also be desireable to only have kiodbc report certain database metrics such as kcml.kdb.io, as a KCML process may produce too many messages. Additional metrics for kiodbc can be configured by listing them in the [odbc] section of /etc/kcml/msgq.conf :-
# Additional default metrics for kiodbc only [odbc] kcml.kdb.io=1 kcml.kdb.fetch=1 kcml.odbc.fetch=1 kcml.odbc.prepare=1