【OutSystems】サーバー現在時刻をマイクロ秒単位で取得しよう!

ババーンと推参!
勇気無限大ミスターEです。

今回はナレッジ君で開発部内で共有されていた
サーバー現在時刻をマイクロ秒単位で取得についてご説明したいと思います!

ナレッジ君へ共有していただいたのは前回も紹介した

とある金色のKさん

以下、ナレッジ君で共有された内容

1. はじめに

皆さんはサーバーアクションの処理時間の調査方法をご存じですか?
基本的にはAggregate/サーバーアクションの処理速度に関してはスクリーンからの通信開始時刻・通信完了時刻を確認できるScreen Requestを確認するだけで十分です
↓Service Center > Monitering > Screen Reques

しかし極まれに遅いロジックの調査をする場合に、サーバーアクション内の一定区間の処理時間が欲しいといった場面に出くわすことがあります。
ただ自分が調べた範囲ですと、現在OutSystems公式ではサーバーアクション内で処理を分割して個別に時間を計測する方法は用意されていません!
OutSystemsに限らず、プログラムの処理時間を取得する際には基本的に計測区間の前後の現在時刻を取得し、その差分を取ることで計測します。

この際ロジックは基本ミリ秒単位で処理されていくので時刻をミリ秒単位で取得するのが一般的ですが、OutSystemsが用意している基本型のTimeは秒単位でしか情報を保持してくれません(OutSystems公式Function:DiffDays()の説明には「ミリ秒」の情報を持っている可能性を示唆する記載があったりしますが)

これは非常に困ったことでして、ミリ秒の現在時刻を得るためにはミリ秒まで取得できるForge(参考ナレッジ:ミリ秒単位でロジックの処理時間計測を行いログ出力する方法)を使用したりIntegration StudioでC#のミリ秒取得アクションを作成したりする必要が出てきます。
今回はそういった案件によっては使用できない可能性がある処理に頼らず、ServiceStudioだけでミリ秒単位でサーバー時間を取得する方法をお伝えします。
ミリ秒じゃ足りない、、、マイクロ秒まで欲しい!という人も必見!!

【使うのはズバリ!データベースサーバーの時間】
タイトルがそのまま答えとなっていますが、
サーバーの時間を取得できるのは何もOutSystemsのアプリケーション実行サーバーからだけではありません。
データベースもまた、当然の様にサーバー時間を持っています。
そしてデータベースからはSQLを記述することで、ミリ秒だけでなくマイクロ秒単位での取得が可能となっています(データベースの設定によってはナノ秒[小数桁9桁]まで取得できたりします)
そんなSQLを使ってミリ秒/マイクロ秒を取得しよう!というのが今回紹介する方法です。

【用意するデータ】
SQLを記述する際、必要なのがOutputParameterとなるStructure及びEntity(Oracleでは必須)になります。
それぞれ下記のデータ型で作成しましょう!
Structure「TimeWithMilliSecond」
Time : Time型
MilliSecond:Integer型

Structure「TimeWithMicroSecond」
Time : Time型
MicroSecond:Integer型

StaticEntity「TimeStamp」<Record数1>
 – id
 – Is_Active


※Entity内のデータ取得はしないので、Record数が少ないStaticEntityがあるならそちらを使っても問題ないです!

【SQL文】
ミリ秒取得
[SQL Server] SELECT FORMAT(SYSDATETIME(), ‘HH:mm:ss’), DATEPART(millisecond, SYSDATETIME())
[Oracle DB]  SELECT TO_CHAR(SYSTIMESTAMP, ‘HH24:MI:SS’), TO_CHAR(SYSTIMESTAMP, ‘ff3’) FROM {TimeStamp}

マイクロ秒取得
[SQL Server] SELECT FORMAT(SYSDATETIME(), ‘HH:mm:ss’), DATEPART(microsecond, SYSDATETIME())
[Oracle DB]  SELECT TO_CHAR(SYSTIMESTAMP, ‘HH24:MI:SS’), TO_CHAR(SYSTIMESTAMP, ‘ff6’) FROM {TimeStamp}

[SQL Server]
参考①:SQL Server – 現在のシステム日時・年月日・時刻を取得する
参考②:SQL Server – DateTime型から年月日時分秒を数値で取り出す

[Oracle DB] 
参考①:Oracle「SysTimeStamp」
参考②:【Oracke】SYSTIMESTAMPを使ってミリ秒以下を表示する

これらのSQLを記載することでミリ秒/マイクロ秒単位でのサーバー時間を取得できます!
また全てサーバー内の処理なので、Functionとして実装できます。
注意点としてはそれぞれミリ秒/マイクロ秒での取得になるので、差分を取る際は秒との桁数差はしっかりと意識してください。
※差分の式はそれぞれ下記
ミリ秒:DiffSecond(Start.Time, End.Time) * 1000 + End.MilliSecond – Start.MilliSecond
マイクロ秒:DiffSecond(Start.Time, End.Time) * 1000000 + End.MicroSecond – Start.MicroSecond

2. さいごに

実はこの方法はサーバーとデータベース間で通信が発生するので、別途時間取得アクションを使用する回数分呼び出すことで、呼び出し時間を計測する必要があります。

特に苦も無く使用できるのであれば、ミリ秒まで取得できるForgeを使用したりIntegration Studioで
C#のミリ秒取得アクションを作成した方が良いと思います。

ただForgeを使用するのに許可が必要だったり、Visual Studioを契約していないため自分でC#アクションを作れなかったりする場合も当然ありえるかと思われますので、そういった場合に必要となればOutSystems内の実装だけで取得できるこの手法を使うことを検討してみてはいかがでしょうか?

3. 補足

補足①
この手法を用いて調査した5000件エクセル取り込みの時間(2分でタイムアウトする原因調査)
・5000件分のデータ転送(サーバー処理開始までの時間) (約13秒)
・処理用データ作成(約0.3秒)
・バリデーションチェック(約15秒)
・計算項目計算処理(約5秒)
・更新確認処理(約7秒)
・CreateOrUpdateによる登録/更新処理(約70秒)
※タイムスタンプ取得処理<20000回>(約9秒)

恐らく129カラム(3カラムはText1000文字)のビッグEntityだという理由もあるとは思いますが、
5000件にもなるとただのCreateOrUpdateの登録/更新処理にもの凄く時間がかかることがよく分かりますね!
エクセル取り込みを行う際は、まず件数を聞くようにしましょう!

バッチ処理の方が良いのにオンライン処理で実装すると、色々と後々大変です!

補足②
ODC(OutSystems Developer Cloud)では待望のDate Time型がもつ秒以下のデータを取得するアクションが追加されました!
その名もGetTicks関数です!
なんと100ナノ秒単位で取得できます!!(1秒の1000万分の1単位)
詳しくはOutSystems公式ドキュメント「Date Time型(ODC)」をご覧ください

  • URLをコピーしました!
目次