【IRIS】【計測関連】ライセンスの使用量を計測しよう

本記事は、計測シリーズとして「ライセンスの使用量」に関するデータの収集について解説します。

※この記事は下記の方向けになります。
  • ライセンスの使用量について調査方法を探している方
  • どのタイミングでライセンスが消費されているか確認したい方
  • ライセンス購入数を把握したい方

はじめに

ライセンス数の計測として、下記3種の方法を解説したいと思います。

  1. messages.logにライセンスログイン・ログアウトを出力させる
  2. 定期的にライセンス使用量を記録する
  3. 履歴モニタを使用する

では、確認していきます。

messages.logにライセンスログイン・ログアウトを出力させる

ネームスペースは問わず、下記コマンドを実行する事で、ライセンスのログイン/ログアウトがmessage.logに出力します。

■開始

d traceon^%SYS.LICENSE

■停止

d traceoff^%SYS.LICENSE

では、どのように出力されるか確認します。
 ※ 日時は省略しています

ターミナル

略) 0 [Generic.Event] LicenseTrace: Login, Role = User, UserId = 127.0.0.1, Routine = , Result = 1
略) 0 [Generic.Event] LicenseTrace: Logout, Role = User, UserId = 127.0.0.1, Routine = HALT, Result = 1

管理ポータル

略) 0 [Generic.Event] LicenseTrace: Login, Role = CSP, UserId = _SYSTEM@127.0.0.1, Routine = %SYS.cspServer, Result = 1
略) 0 [Generic.Event] LicenseTrace: Logout, Role = CSP, UserId = _SYSTEM@127.0.0.1, Routine = %SYS.cspServer, Result = 1

VS Code

■ログイン時

略) 0 [Utility.Event] LicenseTrace: Get peer from header, HTTP_FORWARDED='', HTTP_X_FORWARDED_FOR='', REMOTE_ADDR='127.0.0.1'
略) 0 [Utility.Event] LicenseTrace: Requesting CSP license, Id='_SYSTEM@127.0.0.1', Process Session = 'nlrsF5DMCD', $USERNAME=CSPSystem, peer=127.0.0.1, SOAP.WebService=0.
略) 0 [Generic.Event] LicenseTrace: Login, Role = CSP, UserId = _SYSTEM@127.0.0.1, Routine = %SYS.cspServer, Result = 2
略) 0 [Utility.Event] LicenseTrace: Get peer from header, HTTP_FORWARDED='', HTTP_X_FORWARDED_FOR='', REMOTE_ADDR='127.0.0.1'
略) 0 [Utility.Event] LicenseTrace: Requesting CSP license, Id='_SYSTEM@127.0.0.1', Process Session = 'TtaNdATA4T', $USERNAME=CSPSystem, peer=127.0.0.1, SOAP.WebService=0.
略) 0 [Generic.Event] LicenseTrace: Login, Role = CSP, UserId = _SYSTEM@127.0.0.1, Routine = %SYS.cspServer, Result = 3
略) 0 [Generic.Event] LicenseTrace: Logout, Role = CSP, UserId = _SYSTEM@127.0.0.1, Routine = %SYS.cspServer, Result = 1
略) 0 [Utility.Event] LicenseTrace: Get peer from header, HTTP_FORWARDED='', HTTP_X_FORWARDED_FOR='', REMOTE_ADDR='127.0.0.1'
略) 0 [Utility.Event] LicenseTrace: Requesting CSP license, Id='_SYSTEM@127.0.0.1', Process Session = 'a1x8qkvgxv', $USERNAME=CSPSystem, peer=127.0.0.1, SOAP.WebService=0.
略) 0 [Generic.Event] LicenseTrace: Login, Role = CSP, UserId = _SYSTEM@127.0.0.1, Routine = %SYS.cspServer, Result = 3

■ログアウト時

略) 0 [Generic.Event] LicenseTrace: Logout, Role = CSP, UserId = _SYSTEM@127.0.0.1, Routine = %SYS.cspServer, Result = 1

RESTサービス

