z/OSの新しい管理方法を探る - (3)CICSヒストリカルデータのElasticsearchへの取り込み

# はじめに
z/OS上の情報をOSSに取り込んでみるという話の第3弾です。
今回はz/OSそのものではなく、その上で動いているCICSの情報を扱います。

CICSのヒストリカルデータを取得すると、割とリアルタイムに(SMFを後からオフラインでフォーマットするのではなく)、タスク毎のパフォーマンスデータを参照することができます(例えば、CPU time, Reponse Time, ストレージ使用状況、各種待ち時間、などなど...)。
しかもこの情報はREST APIで取得することができます。
CICSヒストリカルデータの詳細は以下もご参照下さい。
[REST APIによるCICSヒストリカルデータの取得](https://qiita.com/tomotagwork/items/b14fe41c9f5f1504b63e)

ここでは、REST経由で取得したCICSヒストリカルデータをElasticsearchにぶち込んでKibanaで可視化ってのをやってみます。

## 関連記事
[z/OSの新しい管理方法を探る - (1)DAパネル情報のElasticsearchへの取り込み](https://qiita.com/tomotagwork/items/362b0db5d4479eecebac)
[z/OSの新しい管理方法を探る - (2)-1 SYSLOGのElasticsearchへの取り込み](https://qiita.com/tomotagwork/items/867dd353cf8c985eab76)
[z/OSの新しい管理方法を探る - (2)-2 SYSLOGのElasticsearchへの取り込み part2](https://qiita.com/tomotagwork/items/e2c6c59a40f7ea00160b)
[z/OSの新しい管理方法を探る - (2)-3 SYSLOGのElasticsearchへの取り込み part3](https://qiita.com/tomotagwork/items/79faddc4e6afa28849ec)
[z/OSの新しい管理方法を探る - (3)CICSヒストリカルデータのElasticsearchへの取り込み](https://qiita.com/tomotagwork/items/c7cd4b9e5ffcb8ede0f1)
[z/OSの新しい管理方法を探る - (4) RMF MonitorIIIレポートのElasticsearchへの取り込み](https://qiita.com/tomotagwork/items/7e7e9b8b6432739b3e3a)


# 実装

## 全体像

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/346c5047-c4de-75de-4ba4-8cd99eeb2c32.png)

全体のイメージはこれまでの流れと同様です。

## 前提

対象のCICSリージョンでCICSヒストリカルデータを取得するための設定を行っておく必要があります。ヒストリカルデータを取得するにはCICSplex構成が前提となります(構成の詳細は上の記事参照)。
WUIに対してCMCIを使ってヒストリカルデータを取得することになりますので、WUIの構成としてCMCIが使えるようにしておく必要があります。
例によってELKスタックはIntel Linuxサーバー上に配置し、そこにデータを取り込む想定です。
Linux上のシェル・スクリプトでJSONハンドリングのために"jq"というコマンドを利用していますので、jqが使えるようセットアップしておく必要があります。
参考: [jq](https://stedolan.github.io/jq/)

今回ホスト側は設定のみで、作り物は無しです。

## Linux / CMCI経由でヒストリカルデータ取得用シェル・スクリプト

### CMCIリクエスト部分

CMCIを使うと、様々な管理情報を取得することができますが、今回はヒストリカルデータを取得します。以下の辺りを参考に。

CMCIのGET要求のシンタックス:
　[CICS 管理クライアント・インターフェース GET 要求 URI](https://www.ibm.com/support/knowledgecenter/ja/SSGMCP_5.4.0/reference/cmci/clientapi_get_uri.html)
CRITERIAオプションによるフィルターの指定方法:
　[フィルター式の作成方法](https://www.ibm.com/support/knowledgecenter/ja/SSGMCP_5.4.0/system-programming/cpsm/eyup1a0.html)
PARAMETER指定:
　[履歴データ](https://www.ibm.com/support/knowledgecenter/ja/SSGMCP_5.4.0/monitoring/cpsm/eyuabc0018.html)

例えば、こんな感じでhttpのGETリクエストを発行することになります。
`http://hostname:54002/CICSSystemManagement/CICSTaskHistory/C71PLX/CT54D4A1?CRITERIA=(tranid=C*)&PARAMETER=STARTDATE(06/05/2018) STARTTIME(02:15:00)`
結果は残念ながらJSONではなくXMLで返されます。
(※最新版のCICS TS V5.5ではGraphQLをサポートしたのでGraphQLで情報取得もできますが、まだV5.5を利用しているユーザーは少ないので、ここではすぐに試せる方式ということで敢えてこの方式でやっています。)

```xxx:返されるXMLサンプル
<?xml version="1.0" ?>
<responsexmlns="http://www.ibm.com/xmlns/prod/CICS/smw2int"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.ibm.com/xmlns/prod/CICS/smw2int http://hostname:54002/CICSSystemManagement/schema/CICSSystemManagement.xsd"version="3.0"connect_version="0540">
<resultsummaryapi_response1="1024"api_response2="0"api_response1_alt="OK"api_response2_alt=""recordcount="8"displayed_recordcount="8"/>
<records>
<cicstaskhistory_keydata="D46EBE1DAD15CF86"abcodec=""abcodeo=""acapplname=""acmajorver="0"acmicrover="0"acminorver="0"acopername=""acplatname=""actvtyid="00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"actvtynm=""allocates="0"applnameprog=""applnametran=""asfreect="0"asftchct="0"asftchwt="0000:00:00.000000"asrnatwt="0000:00:00.000000"asrunct="0"astotct="0"baacdcct="0"baacqpct="0"badactct="0"badcpact="0"badfiect="0"badproct="0"balkpact="0"baprdcct="0"barasyct="0"baratect="0"barmpact="0"barspact="0"barsynct="0"basupact="0"batiaect="0"batotcct="0"batotect="0"batotpct="0"bmscount="0"bmsincnt="0"bmsmapcnt="0"bmsoutcnt="0"brdgtran="NO"bridge=""btecomp="YES"cdsagetm="0"cdsapshwm="0"cdsashwm="0"cdsasocc="0"cecmchtp="2964"cecmdlid="740"cfdtwait="0000:00:00.000000"charin="0"charinsec="0"charout="0"charoutsec="0"cicswait="0000:00:00.000000"clipaddr=""controlwait="0000:00:00.000000"correuow="D1D7C9C2D4D8C8C54BC3E3F5F4C4F4C1F16EBE1DAD1909"cputime="0000:00:00.000237"cputoncp="0000:00:00.000237"curtasks="0"db2conwt="0000:00:00.000000"db2rdyqw="0000:00:00.000000"db2reqct="0"dettrantype="SYSTEM"dhcrect="0"dhinsct="0"dhretct="0"dhsetct="0"dhtotct="0"dhtotdcl="0"disptime="0000:00:00.000302"dsapthwt="0000:00:00.000000"dspdelay="0000:00:00.000013"ecdsagetm="2"ecdsapshwm="0"ecdsashwm="21072"ecdsasocc="334"enqdelay="0000:00:00.000000"execomp="NO"externwait="0000:00:00.000000"exwait="0000:00:00.000000"eyu_cicsname="CT54D4A1"eyu_cicsrel="E710"eyu_reserved="0"facility=""facilitytype="START"fcaddcnt="0"fcamcnt="0"fcbrwcnt="0"fccount="0"fcdelcnt="0"fcgetcnt="0"fciotime="0000:00:00.000000"fcputcnt="0"fcvswtt="0000:00:00.000000"fcxcwtt="0000:00:00.000000"firstprgm="EYU9XLOP"gcdsagetm="0"gcdsashwm="0"gnqdelay="0000:00:00.000000"gudsagetm="0"gudsashwm="0"iccount="0"imsreqct="0"imswait="0000:00:00.000000"indoubt="BACKWARD"indoubtfail="NO"indoubtwait="YES"intvlc="0"intvlwait="0000:00:00.000000"iriotime="0000:00:00.000000"isalwtt="0000:00:00.000000"isolatest="YES"jciotime="0000:00:00.000000"jcusrwcnt="0"jrnlwritreq="0"jvmsusp="0000:00:00.000000"jvmtime="0000:00:00.000000"lockmgrwait="0000:00:00.000000"loggrwritreq="0"lparname="CEC1LP5"luname=""lu61wtt="0000:00:00.000000"lu62wtt="0000:00:00.000000"l8cput="0000:00:00.000000"maxtasks="50"mpprtxcd="0"mpsract="0"mpsrect="0"mscput="0000:00:00.000000"msdispt="0000:00:00.000000"msgin="0"msginsec="0"msgout="0"msgoutsec="0"mxtdelay="0000:00:00.000000"mxtotdly="0000:00:00.000000"ncgetcnt="0"netname="JPIBMQHE.CT54D4A1"netuowid="1A11D1D7C9C2D4D8C8C54BC3E3F5F4C4F4C1F16EBE1DAD19090001"oadata1=""oadata2=""oadata3=""oadid=""oapplid="CT54D4A1"oclipadr=""ocliport="0"ofctynme=""offlcput="0000:00:00.000000"onetwkid="JPIBMQHE"oportnum="0"origintype="NONE"ostart="2018-06-05T02:13:37.711452+00:00"otcpsvce=""otran="COHT"otranflg="8080804001800000"otrannum="0000057"ousercor=""ouserid="CICSUSER"pcdplct="0"pclinkcnt="1"pcloadcnt="0"pcloadtm="0000:00:00.000000"pclurmct="0"pcxctlcnt="0"pc24rhwm="6088"pc24shwm="0"pc31shwm="0"perfreccnt="1"pgcsthwm="0"phapplid=""phcount="0"phntwkid=""phstart="0000-00-00T00:00:00.000000+00:00"phtran=""phtranno="0000000"prcsid="00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"prcsname=""prcstype=""priority="200"pstghwm="6088"pstg24hwm="6088"pstg31hwm="0"ptcount="0"ptstart="0000-00-00T00:00:00.000000+00:00"pttran=""pttranno="0000000"qrcput="0000:00:00.000237"qrdispt="0000:00:00.000302"qrmoddly="0000:00:00.000000"rectype=" T"resolveact="NO"resptime="0000:00:00.000315"rlscput="0000:00:00.000000"rlswaittime="0000:00:00.000000"rmicpsmtime="0000:00:00.000001"rmidbctltime="0000:00:00.000000"rmidb2time="0000:00:00.000000"rmiexecdlitm="0000:00:00.000000"rmimqseriest="0000:00:00.000000"rmiothertime="0000:00:00.000000"rmisusp="0000:00:00.000000"rmitcpiptime="0000:00:00.000000"rmitime="0000:00:00.000001"rmitotaltime="0000:00:00.000001"rofail="NO"romoddly="0000:00:00.000000"rops31hwm="0"rrmsurid="00000000000000000000000000000000"rrmswait="0000:00:00.000000"rsysid=""runtrwtt="0000:00:00.000000"sharedtswait="0000:00:00.000000"shstgbytefma="16"shstgbytefmb="0"shstgbytefmg="0"shstgbytegma="0"shstgbytegmb="0"shstgbytegmg="0"shstggmcabv="0"shstggmcbar="0"shstggmcbel="0"shunted="NO"sobydect="0"sobyenct="0"socipher="00000000"soiowtt="0000:00:00.000000"somoddly="0000:00:00.000000"srvsywtt="0000:00:00.000000"start="2018-06-05T02:13:37.711452+00:00"stop="2018-06-05T02:13:37.711768+00:00"subexecomp="NO"subtype="T"susptime="0000:00:00.000013"synccount="1"syncdly="0000:00:00.000000"syncptwaittm="0000:00:00.000019"szallcto="0"szalloct="0"szchrin="0"szchrout="0"szrcvct="0"szrcvto="0"szsendct="0"szstrtct="0"sztotct="0"szwait="0000:00:00.000000"s8cput="0000:00:00.000000"task="0000057"taskdatakey="CICS"taskdataloc="ANY"taskflag="0"tcalwtt="0000:00:00.000000"tcbattct="0"tcc62in2="0"tcc62ou2="0"tciotime="0000:00:00.000000"tcldelay="0000:00:00.000000"tcm62in2="0"tcm62ou2="0"tdcount="0"tdelwtt="0000:00:00.000000"tdgetcnt="0"tdilwtt="0000:00:00.000000"tdiotime="0000:00:00.000000"tdpurcnt="0"tdputcnt="0"termconname=""termid=""termnalinfo="00000000"time="D46EBE1DAD15CF86"tmratmsn=""tmrbfdgc="0"tmrbftc="0"tmrcfact="0"tmrcipor="0"tmrcmdly="0000:00:00.000000"tmrdhdlc="0"tmrdscwt="0000:00:00.000000"tmrdsmwt="0000:00:00.000000"tmrdsthw="0"tmrecevc="0"tmrecfoc="0"tmrecsec="0"tmrecsge="0"tmreictc="6"tmricscc="0"tmricscd="0"tmricsrc="0"tmricsrd="0"tmrisact="0"tmriscnm=""tmriswt="0000:00:00.000000"tmrjstwt="0000:00:00.000000"tmrjvmit="0000:00:00.000000"tmrjvmrt="0000:00:00.000000"tmrky8cp="0000:00:00.000000"tmrky8ds="0000:00:00.000000"tmrky9cp="0000:00:00.000000"tmrky9ds="0000:00:00.000000"tmrl9cpu="0000:00:00.000000"tmrmlctm="0000:00:00.000000"tmrmltdl="0"tmrmlxtc="0"tmrmqast="0000:00:00.000000"tmrmqgwt="0000:00:00.000000"tmrnetid=""tmrnetsx="6EBE1DAD19090001"tmroidwt="0000:00:00.000000"tmrotsid=""tmrpcdcc="0"tmrpcdll="0"tmrpcdrl="0"tmrpclcc="0"tmrpcrcc="0"tmrpcrcl="0"tmrpcxcc="0"tmrpgbcc="0"tmrpgccc="0"tmrpgctc="0"tmrpggcc="0"tmrpggcl="0"tmrpgmcc="0"tmrpgpcc="0"tmrpgpcl="0"tmrpipln=""tmrportn="0"tmrptpwt="0000:00:00.000000"tmrrlunm=""tmrrocpu="0000:00:00.000000"tmrrodsp="0000:00:00.000000"tmrrqpwt="0000:00:00.000000"tmrrqrwt="0000:00:00.000000"tmrsocin="0"tmrsocns="0"tmrsocot="0"tmrsocps="0"tmrsoerc="0"tmrsoimc="0"tmrsoi1c="0"tmrsonhw="0"tmrsoomc="0"tmrsoowt="0000:00:00.000000"tmrsoo1c="0"tmrsophw="0"tmrsorct="0"tmrsosct="0"tmrsotc="0"tmrstdly="0000:00:00.000000"tmrtcpsv=""tmrtgpid="1A11D1D7C9C2D4D8C8C54BC3E3F5F4C4F4C1F1D46EBE1DAD194C3A00"tmrtiatc="0"tmrtitc="0"tmrttdly="0000:00:00.000000"tmrt8cpu="0000:00:00.000000"tmrurimn=""tmrwbboc="0"tmrwbbrc="0"tmrwberc="0"tmrwbirc="0"tmrwbiwc="0"tmrwbi1c="0"tmrwbosc="0"tmrwbo1c="0"tmrwbprc="0"tmrwbrdl="0"tmrwbroc="0"tmrwbrpr="0"tmrwbrrc="0"tmrwbwdl="0"tmrwbwoc="0"tmrwbwrc="0"tmrwmqrc="0"tmrwpbmn=""tmrwsatc="0"tmrwscbc="0"tmrwscgc="0"tmrwsepc="0"tmrwsopn=""tmrwsvcn=""tmrxtdly="0000:00:00.000000"tmrx8cpu="0000:00:00.000000"tmrx9cpu="0000:00:00.000000"tranclass=""tranflags="8080804001800000"tranid="COHT"trantype="U"tscount="0"tsgetcnt="0"tsgetscnt="0"tsiotime="0000:00:00.000000"tsputacnt="0"tsputmcnt="0"tsputscnt="0"unshunted="NO"uowid="D46EBE1DAD190962"uowinstseq="6EBE1DAD19090001"userid="CICSUSER"usrps24hwm="6088"usrps31hwm="0"ustg24cnt="0"ustg24hwm="0"ustg24occ="0"ustg31cnt="0"ustg31hwm="0"ustg31occ="0"waittime="0000:00:00.000000"wbchrin="0"wbchrout="0"wbissfct="0"wbjsnrpl="0"wbjsnrql="0"wbrcvct="0"wbrepwct="0"wbsendct="0"wbsfcrct="0"wbsftoct="0"wbsreqbl="0"wbsrspbl="0"wbtotct="0"wlmrptrcname="RPCICS1"wlmsrvcname="PRDONL_M"/>
... <以下略>

```
タスク毎の大量の情報がぐわーっと返って来ます(上の抜粋は1タスク分の情報です)。

シェルスクリプトからはcurlコマンドでhttpリクエストを出せるので、curlでCMCIのリクエストを出すことにします。

### XMLの解釈部分
さて、上のようにXML形式、しかも要素ではなく全て属性で情報が返されるというちょっとやっかいな形なのでどうしたものかなと。で、今回もlogstash経由でElasticsearchに取り込みますが、取り込みやすいように事前に1次加工をしちゃった方が良さそうだなと。
ということで、XMLを解釈して必要なデータを抽出してJSON形式に変換するXSLTを作成することにします。
今回は、サンプルということで、とりあえずリージョン名、トランザクションID, 起動時刻、終了時刻、cpu time, response time あたりの情報を抽出してみることにします。

返される各フィールドはこちらを参照のこと。
参考: [Completed tasks - HTASK](https://www.ibm.com/support/knowledgecenter/ja/SSGMCP_5.4.0/reference/cpsm-ops-views/topics/eyua3_htask.html)

用意したXSLTはこちら。

```xslt:filter_HistoricalData.xsl
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:h="http://www.w3.org/1999/xhtml"
                xmlns:cics="http://www.ibm.com/xmlns/prod/CICS/smw2int">
    <xsl:output method="text"/>

<xsl:template match="/">
  <xsl:for-each select="//cics:cicstaskhistory">
   <xsl:variable name="cpu_hour" select="substring(./@cputime,1,4)"/>
   <xsl:variable name="cpu_min" select="substring(./@cputime,6,2)"/>
   <xsl:variable name="cpu_sec" select="substring(./@cputime,9,9)"/>
   <xsl:variable name="resp_hour" select="substring(./@resptime,1,4)"/>
   <xsl:variable name="resp_min" select="substring(./@resptime,6,2)"/>
   <xsl:variable name="resp_sec" select="substring(./@resptime,9,9)"/>
    {
     "cics_region":"<xsl:value-of select="./@eyu_cicsname"/>",
     "tranid":"<xsl:value-of select="./@tranid"/>",
     "cputime":"<xsl:value-of select="./@cputime"/>",
     "cputime_sec":<xsl:value-of select="$cpu_hour * 60 * 60 + $cpu_min * 60 + $cpu_sec"/>,
     "resptime":"<xsl:value-of select="./@resptime"/>",
     "resptime_sec":<xsl:value-of select="$resp_hour * 60 * 60 + $resp_min * 60 + $resp_sec"/>,
     "start":"<xsl:value-of select="./@start"/>",
     "stop":"<xsl:value-of select="./@stop"/>"
    }
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>
```

cpu time, reponse timeのフィールドは、"00:00:00.000000" というめんどくさいフォーマットになっているので、秒単位の数値として算出しています。

xsltprocというコマンドを使うと、XSLTを通してXMLの解釈が行えます(第1引数にXSLTファイル、第2引数に対象のXMLファイルを指定)。
xsltprocコマンドで上のxsltを使って解釈させてみるとこんな感じになります。

```xxx:xsltproc実行例
# xsltproc filter_HistoricalData.xsl tempHistoricalData.xml

    {
     "cics_region":"CT54D4A1",
     "tranid":"COHT",
     "cputime":"0000:00:00.000271",
     "cputime_sec":0.000271,
     "resptime":"0000:00:00.000684",
     "resptime_sec":0.000684,
     "start":"2018-06-11T06:45:52.807420+00:00",
     "stop":"2018-06-11T06:45:52.808105+00:00"
    }

    {
     "cics_region":"CT54D4A1",
     "tranid":"COHT",
     "cputime":"0000:00:00.000198",
     "cputime_sec":0.000198,
     "resptime":"0000:00:00.001352",
     "resptime_sec":0.001352,
     "start":"2018-06-11T06:45:53.897448+00:00",
     "stop":"2018-06-11T06:45:53.898800+00:00"
    }

...以下略
```

### 情報取得用シェル・スクリプト

これらを組み合わせて、情報取得用のシェル・スクリプトを作ります。

```sh:cmci_hist_c71plx.sh
#!/bin/sh

### change Timezone to UTC
export TZ=UTC

### temporary file for CMCI response file
CMCIResponseFile=temp_CMCI_response.xml

### tempporary file for previous requested time
tempFile=previousDateTime_CMCI.txt

### XSLT file
xsltFile=filter_HistoricalData.xsl

### CMCI Profile
hostName=localhost
port=54002
URI_historyData=/CICSSystemManagement/CICSTaskHistory
#targetRegion=/C71PLX/CT54D4A1
targetRegion=/C71PLX
targetTranId=*
startDate=
startTime=
endDate=
endTime=


### get Date and Time
thisDateTime=$(date '+%m/%d/%Y %H:%M:%S')
nextDateTime=$(date -d"${thisDateTime} 1 second " '+%m/%d/%Y %H:%M:%S')

endDate=${thisDateTime:0:10}
endTime=${thisDateTime:11:8}


if [[ -e ${tempFile} ]]
then
        read startDate startTime < ${tempFile}
else
        startDate=${endDate}
        startTime=00:00:00
fi

echo startDate: ${startDate}
echo startTime: ${startTime}
echo endDate: ${endDate}
echo endTime: ${endTime}

outputDir=/var/log/cics_historicalData/
yyyymmdd=$(date '+%Y%m%d')
outputFile=${outputDir}cics_c71plx_${yyyymmdd}.txt


### Issue CMCI Request
URI_all="http://${hostName}:${port}${URI_historyData}${targetRegion}?CRITERIA=tranid=${targetTranId}&PARAMETER=STARTDATE(${startDate})%20STARTTIME(${startTime})%20ENDDATE(${endDate})%20ENDTIME(${endTime})"
#echo ${URI_all}
curl "${URI_all}" -o ${CMCIResponseFile}
rc=$?
#echo rc: ${rc}


if [ $? -gt 0 ]; then
        exit 1

else
        xsltproc ${xsltFile} ${CMCIResponseFile} | jq . -c >> ${outputFile}
        echo ${nextDateTime} > ${tempFile}
fi
```

SYSLOG取り込みと同じような仕様にしています。
前回実行時のタイムスタンプを保持しておき、その時刻から現在時刻までの範囲のデータを取得し、結果(JSON形式)をLinux上のテキストファイルに保存します。
ヒストリカルデータのタイムスタンプはUTCで記録されていたので、シェル・スクリプトの先頭でTimeZoneをUTCに設定しています。
xsltprocで生成されるJSONデータは改行が含まれる形式になっているので、Logstashで取り込みやすいように、jqコマンドを使って1行1レコードに整形してファイルに格納するようにしています。

結果は以下のような形式で保存されます。

```text:/var/log/cics_historicalData/cics_c71plx_yyyymmdd.txt
{"cics_region":"CT54D4A1","tranid":"CWBG","cputime":"0000:00:00.000211","cputime_sec":0.000211,"resptime":"0000:00:00.000684","resptime_sec":0.000684,"start":"2019-04-15T00:27:46.580691+00:00","stop":"2019-04-15T00:27:46.581376+00:00"}
{"cics_region":"CT54D4A1","tranid":"CWBG","cputime":"0000:00:00.000201","cputime_sec":0.000201,"resptime":"0000:00:00.000410","resptime_sec":0.00041,"start":"2019-04-15T01:27:46.604214+00:00","stop":"2019-04-15T01:27:46.604625+00:00"}
{"cics_region":"CT54D4A1","tranid":"COHT","cputime":"0000:00:00.000357","cputime_sec":0.000357,"resptime":"0000:00:00.001048","resptime_sec":0.001048,"start":"2019-04-15T02:20:52.648337+00:00","stop":"2019-04-15T02:20:52.649385+00:00"}
{"cics_region":"CT54D4A1","tranid":"COHT","cputime":"0000:00:00.000375","cputime_sec":0.000375,"resptime":"0000:00:00.001161","resptime_sec":0.001161,"start":"2019-04-15T02:20:59.049773+00:00","stop":"2019-04-15T02:20:59.050935+00:00"}
{"cics_region":"CT54D4A1","tranid":"CWBG","cputime":"0000:00:00.000195","cputime_sec":0.000195,"resptime":"0000:00:00.000670","resptime_sec":0.00067,"start":"2019-04-15T02:27:46.627707+00:00","stop":"2019-04-15T02:27:46.628377+00:00"}
...
```

適当な間隔でこのシェル・スクリプトを実行すれば、その都度、前回取得したタイミングから最新の情報を取り込むことができます。
cronなどで定期的に実行する想定です。


## LogstashによるElasticsearchへのデータ取り込み
下準備が整いましたので、JSON形式で保存されたファイルをLogstash経由でElasticsearchに取り込みます。

1次加工でJSON形式にまでしてるので、ここは割りとシンプルにできます。
Logstashの構成ファイルはこんな感じ。

```conf:cics_hist_c71plx.conf
input {
        file{
                #path => ["/home/taguchi/CMCI/cmci_json.txt"]
                path => ["/var/log/cics_historicalData/*.txt"]
                start_position => "beginning"
                sincedb_path => "/var/log/cics_historicalData/temp.sincedb"
                codec => "json"
        }
}

filter{
        date{
                match => ["start", "ISO8601"]
                target =>  "@timestamp"
                remove_field => ["path", "@version", "host"]
        }
        date{
                match => ["stop", "ISO8601"]
                target => "stop_time"
        }

}


#output {
#  stdout { codec => rubydebug }
#}

output{
        elasticsearch{
                hosts => ["http://localhost:9200"]
                index => "cics-hist-c71plx-%{+YYYY.MM.dd}"
        }
}
```

ヒストリカルデータで取得されたstart(タスクの起動時刻)を、Elasticsearchに取り込む際の`@timestamp`として認識させます。
stop(タスクの終了時刻)も一応date型に変換して別フィールドとして作成しておきます。
ちなみに、このタイムスタンプはミリ秒単位でしか情報を保持できないらしく、それ以下はまるめられてしまうようです。そのため、元のフィールドも残しておくようにしました。

これで、Elasticsearch上にcics-hist-c71plx-yyyy.mm.ddというインデックスに取り込まれます！

ちなみに、CMCIで情報を取得する際に指定している STARTDATE,STARTTIME / ENDDATE,ENDTIME についてですが、START～ENDで指定した範囲に**完了した**タスクの情報が取得されます。つまりタスク終了時刻が基点になっています。
一方でElasticsearchに取り込む際のタイムスタンプはタスク開始時としています。
パフォーマンスデータはタスク終了時に書き込まれるので、ロングランニングのタスクがあった場合は取り込まれるタイミグが遅くなる(当然のことながらタスク完了後)のでご注意を。


## Kibanaで可視化
とりあえずインデックスパターン作って、Discoverで見てみると、ヒストグラムでトランザクションのレートが分かりますし、どのトランザクションの使用率が高いか、みたいなものがすぐ分かりますね！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/eb94bd2a-0052-61c4-859b-2bb4313803cd.png)

今回、cpu timeとresponse timeの情報を取っているので、その辺をグラフ化してみると...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/2d137789-ddf7-9a81-38c3-ba98e94424cf.png)

トランザクション毎の、CPU timeの平均値推移、Response timeの平均値推移、実行件数の推移、を時系列のグラフにして、表で各フィールドの平均、最大を出しています。
こういうのはサクッとできますね。

他にもヒストリカルデータで取得できる値は沢山あるので、xsltの部分をカスタマイズしてあげれば、追加で情報を取り込んで、より詳しい分析もできると思います。