検索

クリアフィルター
記事
Mihoko Iijima · 2020年10月27日

【はじめてのInterSystems IRIS】Interoperability(相互運用性)を使ってみよう!

皆さん、こんにちは! InterSystems IRIS には [Interoperability(相互運用性)]というメニューがあります。 このメニューには、システム統合を簡単に作成できる仕組み(アダプタ、レコードマップ、BPM、データ変換など)が用意されていて、異なるシステムを簡単に接続することができます。 例えば、普段繋がっていないシステムを繋げるために相手の仕様に合わせてデータを受信(または送信)したり、データ送信前に別システムから情報を取得して追加したり、データベース(IRIS でもそれ以外でも)から情報を取得したり更新したり、データ中継の流れの中に様々な処理を含むことができます。 この記事のシリーズでは、Interoperability(相互運用性)でシステム統合を行う際、どのような仕組みで動作するのか、またどのような開発が必要になってくるのか、をご理解いただくためにサンプルコードをご覧いただきながら以下の項目を解説します。 動作の仕組み プロダクションとは メッセージ コンポーネントの作成 ビジネス・オペレーション ビジネス・プロセス ビジネス・サービス まずはこのシリーズで使用するテーマをご紹介します。 ショッピングサイトを運営している会社があり、季節に合わせ商品情報の表示順を変更する作業を行っています。ところが、季節を問わず良く売れるもの、想定しなかった時期に売れるものもあり、現在の表示順変更ルールにうまく合いません。そこで、季節に合わせた表示順ではなく、そのときの気温にあわせた表示順に変更できないか検討した結果、購入物品に対してそのときの気温を調査する必要が出てきました。気象情報の確認には、外部の Web API が利用できるため、購入されたタイミングで気象情報を収集し、後で確認できるようにデータベースに情報を登録していく予定です。 とても簡単な内容ですが、「外部の Web API」を利用して情報収集する必要があるのと、取得できた情報と購入情報をデータベースに登録する作業をひとまとめにする必要があります。 具体的な方法は関連記事に続きます(Webサイトの作成は含みません)。ぜひご参照ください! さて、今回利用している「外部の Web API」ですが、OpenWether の Current weather data を使用しています。 (実際お試しになる場合は、アカウント登録を行い、APIIDを取得する必要があります。) REST クライアントから GET 要求を行った結果は以下の通りです(この内容を Interoperability で実装する仕組みの中で実行していく予定です)。 HTTP 応答の JSON は以下の通りです。 { "coord": { "lon": 138.1, "lat": 36.64 }, "weather": [ { "id": 801, "main": "Clouds", "description": "薄い雲", "icon": "02d" } ], "base": "stations", "main": { "temp": 10.12, "feels_like": 9.1, "temp_min": 8.33, "temp_max": 11.67, "pressure": 1013, "humidity": 86 }, "visibility": 10000, "wind": { "speed": 0.76, "deg": 233 }, "clouds": { "all": 24 }, "dt": 1603584269, "sys": { "type": 3, "id": 19237, "country": "JP", "sunrise": 1603573442, "sunset": 1603612743 }, "timezone": 32400, "id": 1856215, "name": "Nagano", "cod": 200} 次の記事では、Interoperability(相互運用性) メニューを利用してシステム統合を行う際、どのような仕組みで動作しているのか について解説します。
記事
Mihoko Iijima · 2020年10月27日

【はじめてのInterSystems IRIS】Interoperability(相互運用性):コンポーネントの作成(ビジネス・サービス)