■UseSession=1で、ライセンス・ログインを行った場合
 → sessionID = 7Mmds4M9SM, ライセンスユーザ = sample

略) 0 [Utility.Event] LicenseTrace: Logout, Role = CSP, UserId = sample@127.0.0.1, Routine = %SYS.cspServer, Result = 1...(repeated 1 times)
略) 0 [Utility.Event] LicenseTrace: Get peer from header, HTTP_FORWARDED='', HTTP_X_FORWARDED_FOR='', REMOTE_ADDR='::1'
略) 0 [Utility.Event] LicenseTrace: Requesting CSP license, Id='7Mmds4M9SM', Process Session = '7Mmds4M9SM', $USERNAME=CSPSystem, peer=127.0.0.1, SOAP.WebService=0.
略) 0 [Generic.Event] LicenseTrace: Login, Role = CSP, UserId = 7Mmds4M9SM, Routine = %SYS.cspServer, Result = 1
略) 0 [Utility.Event] LicenseTrace: Get peer from header, HTTP_FORWARDED='', HTTP_X_FORWARDED_FOR='', REMOTE_ADDR='::1'
略) 0 [Utility.Event] TradeLicense: CSP relogin, new Id='sample@127.0.0.1', old Id='7Mmds4M9SM', Process Session = '7Mmds4M9SM', SOAPRequestCount = 1.
略) 0 [Generic.Event] LicenseTrace: Logout, Role = CSP, UserId = 7Mmds4M9SM, Routine = %SYS.cspServer, Result = 1
略) 0 [Generic.Event] LicenseTrace: Login, Role = CSP, UserId = sample@127.0.0.1, Routine = %SYS.cspServer, Result = 1
略) 0 [Generic.Event] LicenseTrace: Logout, Role = CSP, UserId = sample@127.0.0.1, Routine = %SYS.cspServer, Result = 1

■UseSession=0で、ライセンス・ログインを行った場合
 → sessionID = q2mibupMCp, ライセンスユーザ = sample

略) 0 [Utility.Event] LicenseTrace: Logout, Role = CSP, UserId = sample@127.0.0.1, Routine = %SYS.cspServer, Result = 1...(repeated 1 times)
略) 0 [Utility.Event] LicenseTrace: Get peer from header, HTTP_FORWARDED='', HTTP_X_FORWARDED_FOR='', REMOTE_ADDR='::1'
略) 0 [Utility.Event] LicenseTrace: Requesting CSP license, Id='q2mibupMCp', Process Session = 'q2mibupMCp', $USERNAME=CSPSystem, peer=127.0.0.1, SOAP.WebService=0.
略) 0 [Generic.Event] LicenseTrace: Login, Role = CSP, UserId = q2mibupMCp, Routine = %SYS.cspServer, Result = 1
略) 0 [Generic.Event] LicenseTrace: Logout, Role = CSP, UserId = q2mibupMCp, Routine = %SYS.cspServer, Result = 1
略) 0 [Utility.Event] LicenseTrace: Get peer from header, HTTP_FORWARDED='', HTTP_X_FORWARDED_FOR='', REMOTE_ADDR='::1'
略) 0 [Utility.Event] TradeLicense: Requesting CSP license for UserName='sample@127.0.0.1', Process Session = 'q2mibupMCp', $USERNAME=UnknownUser.
略) 0 [Generic.Event] LicenseTrace: Login, Role = CSP, UserId = sample@127.0.0.1, Routine = %SYS.cspServer, Result = 1
略) 0 [Generic.Event] LicenseTrace: Logout, Role = CSP, UserId = q2mibupMCp, Routine = %SYS.cspServer, Result = 1
略) 0 [Generic.Event] LicenseTrace: Logout, Role = CSP, UserId = sample@127.0.0.1, Routine = %SYS.cspServer, Result = 1\

■UseSession=1で、ライセンス・ログインを行わなかった場合
 → sessionID = m24fJTk9Sk

略) 0 [Utility.Event] LicenseTrace: Get peer from header, HTTP_FORWARDED='', HTTP_X_FORWARDED_FOR='', REMOTE_ADDR='::1'
略) 0 [Utility.Event] LicenseTrace: Requesting CSP license, Id='m24fJTk9Sk', Process Session = 'm24fJTk9Sk', $USERNAME=CSPSystem, peer=127.0.0.1, SOAP.WebService=0.
略) 0 [Generic.Event] LicenseTrace: Login, Role = CSP, UserId = m24fJTk9Sk, Routine = %SYS.cspServer, Result = 1

ログインしっぱなしのため、「Logout」のログがない

■UseSession=0で、ライセンス・ログインを行わなかった場合
 → sessionID = KDzMXR99S9

略) 0 [Utility.Event] LicenseTrace: Get peer from header, HTTP_FORWARDED='', HTTP_X_FORWARDED_FOR='', REMOTE_ADDR='::1'
略) 0 [Utility.Event] LicenseTrace: Requesting CSP license, Id='KDzMXR99S9', Process Session = 'KDzMXR99S9', $USERNAME=CSPSystem, peer=127.0.0.1, SOAP.WebService=0.
略) 0 [Generic.Event] LicenseTrace: Login, Role = CSP, UserId = KDzMXR99S9, Routine = %SYS.cspServer, Result = 1
略) 0 [Generic.Event] LicenseTrace: Logout, Role = CSP, UserId = KDzMXR99S9, Routine = %SYS.cspServer, Result = 1

定期的にライセンス使用量を記録する

定期的にライセンスを管理しているクラス「%SYSTEM.License」から、SQLを利用してライセンス情報を取得します。

■サンプルPG
 取得したライセンス情報を、永続クラス「developer.LicenseData」に保存しています。

ClassMethod list(hangTime As %Double = 0.1)
{
	s ns = $namespace // 実行ネームスペース
	try {
		f {
			new $namespace
			s $namespace = "%SYS"

			s rs = ##class(%Library.ResultSet).%New("%SYSTEM.License:UserListAll")
			d rs.Execute()
			while (rs.Next()) {
				s userId = rs.Get("UserId")
				
				// データの登録
				s $namespace = ns
				s obj = ##class(developer.LicenseData).%New(
					userId,
					rs.Get("Type"), // ログインタイプ
					rs.Get("Connects"), // 接続数
					rs.Get("MaxCon"), // 最大接続数
					rs.Get("CSPCon"), // CSPセッション数
					rs.Get("LU"), // ライセンス数
					rs.Get("Active"), // 接続時間(秒)
					rs.Get("Grace") // グレースピリオド(秒)
				)
				$$$ThrowOnError(obj.%Save())
			}		
			
			h hangTime
		}
	} catch e {
		w !,$system.Status.DisplayError(e.AsStatus())
	}
}

■永続クラス