この記事はこちらの投稿の続きの内容です。 前回の記事では、システム統合に必要なコンポーネントの中から、プロダクション内の処理の調整役となるビジネス・プロセスの作成について解説しました。 今回の記事では、プロダクションの情報入力窓口である、ビジネス・サービスの作成について解説します。 プロダクション メッセージ コンポーネント ビジネス・サービス ビジネス・プロセス(前回の記事) ビジネス・オペレーション いよいよ「Interoperability(相互運用性)を使ってみよう!」の最後のコンポーネントです。 ビジネス・サービスは、IRIS 外部からの送信される情報の入力窓口で、外部 I/F に対してアダプタを使用する/しないを選択できます。 サンプルでは、3 種類のビジネス・サービスを用意しています(括弧内のリンクはサンプルコードへのリンク)。 ファイルインバウンドアダプタを利用したファイル用ビジネス・サービス(Start.FileBS) SOAP インバウンドアダプタを利用する Web サービス用ビジネス・サービス(Start.WS.WebServiceBS) アダプタを使用せず、ストアドプロシージャや REST で呼び出されるビジネス・サービス(Start.NonAdapterBS) 情報入力に使用する接続方法が異なるだけ、ビジネス・サービス数が増えますが、ビジネス・サービス内で行う処理は 外部から入力された情報を利用して、送信する要求メッセージを作成し、ビジネス・コンポーネント を呼び出すだけ とてもシンプルです。 それでは、ファイルインバウンドアダプタを使用するコンポーネントから作成方法概要を説明します。 ビジネス・サービスはスクリプトを記述するので、VSCode かスタジオで作成します(VSCodeの使い方についてはこちらの記事もご参照ください。)。 1、ファイルインバウンドアダプタを利用したファイル用ビジネス・サービス(Start.FileBS) VSCode で作成する場合は、Ens.BusinessService を継承するクラスを作成します。アダプタについては、使用する場合は、以下のように ADAPTER パラメータにアダプタクラス名をしています(例はファイルインバウンドアダプタのクラスを指定しています)。アダプタを使用しない場合は、設定は不要です。 Class Start.FileBS Extends Ens.BusinessService { Parameter ADAPTER = "EnsLib.File.InboundAdapter"; ファイルインバウンドアダプタでは、監視対象ディレクトリの指定をプロダクションのビジネス・サービス用設定の「ファイル・パス」で指定できます。 「ファイル・パス」に置かれたファイルが「ファイル・スペック」に指定した情報と合致する場合、ファイルをストリームオブジェクトとしてオープンし、ビジネス・サービスの ProcessInput() を呼び出すときの第1引数に指定します。 ProcessInput() が起動すると自動的に OnProcessInput() が呼び出されます。この時、OnProcessInput() には、ProcessInput() で渡された引数がそのまま渡ります。 OnProcessInput() では、第1引数に渡されるファイルストリームオブジェクトから情報を取得し、次のコンポーネントへ渡すメッセージを作成し、次のコンポーネントを呼び出す処理を記述したら基本ロジックは終了です。 【メモ】スタジオの場合は、新規作成メニューのビジネス・サービスウィザードを起動し、アダプタを選択して完了ボタンを押下します。 OnProcessInput() のメソッド定義は以下の通りです。 Method OnProcessInput(pInput As %Stream.Object, Output pOutput As %RegisteredObject) As %Status pInput には、テキストファイルの場合 %Steam.FileCharacter クラス、バイナリファイルの場合 %Stream.FileBinary クラスのインスタンスが渡されます。 サンプルでは、テキスト形式のファイルが入力される予定で、1依頼1行として、複数行の依頼も受け付けるように記述しています。 End Of File を検知すると1を設定する AtEnd プロパティを利用してループ処理を行います。ループ内では、ファイルの中身を1行ずつ情報を取得できる ReadLine() メソッドを使い、行を読み取ります(ファイルアダプタ詳細は、ドキュメントをご参照ください)。 1行ずつ情報を取得しながらメッセージを作成し、他コンポーネントを呼び出す ..SendRequestAsync() メソッドを実行します。 メソッド実行時、第1引数に呼び出したいコンポーネント名を文字列で指定し、第2引数には作成した要求メッセージを指定します。なお、..SendRequestAsync()は非同期呼び出し のため、応答を待ちません。 メモ:同期呼び出し用に SendRequestSync() もあります。 サンプルコードは以下の通りです。 ご参考:上記例文中の $piece()関数の使い方の解説 $piece(“文字列”,”区切りマーク”,”ポジション番号”) 区切りマーク付き文字列の設定/取得が行える関数で、サンプルでは、カンマ区切りデータの1番目と2番目の値を取得するため、以下の構文で記述されています。 set request.Product=$piece(record,",",1) set request.Area=$piece(record,",",2) では、上記説明に登場した Start.FileBS の動作を確認します。 サンプルプロダクションでは「ファイル・パス」に /irisdev/src 「ファイル・スペック」に check.txt を指定しています。同じディレクトリをご用意いただくか、別ディレクトリに変更いただき、check.txtファイルに以下の形式(購入商品名,都市名)でサンプルデータを登録してください。 ※ サンプルのコンテナを利用されている場合は、git clone で作成したディレクトリ以下の src ディレクトリ以下にある [Test用-check.txt] をリネームしてご利用ください。 2、SOAP インバウンドアダプタを利用する Web サービス用ビジネス・サービス(Start.WS.WebServiceBS) つづいて、Web サービス用ビジネス・サービスの作成概要をご説明します。 Web サービス用ビジネス・サービスクラスは、Web サービス提供側= Web サービスサーバとして動作します。 サンプルでは、Web サービスクライアントから情報を送信してもらうため、今回のサンプルプロダクションに合わせて Web サービスメソッドに2つの引数を用意しています。Web メソッドでは、引数に入力された情報を利用してメッセージクラスを作成し、他コンポーネントを呼び出しています。 Web サービスクラスを定義するとテスト用画面が用意されますが、デフォルトでは表示しない設定になっています。 IRIS へログインし(またはターミナルを起動し)、プロダクションがあるネームスペースに移動して以下実行してください。 ご参考:https://docs.intersystems.com/irislatestj/csp/docbook/DocBook.UI.Page.cls?KEY=GSOAP_service_catalog_page 以下、サンプルコードの docker-compose up -d でコンテナを開始した環境での設定例です(%SYS ネームスペースで実行します)。 set $namespace="%SYS" set ^SYS("Security","CSP","AllowClass","/csp/user/","%SOAP.WebServiceInfo")=1 set ^SYS("Security","CSP","AllowClass","/csp/user/","%SOAP.WebServiceInvoke")=1 【注意】実行文には大文字小文字の区別がありますので、注意して記述してください。また、プロダクションを使用するネームスペースによって指定文字が変わります。例文はサンプルをUSERネームスペースへインポートした前提で記述しています。もし、サンプルコードをABCネームスペースにインポートしている場合は、第4番目の添え字は "/csp/abc/" を指定します。 設定が完了したら、以下の URL にアクセスします。 http://localhost:52773/csp/user/Start.WS.WebServiceBS.cls WSDL を Web サービスクライアントへ提示する場合は、以下のURLの末尾に WSDL=1 を指定してください。 http://localhost:52773/csp/user/Start.WS.WebServiceBS.cls?WSDL 3,アダプタを使用せず、ストアドプロシージャや REST で呼び出されるビジネス・サービス(Start.NonAdapterBS) 次は、アダプタを使用しないビジネス・サービス(Start.NonAdapterBS)をご紹介します。 アダプタを使用するビジネス・サービスでは、アダプタが情報を検知すると、ビジネス・サービスの ProcessInput() メソッドを呼び出します。 アダプタを使用しない場合も、ProcessInput() メソッドを呼び出せばいいのですが、このメソッドは外部公開していないため、アダプタを使用しないビジネス・サービスを実装する場合、ProcessInput()を実行するための方法を検討する必要があります。 サンプルでは、以下2種類の方法を利用しています。 ストアドプロシージャ(Start.Utilsクラス) REST 用ディスパッチクラス(Start.REST)→ こちらの記事で実行したサービスです。 では、ストアドプロシージャの例をご紹介します。 プロダクションにアダプタを使用しないビジネス・サービス(Start.NonAdapterBS)を追加した後で(サンプルでは追加済に状態)以下ストアドプロシージャを実行します。 call Start.Utils_CallProduction('うなぎ','浜松市') 実行結果のトレースは以下の通りです。 続いて、REST 用ディスパッチクラス作成例をご紹介します。 XData Url Map に定義されている XML は、REST 呼び出しのときの URL に対して、どのメソッドが呼び出されるかを定義しています。サンプルは、GET 要求で /weather/第1引数(購入商品名)/第2引数(都市名)の URL が渡されると、WeatherCheck() メソッドを呼び出す定義を記述しています。 <Route Url="/weather/:product/:arecode" Method="GET" Call="WeatherCheck"/> 後は、 上記 URL を指定するためのベース URL を管理ポータルのウェブアプリケーションパス設定画面で定義したら完成です。 設定詳細については、こちらの記事をご参照ください。 準備ができたら、REST で情報を送信できるビジネスサービスを利用して、情報を流してみます。 例)http://localhost:52773/start/weather/ちくわ/豊橋市 アダプタを使用しない場合、直接外部から ProcessInput() が呼び出せないため、REST やストアドプロシージャを通して実行されるロジックの中でビジネス・サービス用オブジェクトを生成し(Ens.Director クラスの CreateBusinessService() メソッドを使用) ProcessInput() を呼び出しました。 アダプタを使用する場合は、アダプタが入力を検知し専用オブジェクトに情報を格納しビジネス・サービスに渡してくれますが、アダプタを使わない場合、その部分だけが異なるだけで後の処理はほとんど一緒です。 ビジネス・サービスは、IRIS 外部から入力された情報を利用して要求メッセージを作成し、ビジネス・コンポーネントを呼び出すだけのシンプル設計です。 サンプルプロダクションを通して以下の内容が確認できました。 プロダクションを動作させるために役割が異なるコンポーネントがある(ビジネス・サービス、ビジネス・プロセス、ビジネス・オペレーション) コンポーネント間で情報を伝達するためには、メッセージを使用する メッセージは削除しない限りデータベースに保存されているので、いつでもトレースできる 接続周りの処理を簡単にしてくれるアダプタがある IRIS の Interoperability(相互運用性)の使い方についての基本操作は以上の通りです。 この他、CSVファイルなどの形式の決まったファイルの入出力に便利なレコードマップ(ご参考:FAQトピック)や、データ変換ツールなどもあります。また、このシリーズと同様にInteroperability を利用して InterSystems IRISでシンプルに開発するIoTアプリケーションの記事もあります。ぜひご参照ください。 この他、IRIS for Health では FHIR や HL7(SS-MIX2も含む)の送受信についてもサポートしています。 また別の記事でご説明できたらと思います。ご興味ある内容ありましたら、ぜひコメント欄にご記入ください! 最後に、Interoperability(相互運用性)の使い方についてはトレーニングコースもご用意しています。講師と一緒にじっくり試してみたい方は、ぜひトレーニングコースへのご参加もご検討ください!
お知らせ
Mihoko Iijima · 2022年6月24日

テクノロジーボーナス詳細:InterSystems Full Stack コンテスト 2022:気候変動問題に挑戦!

開発者の皆さん、こんにちは! Full Stackコンテスト 2022 のテクノロジーボーナスについてご紹介します!​​​​​ 気候変動問題に関係したもの - 5 isc.rest パッケージ - 2 isc.ipm.js パッケージ - 2 Embedded Python - 3 Adaptive Analytics (AtScale) キューブの使用 - 2 Docker コンテナの使用 - 2 ZPM パッケージのデプロイ - 2 オンラインデモの作成 - 2 ユニットテストの使用 - 2 コミュニティへの最初の記事の投稿 - 2 コミュニティへの2つ目の記事投稿 - 1 Code Quality をパスする - 1 YouTube にビデオを投稿する - 3 気候変動問題に関係したもの - 5 points あなたのソリューションが地球温暖化や気候変動問題への対策に役立つ内容である場合、ボーナスポイントを獲得できます。詳しくは27日(月)に開催される Climate Change Full Stack コンテストのキックオフで発表します。ぜひご参加ください。 isc.rest パッケージ - 2 points あなたの full-stack アプリケーションに isc-rest パッケージを使用するとボーナスポイントを獲得できます。使用方法については、isc-perf-ui application をご参照ください。 isc.ipm.js パッケージ - 2 points あなたの full-stack アプリケーションに isc-ipm-js を使用するとボーナスポイントを獲得できます。使用方法については、isc-perf-ui application をご参照ください。 Embedded Python - 3 points あなたのアプリケーションに Embedded Python を使用すると、追加のポイントを獲得できます。Embedded Python を使用される場合は、InterSystems IRIS 2021.2 以降をご利用ください。 Docker コンテナの使用 - 2 points あなたのアプリケーションに Docker コンテナ版 InterSystems IRIS を使用すると、ボーナスポイントを獲得できます。シンプルなテンプレートから利用を開始することができます。ぜひご利用ください。 ZPM パッケージのデプロイ - 2 points 以下のようにデプロイできる ZPM(InterSystems Package Manager)であなたのFull Stackアプリケーションを公開するとボーナスポイントを獲得できます。 zpm "install your-multi-model-solution" 上記コマンドをZPMクライアントがインストールされたIRISで実行します。 ZPM について/ZPM Documentatio オンラインデモ公開 - 2 points オンラインデモとしてアプリケーションをクラウドにプロビジョニングすると、ボーナスポイントを獲得できます。開発環境テンプレートやその他のデプロイメントオプションを使用することができます。例サンプルアプリケーションの使用方法についてはビデオをご参照くださ ユニットテスト- 2 points あなたのアプリケーションにInterSystems IRISのユニットテストを導入するとボーナスポイントを獲得できます。 ObjectScriptのユニットテスト使用方法については、ドキュメントやコミュニティの記事をご参照ください。 コミュニティに記事を投稿する - 2 points コミュニティに応募したアプリケーションの概要を説明する記事を投稿するとポイントを獲得できます。 コミュニティに2つ目の記事を投稿する - 1 point 2つ目の記事を投稿する、または投稿したアプリケーション概要の翻訳記事を投稿することで、さらボーナスポイントを獲得できます。(3記事以降はポイントが加算されません。) Code quality をパスしてBug 0件 を表示させる - 1 point コードの静的制御のためのcode quality Github actionを組み込み、ObjectScriptの Bug 0件 と表示させるとボーナスポイントを獲得できます。 Video on YouTube - 3 points 開発した作品の動画を作成し、YouTube に掲載した場合、3ポイント獲得できます。 ※ ボーナスポイントについては、変更される可能性もあります。予めご了承ください。
記事
Toshihiko Minamoto · 2020年11月5日

Azure BackupによるInterSystems IRISおよびCachéアプリケーション・コンシステントなバックアップ

データベースシステムには非常に特殊なバックアップ要件があり、企業のデプロイメントでは、事前の検討と計画が必要です。 データベースシステムの場合、バックアップソリューションの運用上の目標は、アプリケーションが正常にシャットダウンされた時と同じ状態で、データのコピーを作成することにあります。 アプリケーションの整合性バックアップはこれらの要件を満たし、Cachéは、このレベルのバックアップ整合性を達成するために、外部ソリューションとの統合を容易にする一連のAPIを提供しています。 これらのAPIは**_ExternalFreeze_**と**_ExternalThaw_**です。 _ExternalFreeze_は一時的にディスクへの書き込みを停止し、この期間にCaché はメモリ内の変更をコミットします。 この期間にバックアップ操作を完了させ、_ExternalThaw_の呼び出しを行う必要があります。 この呼び出しによって、書き込みのデーモンがグローバルバッファプール(データべースキャッシュ)で更新されたキャッシュをディスクに書き込むと、通常のCachéデータベースの書き込みデーモン操作が再開します。 このプロセスはCachéのユーザープロセスに対して透過的に行われます。 具体的なAPIクラスメソッドは次のとおりです。 [##Class(Backup.General).ExternalFreeze()](http://docs.intersystems.com/latest/csp/documatic/%25CSP.Documatic.cls?PAGE=CLASS&LIBRARY=%25SYS&CLASSNAME=Backup.General#ExternalFreeze) [##Class(Backup.General).ExternalThaw()](http://docs.intersystems.com/latest/csp/documatic/%25CSP.Documatic.cls?PAGE=CLASS&LIBRARY=%25SYS&CLASSNAME=Backup.General#ExternalThaw) これらのAPIは、スナップショット操作のプリスクリプトとポストスクリプトを実行するAzure Backupの新機能と合わせて、Azure上のCachéのデプロイメントに対する包括的なバックアップソリューションを提供しています。 [Azure Backupのプリスクリプトとポストスクリプト機能](https://azure.microsoft.com/en-us/blog/announcing-application-consistent-backup-for-linux-vms-using-azure-backup)は現在、Linux VMでのみ利用できます。 ## 前提条件 Azure Backupを使用してVMをバックアップする前に、おおまかに3つのステップを実行する必要があります。 1. Recovery Servicesコンテナーを作成する 2. VM Agentの最新バージョンをインストールする 3. VMからAzureサービスへのネットワークアクセスを確認する Recovery Servicesコンテナーは、バックアップの目標、ポリシー、および保護する項目を管理します。 Recovery Servicesコンテナーの作成は、Azure PortalまたはPowerShellを使ったスクリプトによって行います。 Azure BackupにはVMで実行する拡張機能が必要であり、Linux VMエージェントによって管理されています。また、最新バージョンのエージェントも必要です。 拡張機能はAzure StorageとRecovery Servicesコンテナーの外向きのHTTPSエンドポイントと対話します。 VMからこれらのサービスへのセキュアアクセスは、Azure Network Security Groupのプロキシとネットワークルールを使用して構成できます。 上記のステップに関する詳細は、「[Prepare your environment to back up Resource Manager-deployed virtual machines](https://docs.microsoft.com/en-us/azure/backup/backup-azure-arm-vms-prepare)」を参照してください。 ## プリスクリプトとポストスクリプトの構成 バックアップ操作の前と後にスクリプトを呼び出す機能は、Azure Backup Extension(Microsoft.Azure.RecoveryServices.VMSnapshotLinux)の最新バージョンに含まれています。 この拡張機能のインストール方法については、[機能に関する詳細なドキュメント](https://docs.microsoft.com/en-us/azure/backup/backup-azure-linux-app-consistent)を確認してください。 デフォルトでは、拡張機能には、Linux VMの次の場所に、サンプルのプリスクリプトとポストスクリプトが含まれます。 /var/lib/waagent/Microsoft.Azure.RecoveryServices.VMSnapshotLinux-1.0.9110.0/main/tempPlugin そして、スクリプトをそれぞれ次の場所にコピーする必要があります。 /etc/azure/prescript.sh /etc/azure/postScript.sh スクリプトテンプレートは、[GitHub](https://github.com/MicrosoftAzureBackup/Cache)からもダウンロード可能です。 Cachéでは、ExternalFreeze APIを呼び出すprescript.shスクリプトを実装でき、postScript.shにはExternalThawを実行するコードが含まれている必要があります。 **以下は、Cachéの*prescript.sh*の実装例です。** #!/bin/bash # variables used for returning the status of the script success=0 error=1 warning=2 status=$success log_path="/etc/preScript.log" #path of log file printf "Logs:\n" > $log_path # TODO: Replace <CACHE INSTANCE> with the name of the running instance csession <CACHE INSTANCE> -U%SYS "##Class(Backup.General).ExternalFreeze()" >> $log_path status=$? if [ $status -eq 5 ]; then echo "SYSTEM IS FROZEN" printf "SYSTEM IS FROZEN\n" >> $log_path elif [ $status -eq 3 ]; then echo "SYSTEM FREEZE FAILED" printf "SYSTEM FREEZE FAILED\n" >> $log_path status=$error csession <CACHE INSTANCE> -U%SYS "##Class(Backup.General).ExternalThaw()" fi exit $status **以下は、Cachéの*postScript.sh*の実装例です。** #!/bin/bash # variables used for returning the status of the script success=0 error=1 warning=2 status=$success log_path="/etc/postScript.log" #path of log file printf "Logs:\n" > $log_path # TODO: Replace <CACHE INSTANCE> with the name of the running instance csession <CACHE INSTANCE> -U%SYS "##class(Backup.General).ExternalThaw()" status=$? if [ $status req 5]; then echo "SYSTEM IS UNFROZEN" printf "SYSTEM IS UNFROZEN\n" >> $log_path elif [ $status -eq 3 ]; then echo "SYSTEM UNFREEZE FAILED" printf "SYSTEM UNFREEZE FAILED\n" >> $log_path status=$error fi exit $status ## バックアップの実行 Azureポータルで、Recoveryサービスに移動して、最初のバックアップをトリガできます。 初回バックアップまたは後続のバックアップに関係なく、VMスナップショットの時間は数秒であることに注意してください。 最初のバックアップのデータ転送には時間がかかりますが、データ転送は、データベースのフリーズを解除するポストスクリプトの実行後に開始されるため、プリスクリプトとポストスクリプト間の時間に影響を与えることはありません。 データ保護操作が有効であることを確認するには、定期的に非本番環境にバックアップを復元して[データベースの整合性チェック](http://docs.intersystems.com/latestj/csp/docbook/DocBook.UI.Page.cls?KEY=GCDI_integrity#GCDI_integrity_verify_utility)を実行することを強くお勧めします。 バックアップのトリガ方法、およびバックアップスケジュールなどの関連トピックについては、「[Back up Azure virtual machines to a Recovery Services vault](https://docs.microsoft.com/en-us/azure/backup/backup-azure-arm-vms-prepare)」を参照してください。  
記事
Tomoko Furuzono · 2021年4月13日

WindowsプログラムからIRISの起動状況を確認する

これは、InterSystems FAQサイトの記事です。iris.exeを使用し、以下のようにして確認できます。※up:起動中、dn:停止中 c:\>cd c:\InterSystems\IRIS\binc:\InterSystems\IRIS\bin>iris all nodisplay > c:\temp\test.txtc:\InterSystems\IRIS\bin>type c:\temp\test.txt Instance Version ID Port Directory ------------- ---------- ---- ---------dn iris 2019.1.0.510.0 51773 c:\intersystems\irisdn iris20191 2019.1.0.398.0 51774 c:\intersystems\iris20191c:\InterSystems\IRIS\bin>
記事
Mihoko Iijima · 2020年10月27日

【はじめてのInterSystems IRIS】Interoperability(相互運用性):動作の仕組みを知ろう

この記事はこちらの投稿の続きの内容です。 この記事では、Interoperability(相互運用性)メニューを利用してシステム統合を行う際、どのような仕組みで動作しているのかについて解説します。 図の左側は、外部システムから送信される情報の受け入れ窓口です。 情報の受信方法としては、ファイルを読むために指定ディレクトリを一定間隔で監視したり、データベースへ定期的に問い合わせを行ったり、入力を待機したり、または他システムのアプリケーションから直接呼び出して渡してもらうなど、様々な方法を用意しています。 IRIS の Interoperability(相互運用性)メニューで作成するシステム統合の仕組みの中では、受信した情報を メッセージ と呼ぶオブジェクトに格納し、次の処理を担当するコンポーネントへ メッセージ を送信します。メッセージ は受信した情報を全て利用して作成することも、一部抜粋した情報のみを利用することも自由に選択できます。 メッセージ に含まれる情報を外部システムへ 送信したい場合は、外部システムへ処理を依頼する役割があるコンポーネント(図の右側)へメッセージ を送信します。メッセージ を受信したコンポーネントは、外部システムへ処理を依頼します。 また、メッセージ に対して人の審査を必要としたり、データ変換やデータの付け足しなどが必要な場合は、処理の流れを調整する役割の図の中央のコンポーネント(BPM)へ メッセージ を送信します。 各コンポーネント間のデータ送受信には、メッセージ を利用します。メッセージ の送受信が発生すると、自動的に メッセージ をデータベースに格納しています。 メッセージ がデータベースに保存されることを利用して、データ変換前後の違いを確認したり、運用中の場合はトラブル発生時に処理の元となった メッセージ を確認したり、途中からのやり直し(再送)を行ったり、開発・テスト・運用のそれぞれの段階で メッセージ を利用した状態の確認が行えます。 システム統合のための仕組みをシンプルな絵にすると、下図のように3つのコンポーネント(ビジネス・サービス、ビジネス・プロセス、ビジネス・オペレーション)に分かれた絵になります。 また、使用するコンポーネントの情報(接続先情報など)を保存しておく「プロダクション」と呼ぶ定義もあります。 各コンポーネントの役割は、以下の通りです。 ビジネス・サービス外部からの情報を受付、メッセージ を作成し他コンポーネントへ メッセージ を送信する役割 ビジネス・プロセスメッセージ を受信すると起動し、処理の調整(定義した順番どおりにコンポーネントを呼び出す/応答待ちを行う/人が審査する結果を待つ など)を行う役割 ビジネス・オペレーションメッセージ を受信すると起動し、外部システムへ処理の依頼を行う役割 コンポーネント間のデータの送受信には、メッセージ が利用されます。ビジネス・サービス以外のコンポーネントは、メッセージ を受信することで処理を開始します。 さて、この メッセージ 、どのような意図で作成し、利用するものなのでしょうか。 メッセージ は、ビジネス・サービスに入力された情報の中から外部システムへ中継したい情報を取り出して作成します。 IRIS に接続する外部システム全てが同種のデータフォーマットで送信するわけではないのと、中継内容も様々なので、プロダクションでは中継したい情報にあわせ自由にメッセージクラスを定義できます 。 また、メッセージ はリクエスト(=要求メッセージ)とレスポン(=応答メッセージ)の2種類を用意していて、コンポーネントの起動のきっかけになる メッセージ をリクエスト(=要求メッセージ)、コンポーネントが処理を終え、呼び出し元へ応答する メッセージ をレスポンス(=応答メッセージ)として、実装を分けています。 これらメッセージ は、具体的に中継の流れを考えながら設計していきます。 以降の記事では、サンプルのテーマを利用しながらプロダクションやメッセージ 、コンポーネントの作成概要について順番に解説していきます。
記事
Toshihiko Minamoto · 2020年11月11日

Grafana ベースの mgstat(InterSystems Caché / Ensemble / HealthShareのシステム監視ツール)用 GUI

こんにちは! この記事は「[Prometheus で InterSystems Caché を監視する](https://jp.community.intersystems.com/node/482596)」の続きになります。 ここでは [ ^mgstat](http://docs.intersystems.com/latestj/csp/docbook/DocBook.UI.Page.cls?KEY=GCM_mgstat) ツールの動作結果を視覚化する方法を見ていきます。 このツールを使用すると、Caché のパフォーマンス統計、具体的なグローバルとルーチンの呼び出し数(ローカルおよび[ECP](http://docs.intersystems.com/latestj/csp/docbook/DocBook.UI.Page.cls?KEY=GDDM) 経由)、書き込みデーモンのキュー長、ディスクに保存されるブロックと読み取られるブロックの数、ECP トラフィックの量などを取得できます。 ^mgstat は(対話的に、または[ジョブ](http://docs.intersystems.com/latestj/csp/docbook/DocBook.UI.Page.cls?KEY=RCOS_cjob)によって)単独で起動したり、別のパフォーマンス測定ツールである [ ^pButtons](http://docs.intersystems.com/latestj/csp/docbook/DocBook.UI.Page.cls?KEY=GCM_pbuttons) と並行して起動したりできます。 ここでは 2 つのパートに分けて説明したいと思います。最初のパートでは ^mgstat によって収集された統計を図示し、2 番目のパートではこの統計を正確に収集する方法を集中して取り上げます。 手短に言えば、ここでは [$zu関数](http://docs.intersystems.com/latestj/csp/docbook/DocBook.UI.Page.cls?KEY=GORIENT_cos_functions_zu) を使用しています。 ただし、[SYS.Stats](http://docs.intersystems.com/latestj/csp/documatic/%25CSP.Documatic.cls?PAGE=CLASS&LIBRARY=%25SYS&CLASSNAME=SYS.Stats&PACKAGE=1) パッケージのクラス経由で収集できる大部分のパラメーターに対応したオブジェクトインターフェースがあります。 ^mgstat に表示されるのは、収集できるパラメーターのほんの一部です。 その後、[Grafana](https://grafana.com/) ダッシュボードですべてのパラメーターを表示してみましょう。 今回は ^mgstat によって提供されるパラメーターのみを使用します。 また、[Docker](https://docs.docker.com/) コンテナについても説明のために少しだけ取り上げます。 ![](/sites/default/files/inline/images/header.jpg) Docker のインストール [最初のパート](https://jp.community.intersystems.com/node/482596)では tarball から Prometheus と Grafana をインストールする方法を説明しています。 ここでは [Docker](https://docs.docker.com/) の機能を使用して監視サーバーを起動する方法を説明します。 以下はデモ用のホストマシンです。 # uname -r4.8.16-200.fc24.x86_64# cat /etc/fedora-releaseFedora release 24 (Twenty Four) さらに 2 台の仮想マシン(192.168.42.131 と 192.168.42.132)が VMWare Workstation Pro 12.0 環境で使用され、どちらも Caché がインストールされています。 これらのマシンが監視対象になります。 バージョンは次のとおりです。 # uname -r3.10.0-327.el7.x86_64# cat /etc/redhat-releaseRed Hat Enterprise Linux Server release 7.2 (Maipo)…USER>write $zversionCache for UNIX (Red Hat Enterprise Linux for x86-64) 2016.2 (Build 721U) Wed Aug 17 2016 20:19:48 EDT ホストマシンに Docker をインストールして起動しましょう。 # dnf install -y docker# systemctl start docker# systemctl status docker● docker.service — Docker Application Container EngineLoaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled)Active: active (running) since Wed 2017-06-21 15:08:28 EEST; 3 days ago... Docker コンテナで Prometheus を起動する 最新の Prometheus イメージをロードしましょう。 # docker pull docker.io/prom/prometheus [Docker ファイル](https://hub.docker.com/r/prom/prometheus/~/dockerfile/)を参照すると、イメージが /etc/prometheus/prometheus.yml ファイルから構成を読み取り、収集された統計が /prometheusフォルダーに保存されていることがわかります。 …CMD [ "-config.file=/etc/prometheus/prometheus.yml", \"-storage.local.path=/prometheus", \... Docker コンテナで Prometheus を起動する際に、ホストマシンから構成ファイルとメトリックデータベースをロードするようにしましょう。 こうすることで、コンテナの再起動を「乗り切る」ことができます。 次に、ホストマシン上に Prometheus 用のフォルダーを作成しましょう。 # mkdir -p /opt/prometheus/data /opt/prometheus/etc そして、次のような Prometheus の構成ファイルを作成しましょう。 # cat /opt/prometheus/etc/prometheus.ymlglobal:  scrape_interval: 10sscrape_configs:  - job_name: 'isc_cache'    metrics_path: '/mgstat/5' # Tail 5 (sec) it's a diff time for ^mgstat. Should be less than scrape interval.    static_configs:    - targets: ['192.168.42.131:57772','192.168.42.132:57772']    basic_auth:      username: 'PromUser'      password: 'Secret' これで、Prometheus を含むコンテナを起動できます。 # docker run -d --name prometheus \--hostname prometheus -p 9090:9090 \-v /opt/prometheus/etc/prometheus.yml:/etc/prometheus/prometheus.yml \-v /opt/prometheus/data/:/prometheus \docker.io/prom/prometheus 正常に起動したかどうかを確認してください。 # docker ps --format "{{.ID}}: {{.Command}} {{.Status}} {{.Names}}"d3a1db5dec1a: "/bin/prometheus -con" Up 5 minutes prometheus Docker コンテナで Grafana を起動する まずは最新のイメージをダウンロードしましょう。 # docker pull docker.io/grafana/grafana 次に、Grafana データベース(デフォルトでは SQLite)をホストマシンに保存するように指定して起動します。 また、Prometheus を含むコンテナへのリンクを作成し、Grafana を含むコンテナからそのコンテナにリンクできるようにします。 # mkdir -p /opt/grafana/db# docker run -d --name grafana \--hostname grafana -p 3000:3000 \--link prometheus \-v /opt/grafana/db:/var/lib/grafana \docker.io/grafana/grafana# docker ps --format "{{.ID}}: {{.Command}} {{.Status}} {{.Names}}"fe6941ce3d15: "/run.sh" Up 3 seconds grafanad3a1db5dec1a: "/bin/prometheus -con" Up 14 minutes prometheus Docker-compose を使用する 両方のコンテナは別々に起動されます。 [Docker-compose](https://docs.docker.com/compose/) を使用すると、まとめて複数のコンテナを起動できるので便利です。 このツールをインストールし、現在の 2 つのコンテナを一時停止しましょう。その後、Docker-compose 経由で再起動するように再構成し、これらのコンテナをもう一度起動します。 これを cli で書くと次のようになります。 # dnf install -y docker-compose# docker stop $(docker ps -a -q)# docker rm $(docker ps -a -q)# mkdir /opt/docker-compose# cat /opt/docker-compose/docker-compose.ymlversion: '2'services:  prometheus:     image: docker.io/prom/prometheus    container_name: prometheus    hostname: prometheus    ports:       - 9090:9090    volumes:      - /opt/prometheus/etc/prometheus.yml:/etc/prometheus/prometheus.yml      - /opt/prometheus/data/:/prometheus  grafana:     image: docker.io/grafana/grafana    container_name: grafana    hostname: grafana    ports:       - 3000:3000    volumes:      - /opt/grafana/db:/var/lib/grafana# docker-compose -f /opt/docker-compose/docker-compose.yml up -d# # 両方のコンテナを次のコマンドを使用して無効化および削除できます。 # # docker-compose -f /opt/docker-compose/docker-compose.yml down# docker ps --format "{{.ID}}: {{.Command}} {{.Status}} {{.Names}}"620e3cb4a5c3: "/run.sh" Up 11 seconds grafanae63416e6c247: "/bin/prometheus -con" Up 12 seconds prometheus インストール後の手順 Grafana を初めて起動した後は、Web インターフェイスの管理者パスワードを変更し(デフォルトでは、ログインとパスワードの組み合わせは admin/admin です)、Prometheus をデータソースとして追加する必要があります。 この手順は Web インターフェイスから実施できますが、Grafana SQLite データベース(デフォルトの位置は /opt/grafana/db/grafana.db)を直接編集するか、[REST リクエスト](http://docs.grafana.org/http_api/)を使用することによっても実施できます。 さらにもう 1 つの方法をご紹介します。次をご覧ください。 # curl -XPUT "admin:admin@localhost:3000/api/user/password" \-H "Content-Type:application/json" \-d '{"oldPassword":"admin","newPassword":"TopSecret","confirmNew":"TopSecret"}'パスワードが正常に変更された場合は次の応答が返ってきます。{"message":"User password changed"}次のような応答が返ってくる場合があります:curl: (56) Recv failure: Connection reset by peerこれは、Grafana サーバーがまだ起動しておらず、前述のコマンドを再度実行する前に少し待機する必要があることを意味しています。 例えば、次のように待機できます。# until curl -sf admin:admin@localhost:3000 > /dev/null; do sleep 1; echo "Grafana is not started yet";done; echo "Grafana is started"パスワードを正常に変更したら、Prometheus のデータソースを追加してください。# curl -XPOST "admin:TopSecret@localhost:3000/api/datasources" \-H "Content-Type:application/json" \-d '{"name":"Prometheus","type":"prometheus","url":"http://prometheus:9090","access":"proxy"}'データソースが正常に追加されると、次の応答が返ってきます。{"id":1,"message":"Datasource added","name":"Prometheus"} ^mgstat に相当するものを作成する ^mgstat は対話モードで出力をファイルとターミナルに保存します。 ここではファイルへの出力は取り上げません。 このため、Studio を使用して USER スペースに ^mgstat をオブジェクト指向で実装した my.Metrics というクラスを作成してコンパイルします。 /// このクラスは ^mgstat ルーチンをオブジェクト指向で実装しています。/// 前回とは異なり、Caché のバージョンチェックはスキップされます。/// seizes を監視したい場合はパラメーター ISSEIZEGATHERED を 1 に設定する必要があります。/// ^mgstat ルーチンとは異なり、Seizes メトリックは(パーセンテージではなく)差分として表示されます。/// 一部の $zutil 関数についてはよく分かりませんが、^mgstat で使用されているので残しておきます。Class my.Metrics Extends %RegisteredObject{ /// メトリックの接頭辞Parameter PREFIX = "isc_cache_mgstat_"; /// Prometheus のメトリックは改行で区切る必要があります。Parameter NL As COSEXPRESSION = "$c(10)"; /// 不明なパラメーターです -) ^mgstat.int と同じものを使用しています。Parameter MAXVALUE = 1000000000; /// 2**64 - 10 です。 なぜマイナス 10 なのでしょうか? 分かりません -) ^mgstat.int と同じものを使用しています。Parameter MAXVALGLO = 18446744073709551610; /// 監視対象にするリソースです。 このリストは変更できます。Parameter SEIZENAMES = "Global,ObjClass,Per-BDB"; /// デフォルト値は $zutil(69,74) です。 "1" を設定すると seize 統計の収集を開始できます。Parameter ISSEIZEGATHERED = 0; Parameter MAXECPCONN As COSEXPRESSION = "$system.ECP.MaxClientConnections()"; /// グローバルバッファタイプの数(8K、16K など)Parameter NUMBUFF As COSEXPRESSION = "$zutil(190, 2)"; /// メモリオフセット(用途不明 )Parameter WDWCHECK As COSEXPRESSION = "$zutil(40, 2, 146)"; /// 書き込みデーモンフェーズ用のメモリオフセットParameter WDPHASEOFFSET As COSEXPRESSION = "$zutil(40, 2, 145)"; /// ジャーナル用のオフセットParameter JOURNALBASE As COSEXPRESSION = "$zutil(40, 2, 94)"; ClassMethod getSamples(delay As %Integer = 2) As %Status{    set sc = $$$OK    try {        set sc = ..gather(.oldValues)        hang delay        set sc = ..gather(.newValues)        set sc = ..diff(delay, .oldValues, .newValues, .displayValues)        set sc = ..output(.displayValues)    } catch e {        write "Error: "_e.Name_"_"_e.Location, ..#NL    }    quit sc} ClassMethod gather(Output values) As %Status{    set sc = $$$OK        // グローバルの統計を取得    set sc = ..getGlobalStat(.values)        // 書き込みデーモンの統計を取得    set sc = ..getWDStat(.values)        // ジャーナルの書き込みを取得    set values("journal_writes") = ..getJournalWrites()        // seize の統計を取得    set sc = ..getSeizeStat(.values)        // ECP の統計を取得    set sc = ..getECPStat(.values)        quit sc} ClassMethod diff(delay As %Integer = 2, ByRef oldValues, ByRef newValues, Output displayValues) As %Status{    set sc = $$$OK        // グローバルのメトリックを処理    set sc = ..loopGlobal("global", .oldValues, .newValues, delay, 1, .displayValues)        set displayValues("read_ratio") = $select(        displayValues("physical_reads") = 0: 0,        1: $number(displayValues("logical_block_requests") / displayValues("physical_reads"),2)    )    set displayValues("global_remote_ratio") = $select(        displayValues("remote_global_refs") = 0: 0,        1: $number(displayValues("global_refs") / displayValues("remote_global_refs"),2)    )        // 書き込みデーモンのメトリックを処理(秒単位ではない)    set sc = ..loopGlobal("wd", .oldValues, .newValues, delay, 0, .displayValues)        // ジャーナルの書き込みを処理    set displayValues("journal_writes") = ..getDiff(oldValues("journal_writes"), newValues("journal_writes"), delay)        // seize メトリックの処理    set sc = ..loopGlobal("seize", .oldValues, .newValues, delay, 1, .displayValues)        // ECP クライアントメトリックの処理    set sc = ..loopGlobal("ecp", .oldValues, .newValues, delay, 1, .displayValues)    set displayValues("act_ecp") = newValues("act_ecp")        quit sc} ClassMethod getDiff(oldValue As %Integer, newValue As %Integer, delay As %Integer = 2) As %Integer{    if (newValue < oldValue) {        set diff = (..#MAXVALGLO - oldValue + newValue) \ delay        if (diff > ..#MAXVALUE) set diff = newValue \ delay    } else {        set diff = (newValue - oldValue) \ delay    }    quit diff} ClassMethod loopGlobal(subscript As %String, ByRef oldValues, ByRef newValues, delay As %Integer = 2, perSecond As %Boolean = 1, Output displayValues) As %Status{    set sc = $$$OK        set i = ""    for {        set i = $order(newValues(subscript, i))         quit:(i = "")        if (perSecond = 1) {            set displayValues(i) = ..getDiff(oldValues(subscript, i), newValues(subscript, i), delay)        } else {            set displayValues(i) = newValues(subscript, i)        }    }        quit sc} ClassMethod output(ByRef displayValues) As %Status{    set sc = $$$OK    set i = ""    for {        set i = $order(displayValues(i))        quit:(i = "")        write ..#PREFIX_i," ", displayValues(i),..#NL    }    write ..#NL    quit sc} ClassMethod getGlobalStat(ByRef values) As %Status{    set sc = $$$OK        set gloStatDesc = "routine_refs,remote_routine_refs,routine_loads_and_saves,"_        "remote_routine_loads_and_saves,global_refs,remote_global_refs,"_        "logical_block_requests,physical_reads,physical_writes,"_        "global_updates,remote_global_updates,routine_commands,"_        "wij_writes,routine_cache_misses,object_cache_hit,"_        "object_cache_miss,object_cache_load,object_references_newed,"_        "object_references_del,process_private_global_refs,process_private_global_updates"            set gloStat = $zutil(190, 6, 1)        for i = 1:1:$length(gloStat, ",") {        set values("global", $piece(gloStatDesc, ",", i)) = $piece(gloStat, ",", i)    }     quit sc} ClassMethod getWDStat(ByRef values) As %Status{    set sc = $$$OK        set tempWdQueue = 0     for b = 1:1:..#NUMBUFF {         set tempWdQueue = tempWdQueue + $piece($zutil(190, 2, b), ",", 10)     }        set wdInfo = $zutil(190, 13)    set wdPass = $piece(wdInfo, ",")    set wdQueueSize = $piece(wdInfo, ",", 2)    set tempWdQueue = tempWdQueue - wdQueueSize     if (tempWdQueue < 0) set tempWdQueue = 0        set misc = $zutil(190, 4)    set ijuLock = $piece(misc, ",", 4)    set ijuCount = $piece(misc, ",", 5)        set wdPhase = 0     if (($view(..#WDWCHECK, -2, 4)) && (..#WDPHASEOFFSET)) {        set wdPhase = $view(..#WDPHASEOFFSET, -2, 4)    }        set wdStatDesc = "write_daemon_queue_size,write_daemon_temp_queue,"_        "write_daemon_pass,write_daemon_phase,iju_lock,iju_count"        set wdStat = wdQueueSize_","_tempWdQueue_","_wdPass_","_wdPhase_","_ijuLock_","_ijuCount        for i = 1:1:$length(wdStat, ",") {        set values("wd", $piece(wdStatDesc, ",", i)) = $piece(wdStat, ",", i)    }        quit sc} ClassMethod getJournalWrites() As %String{    quit $view(..#JOURNALBASE, -2, 4)} ClassMethod getSeizeStat(ByRef values) As %Status{    set sc = $$$OK        set seizeStat = "", seizeStatDescList = ""    set selectedNames = ..#SEIZENAMES        set seizeNumbers = ..getSeizeNumbers(selectedNames)  // seize statistics    set isSeizeGatherEnabled = ..#ISSEIZEGATHERED    if (seizeNumbers = "") {         set SeizeCount = 0     } else {         set SeizeCount = isSeizeGatherEnabled * $length(seizeNumbers, ",")     }        for i = 1:1:SeizeCount {         set resource = $piece(seizeNumbers, ",", i)        set resourceName = ..getSeizeLowerCaseName($piece(selectedNames, ",", i))        set resourceStat = $zutil(162, 3, resource)        set seizeStat = seizeStat_$listbuild($piece(resourceStat, ","))        set seizeStat = seizeStat_$listbuild($piece(resourceStat, ",", 2))        set seizeStat = seizeStat_$listbuild($piece(resourceStat, ",", 3))        set seizeStatDescList = seizeStatDescList_$listbuild(            resourceName_"_seizes", resourceName_"_n_seizes", resourceName_"_a_seizes"        )    }    set seizeStatDesc = $listtostring(seizeStatDescList, ",")        set seizeStat = $listtostring(seizeStat, ",")        if (seizeStat '= "") {        for k = 1:1:$length(seizeStat, ",") {            set values("seize", $piece(seizeStatDesc, ",", k)) = $piece(seizeStat, ",", k)        }    }        quit sc} ClassMethod getSeizeNumbers(selectedNames As %String) As %String{    /// USER>write $zu(162,0)    // Pid,Routine,Lock,Global,Dirset,SatMap,Journal,Stat,GfileTab,Misc,LockDev,ObjClass...    set allSeizeNames = $zutil(162,0)_"," //すべてのリソース名を返す        set seizeNumbers = ""    for i = 1:1:$length(selectedNames, ",") {        set resourceName = $piece(selectedNames,",",i)        continue:(resourceName = "")||(resourceName = "Unused")        set resourceNumber = $length($extract(allSeizeNames, 1, $find(allSeizeNames, resourceName)), ",") - 1        continue:(resourceNumber = 0)        if (seizeNumbers = "") {            set seizeNumbers = resourceNumber        } else {            set seizeNumbers = seizeNumbers_","_resourceNumber        }    }    quit seizeNumbers} ClassMethod getSeizeLowerCaseName(seizeName As %String) As %String{    quit $tr($zcvt(seizeName, "l"), "-", "_")} ClassMethod getECPStat(ByRef values) As %Status{    set sc = $$$OK        set ecpStat = ""        if (..#MAXECPCONN '= 0) {        set fullECPStat = $piece($system.ECP.GetProperty("ClientStats"), ",", 1, 21)        set activeEcpConn = $system.ECP.NumClientConnections()        set addBlocks = $piece(fullECPStat, ",", 2)        set purgeBuffersByLocal = $piece(fullECPStat, ",", 6)        set purgeBuffersByRemote = $piece(fullECPStat, ",", 7)        set bytesSent = $piece(fullECPStat, ",", 19)        set bytesReceived = $piece(fullECPStat, ",", 20)    }    set ecpStatDesc = "add_blocks,purge_buffers_local,"_        "purge_server_remote,bytes_sent,bytes_received"        set ecpStat = addBlocks_","_purgeBuffersByLocal_","_        purgeBuffersByRemote_","_bytesSent_","_bytesReceived            if (ecpStat '= "") {        for l = 1:1:$length(ecpStat, ",") {            set values("ecp", $piece(ecpStatDesc, ",", l)) = $piece(ecpStat, ",", l)        }        set values("act_ecp") = activeEcpConn    }        quit sc} } REST 経由で my.Metrics を呼び出すため、USER スペースにラッパークラスを作成しましょう。 Class my.Mgstat Extends %CSP.REST{ XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]{} ClassMethod getMgstat(delay As %Integer = 2) As %Status{    // デフォルトでは 2 秒間隔で平均値を取得します    quit ##class(my.Metrics).getSamples(delay)} } **リソース、ユーザー、Web アプリケーションを作成する** メトリックを提供するクラスが完成し、RESTful Web アプリケーションを作成できるようになりました。 最初の記事と同様に、この Web アプリケーションにリソースを割り当て、そのリソースを使用して Prometheus がメトリックを収集するユーザーを作成します。 作成したら、特定のデータベースにユーザー権限を付与しましょう。 最初の記事とは異なり、CACHESYS データベースに書き込むための権限( loop+1^mymgstat *gmethod" エラーを回避するため)を追加し、%Admin_Manage リソースを使用できるようにしました( gather+10^mymgstat *GetProperty,%SYSTEM.ECP" エラーを回避するため)。 192.168.42.131 と 192.168.42.132 の両方の仮想サーバーでこれらの手順を繰り返しましょう。 ただし、その前に作成した my.Metrics クラスと my.Mgstat クラスのコードを両方のサーバーの USER スペースにアップロードします(コードは [GitHub](https://github.com/myardyas/prometheus/tree/master/mgstat/cos) で取得できます)。 具体的にはそれぞれの仮想サーバーで次の手順を実行します。 # cd /tmp# wget https://raw.githubusercontent.com/myardyas/prometheus/master/mgstat/cos/udl/Metrics.cls# wget https://raw.githubusercontent.com/myardyas/prometheus/master/mgstat/cos/udl/Mgstat.cls## # サーバーがインターネットに接続されていない場合はプログラムとクラスをローカル環境でコピーし、 scp を使用してください。## csession -U userUSER>do $system.OBJ.Load("/tmp/Metrics.cls*/tmp/Mgstat.cls","ck")USER>zn "%sys"%SYS>write ##class(Security.Resources).Create("PromResource","Resource for Metrics web page","") 1%SYS>write ##class(Security.Roles).Create("PromRole","Role for PromResource","PromResource:U,%Admin_Manage:U,%DB_USER:RW,%DB_CACHESYS:RW")1%SYS>write ##class(Security.Users).Create("PromUser","PromRole","Secret")1%SYS>set properties("NameSpace") = "USER"%SYS>set properties("Description") = "RESTfull web-interface for mgstat"%SYS>set properties("AutheEnabled") = 32 ; 説明を参照してください%SYS>set properties("Resource") = "PromResource"%SYS>set properties("DispatchClass") = "my.Mgstat" %SYS>write ##class(Security.Applications).Create("/mgstat",.properties)1 #### **curl を使用してメトリックにアクセスできることを確認する** **(**ファイアウォールで 57772 番ポートを忘れずに開いてください**)** # curl --user PromUser:Secret -XGET http://192.168.42.131:57772/mgstat/5isc_cache_mgstat_global_refs 347isc_cache_mgstat_remote_global_refs 0isc_cache_mgstat_global_remote_ratio 0…# curl --user PromUser:Secret -XGET http://192.168.42.132:57772/mgstat/5isc_cache_mgstat_global_refs 130isc_cache_mgstat_remote_global_refs 0isc_cache_mgstat_global_remote_ratio 0... Prometheus からメトリックにアクセスできることを確認する Prometheus は 9090 番ポートをリッスンします。 まずは [Targets] のステータスを確認しましょう。 ![](/sites/default/files/inline/images/prometheus_targets_0.jpg) その後、任意のメトリックを確認してください。 ![](/sites/default/files/inline/images/prometheus_random_metrics.jpg) 1 つのメトリックを表示する ここでは 1 つのメトリック(isc\_cache\_mgstat\_global\_refs)を例としてグラフに表示します。 まず、ダッシュボードを更新し、そこにグラフを挿入する必要があります。 そのためには Grafana(http://localhost:3000、ログイン/パスワードは admin/TopSecret)に移動し、新しいダッシュボードを追加してください。 ![](/sites/default/files/inline/images/grafana_new_dashboard.jpg) グラフを追加します。 ![](/sites/default/files/inline/images/grafana_add_graph.jpg) [Panel title]、[Edit] の順にクリックし、グラフを編集します。 ![](/sites/default/files/inline/images/grafana_graph_edit.jpg) Prometheus をデータソースとして設定し、isc\_cache\_mgstat\_global\_refs メトリックを選択します。 解像度は 1/1 に設定します。 ![](/sites/default/files/inline/images/grafana_global_refs_metrics.jpg) このグラフに名前を付けましょう。 ![](/sites/default/files/inline/images/grafana_set_graph_name.jpg) 凡例を追加します。 ![](/sites/default/files/inline/images/grafana_add_legend.jpg) ウィンドウの上部にある [Save] ボタンをクリックし、ダッシュボードの名前を入力します。 ![](/sites/default/files/inline/images/grafana_set_dashboard_name.jpg) 最終的には次のように表示されます。 ![](/sites/default/files/inline/images/grafana_global_refs_graph.jpg) すべてのメトリックを表示する 残りのメトリックも同じように追加しましょう。 2 つのテキストメトリックがあります([Singlestat](http://docs.grafana.org/features/panels/singlestat/#singlestat-panel))。 その結果、次のダッシュボードが表示されます(ここでは上部と下部に分けて掲載しています)。 ![](/sites/default/files/inline/images/all_metrics_top.jpg) ![](/sites/default/files/inline/images/all_metrics_bottom.jpg) 次の 2 つは明らかに問題があるように思われます。 — 凡例のスクロールバー(サーバーの数が増えるとスクロールバーが長くなります)。 — Singlestat パネルにデータがありません(値が単一であることを意味します)。 私たちには 2 台のサーバーとそれに対応する 2 つの値があります。 テンプレートを使用する インスタンスに[テンプレート](http://docs.grafana.org/reference/templating/#templating)を導入し、これらの問題を解決してみましょう。 そのためにはインスタンスの値を格納する変数を作成し、[ルール](http://docs.grafana.org/features/datasources/prometheus/#templating)に従って Prometheus へのリクエストを少しだけ編集する必要があります。 つまり、“_instance_” 変数を作成した後に "_isc\_cache\_mgstat\_global\_refs_" リクエストの代わりに"_isc\_cache\_mgstat\_global\_refs{instance="[[instance]]"}_" を使用する必要があります。 変数を作成します。 ![](/sites/default/files/inline/images/grafana_create_variable.jpg) ![](/sites/default/files/inline/images/grafana_create_variable_2.jpg) Prometheus へのリクエストでは、各メトリックからインスタンスラベルの値を選択しましょう。 画面の下のほうで 2 つのインスタンスの値が識別されていることがわかります。 [Add] ボタンをクリックしてください。 ![](/sites/default/files/inline/images/grafana_templating.jpg) ダッシュボードの上部に、使用可能な値を持つ変数が追加されました。 ![](/sites/default/files/inline/images/grafana_variable_values.jpg) 次に、ダッシュボードの各パネルのリクエストにこの変数を追加しましょう。つまり、"_isc\_cache\_mgstat\_global\_refs_" のようなリクエストを "_isc\_cache\_mgstat\_global\_refs{instance="[[instance]]"}_" に変更します。 最終的なダッシュボードは次のようになります(インスタンス名は意図的に凡例の横に残されています)。 ![](/sites/default/files/inline/images/grafana_dashboard_final.jpg) Singlestat パネルが機能するようになりました。 ![](/sites/default/files/inline/images/grafana_working_singlestat_0.jpg) このダッシュボードのテンプレートは [GitHub](https://github.com/myardyas/prometheus/raw/master/mgstat/grafana/mgstat_with_var_instance.json) からダウンロードできます。 テンプレートを Grafana にインポートする手順は[この記事のパート 1](https://community.intersystems.com/post/making-prometheus-monitoring-intersystems-cach%C3%A9)で説明しています。 最後に、サーバー 192.168.42.132 を 192.168.42.131 の ECP クライアントにして ECP トラフィックを生成するためのグローバルを作成しましょう。 次のように、ECP クライアントの監視が機能していることがわかります。 ![](/sites/default/files/inline/images/grafana_ecp.jpg) まとめ ^mgstat の結果を Excel で表示する代わりに、見栄えの良いグラフを使ったダッシュボードをオンラインで使用することができます。 デメリットは、^mgstat の代替バージョンを使用しなければならないことです。 一般的には元になるツールのコードは変更される可能性がありますが、その事は考慮されていません。 ただし、非常に楽な方法で Caché のパフォーマンスを監視することができます。 最後までお読みいただき、ありがとうございました! _つづく..._ **追伸** デモ(1 つのインスタンス用)はこちらで利用できます。ログイン/パスワードは必要ありません。
記事
Mihoko Iijima · 2020年4月27日

GitLabを使用したInterSystemsソリューションの継続的デリバリー - パート II:GitLabワークフロー

この連載記事では、InterSystemsの技術とGitLabを使用したソフトウェア開発に向けて実現可能な複数の手法を紹介し、議論したいと思います。 次のようなトピックについて説明します。 Git 101 Gitフロー(開発プロセス) GitLabのインストール GitLabワークフロー 継続的デリバリー GitLabのインストールと構成 GitLab CI/CD 前の記事では、Gitの基本、Gitの概念を高度に理解することが現代のソフトウェア開発にとって重要である理由、Gitを使用してソフトウェアを開発する方法について説明しました。 なお、前の記事ではソフトウェア開発の実装部分を中心に取り扱っていましたが、このパートでは以下を取り扱います。 GitLabワークフロー - アイデアからユーザーフィードバックまでの完全なソフトウェアライフサイクルプロセス。 継続的デリバリー - チームが短いサイクルでソフトウェアを作成し、ソフトウェアをいつでも確実にリリースできるようにするソフトウェアエンジニアリング手法です。 この手法はソフトウェアの構築、テスト、リリースをより速く、より頻繁に行うことを目指しています。 GitLabワークフロー GitLabワークフローは、ソフトウェア開発プロセスのライフサイクル全体で実行可能な操作を論理的に並べたものです。 GitLabワークフローは、前の記事で説明したGitLabフローを考慮に入れています。 以下にそのイメージを掲載します。 アイデア:新しい提案はすべて、アイデアから始まります。 課題:アイデアを議論するには、そのための課題を作成するのが最も効果的です。 チームとコラボレーターが課題トラッカーでアイデアの洗練と改善を支援します。 計画:議論が合意に達したら、コーディングに取りかかります。 ただし、まずは課題をマイルストーンと課題ボードに割り当て、ワークフローに優先順位を付けて整理する必要があります。 コード:すべてを整理したら、コードを作成できるようになります。 コミット:ドラフトに満足したら、バージョン管理機能を使ってフィーチャーブランチにコードをコミットできるようになります。 GitLabフローについては、前の記事で詳しく説明しています。 テスト:GitLab CIを使用してスクリプトを実行し、アプリケーションをビルドおよびテストします。 レビュー:スクリプトが機能し、テストとビルドが成功すると、コードをレビューして承認する準備が整います。 ステージング:ここではコードをステージング環境にデプロイし、すべてが期待どおりに機能したかどうか、または調整が必要かどうかを確認します。 プロダクション:すべてが正常に機能するようになったら、プロダクション環境にデプロイします! フィードバック:ここでは作業を振り返り、作業のどのステージで改善が必要かを確認します。 繰り返しになりますが、このプロセス自体は新しいものではなく(その点ではGitLabに固有のものではありません)、その他お好みのツールでも実現できます。 これらのステージのいくつかと、その内容について説明しましょう。 ドキュメントも入手できます。 課題と計画 GitLabワークフローの最初のステージでは、課題(機能やバグ、あるいは意味的に区別されたその他の各種作業)に重点が置かれます。 課題には、次のようないくつかの目的があります。 実行管理:課題には期日、担当者、経過時間、見積などがあり、 問題解決の追跡に役立てることができます。 目標管理:課題は、バージョンが進化するにつれてソフトウェアを追跡できるマイルストーンやかんばんボードを構成しています。 開発:課題には関連する議論とコミットがあります。 計画ステージでは、課題を優先度、マイルストーン、かんばんボードごとにグループ化し、その概要を把握できます。 前のパートでは開発について説明しましたが、単にあなたが希望するgitフローに従ってください。 新しい機能を開発し、それをマスターにマージした後はどうなるでしょうか? 継続的デリバリー 継続的デリバリー - チームが短いサイクルでソフトウェアを作成し、ソフトウェアをいつでも確実にリリースできるようにするソフトウェアエンジニアリング手法です。 この手法はソフトウェアの構築、テスト、リリースをより速く、より頻繁に行うことを目指しています。 この手法では、実稼働中のアプリケーションに対してより多くの増分更新を行うことができ、それによって変更を配信するコスト、時間、およびリスクを削減することができます。 継続的デリバリーには、簡単で繰り返し可能な配信プロセスが重要です。 GitLabでの継続的デリバリー GitLabでは、継続的デリバリーの構成はリポジトリごとにYAML設定ファイルとして定義されます。 継続的デリバリーの設定は複数の連続するステージから構成されます。 各ステージには並列に実行される1つ以上のスクリプトがあります。 スクリプトは1つのアクションと、それを実行するために満たすべき条件を定義します。 何を実行するか(OSコマンドの実行、コンテナの実行)? スクリプトを実行するタイミング: トリガーは何か(特定ブランチへのコミット)? 前のステージが失敗した場合にアクションを実行するかどうか? 手動または自動のどちらで実行するのか? どの環境でスクリプトを実行するのか? スクリプトを実行した後にどのアーティファクトを保存するのか(これらはアクセスしやすいように環境からGitLabにアップロードされます)? 環境はスクリプトを実行できる構成済みのサーバーまたはコンテナです。 ランナーは特定の環境でスクリプトを実行します。 これらはGitLabに接続され、必要に応じてスクリプトを実行します。 ランナーは、サーバー、コンテナ、またはローカルマシンにデプロイできます。 継続的デリバリーはどのように行われますか? 新しいコミットがリポジトリにプッシュされます。 GitLabが継続的デリバリーの構成をチェックします。 継続的デリバリーの構成にはあらゆるケースに対応したすべてのスクリプトが含まれているため、この特定のコミットに対して実行する必要があるスクリプトセットに絞り込まれます(例えばmasterブランチへのコミットの場合、masterブランチに関連するアクションのみをトリガーします)。 このセットはパイプラインと呼ばれます。 パイプラインはターゲット環境で実行され、実行結果はGitLabに保存および表示されます。 例えば、masterブランチへのコミット後に実行される1つのパイプラインは次のとおりです。 これは連続して実行される4つのステージで構成されています。 読み込みステージではコードがサーバーに読み込まれます。 テストステージではユニットテストが実行されます。 パッケージステージでは、次の2つのスクリプトが並列実行されます。 クライアントのビルド サーバーコードのエクスポート(主に情報提供のため) デプロイステージでは、ビルドされたクライアントがウェブサーバーのディレクトリに移動されます。 ご覧のとおり、各スクリプトは順番に実行されます。デフォルトではいずれかのスクリプトが失敗した場合、後続のスクリプトは実行されません(ただし、この動作は変更できます)。 スクリプトを開くと、ログを確認して失敗の原因を特定できます。 Running with gitlab-runner 10.4.0 (857480b6) on test runner (ab34a8c5) Using Shell executor... Running on gitlab-test... Fetching changes... Removing diff.xml Removing full.xml Removing index.html Removing tests.html HEAD is now at a5bf3e8 Merge branch '4-versiya-1-0' into 'master' From http://gitlab.eduard.win/test/testProject * [new branch] 5-versiya-1-1 -> origin/5-versiya-1-1 a5bf3e8..442a4db master -> origin/master d28295a..42a10aa preprod -> origin/preprod 3ac4b21..7edf7f4 prod -> origin/prod Checking out 442a4db1 as master... Skipping Git submodules setup $ csession ensemble "##class(isc.git.GitLab).loadDiff()" [2018-03-06 13:58:19.188] Importing dir /home/gitlab-runner/builds/ab34a8c5/0/test/testProject/ [2018-03-06 13:58:19.188] Loading diff between a5bf3e8596d842c5cc3da7819409ed81e62c31e3 and 442a4db170aa58f2129e5889a4bb79261aa0cad0 [2018-03-06 13:58:19.192] Variable modified var=$lb("MyApp/Info.cls") Load started on 03/06/2018 13:58:19 Loading file /home/gitlab-runner/builds/ab34a8c5/0/test/testProject/MyApp/Info.cls as udl Load finished successfully. [2018-03-06 13:58:19.241] Variable items var="MyApp.Info.cls" var("MyApp.Info.cls")="" Compilation started on 03/06/2018 13:58:19 with qualifiers 'cuk /checkuptodate=expandedonly' Compiling class MyApp.Info Compiling routine MyApp.Info.1 ERROR: MyApp.Info.cls(version+2) #1003: Expected space : '}' : Offset:14 [zversion+1^MyApp.Info.1] TEXT: quit, "1.0" } Detected 1 errors during compilation in 0.010s. [2018-03-06 13:58:19.252] ERROR #5475: Error compiling routine: MyApp.Info.1. Errors: ERROR: MyApp.Info.cls(version+2) #1003: Expected space : '}' : Offset:14 [zversion+1^MyApp.Info.1] > ERROR #5030: An error occurred while compiling class 'MyApp.Info' ERROR: Job failed: exit status 1 コンパイルエラーが原因でスクリプトが失敗していました。 まとめ GitLabはソフトウェア開発のすべての主なステージをサポートしています。 継続的デリバリーはソフトウェアのビルド、テスト、デプロイのタスクを自動化するのに役立ちます。 リンク パート I:Git GitLabワークフローの概要 GitLab CI/CDドキュメント GitLabフロー この記事のコード 次の内容 次の記事での実施内容: GitLabをインストールします。 それをInterSystems製品がインストールされているいくつかの環境と連携させます。 継続的デリバリーを構成します。 継続的デリバリーの仕組みを説明しましょう。 まず、いくつかの環境とそれに対応するブランチが必要です。 コードはこのブランチに投入され、ターゲット環境に配信されます。 環境 ブランチ 配信 コミット可能な人 マージ可能な人 Test master 自動 開発者  所有者 開発者  所有者 Preprod preprod 自動 該当なし 所有者 Prod prod 半自動(ボタンを押して配信) 該当なし 所有者 また、GitLabフローを使用して1つの新しい機能を開発し、GitLab CDを使用して配信する例を以下に記載します。 機能はフィーチャーブランチで開発されます。 フィーチャーブランチがレビューされ、masterブランチにマージされます。 しばらくすると(いくつかのフィーチャーブランチがマージされた)マスターがpreprodにマージされます。 しばらくすると(ユーザーテストなどの後に)preprodがprodにマージされます。 これは次のようになります。 開発とテスト 開発者は新しい機能のコードを別のフィーチャーブランチにコミットします。 機能が安定した後、開発者はフィーチャーブランチをmasterブランチにマージします。 masterブランチのコードはテスト環境に配信され、そこで読み込まれてテストされます。 Preprod環境への配信 開発者はmasterブランチからpreprodブランチへのマージリクエストを作成します。 その後、リポジトリ所有者がマージリクエストを承認します。 preprodブランチのコードがPreprod環境に配信されます。 Prod環境への配信 開発者はpreprodブランチからprodブランチへのマージリクエストを作成します。 その後、リポジトリ所有者がマージリクエストを承認します。 リポジトリ所有者が「Deploy」ボタンを押します。 prodブランチのコードがProd環境に配信されます。 同じ内容を図に表すと次のようになります。
記事
Mihoko Iijima · 2020年4月28日

GitLabを使用したInterSystemsソリューションの継続的デリバリー - パートIV:CDの構成

この連載記事では、InterSystemsの技術とGitLabを使用したソフトウェア開発に向けて実現可能な複数の手法を紹介し、議論したいと思います。 次のようなトピックについて説明します。 Git 101 Gitフロー(開発プロセス) GitLabのインストール GitLabワークフロー 継続的デリバリー GitLabのインストールと構成 GitLab CI/CD 第1回の記事では、Gitの基本、Gitの概念を高度に理解することが現代のソフトウェア開発にとって重要である理由、Gitを使用してソフトウェアを開発する方法について説明しました。 第2回の記事では、アイデアからユーザーフィードバックまでの完全なソフトウェアライフサイクルプロセスであるGitLabワークフローについて説明しました。 第3回の記事では、GitLabのインストールと構成ならびに利用環境のGitLabへの接続について説明しました。 この記事では、最終的にCDの構成を作成します。 計画 環境 まず、いくつかの環境とそれに対応するブランチが必要です。 環境 ブランチ デリバリー コミット可能な人 マージ可能な人 Test master 自動 開発者  所有者 開発者  所有者 Preprod preprod 自動 該当なし 所有者 Prod prod 半自動(ボタンを押して配信) 該当なし 所有者 開発サイクル また、GitLabフローを使用して1つの新しい機能を開発し、GitLab CDを使用して配信する例を以下に記載します。 機能はフィーチャーブランチで開発されます。 フィーチャーブランチがレビューされ、masterブランチにマージされます。 しばらくすると(いくつかのフィーチャーブランチがマージされた)マスターがpreprodにマージされます。 しばらくすると(ユーザーテストなどの後に)preprodがprodにマージされます。 その流れは次のようになります(CDのために開発する必要がある部分を筆記体で示しています)。 開発とテスト 開発者は新しい機能のコードを別のフィーチャーブランチにコミットします。 機能が安定した後、開発者はフィーチャーブランチをmasterブランチにマージします。 masterブランチのコードはテスト環境に配信され、そこで読み込まれてテストされます。 Preprod環境への配信 開発者はmasterブランチからpreprodブランチへのマージリクエストを作成します。 その後、リポジトリ所有者がマージリクエストを承認します。 preprodブランチのコードがPreprod環境に配信されます。 Prod環境への配信 開発者はpreprodブランチからprodブランチへのマージリクエストを作成します。 その後、リポジトリ所有者がマージリクエストを承認します。 リポジトリ所有者が「デプロイ」ボタンを押します。 prodブランチのコードがProd環境に配信されます。 同じ内容を図に表すと次のようになります。 アプリケーション 私たちのアプリケーションは次の2つの部分で構成されています。 InterSystemsプラットフォームで開発されたREST API クライアントJavaScriptウェブアプリケーション ステージ 上記の計画から、継続的デリバリーの構成で定義する必要があるステージを決定できます。 読み込み - サーバーサイドのコードをInterSystems IRISにインポートします テスト - クライアントとサーバーのコードをテストします パッケージ - クライアントのコードをビルドします デプロイ - ウェブサーバーを使用してクライアントのコードを「公開」します 以下に .gitlab-ci.yml 構成ファイルの内容を示します。 stages: - load - test - package - deploy スクリプト 読み込み 次に、スクリプトを定義しましょう。 スクリプトのドキュメントはここにあります。 まずは次のようなサーバーサイドのコードを読み込むload serverスクリプトを定義しましょう。 load server: environment: name: test url: http://test.hostname.com only: - master tags: - test stage: load script: irissession IRIS "##class(isc.git.GitLab).load()" ここには何が書かれているのでしょうか? load serverはスクリプトの名前です。 次に、このスクリプトの実行環境について記述します。 only: masterはmasterブランチへのコミットがある場合にのみこのスクリプトを実行するようGitLabに指示しています。 tags: testはこのスクリプトをtestタグを持つランナーでのみ実行するよう指定しています。 stage はスクリプトのステージを指定しています。 script は実行するコードを定義しています。 このケースでは、isc.git.GitLabクラスのloadクラスメソッドを呼び出しています。 それでは、対応するisc.git.GitLabクラスを書きましょう。 このクラスのすべてのエントリポイントは次のようになります。 ClassMethod method() { try { // code halt } catch ex { write !,$System.Status.GetErrorText(ex.AsStatus()),! do $system.Process.Terminate(, 1) } } このメソッドは次の2つの方法で終了できます。 現在のプロセスを停止する。この場合はGitLabに正常終了したものとして登録されます。 $system.Process.Terminateを呼び出す。この場合はプロセスが異常終了し、GitLabにエラーとして登録されます。 したがって、読み込み用のコードは次のようになります。 /// Do a full load /// do ##class(isc.git.GitLab).load() ClassMethod load() { try { set dir = ..getDir() do ..log("Importing dir " _ dir) do $system.OBJ.ImportDir(dir, ..getExtWildcard(), "c", .errors, 1) throw:$get(errors,0)'=0 ##class(%Exception.General).%New("Load error") halt } catch ex { write !,$System.Status.GetErrorText(ex.AsStatus()),! do $system.Process.Terminate(, 1) } } ここでは次の2つのユーティリティメソッドが呼び出されています。 getExtWildcard - 関連するファイル拡張子のリストを取得します getDir - リポジトリのディレクトリを取得します ディレクトリを取得するには? GitLabは最初にスクリプトを実行するとき、多くの環境変数を指定します。 その中にはリポジトリが複製され、ジョブが実行されるフルパスである CI_PROJECT_DIR があります。 この環境変数は、次のように getDir メソッドで簡単に取得できます。 ClassMethod getDir() [ CodeMode = expression ] { ##class(%File).NormalizeDirectory($system.Util.GetEnviron("CI_PROJECT_DIR")) } テスト テストスクリプトは次のとおりです。 load test: environment: name: test url: http://test.hostname.com only: - master tags: - test stage: test script: irissession IRIS "##class(isc.git.GitLab).test()" artifacts: paths: - tests.html 何が変わったのでしょうか? 名前とスクリプトコードはもちろんですが、artifactも追加されました。 アーティファクトとは、ジョブが正常に完了した後にジョブに添付されるファイルとディレクトリのリストです。 このケースでは、テストが完了した後、テスト結果にリダイレクトするHTMLページを生成し、GitLabから利用できるようにします。 ここでは読み込みステージからコピーして貼り付けられたコードがたくさんあることに注意してください。環境は同じです。環境などのスクリプト部分は個別にラベル付けしてスクリプトに添付できます。 次のようにテスト環境を定義しましょう。 .env_test: &env_test environment: name: test url: http://test.hostname.com only: - master tags: - test テストスクリプトの内容は次のようになります。 load test: <<: *env_test script: irissession IRIS "##class(isc.git.GitLab).test()" artifacts: paths: - tests.html 次に、UnitTestフレームワークを使用してテストを実行しましょう。 /// do ##class(isc.git.GitLab).test() ClassMethod test() { try { set tests = ##class(isc.git.Settings).getSetting("tests") if (tests'="") { set dir = ..getDir() set ^UnitTestRoot = dir $$$TOE(sc, ##class(%UnitTest.Manager).RunTest(tests, "/nodelete")) $$$TOE(sc, ..writeTestHTML()) throw:'..isLastTestOk() ##class(%Exception.General).%New("Tests error") } halt } catch ex { do ..logException(ex) do $system.Process.Terminate(, 1) } } この場合、テストの設定はユニットテストが保存されているリポジトリルートに対する相対パスになります。 空の場合はテストをスキップします。 writeTestHTML メソッドは、テスト結果にリダイレクトを含むhtmlを出力するために使用されます。 ClassMethod writeTestHTML() { set text = ##class(%Dictionary.XDataDefinition).IDKEYOpen($classname(), "html").Data.Read() set text = $replace(text, "!!!", ..getURL()) set file = ##class(%Stream.FileCharacter).%New() set name = ..getDir() _ "tests.html" do file.LinkToFile(name) do file.Write(text) quit file.%Save() } ClassMethod getURL() { set url = ##class(isc.git.Settings).getSetting("url") set url = url _ $system.CSP.GetDefaultApp("%SYS") set url = url_"/%25UnitTest.Portal.Indices.cls?Index="_ $g(^UnitTest.Result, 1) _ "&$NAMESPACE=" _ $zconvert($namespace,"O","URL") quit url } ClassMethod isLastTestOk() As %Boolean { set in = ##class(%UnitTest.Result.TestInstance).%OpenId(^UnitTest.Result) for i=1:1:in.TestSuites.Count() { #dim suite As %UnitTest.Result.TestSuite set suite = in.TestSuites.GetAt(i) return:suite.Status=0 $$$NO } quit $$$YES } XData html { <html lang="en-US"> <head> <meta charset="UTF-8"/> <meta http-equiv="refresh" content="0; url=!!!"/> <script type="text/javascript"> window.location.href = "!!!" </script> </head> <body> If you are not redirected automatically, follow this <a href='!!!'>link to tests</a>. </body> </html> パッケージ クライアントは次のようなシンプルなHTMLページです。 <html> <head> <script type="text/javascript"> function initializePage() { var xhr = new XMLHttpRequest(); var url = "${CI_ENVIRONMENT_URL}:57772/MyApp/version"; xhr.open("GET", url, true); xhr.send(); xhr.onloadend = function (data) { document.getElementById("version").innerHTML = "Version: " + this.response; }; var xhr = new XMLHttpRequest(); var url = "${CI_ENVIRONMENT_URL}:57772/MyApp/author"; xhr.open("GET", url, true); xhr.send(); xhr.onloadend = function (data) { document.getElementById("author").innerHTML = "Author: " + this.response; }; } </script> </head> <body onload="initializePage()"> <div id = "version"></div> <div id = "author"></div> </body> </html> また、これをビルドするには ${CI_ENVIRONMENT_URL} をその値と置き換える必要があります。 当然ながら、実際のアプリケーションではおそらくnpmが必要になるでしょう。しかし、これは単なる見本です。 スクリプトは次のとおりです。 package client: <<: *env_test stage: package script: envsubst < client/index.html > index.html artifacts: paths: - index.html デプロイ 最後に、index.htmlをウェブサーバーのルートディレクトリにコピーし、クライアントをデプロイします。 deploy client: <<: *env_test stage: deploy script: cp -f index.html /var/www/html/index.html 以上です! 複数の環境 複数の環境で同じ(同様の)スクリプトを実行する必要がある場合はどうしますか? スクリプト部分はラベルにすることもできます。そのため、test環境とpreprod環境でコードを読み込むサンプル構成を次に示します。 stages: - load - test .env_test: &env_test environment: name: test url: http://test.hostname.com only: - master tags: - test .env_preprod: &env_preprod environment: name: preprod url: http://preprod.hostname.com only: - preprod tags: - preprod .script_load: &script_load stage: load script: irissession IRIS "##class(isc.git.GitLab).loadDiff()" load test: <<: *env_test <<: *script_load load preprod: <<: *env_preprod <<: *script_load このようにして、コードのコピー&ペーストを回避することができます。 完全なCDの構成はこちらから取得できます。 この構成はtest環境、preprod環境、prod環境間でコードを移動するという当初の計画に従っています。 まとめ 継続的デリバリーは、必要な開発ワークフローを自動化するように構成できます。 リンク Hooksリポジトリ(およびサンプル構成) テストリポジトリ スクリプトのドキュメント 利用可能な環境変数 次の内容 次の記事では、InterSystems IRIS Dockerコンテナを活用するCD構成を作成します。
記事
Toshihiko Minamoto · 2020年5月10日

例: デフォルトREST APIを使用したInterSystems IRISの監視メトリックのレビュー

次の手順で、/api/monitor サービスから利用可能なメトリックのサンプル一覧を表示することができます。 前回の投稿では、IRISのメトリックをPrometheus形式で公開するサービスの概要を説明しました。 この投稿では、コンテナにIRISプレビューリリース2019.4 をセットアップして実行し、メトリックを一覧表示する方法をお伝えします。 この投稿は、Dockerがインストールされた環境があることを前提としています。 そうでない場合は、今すぐお使いのプラットフォームにインストールしてください :) ステップ 1. dockerでIRISプレビューをダウンロードして実行する 「プレビューの配布」のダウンロード手順に従い、プレビューライセンスキーとIRISのDockerイメージをダウンロードします。 この例では、InterSystems IRIS for Health 2019.4を選択しています。 「機能紹介:Dockerコンテナ内のInterSystems製品について」の指示に従ってください。 すでにコンテナに精通している場合は、「InterSystems IRISのDockerイメージをダウンロードする」というタイトルのセクションに進んでください。 次のターミナル出力は、私がDockerイメージの読み込みに使用している手順を示しています。 docker loadコマンドの実行には数分かかる場合があります。 $ pwd /Users/myhome/Downloads/iris_2019.4 $ ls InterSystems IRIS for Health (Container)_2019.4.0_Docker(Ubuntu)_12-31-2019.ISCkey irishealth-2019.4.0.379.0-docker.tar $ docker load -i irishealth-2019.4.0.379.0-docker.tar 762d8e1a6054: Loading layer [==================================================>] 91.39MB/91.39MB e45cfbc98a50: Loading layer [==================================================>] 15.87kB/15.87kB d60e01b37e74: Loading layer [==================================================>] 12.29kB/12.29kB b57c79f4a9f3: Loading layer [==================================================>] 3.072kB/3.072kB b11f1f11664d: Loading layer [==================================================>] 73.73MB/73.73MB 22202f62822e: Loading layer [==================================================>] 2.656GB/2.656GB 50457c8fa41f: Loading layer [==================================================>] 14.5MB/14.5MB bc4f7221d76a: Loading layer [==================================================>] 2.048kB/2.048kB 4db3eda3ff8f: Loading layer [==================================================>] 1.491MB/1.491MB Loaded image: intersystems/irishealth:2019.4.0.379.0 $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE intersystems/irishealth 2019.4.0.379.0 975a976ad1f4 3 weeks ago 2.83GB 作業しやすくするため、永続ストレージに使用するフォルダーの場所にキーファイルをコピーし、名前を iris.keyに変更します。 $ mkdir -p /Users/myhome/iris/20194 $ cp 'InterSystems IRIS for Health (Container)_2019.4.0_Docker(Ubuntu)_12-31-2019.ISCkey' /Users/myhome/iris/20194/iris.key $ cd /Users/myhome/iris/20194 $ ls iris.key 次のように、永続ストレージに作成したフォルダーを使用してIRISを起動します。 $ docker run --name iris --init --detach --publish 52773:52773 --volume `pwd`:/external intersystems/irishealth:2019.4.0.379.0 --key /external/iris.key $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 009e52c121f0 intersystems/irishealth:2019.4.0.379.0 "/iris-main --key /e…" About a minute ago Up About a minute (healthy) 0.0.0.0:52773->52773/tcp iris 成功しました。 これでコンテナ内で実行中のシステム管理ポータルに接続できるようになりました。 今回はパスワードに「SuperUser/SYS」を使用しましたが、初回実行時はパスワードの変更が促されます。 「システム > セキュリティ管理 > Webアプリケーション」を開き、Webアプリケーションに移動します。 次のWebアプリケーションが表示されています:/api/monitorはIRISのメトリックを公開するサービスです。 メトリックスを返すために何か特別な設定を行う必要はありません。何もしなくても機能します。 ステップ 2. メトリックをプレビューする 今後の投稿では、このエンドポイントをPrometheusやSAMを使ってスクレイピングし、設定された間隔でメトリックを収集します。 しかし、現時点ではこのインスタンスに対して返されるメトリックの完全なリストを見ることにしましょう。 例えば、LinuxとOSXでは curl コマンドを使用してHTTP GETを発行するのがお手軽です。 例えば、私の(あまり活用していない)コンテナでは次のようなメトリックからリストが表示されます。 $ curl localhost:52773/api/monitor/metrics : : iris_cpu_usage 0 iris_csp_activity{id="127.0.0.1:52773"} 56 iris_csp_actual_connections{id="127.0.0.1:52773"} 8 iris_csp_gateway_latency{id="127.0.0.1:52773"} .588 iris_csp_in_use_connections{id="127.0.0.1:52773"} 1 iris_csp_private_connections{id="127.0.0.1:52773"} 0 iris_csp_sessions 1 iris_cache_efficiency 35.565 : : 以下、同様です。このリストは、本番環境では非常に長くなることがあります。 この投稿の最後に完全なリストを掲載しています。 Postmanアプリケーションを使用するのも便利ですが、他にも方法はあります。 ご利用中のプラットフォームにPostmanがインストールされている場合、HTTP GETを発行すれば返されるメトリックを確認できます。 概要 現時点でやるべきことは以上です。 次の投稿では、先にPrometheusでのデータ収集について説明し、その後にGrafanaダッシュボードのサンプルをご紹介します。 プレビューコンテナの完全なリスト 本番環境では、より多くのメトリックを使用できます。 いくつかのラベルからお分かりのように、{id="IRISLOCALDATA"} のようにデータベースごと、またはプロセスタイプ {id="CSPDMN"} ごとのCPUメトリックもあります。 iris_cpu_pct{id="CSPDMN"} 0 iris_cpu_pct{id="CSPSRV"} 0 iris_cpu_pct{id="ECPWorker"} 0 iris_cpu_pct{id="GARCOL"} 0 iris_cpu_pct{id="JRNDMN"} 0 iris_cpu_pct{id="LICENSESRV"} 0 iris_cpu_pct{id="WDSLAVE"} 0 iris_cpu_pct{id="WRTDMN"} 0 iris_cpu_usage 0 iris_csp_activity{id="127.0.0.1:52773"} 57 iris_csp_actual_connections{id="127.0.0.1:52773"} 8 iris_csp_gateway_latency{id="127.0.0.1:52773"} .574 iris_csp_in_use_connections{id="127.0.0.1:52773"} 1 iris_csp_private_connections{id="127.0.0.1:52773"} 0 iris_csp_sessions 1 iris_cache_efficiency 35.850 iris_db_expansion_size_mb{id="ENSLIB"} 0 iris_db_expansion_size_mb{id="HSCUSTOM"} 0 iris_db_expansion_size_mb{id="HSLIB"} 0 iris_db_expansion_size_mb{id="HSSYS"} 0 iris_db_expansion_size_mb{id="IRISAUDIT"} 0 iris_db_expansion_size_mb{id="IRISLOCALDATA"} 0 iris_db_expansion_size_mb{id="IRISSYS"} 0 iris_db_expansion_size_mb{id="IRISTEMP"} 0 iris_db_free_space{id="ENSLIB"} .055 iris_db_free_space{id="HSCUSTOM"} 2.3 iris_db_free_space{id="HSLIB"} 113 iris_db_free_space{id="HSSYS"} 9.2 iris_db_free_space{id="IRISAUDIT"} .094 iris_db_free_space{id="IRISLOCALDATA"} .34 iris_db_free_space{id="IRISSYS"} 6.2 iris_db_free_space{id="IRISTEMP"} 20 iris_db_latency{id="ENSLIB"} 0.030 iris_db_latency{id="HSCUSTOM"} 0.146 iris_db_latency{id="HSLIB"} 0.027 iris_db_latency{id="HSSYS"} 0.018 iris_db_latency{id="IRISAUDIT"} 0.017 iris_db_latency{id="IRISSYS"} 0.020 iris_db_latency{id="IRISTEMP"} 0.021 iris_db_max_size_mb{id="ENSLIB"} 0 iris_db_max_size_mb{id="HSCUSTOM"} 0 iris_db_max_size_mb{id="HSLIB"} 0 iris_db_max_size_mb{id="HSSYS"} 0 iris_db_max_size_mb{id="IRISAUDIT"} 0 iris_db_max_size_mb{id="IRISLOCALDATA"} 0 iris_db_max_size_mb{id="IRISSYS"} 0 iris_db_max_size_mb{id="IRISTEMP"} 0 iris_db_size_mb{id="HSLIB",dir="/usr/irissys/mgr/hslib/"} 1321 iris_db_size_mb{id="HSSYS",dir="/usr/irissys/mgr/hssys/"} 21 iris_db_size_mb{id="ENSLIB",dir="/usr/irissys/mgr/enslib/"} 209 iris_db_size_mb{id="IRISSYS",dir="/usr/irissys/mgr/"} 113 iris_db_size_mb{id="HSCUSTOM",dir="/usr/irissys/mgr/HSCUSTOM/"} 11 iris_db_size_mb{id="IRISTEMP",dir="/usr/irissys/mgr/iristemp/"} 21 iris_db_size_mb{id="IRISAUDIT",dir="/usr/irissys/mgr/irisaudit/"} 1 iris_db_size_mb{id="IRISLOCALDATA",dir="/usr/irissys/mgr/irislocaldata/"} 1 iris_directory_space{id="HSLIB",dir="/usr/irissys/mgr/hslib/"} 53818 iris_directory_space{id="HSSYS",dir="/usr/irissys/mgr/hssys/"} 53818 iris_directory_space{id="ENSLIB",dir="/usr/irissys/mgr/enslib/"} 53818 iris_directory_space{id="IRISSYS",dir="/usr/irissys/mgr/"} 53818 iris_directory_space{id="HSCUSTOM",dir="/usr/irissys/mgr/HSCUSTOM/"} 53818 iris_directory_space{id="IRISTEMP",dir="/usr/irissys/mgr/iristemp/"} 53818 iris_directory_space{id="IRISAUDIT",dir="/usr/irissys/mgr/irisaudit/"} 53818 iris_disk_percent_full{id="HSLIB",dir="/usr/irissys/mgr/hslib/"} 10.03 iris_disk_percent_full{id="HSSYS",dir="/usr/irissys/mgr/hssys/"} 10.03 iris_disk_percent_full{id="ENSLIB",dir="/usr/irissys/mgr/enslib/"} 10.03 iris_disk_percent_full{id="IRISSYS",dir="/usr/irissys/mgr/"} 10.03 iris_disk_percent_full{id="HSCUSTOM",dir="/usr/irissys/mgr/HSCUSTOM/"} 10.03 iris_disk_percent_full{id="IRISTEMP",dir="/usr/irissys/mgr/iristemp/"} 10.03 iris_disk_percent_full{id="IRISAUDIT",dir="/usr/irissys/mgr/irisaudit/"} 10.03 iris_ecp_conn 0 iris_ecp_conn_max 2 iris_ecp_connections 0 iris_ecp_latency 0 iris_ecps_conn 0 iris_ecps_conn_max 1 iris_glo_a_seize_per_sec 0 iris_glo_n_seize_per_sec 0 iris_glo_ref_per_sec 7 iris_glo_ref_rem_per_sec 0 iris_glo_seize_per_sec 0 iris_glo_update_per_sec 2 iris_glo_update_rem_per_sec 0 iris_journal_size 2496 iris_journal_space 50751.18 iris_jrn_block_per_sec 0 iris_jrn_entry_per_sec 0 iris_jrn_free_space{id="WIJ",dir="default"} 50751.18 iris_jrn_free_space{id="primary",dir="/usr/irissys/mgr/journal/"} 50751.18 iris_jrn_free_space{id="secondary",dir="/usr/irissys/mgr/journal/"} 50751.18 iris_jrn_size{id="WIJ"} 100 iris_jrn_size{id="primary"} 2 iris_jrn_size{id="secondary"} 0 iris_license_available 31 iris_license_consumed 1 iris_license_percent_used 3 iris_log_reads_per_sec 5 iris_obj_a_seize_per_sec 0 iris_obj_del_per_sec 0 iris_obj_hit_per_sec 2 iris_obj_load_per_sec 0 iris_obj_miss_per_sec 0 iris_obj_new_per_sec 0 iris_obj_seize_per_sec 0 iris_page_space_per_cent_used 0 iris_phys_mem_per_cent_used 95 iris_phys_reads_per_sec 0 iris_phys_writes_per_sec 0 iris_process_count 29 iris_rtn_a_seize_per_sec 0 iris_rtn_call_local_per_sec 10 iris_rtn_call_miss_per_sec 0 iris_rtn_call_remote_per_sec 0 iris_rtn_load_per_sec 0 iris_rtn_load_rem_per_sec 0 iris_rtn_seize_per_sec 0 iris_sam_get_db_sensors_seconds .000838 iris_sam_get_jrn_sensors_seconds .001024 iris_system_alerts 0 iris_system_alerts_new 0 iris_system_state 0 iris_trans_open_count 0 iris_trans_open_secs 0 iris_trans_open_secs_max 0 iris_wd_buffer_redirty 0 iris_wd_buffer_write 0 iris_wd_cycle_time 0 iris_wd_proc_in_global 0 iris_wd_size_write 0 iris_wd_sleep 10002 iris_wd_temp_queue 42 iris_wd_temp_write 0 iris_wdwij_time 0 iris_wd_write_time 0 iris_wij_writes_per_sec 0
記事
Tomohiro Iwamoto · 2020年6月3日

InterSystemsデータプラットフォームのキャパシティプランニングとパフォーマンス」シリーズの索引

「データプラットフォームのキャパシティプランニングとパフォーマンス」シリーズの全記事をリストしました。 その下には私の一般的なその他の記事も記載しています。 このシリーズに新しい記事が追加されるたびに、このリストを更新する予定です。 「キャパシティプランニングとパフォーマンス」シリーズ 通常、各記事はその前の記事の続きとして書かれていますが、ほかの記事を飛び越して気になるものを読むこともできます。 パート1 - はじめの一歩、メトリックの収集 パート2 - 収集したメトリックの確認 パート3 - CPUに注目 パート4 - メモリの確認 パート5 - SNMPによる監視 パート6 - CachéストレージIOプロファイル パート7 - パフォーマンス、スケーラビリティ、可用性のためのECP パート8 - ハイパーコンバージドインフラストラクチャのキャパシティとパフォーマンス計画 パート9 - Caché VMwareのベストプラクティスガイド パート10 - VMバックアップとCachéのFreeze/Thawスクリプト パート11 - 大規模データベースの仮想化 - VMWareのCPUキャパシティプランニング その他の記事 コミュニティに掲載中のアーキテクチャ全般の記事を集めたリストです。 組み込みREST APIを使ったInterSystems IRISのモニタリング - Prometheus形式の使用 例: デフォルトのREST APIを使用したInterSystems IRISの監視メトリックの確認 InterSystemsデータプラットフォームとパフォーマンス - pButtonsの更新方法 pButtonsデータをcsvファイルに抽出してチャートを簡単に作成する Ansibleを使ったCachéアプリケーションのプロビジョニング(パート1) WindowsとCachéとウイルススキャナ ECPの魔法 コミュニティ記事を作成するためのMarkdownワークフロー Yape - Yet another pButtons extractor - もう1つのpButtonsエクストラクタ(及びチャートの自動作成) データベースの暗号化にかかる時間 最低限の監視及び警告ソリューション LVM PEストライピングでハイパーコンバージドストレージのスループットを最大化 YapeによるpButtonsの解凍 - 更新ノートとクイックガイド InterSystems テクノロジーアーキテクト マレー・オールドフィールド Twitterでコミュニティまたは@murray_oldfieldをフォロー
記事
Mihoko Iijima · 2020年7月6日

GitLabを使用したInterSystemsソリューションの継続的デリバリー - パートIX: コンテナアーキテクチャ

​​​​​​この連載記事では、InterSystemsの技術とGitLabを使用したソフトウェア開発に向けていくつかの可能性のあるアプローチを紹介し、説明したいと思います。以下のようなトピックについて取り上げます。 Git 101 Gitフロー(開発プロセス) GitLabのインストール GitLabワークフロー 継続的デリバリー GitLabのインストールと構成 GitLab CI/CD コンテナを使用する理由 コンテナインフラストラクチャ コンテナを使用したCD ICMを使用したCD コンテナアーキテクチャ この記事では、独自のコンテナを構築してデプロイ展開する方法について説明します。 Durable %SYS コンテナは一時的なものなので、アプリケーションデータを保存するべきではありません。Durable %SYS の機能により設定、構成、 %SYSデータなどをホストボリュームに保存することができます。 iris.cpfファイル /cspディレクトリ:Webゲートウェイの構成とログファイルが含まれています。 /httpd/httpd.confファイル:インスタンスのプライベートWebサーバーの構成ファイル。 /mgrディレクトリ: IRIS.DATおよびiris.lckファイルとストリームディレクトリで構成されるRISSYS システム・データベース、および IRISTEMP、IRISAUDIT、IRIS、USER システム・データベースを含む IRISTEMP、IRISAUDIT、IRIS、USER ディレクトリ。 ライトイメージジャーナルファイル:IRIS.WIJ ジャーナルファイルが格納される /jounal directory 一時ファイル用の /temp ディレクトリ messages.log、journal.log、およびSystemMonitor.logを含むログファイル。 コンテナアーキテクチャ 一方、必要に応じてアップグレードできるように、コンテナ内にアプリケーションコードを保存しておく必要があります。 これにより、次のアーキテクチャが実現します。 ビルド時にこれを実現するには、最低限、追加のデータベース(アプリケーション・コードを格納するための)を作成し、それをアプリケーションのネームスペースにマッピングする必要があります。 この例では、アプリケーションデータがすでに存在して耐久性もあるので、USERネームスペースを利用して保存します。 インストーラ 上記に基づいて、インストーラは次のことをする必要があります: APPネームスペース/データベースを作成する APPネームスペースにコードをロードする アプリケーションクラスをUSER ネームスペースにマッピングする 他のすべてのインストールを実行する(この場合、CSP WebアプリとRESTアプリを作成しました) Class MyApp.Hooks.Local{ Parameter Namespace = "APP"; /// See generated code in zsetup+1^MyApp.Hooks.Local.1XData Install [ XMLNamespace = INSTALLER ]{<Manifest> <Log Text="Creating namespace ${Namespace}" Level="0"/><Namespace Name="${Namespace}" Create="yes" Code="${Namespace}" Ensemble="" Data="IRISTEMP"><Configuration><Database Name="${Namespace}" Dir="/usr/irissys/mgr/${Namespace}" Create="yes" MountRequired="true" Resource="%DB_${Namespace}" PublicPermissions="RW" MountAtStartup="true"/></Configuration> <Import File="${Dir}Form" Recurse="1" Flags="cdk" IgnoreErrors="1" /></Namespace><Log Text="End Creating namespace ${Namespace}" Level="0"/> <Log Text="Mapping to USER" Level="0"/><Namespace Name="USER" Create="no" Code="USER" Data="USER" Ensemble="0"><Configuration><Log Text="Mapping Form package to USER namespace" Level="0"/><ClassMapping From="${Namespace}" Package="Form"/><RoutineMapping From="${Namespace}" Routines="Form" /></Configuration> <CSPApplication Url="/" Directory="${Dir}client" AuthenticationMethods="64" IsNamespaceDefault="false" Grant="%ALL" Recurse="1" /></Namespace> </Manifest>} /// This is a method generator whose code is generated by XGL./// Main setup method/// set vars("Namespace")="TEMP3"/// do ##class(MyApp.Hooks.Global).setup(.vars)ClassMethod setup(ByRef pVars, pLogLevel As %Integer = 0, pInstaller As %Installer.Installer) As %Status [ CodeMode = objectgenerator, Internal ]{ Quit ##class(%Installer.Manifest).%Generate(%compiledclass, %code, "Install")} /// Entry pointClassMethod onAfter() As %Status{ try { write "START INSTALLER",! set vars("Namespace") = ..#Namespace set vars("Dir") = ..getDir() set sc = ..setup(.vars) write !,$System.Status.GetErrorText(sc),! set sc = ..createWebApp() } catch ex { set sc = ex.AsStatus() write !,$System.Status.GetErrorText(sc),! } quit sc} /// Modify web app RESTClassMethod createWebApp(appName As %String = "/forms") As %Status{ set:$e(appName)'="/" appName = "/" _ appName #dim sc As %Status = $$$OK new $namespace set $namespace = "%SYS" if '##class(Security.Applications).Exists(appName) { set props("AutheEnabled") = $$$AutheUnauthenticated set props("NameSpace") = "USER" set props("IsNameSpaceDefault") = $$$NO set props("DispatchClass") = "Form.REST.Main" set props("MatchRoles")=":" _ $$$AllRoleName set sc = ##class(Security.Applications).Create(appName, .props) } quit sc} ClassMethod getDir() [ CodeMode = expression ]{##class(%File).NormalizeDirectory($system.Util.GetEnviron("CI_PROJECT_DIR"))} } 耐久性のないデータベースを作成するには、/usr/irissys/mgrのサブディレクトリを使用しますがこれは永続的ではありません。 ##class(%File).ManagerDirectory()への呼び出しは、内部コンテナディレクトリへのパスではなく、耐久性のあるディレクトリのパスを返すことに注意してください。 継続的デリバリーの構成 パートVIIをご参照ください。これらの2行(太字)を既存の構成に追加すればよいだけです。 run image: stage: run environment: name: $CI_COMMIT_REF_NAME url: http://$CI_COMMIT_REF_SLUG.docker.eduard.win/index.html tags: - test script: - docker run -d --expose 52773 --volume /InterSystems/durable/$CI_COMMIT_REF_SLUG:/data --env ISC_DATA_DIRECTORY=/data/sys --env VIRTUAL_HOST=$CI_COMMIT_REF_SLUG.docker.eduard.win --name iris-$CI_COMMIT_REF_NAME docker.eduard.win/test/docker:$CI_COMMIT_REF_NAME --log $ISC_PACKAGE_INSTALLDIR/mgr/messages.log volume引数は、ホストディレクトリをコンテナにマウントし、 ISC_DATA_DIRECTORY 変数は、どのディレクトリを使用するかをInterSystems IRISに示します。ドキュメントを引用します。 これらのオプションを使用して InterSystems IRISコンテナを実行すると、次のことが起こります。 指定された外部ボリュームがマウントされています。 環境変数 ISC_DATA_DIRECTORYで指定された耐久性のある%SYSディレクトリ(前に挙げた例のiconfig /)がすでに存在し、その中にdurable %SYSデータが含まれている場合、インスタンスのすべての内部ポインターがそのディレクトリにリセットされ、インスタンスはディレクトリに含まれるデータを使用します。 環境変数 ISC_DATA_DIRECTORYで指定された耐久性のある%SYSディレクトリはすでに存在しているが、耐久性のある%SYSデータが含まれていない場合、データはコピーされず、インスタンスはコンテナ内のインストールツリーのデータを使用して実行されます。つまり、インスタンス固有のデータには持続性がありません。 このため、コンテナを実行する前に、スクリプトにこの条件のチェックを含めることをお勧めします。 ISC_DATA_DIRECTORYで指定された耐久性のある%SYSディレクトリが存在しない場合: 指定された耐久性のある%SYSディレクトリが作成されます。 [耐久性のある%SYS ディレクトリ]のコンテンツにリストされているディレクトリとファイルは、インストールされた場所から耐久性のある%SYS ディレクトリにコピーされます(オリジナルはそのまま同じ場所に残ります)。 インスタンスのすべての内部ポインタは耐久性のある%SYSディレクトリにリセットされ、インスタンスはそこに含まれるデータを使用します。 更新 アプリケーションが進化して新しいバージョン(コンテナ)がリリースされたときに、コードをいくつか実行する必要があるかもしれません。 コンパイル前後のフック、スキーマの移行、単体テストなどが考えられますが、結局のところ、任意のコードを実行する必要があるということです。 そのため、アプリケーションを管理するフレームワークが必要です。 以前の記事 の中で、このフレームワークの基本構造を概説しましたが、もちろん、特定のアプリケーション要件に合わせてかなり拡張することができます。 まとめ コンテナ化されたアプリケーションの作成にはいくつかの考慮事項がありますが、InterSystems IRIS は、このプロセスを容易にするためのいくつかの機能を提供しています。 リンク 索引 記事のコード テストプロジェクト CDの構成を完成する Durable %SYSでCDの構成を完了する
お知らせ
Toshihiko Minamoto · 2023年5月24日

IRIS、IRIS for Health 2025.1 より Zen レポートは削除されます

Intersystems IRISおよびIRIS for Health 2025.1より、Zen レポートのメンテナンスが終了することをお知らせします。 これは、2018年のInterSystems IRIS発表時に非推奨となり、その後、2020年のInterSystems Reportsの搭載により、代替のレポート機能を提供したためです。 時系列の概要は以下の通りです。 2018年3月 InterSystems IRIS 2018.1導入 Zen Reportsの非推奨を発表、既存アプリケーションの継続性を確保するため出荷を継続 2020年4月 InterSystems IRIS 2020.1発表 InterSystems IRISおよびIRIS for Healthのユーザライセンス、Advanced ServerライセンスにIntersystems Reportsを組み入れる。 2023年5月 Zen レポートのメンテナンス終了のお知らせ 2024年の2H Zen レポートがipmモジュールとして利用可能 2025 年 1 月 (InterSystems IRIS 2025.1) Zen Reports パッケージが InterSystems IRIS および IRIS for Health のキットから削除 インターシステムズは、InterSystems IRISおよびIRIS for Health 2020.1より、組み込み型レポートソリューションとして、insightsoftware社(旧Logi Analytics社)のLogi Reportsを搭載したInterSystems Reportsを発表しました。InterSystems Reportsは、InterSystemsの顧客とパートナーに、ドラッグ&ドロップで利用できる最新のレポートソリューションを提供します。 Zen Reportsは、IPM(InterSystems Package Manager)を使用した独立したパッケージに移行し、InterSystems IRISおよびIRIS for Healthバージョン2025.1とともにZen Reportsの出荷を停止する予定です。Zen レポートは今後もIPMモジュールとして利用可能であり、配布される可能性がありますが、インターシステムズ社による保守は行われません。 WRCは、Zen レポートを含むCacheおよびIRISの旧バージョンに関するサポートを継続しますが、Zen レポートの更新は予定されていません。 InterSystems Reports の使用開始に関する詳細については、こちらをご覧ください。 InterSystems ラーニングパス InterSystems ドキュメント グローバルサミットセッション: インターシステムズ・アプリケーション・サービスによる Zen Reports から InterSystems Reports への移行 insightsoftware社 Logi Report ドキュメントならびにチュートリアル 本発表に関するご質問は、以下のコメントまたは dbpprodmgrs@intersystems.com までご連絡ください。

#Web Gateway

13 投稿0 フォロワー
お知らせ
Mihoko Iijima · 2025年4月8日

★受賞者発表!★InterSystems AI プログラミングコンテスト:ベクトル検索、生成AI、AIエージェント(USコミュニティ)

開発者の皆さん、こんにちは! InterSystems AI プログラミングコンテスト:ベクトル検索、生成AI、AIエージェント(USコミュニティ)の勝者が発表されましたのでお知らせします! 今回のコンテストには 15 の素晴らしいアプリケーション 🔥が投稿されました。 ご応募いただきました参加者の皆さん、素敵な作品をありがとうございました。 それでは受賞者を発表します! Experts Nomination 🥇 1位 - $5,000 は、bg-iris-agent を開発された @geotat さん @Elena.Karpova さん @Alena.Krasinskiene さんに贈られました。 🥈 2位 - $2,500 は、mcp-server-iris を開発された @Dmitry.Maslennikov さんに贈られました。 🥉 3位 - $1,000 は、langchain-iris-tool を開発された @Yuri.Gomes さんに贈られました。 🏅 4位 - $500 は、Facilis を開発された @Henrique さん @henry さん @José.Pereira さんに贈られました。 🏅 5位 - $300 は、toot を開発された @Alex.Woodhead さんに贈られました。 🌟 $100 - iris-AgenticAI を開発された @Muhammad.Waseem さんに贈られました。 🌟 $100 - iris-easybot を開発された @Eric.Fortenberry さんに贈られました。 🌟 $100 - oncorag を開発された Patrick Salome さんに贈られました。 🌟 $100 - AiAssistant を開発された @XININGMA さんに贈られました。 🌟 $100 - iris-data-analysis を開発された @lando.miller さんに贈られました。 Community Nomination 🥇 1位 - $1,000 は、AiAssistant を開発された @XININGMA さんに贈られました。 🥈 2位 - $600 は、bg-iris-agent を開発された @geotat さん @Elena.Karpova さん @Alena.Krasinskiene さんに贈られました。 🥉 3位 - $300 は、iris-data-analysis を開発された @lando.miller さんに贈られました。 🏅 4位 - $200 は、Facilis を開発された @Henrique さん @henry さん @José.Pereira さんに贈られました。 🏅 5位 - $100 は、langchain-iris-tool を開発された @Yuri.Gomes さんに贈られました。 受賞された皆さん、おめでとうございます!また、コンテストにご興味お持ちいただきありがとうございました! 次回のコンテストもご期待ください!