Class developer.LicenseData Extends %Persistent
{

/*-- インデックス --*/
Index prim On (UserId, dateTimePix) [ PrimaryKey ];

Index idxUserId On UserId [ Type = bitmap ];

Index idxDateTime On dateTimePix [ Type = bitslice ];

/*-- プロパティ --*/
/// 日時(%PosixTime)
Property dateTimePix As %PosixTime [ InitialExpression = {##class(%PosixTime).CurrentTimeStamp()}, ReadOnly, Required, SqlColumnNumber = 2 ];

/// 日時
Property dateTime As %TimeStamp [ Calculated, SqlColumnNumber = 3, SqlComputeCode = {s {*} = ##class(%PosixTime).LogicalToTimeStamp({dateTimePix}) }, SqlComputed ];

/// ライセンスログインユーザーID
Property UserId As %String [ SqlColumnNumber = 4 ];

/// ログインタイプ
Property Type As %String(VALUELIST = ",User,CSP,Mixed,Grace") [ SqlColumnNumber = 5 ];

/// UserId毎のインスタンス接続数
Property Connects As %Integer [ SqlColumnNumber = 6 ];

/// UserId毎のインスタンス最大同時接続数
Property MaxCon As %Integer [ SqlColumnNumber = 7 ];

/// UserId毎のインスタンスに対するCSPセッション数
Property CSPCon As %Integer [ SqlColumnNumber = 8 ];

/// UserId毎の消費しているライセンス数
Property LU As %Integer [ SqlColumnNumber = 9 ];

/// UserId毎のログイン秒数
Property Active As %Integer [ SqlColumnNumber = 10 ];

/// 全接続が切断された時の猶予期間
Property Grace As %Integer [ SqlColumnNumber = 11 ];

Method %OnNew(UserId As %String, Type As %String, Connects As %Integer, MaxCon As %Integer, CSPCon As %Integer, LU As %Integer, Active As %Integer, Grace As %Integer) As %Status [ Private, ServerOnly = 1 ]
{
	s i%UserId = UserId
	, i%Type = Type
	, i%Connects = Connects
	, i%MaxCon = MaxCon
	, i%CSPCon = CSPCon
	, i%LU = LU
	, i%Active = Active
	, i%Grace = Grace
	q $$$OK
}
}

では、1秒間隔でロギングを行う為、下記コマンドをターミナルで実行します。

w ##class(developer.LicenseData).%KillExtent()
d ##class(developer.Survey).list(1)

では、RESTサービスを使用して、ライセンスの消費を確認してみます。
 → 処理に11秒かかる関数を、RESTサービス内で実行しています。

■UseSession = 1

■UseSession = 0

クラス「%SYSTEM.License」は、管理ポータルの[ライセンス使用量]で見た事があるデータを取得する関数等があります。

機会があれば、そちらの解説も行いたいと思います。

履歴モニタを使用する

履歴モニタを利用し、ライセンスを一定期間の間監視します。

結果を確認する

先ずは、どのよのような結果が取得できるか確認してみましょう。

■クラス「SYS.History.SysData」

ライセンス関連で言えば、下記2プロパティになります。

プロパティ説明
LicUsedDist現在使用中のライセンス数(リモート)
LicUsedLocal現在使用中のライセンス数(ローカル)

長期間のサンプリングを行うときに役に立つ設定ですね。

設定方法

ターミナルを起動し、ネームスペース「%SYS」に変更し、下記コマンドを入力します。

zn "%SYS"
d ^%SYSMONMGR

「5) Manage Application Monitor」を選択

1) Start/Stop System Monitor
2) Set System Monitor Options
3) Configure System Monitor Classes
4) View System Monitor State
5) Manage Application Monitor
6) Manage Health Monitor
7) View System Data
8) Exit
 
Option? 5

「2) Manage Monitor Classes」を選択

1) Set Sample Interval
2) Manage Monitor Classes
3) Change Default Notification Method
4) Manage Email Options
5) Manage Alerts
6) Exit
 
Option? 2

監視対象のクラスをアクティベートします。

1) Activate/Deactivate Monitor Class
2) List Monitor Classes
3) Register Monitor System Classes
4) Remove/Purge Monitor Class
5) Set Class Sample Interval
6) Debug Monitor Classes
7) Exit
 
Option? 1

対象クラスの番号が分からないので「?」を入力し、対象のクラスを表示させます。

Class? ?

クラス名と対象番号が表示されます。

今回の対象クラスは「3) %Monitor.System.HistorySys」です。

 Num  MetricsClassName               Activated
  1)  %Monitor.System.HistoryMemory  N
  2)  %Monitor.System.HistoryPerf    N
  3)  %Monitor.System.HistorySys     N
  4)  %Monitor.System.HistoryUser    N
  5)  %Monitor.System.AuditCount     N
  6)  %Monitor.System.AuditEvents    N
  7)  %Monitor.System.Clients        N
  8)  %Monitor.System.Diskspace      N
  9)  %Monitor.System.Freespace      N
 10)  %Monitor.System.Globals        N
 11)  %Monitor.System.Journals       N
 12)  %Monitor.System.License        N
 13)  %Monitor.System.LockTable      N
 14)  %Monitor.System.Processes      N
 15)  %Monitor.System.Routines       N
 16)  %Monitor.System.Servers        N
 17)  %Monitor.System.CSPGateway     N
 
Class?

「3」を入力後、アクティベートの確認で「y or yes」を入力します。

Class? 3 %Monitor.System.HistorySys
Activate class? Yes => yes

監視の間隔は、初期値で5分間隔となっています。
必要があれば変更します。

「5) Set Class Sample Interval」を選択します。

1) Activate/Deactivate Monitor Class
2) List Monitor Classes
3) Register Monitor System Classes
4) Remove/Purge Monitor Class
5) Set Class Sample Interval
6) Debug Monitor Classes
7) Exit
 
Option? 5

対象のクラス名を確認してくるので「3」を入力後、監視間隔(秒数)を入力します。

Class? 3 %Monitor.System.HistorySys
Class Sample Interval? 0 (Enter '-' to reset) => 30

必要があれば、設定を確認します。

1) Activate/Deactivate Monitor Class
2) List Monitor Classes
3) Register Monitor System Classes
4) Remove/Purge Monitor Class
5) Set Class Sample Interval
6) Debug Monitor Classes
7) Exit
 
Option? 2
Class                                   Active  SampleInterval
-----                                   ------  --------------
%Monitor.System.HistoryMemory           N       default
%Monitor.System.HistoryPerf             N       default
%Monitor.System.HistorySys              Y       30
%Monitor.System.HistoryUser             N       default
%Monitor.System.AuditCount              N       default
%Monitor.System.AuditEvents             N       default
%Monitor.System.Clients                 N       default
%Monitor.System.Diskspace               N       default
%Monitor.System.Freespace               N       default
%Monitor.System.Globals                 N       default
%Monitor.System.Journals                N       default
%Monitor.System.License                 N       default
%Monitor.System.LockTable               N       default
%Monitor.System.Processes               N       default
%Monitor.System.Routines                N       default
%Monitor.System.Servers                 N       default
%Monitor.System.CSPGateway              N       default

設定内容に問題が無ければ、Enterを押して監視モニタの開始/停止の選択肢が表示されるまで戻ります。

1) Activate/Deactivate Monitor Class
2) List Monitor Classes
3) Register Monitor System Classes
4) Remove/Purge Monitor Class
5) Set Class Sample Interval
6) Debug Monitor Classes
7) Exit
 
Option?
 
1) Set Sample Interval
2) Manage Monitor Classes
3) Change Default Notification Method
4) Manage Email Options
5) Manage Alerts
6) Exit
 
Option?
 
1) Start/Stop System Monitor
2) Set System Monitor Options
3) Configure System Monitor Classes
4) View System Monitor State
5) Manage Application Monitor
6) Manage Health Monitor
7) View System Data
8) Exit
 
Option?

監視モニタを開始します。

「1) Start/Stop System Monitor」を選択します。

1) Start/Stop System Monitor
2) Set System Monitor Options
3) Configure System Monitor Classes
4) View System Monitor State
5) Manage Application Monitor
6) Manage Health Monitor
7) View System Data
8) Exit
 
Option? 1

監視モニタを再起動させるため、「stop」→「start」の順に選択します。

1) Start System Monitor
2) Stop System Monitor
3) Exit
 
Option? 2
 
Stopping System Monitor... System Monitor not running!
 
1) Start System Monitor
2) Stop System Monitor
3) Exit
 
Option? 1
 
Starting System Monitor... System Monitor started

設定は以上になります。

監視モニタは、色々なデータを収集する事が可能です。
こちらも機会があれば、解説したいと思います。

おわりに

本記事では、IRISのライセンス使用量を把握するための3つの計測方法をご紹介しました。

ライセンスは一度枯渇すると業務影響が大きい領域だからこそ、「今どれだけ使っている?」を把握する仕組み作りが重要だと思います。

今回紹介した方法がみなさまの監視改善やコスト最適化の一助になれば嬉しいです。
気づきや追加の知見があれば、ぜひコメントで共有してください!