検索

クリアフィルター
記事
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構成を作成します。
記事
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 · 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
記事
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年10月27日

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

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

GitLabを使用したInterSystemsソリューションの継続的デリバリー - パートVI:コンテナインフラストラクチャ

この連載記事では、InterSystemsの技術とGitLabを使用したソフトウェア開発に向けて実現可能な複数の手法を紹介し、議論したいと思います。 次のようなトピックについて説明します。 Git 101 Git Flow(開発プロセス) GitLabのインストール GitLabワークフロー 継続的デリバリー GitLabのインストールと構成 GitLab CI/CD コンテナを使用する理由 コンテナインフラストラクチャ コンテナを使用するGitLab CI/CD 第1回の記事では、Gitの基本、Gitの概念を高度に理解することが現代のソフトウェア開発にとって重要である理由、Gitを使用してソフトウェアを開発する方法について説明しています。 第2回の記事では、アイデアからユーザーフィードバックまでの完全なソフトウェアライフサイクルプロセスであるGitLabワークフローについて説明しています。 第3回の記事では、GitLabのインストールと構成ならびに利用環境のGitLabへの接続について説明しています。 第4回の記事では、CDの構成を作成しています。 第5回の記事では、コンテナとその使用方法(および使用する理由)について説明しています。 この記事では、コンテナを使用して継続的デリバリーのパイプラインを実行する必要がある主なコンポーネントと、それらすべての連携の仕組みについて説明します。 次のような構成になります。 ここでは、次の3つの主なステージに分かれていることが分かります。 Build Ship Run Build 前パートのビルドは多くの場合は増分ビルドであり、現在の環境と現在のコードベースの違いを計算してコードベースに対応するように環境が修正されていました。 コンテナの場合、各ビルドはフルビルドになります。 ビルドの成果物は、依存関係に関係なくどこでも実行できるイメージです。 Ship イメージが構築されてテストに合格すると、該当イメージが Docker イメージをホストする専用サーバーであるレジストリにアップロードされます。 そこで、同じタグを持つ前のイメージを置き換えることができます。 例えば、masterブランチに新たにコミットが行われたために新しいイメージ(project/version:master)を構築したとします。そして該当イメージがテストに合格した場合はレジストリ内のイメージを同じタグを持つ新しいイメージと置き換えることができるため、project/version:masterをプルする人全員が新しいバージョンを取得することになります。 Run 最後に、イメージがデプロイされます。 GitLabなどのCIソリューションはこの動作や専用のオーケストレーターを制御できますが、ポイントは同じです。一部のイメージが実行され、定期的に正常性がチェックされ、新しいイメージのバージョンが利用可能になると更新されます。 これらの各種ステージを説明したDockerのウェビナーをご覧ください。 あるいは、コミットの観点から見た場合は以下のようになります。 デリバリーの構成では以下を実施します。 GitLabリポジトリにコードをプッシュする Dockerイメージをビルドする テストする Dockerレジストリにイメージを公開する 古いコンテナをレジストリの新しいバージョンと入れ替える そのためには、次の内容が必要です。 Docker Dockerレジストリ 登録済みドメイン(任意ですが推奨します) GUIツール(任意) Docker まず、どこかでDockerを実行する必要があります。 Ubuntu、RHEL、SUSEといった主流のLinuxフレーバーを搭載した1台のサーバーから開始することをお勧めします。 CoreOSやRancherOSといったクラウド指向のディストリビューションは使用しないでください。 これらはまったく初心者向けではありません。 ストレージドライバーをdevicemapperに必ず切り替えてください。 大規模なデプロイの場合はKubernetes、Rancher、Swarmなどのコンテナオーケストレーションツールを使用するとほとんどのタスクを自動化できますが、ここではそれらについては(少なくともこのパートでは)説明しません。 Dockerレジストリ これは実行する必要がある最初のコンテナであり、Dockerイメージを格納および配布できるステートレスでスケーラブルなサーバーサイドアプリケーションです。 次の場合はレジストリを使用する必要があります。 イメージの保存場所を厳密に管理したい イメージの配信パイプラインを完全に所有したい イメージの保存と配布を社内の開発ワークフローにしっかりと統合したい こちらにレジストリのドキュメントがあります。 レジストリとGitLabの接続 注意:GitLabにはレジストリの機能が組み込まれています。 このレジストリを外部レジストリの代わりに実行できます。 この段落でリンクされているGitLabのドキュメントをお読みください。 レジストリをGitLabに接続するには、HTTPSサポート付きでレジストリを実行する必要があります。私はLet's Encryptを使用して証明書を取得してからこのGistに従い、証明書を取得してコンテナに渡しました。 レジストリがHTTPS経由で利用可能であることを確認した後(ブラウザから確認できます)、レジストリをGitLabに接続する際のこちらの手順に従ってください。これらの手順は、要件とGitLabのインストール形態によって異なります。私の場合は構成にレジストリの証明書と(適切な名前を付け、適切な権限を付与した)鍵を/etc/gitlab/sslに追加し、以下の行を/etc/gitlab/gitlab.rbに追加しました。 registry_external_url 'https://docker.domain.com' gitlab_rails['registry_api_url'] = "https://docker.domain.com" そしてGitLabを再構成すると、新しくビルドしたイメージに適切にタグを付ける方法に関する情報を含む新しいレジストリタブが表示されました。このように表示されていました。 ドメイン 継続的デリバリーの構成ではブランチごとにイメージを自動的にビルドし、イメージがテストに合格した場合にそれをレジストリに公開して自動的に実行したため、アプリケーションはすべての「状態」で自動的に利用できるようになりました。例えば、以下を利用できます。 <featureName>.docker.domain.com のいくつかのフィーチャーブランチ master.docker.domain.com のTestバージョン preprod.docker.domain.com のPreprodバージョン prod.docker.domain.com のProdバージョン そのためにはドメイン名が必要で、*.docker.domain.com を docker.domain.com のIPアドレスに向けるワイルドカードDNSレコードを追加する必要があります。 その他、異なるポートを使用するという選択肢もあります。 Nginxプロキシ いくつかのフィーチャーブランチがある場合、サブドメインを正しいコンテナに自動的にリダイレクトする必要があります。 そのためには、Nginxをリバースプロキシとして使用できます。 こちらにガイドがあります。 GUIツール コンテナの操作を開始するには、コマンドラインまたはGUIインターフェイスのいずれかを使用できます。 多くのツールを利用できますが、例えば次のようなものがあります。 Rancher MicroBadger Portainer Simple Docker UI HYPERLINK "https://www.google.com/search?q=gui+container+managers"... これらを使用すると、CLIではなくGUIからコンテナを作成し、管理できます。 Rancherは次のような外観をしています。 GitLab Runner 前と同じように、他のサーバーでスクリプトを実行するにはGitLab Runnerをインストールする必要があります。 この件は第3回目の記事で説明しました。 Docker executorではなく、Shell executorを使用する必要があることに注意してください。 Docker executorはイメージ内側から何かが必要な場合に使用されます。例えば、JavaコンテナでAndroidアプリケーションを構築していて、apkのみが必要な場合があります。 この場合はコンテナ全体が必要になり、そのためにShell executorが必要になります。 まとめ コンテナの実行を開始するのは簡単で、選択できるツールは多数あります。 コンテナを使用した継続的デリバリーは、次のような点で通常の継続的デリバリー構成とは異なります。 ビルド時に依存関係が満たされるため、イメージがビルドされた後に依存関係について考える必要はありません。 再現性 - 同じコンテナをローカルで実行することで、既存の環境を簡単に再現できます。 速度 - コンテナには明示的に追加したもの以外は何も含まれないため、高速にビルドすることができます。また、さらに重要なことには一度ビルドしてしまえば必要なときにいつでも使用できます。 効率 - 上記と同様、コンテナはVMなどよりもオーバーヘッドが少なくなります。 スケーラビリティ - オーケストレーションツールを使用すると、アプリケーションをワークロードに合わせて自動的にスケーリングし、現在必要なリソースのみを消費できます。 次の内容 次の記事では、InterSystems IRIS Dockerコンテナを活用するCD構成の作成について説明します。
記事
Mihoko Iijima · 2023年7月14日

InterSystemsコンテナレジストリの使い方とコンテナ開始までの流れ(解説ビデオ付き)

開発者の皆さん、こんにちは! InterSystems IRIS 、InterSystems IRIS for Healthのコミュニティエディションは、WindowsやLinuxにインストールするキットの他にコンテナ版も公開されています。 コンテナ版はダウンロードページからではなく、InterSystemsコンテナレジストリ よりpullいただけます。 この記事では、InterSystemsコンテナレジストリ の使い方と、コンテナ開始までの流れをご紹介します。 1.コンテナレジストリの使い方とdocker pullまでの手順 (ビデオ ~2:44まで) 2023/12/14更新:コミュニティエディションのイメージをpullする場合は、下記1のコンテナレジストリ画面へのログインやdocker loginは不要です。 開発者コミュニティのアカウント、またはWRCアカウントをお持ちの方はそのアカウントを使用して、InterSystemsコンテナレジストリにログインします。 ログインすると以下のように docker login 情報が表示されますので(「Click here」をクリックすると表示されます)docker pull を行う前に docker loginコマンドを実行します。 画面左のリストからpull対象バージョンを選択し、画面右の docker pullコマンドをコピーし、お手元でpullを開始します。 2.コンテナ開始(docker run) イメージをpullできたらあとはコンテナを開始するだけです。(ビデオ 2:44~6:30) コンテナ開始前に、IRISの管理ポータルが使用するWebサーバポート:52773番をコンテナ外の何番のポートで利用できるようにするか決定します。 以下の例では、9093番をコンテナ外ポートとして利用しています。またコンテナ名を「irisx」としています(使用するイメージは環境に合わせてご変更ください)。 docker run --name irisx -d --publish 9093:52773 containers.intersystems.com/intersystems/irishealth-community:2023.1.1.380.0 docker run の実行ができたら、次はコンテナにログインします。 docker exec -it irisx bash 続いて、IRISにログインするため、IRISの構成名を確認します。(iris list で確認できます) 実行例は以下の通りです。 irisowner@3bf381d49dca:~$ iris list Configuration 'IRIS' (default) directory: /usr/irissys versionid: 2023.1.1.380.0com datadir: /usr/irissys conf file: iris.cpf (SuperServer port = 1972, WebServer = 52773) status: running, since Fri Jul 14 03:14:40 2023 state: ok product: InterSystems IRISHealth irisowner@3bf381d49dca:~$ コンテナ版IRISの構成名(Configuration)は、IRIS で、Webサーバポートは52773番が指定されています。 管理ポータルはこちらのURLでアクセスできます👉 http://localhost:9093/csp/sys/UtilHome.csp ユーザ名:_SYSTEM、パスワード:SYS で初回ログインします。ログイン後、パスワードをご変更いただけます。 IRISにログインするためには、irisコマンドを使用して以下実行します。(iris session 構成名) irisowner@3bf381d49dca:~$ iris session iris Node: 3bf381d49dca, Instance: IRIS USER>halt irisowner@3bf381d49dca:~$ exit exit isjedu@xxxx:~/container/Simple$ ​​IRISにログインできるとUSERネームスペースのプロンプトが表示されます。 IRISからログアウトする場合は、haltコマンドを使用します。 コンテナからログアウトする場合は、exitを実行します。 コンテナを停止: docker stop irisx コンテナの破棄: docker rm irisx 3.コンテナ開始(docker-compose.ymlの利用) 続いて、docker-compose .ymlを利用する例をご紹介します。(ビデオ 6:30~) (使用するイメージは環境に合わせてご変更ください) version: '3.7' services: iris: image: containers.intersystems.com/intersystems/irishealth-community:2023.1.1.380.0 ports: ["9095:52773"] container_name: iriscontainer1 volumes: ["./src:/src"] environment: - TZ=JST-9 コンテナ外のポート番号を9095番として開始します。 管理ポータルはこちらのURLでアクセスできます👉 http://localhost:9095/csp/sys/UtilHome.csp ユーザ名:_SYSTEM、パスワード:SYS で初回ログインします。ログイン後、パスワードをご変更いただけます。 コンテナ開始: docker-compose up -d コンテナ停止: docker-compose stop -d コンテナ破棄: docker-compose down ぜひお試しください!​​​​​​ ドキュメント(IRIS):InterSystems IRIS イメージからのコンテナの実行 ドキュメント(IRIS for Health):InterSystems IRIS イメージからのコンテナの実行
記事
Mihoko Iijima · 2022年6月28日

【はじめてのInterSystems IRIS】Embedded Python セルフラーニングビデオシリーズ公開!

開発者の皆さん、こんにちは! この記事では、Embedded Pythonをご自身の好きなタイミングで学習できる📚セルフラーニングビデオ📚の YouTube プレイリストをご紹介します! 👆こんな具合に👆学習内容別 Embedded Python セルフラーニングビデオを公開しています! この記事では、これから Embedded Python でプログラミングを開始してみたい方向けに最適なビデオをご紹介します!​​​​​​ ◆ Embedded Python概要から学習を始めたい方はこちら👇 以下の内容を確認できるプレイリスト:1-Embedded Python概要編 - YouTube をご用意しています。 Embedded Pythonとは? Python開発者から見た使い道(解説&実演) IRIS開発者からみた使い道(解説&実演) この後、実際の操作を試されたい場合は、次のプレイリスト:2-Embedded Python利用前の準備 - YouTube が最適です。 ◆ Embedded Python利用前の準備 を知りたい方はこちら👇 操作を開始する前に、必要な利用前の準備についてご紹介しているプレイリスト:2-Embedded Python利用前の準備 - YouTube をご用意しています。 PythonとIRISのインストール 管理ポータルの開き方 構成設定の変更 ネームスペースとデータベースについて この後は、ご興味のある内容から学習を進めていただくことができます。 どんなビデオ(コース)があるかについては、以下ビデオでご紹介しています。ぜひご覧さい!​​​​​​ 次にどの内容をお試しいただくか確認ができましたら、以降のプレイリストから学習を開始してください。 以下、プレイリストのビデオ内で使用しているコードサンプルは、👇以下Gitで公開しています👇ぜひご利用ください。 ​​​​​​https://github.com/Intersystems-jp/ISJDevComPlayList-EmbeddedPython ◆ Embedded Pythonでデータベースプログラミング:SQLアクセス編 InterSystems IRIS data platform(以降IRIS)が提供するサーバーサイドで動くEmbedded Pythonを利用してストアドプロシージャや計算フィールドのロジックをPythonで記述することができます。 プレイリスト:3-Embedded Pythonでデータベースプログラミング:SQLアクセス編 - YouTube ビデオを利用して、以下の内容を1つずつ確認することができます。 irispythonコマンドを使用してPythonシェルを起動する 計算フィールドのロジックをPythonで書いてみる テーブルを作成し、計算フィールドが正しく動作するか確認する ストアドプロシージャをPythonで作成し実行する Pythonのスクリプトファイルを作成し実行する テーブル=永続クラスの関係を確認する 補足:オブジェクトアクセスで作成したデータにアクセスしてみる 実演の中で使用しているコードのコピー&ペースト元や補足解説資料(PDF)は👇こちら👇に公開しています。ぜひご利用ください。 https://github.com/Intersystems-jp/ISJDevComPlayList-EmbeddedPython/tree/master/3-SQLAccess ◆ Embedded Pythonでデータベースプログラミング:オブジェクトアクセス編 InterSystems IRIS data platform(以降IRIS)が提供するサーバーサイドで動くEmbedded Pythonを利用してIRIS の永続クラスの定義方法、オブジェクト操作方法、メソッドの記述と実行方法を習得し、1つのデータに対してSQLでもオブジェクトでもアクセスできる「マルチモデルデータベース」の特徴をご理解いただけるビデオです。 プレイリスト:4-Embedded Pythonでデータベースプログラミング:オブジェクト編-YouTube ビデオでは、以下の内容をご自身のペースで学習いただけます。 IRISのクラス定義作成練習(VSCode) PythonからIRIS内クラスに対するインスタンス操作練習 language=pythonのメソッド記述と実行練習 引数・戻り値のデータタイプについて ObjectScriptのシステムクラスによくある%Statusの扱い 実演の中で使用しているコードのコピー&ペースト元やVSCodeの使い方も含めた補足解説資料(PDF)は👇こちら👇に公開しています。ぜひご利用ください。 https://github.com/Intersystems-jp/ISJDevComPlayList-EmbeddedPython/tree/master/4-ObjectAccess ◆ IRISでPythonを使ってみよう! InterSystems IRIS data platform(以降IRIS)が提供するサーバーサイドで動くEmbedded Pythonを利用して、IRISからPythonモジュール/スクリプトファイルを使用する方法、Pythonでメソッドを記述する方法を習得し、Pythonの豊富なライブラリをIRIS内で自由に組み合わせて利用できることをご理解いただけるビデオです。 プレイリスト:5-IRISでPythonを使ってみよう(Embedded Python)-YouTube ビデオでは、以下の内容をご自身のペースで学習いただけます。 IRISターミナルからPythonシェルを起動して、Pythonの操作体験 ObjectScriptからPythonのスクリプトファイル(含クラス)をインポートして使う方法 Pythonの組み込み関数(builtins)をObjectScriptで操作する方法の確認 メソッドの記述 ObjectScript/Pythonメソッドの記述と実行練習 可変長引数について PythonのTrue/False/NoneをObjectScriptで扱う方法 Python側でエラーが発生した場合の対応方法 実演の中で使用しているコードのコピー&ペースト元は👇こちら👇に公開しています。ぜひご利用ください。 https://github.com/Intersystems-jp/ISJDevComPlayList-EmbeddedPython/tree/master/5-PythonWithIRIS 実演通りに動かない!などありましたら、ぜひコミュニティの質問やこの記事の返信欄にご記入ください。 それでは、🐍PythonとIRISでプログラミングを楽しんでみてください🌈
記事
Masahito Miura · 2024年10月24日

InterSystems IRIS、IRIS for Health、HealthShare HealthConnect のメンテナンスリリース 2023.1.5 と 2024.1.2 のご案内

InterSystems IRIS、IRIS for Health、HealthShare HealthConnect のメンテナンスリリース 2023.1.5 と 2024.1.2 がリリースされました InterSystems IRIS、InterSystems IRIS for Health、HealthShare Health Connect の2つのメンテナンスリリースがリリースされました。✅ 2023.1.5 リリース 2023.1.5 は、以前のリリース 2023.1.x のバグフィックスを提供します。 詳細な変更リストとアップグレード・チェックリストは、以下のページにあります : InterSystems IRIS InterSystems IRIS for Health HealthShare Health Connect ✅ 2024.1.2リリース 2024.1.2 は、以前のリリース 2024.1.x のバグフィックスを提供します。 詳細な変更リストとアップグレード・チェックリストは、以下のページにあります : InterSystems IRIS InterSystems IRIS for Health HealthShare Health Connect 【キットのご案内】本製品は、従来からのインストーラパッケージ形式と、コンテナイメージ形式をご用意しています。その一覧は、サポートプラットフォームページ をご覧ください。インストーラパッケージは WRC Direct から入手できます。InterSystems IRIS、IRIS for Health は IRIS ダウンロードページ から、HealthShare Health Connect は HealthShare ダウンロードページ から、それぞれ入手してください。コンテナイメージは InterSystems Container Registry から入手できます。このリリースには、コミュニティ・エディションのインストーラパッケージやコンテナイメージはありません。 各製品のバージョン番号は以下になります : 2023.1.5.697.0 2024.1.2.398.0
記事
Toshihiko Minamoto · 2023年12月20日

Dockerfile と共同開発ユーザー。InterSystems IRIS で ObjectScript プロジェクトの共同作業を実行するには

開発者の皆さん、こんにちは! 多くの方が、[Open Exchange](https://openexchange.intersystems.com/) と GitHub で InterSystems ObjectScript ライブラリを公開しています。 でも、開発者がプロジェクトの使用とコラボレーションを簡単に行えるようにするにはどうしていますか? この記事では、ファイルの標準セットをリポジトリにコピーするだけで、ObjectScript プロジェクトを簡単に起動して作業する方法をご紹介します。 では始めましょう! **概要** - 以下のファイルを[こちらのリポジトリ](https://github.com/intersystems-community/objectscript-docker-template)からお使いのリポジトリにコピーしてください。 [Dockerfile](https://github.com/intersystems-community/objectscript-docker-template/blob/master/Dockerfile) [docker-compose.yml](https://github.com/intersystems-community/objectscript-docker-template/blob/master/docker-compose.yml) [Installer.cls](https://github.com/intersystems-community/objectscript-docker-template/blob/master/Installer.cls) [iris.script](https://github.com/intersystems-community/objectscript-docker-template/blob/master/iris.script) [settings.json](https://github.com/intersystems-community/objectscript-docker-template/blob/master/.vscode/settings.json "settings.json"){#9f423fcac90bf80939d78b509e9c2dd2-d165a4a3719c56158cd42a4899e791c99338ce73} [.dockerignore](https://github.com/intersystems-community/objectscript-docker-template/blob/master/.dockerignore ".dockerignore"){#f7c5b4068637e2def526f9bbc7200c4e-c292b730421792d809e51f096c25eb859f53b637} [.gitattributes](https://github.com/intersystems-community/objectscript-docker-template/blob/master/.gitattributes ".gitattributes"){#fc723d30b02a4cca7a534518111c1a66-051218936162e5338d54836895e0b651e57973e1} [.gitignore](https://github.com/intersystems-community/objectscript-docker-template/blob/master/.gitignore ".gitignore"){#a084b794bc0759e7a6b77810e01874f2-e6aff5167df2097c253736b40468e7b21e577eeb} すると、プロジェクトを起動して共同作業する標準的な方法が得られます。 以下は、この仕組みと動作する理由についての記事です。 **注意:** この記事では、InterSystems IRIS 2019.1 以降で実行可能なプロジェクトを対象としています。 **InterSystems IRIS プロジェクトの起動環境の選択** 通常、開発者には、プロジェクト/ライブラリを試して、素早く安全な方法であることを確認していただきたいと思っています。 私見としては、新しいものを素早く安全に起動するには、Docker コンテナが理想的だと考えています。起動、インポート、コンパイル、計算するあらゆるものがホストマシンにとって安全であり、いかなるシステムやコードも破壊されたり損なわれたりすることがないことを開発者に保証できるためです。 何らかの問題が発生した場合は、コンテナを止めて削除するだけで済みます。 アプリケーションが膨大なディスクスペースを占有するのであれば、コンテナを削除すれば、容量を解放できます。 アプリケーションがデータベース構成を破損するのであれば、破損した構成のあるコンテナを削除するだけです。 このように単純で安全なのです。 Docker コンテナでは、安全と標準化を得られます。 バニラ InterSystems IRIS Docker コンテナを実行するには、[IRIS Community Edition イメージ](https://hub.docker.com/_/intersystems-iris-data-platform/plans/222f869e-567c-4928-b572-eb6a29706fbd?tab=instructions)を実行するのが最も簡単です。 1. [Docker デスクトップ](https://www.docker.com/products/docker-desktop)をインストールします。  2. OS のターミナルで以下を実行します。 docker run --rm -p 52773:52773 --init --name my-iris store/intersystems/iris-community:2020.1.0.199.0 3. 次に、ホストブラウザで管理ポータルを開きます。 4. または IRIS へのターミナルを開きます。 docker exec -it my-iris iris session IRIS 5. IRIS コンテナが不要になれば、それを停止します。 docker stop my-iris さて、 IRIS を Docker コンテナで実行しますが、 開発者にはコードを IRIS にインストールして、いくらかの設定を行ってほしいと考えているとします。 以下ではこれについて説明します。 **ObjectScript ファイルのインポート** 最も単純な InterSystems ObjectScript プロジェクトには、クラス、ルーチン、マクロ、グローバルなどの一連の ObjectScript ファイルが含めることができます。 [命名規則](https://community.intersystems.com/post/objectscript-package-manager-naming-convention)と[フォルダ構造の提案](https://community.intersystems.com/post/simplified-objectscript-source-folder-structure-package-manager)についての記事をご覧ください。 問題は、このコードをどのようにして IRIS コンテナにインポートするかです。 ここで役立つのが Dockerfile です。これを使用して、バニラ IRIS コンテナを取得し、リポジトリから IRIS にすべてのコードをインポートして、必要に応じて IRIS で設定を行います。 リポジトリに Dockerfile を追加する必要があります。 [ObjectScript テンプレート](https://github.com/intersystems-community/objectscript-docker-template)リポジトリから取得した [Dockerfile](https://github.com/intersystems-community/objectscript-docker-template/blob/master/Dockerfile) を調べてみましょう。 ARG IMAGE=store/intersystems/irishealth:2019.3.0.308.0-community ARG IMAGE=store/intersystems/iris-community:2019.3.0.309.0 ARG IMAGE=store/intersystems/iris-community:2019.4.0.379.0 ARG IMAGE=store/intersystems/iris-community:2020.1.0.199.0 FROM $IMAGE USER root WORKDIR /opt/irisapp RUN chown ${ISC_PACKAGE_MGRUSER}:${ISC_PACKAGE_IRISGROUP} /opt/irisapp USER irisowner COPY Installer.cls . COPY src src COPY iris.script /tmp/iris.script # run iris and initial  RUN iris start IRIS \     && iris session IRIS < /tmp/iris.script   最初の ARG の行は $IMAGE 変数を設定しており、それを FROM で使用します。 これは、$IMAGE 変数を変更するために FROM の前の最後の行が何であるかだけを切り替えて、さまざまな IRIS バージョンでコードをテスト/実行するのに適しています。  以下のコードがあります。  ARG IMAGE=store/intersystems/iris-community:2020.1.0.199.0 FROM $IMAGE これは、IRIS 2020 Community Edition ビルド 199 を使用するということです。 リポジトリからコードをインポートするため、リポジトリのファイルを Docker コンテナにコピーする必要があります。 以下の行はそれを行います。 USER root WORKDIR /opt/irisapp RUN chown ${ISC_PACKAGE_MGRUSER}:${ISC_PACKAGE_IRISGROUP} /opt/irisapp USER irisowner COPY Installer.cls . COPY src src USER root - ここで、ユーザーをルートに切り替えて、フォルダを作成してファイルを Docker にコピーします。 WORKDIR /opt/irisapp - この行では、ファイルをコピーする workdir をセットアップしています。 RUN chown ${ISC_PACKAGE_MGRUSER}:${ISC_PACKAGE_IRISGROUP} /opt/irisapp   -  ここでは、irisowner ユーザーと IRIS を実行するグループに権限を付与しています。 USER irisowner - ユーザーを root から irisowner に切り替えます。 COPY Installer.cls .  - workdir のルートに [Installer.cls](https://github.com/intersystems-community/objectscript-docker-template/blob/master/Installer.cls) をコピーしています。 このピリオドを忘れないでください。 COPY src src - ソースファイルを[リポジトリの src フォルダ](https://github.com/intersystems-community/objectscript-docker-template/tree/master/src/)から Docekr の workdir の src フォルダにコピーします。 次のブロックでは、初期スクリプトを実行し、インストーラーと ObjectScript コードを呼び出します。 COPY iris.script /tmp/iris.script # run iris and initial  RUN iris start IRIS \     && iris session IRIS < /tmp/iris.script COPY iris.script / - iris.script をルートディレクトリにコピーします。 コンテナをセットアップするために呼び出す ObjectScript が含まれます。 RUN iris start IRIS\  - IRIS を起動します。 && iris session IRIS < /tmp/iris.script - IRIS ターミナルを起動し、それに最初の ObjectScript を入力します。 以上です! Docker にファイルをインポートする Dockerfile ができました。 installer.cls と iris.script の 2 つのファイルが残っています。ではそれらを詳しく見てみましょう。 [**Installer.cls**](https://github.com/intersystems-community/objectscript-docker-template/blob/master/Installer.cls) Class App.Installer { XData setup {                                   } ClassMethod setup(ByRef pVars, pLogLevel As %Integer = 3, pInstaller As %Installer.Installer, pLogger As %Installer.AbstractLogger) As %Status [ CodeMode = objectgenerator, Internal ] {   #; Let XGL document generate code for this method.    Quit ##class(%Installer.Manifest).%Generate(%compiledclass, %code, "setup") } } 率直に言って、ファイルのインポートに Installer.cls は必要ありません。 これは 1 行で実行可能です。 ただし、コードをインポートするほかに、CSP アプリのセットアップ、セキュリティ設定の追加、データベースとネームスペースの作成を行わなければなりません。 この Installer.cls では、 IRISAPP という名前で新しいデータベースとネームスペースを作成し、このネームスペースのデフォルトの /csp/irisapp アプリケーションを作成します。 すべては、<Namespace> 要素で行います。 <Namespace Name="${Namespace}" Code="${Namespace}" Data="${Namespace}" Create="yes" Ensemble="no"> <Configuration> <Database Name="${Namespace}" Dir="/opt/${app}/data" Create="yes" Resource="%DB_${Namespace}"/> <Import File="${SourceDir}" Flags="ck" Recurse="1"/> </Configuration> <CSPApplication Url="/csp/${app}" Directory="${cspdir}${app}" ServeFiles="1" Recurse="1" MatchRoles=":%DB_${Namespace}" AuthenticationMethods="32" /> </Namespace> そして、Import タグを使って、SourceDir からすべてのファイルをインポートします。 <Import File="${SourceDir}" Flags="ck" Recurse="1"/> この SourceDir は変数であり、現在のディレクトリ/src フォルダに設定されています。 <Default Name="SourceDir" Value="#{$system.Process.CurrentDirectory()}src"/> これらの設定を含む Installer.cls によって、src フォルダから任意の ObjectScript コードをインポートするわかりやすい新しいデータベース IRISAPP を作成できるという確信を持つことができます。 [iris.script](https://github.com/intersystems-community/objectscript-docker-template/blob/master/iris.script) ここに、IRIS コンテナを起動する初期の ObjectScript セットアップコードを挿入してください。 例: 開発にはパスワードのプロンプトは不要であるため、ここでは、installer.cls を読み込んで実行してから、パスワードの初回変更リクエストを回避するために、UserPasswords を永久にしています。 ; run installer to create namespace do $SYSTEM.OBJ.Load("/opt/irisapp/Installer.cls", "ck") set sc = ##class(App.Installer).setup()  zn "%SYS" Do ##class(Security.Users).UnExpireUserPasswords("*") ; call your initial methods here halt [docker-compose.yml](https://github.com/intersystems-community/objectscript-docker-template/blob/master/docker-compose.yml) docker-compose.yml はなぜ必要なのでしょうか。Dockerfile と同様に、イメージをただビルドして実行するだけではいけないのでしょうか。 もちろん、そうすることは可能です。 ただし、docker-compose.yml を使用すれば作業が単純になります。 通常、docker-compose.yml は、1 つのネットワークに接続された複数の Docker イメージを起動するために使用されます。 docker-compose.yml は、多数のパラメーターを処理する場合に、1 つの Docker イメージの起動をより簡単にするためにも使用できます。 これを使用すれは、ポートのマッピング、ボリューム、VSCode 接続パラメーターなどを Docker に渡すことができます。 version: '3.6' services: iris: build: context: . dockerfile: Dockerfile restart: always ports: - 51773 - 52773 - 53773 volumes: - ~/iris.key:/usr/irissys/mgr/iris.key - ./:/irisdev/app ここでは、サービス iris を宣言しています。これは Dockerfile を使用し、IRIS の 51773、52773、53773 ポートを公開するサービスです。 また、このサービスは、ホストマシンのホームディレクトリの iris.key と期待される IRIS フォルダ、およびソースコードのルートフォルダと /irisdev/app フォルダの 2 つのボリュームのマッピングも行います。 docker-compose によって、セットアップされるパラメーターに関係なく、イメージをビルドして実行するためのコマンドをより短く、統一することができます。 いずれの場合でも、以下のようにしてイメージをビルドします。 $ docker-compose up -d  そして以下のようにして IRIS ターミナルを開きます。 $ docker-compose exec iris iris session iris Node: 05a09e256d6b, Instance: IRIS USER> また、docker-compose.yml では、VSCode ObjectScript プラグインの接続もセットアップできます。 [.vscode/settings.json](https://github.com/intersystems-community/objectscript-docker-template/blob/master/.vscode/settings.json) ObjectScript アドオン接続設定に関連しているのは、以下の部分です。 { "objectscript.conn" :{ "ns": "IRISAPP", "active": true, "docker-compose": { "service": "iris", "internalPort": 52773 } } } ここにあるのは設定です。VSCode ObjectScript プラグインのデフォルトの設定とは異なります。 ここでは、IRISAPP ネームスペース(Installer.cls で作成)に接続すると述べています。 "ns": "IRISAPP", そして、docker-compose の設定があります。これは、サービス「iris」内の docker-compose ファイルで、VSCode が 52773 がマッピングされているポートに接続すると書かれています。 "docker-compose": { "service": "iris", "internalPort": 52773 } 52773 について調べたところ、これはマップされたポートが 52773 に対して定義されていないことがわかります。 ports: - 51773 - 52773 - 53773 つまり、ホストマシンのポートで利用できるランダムなポートが取得され、VSCode は自動的にランダムなポートを介して、docker 上でこの IRIS に接続するということです。 **これは非常に便利な機能です。IRIS を使用して任意の量の Docker イメージをランダムなポート上で実行し、VSCode をそれらのポートに自動的に接続するオプションが提供されるためです。** 他のファイルはどうでしょうか? 以下のファイルもあります。 [.dockerignore](https://github.com/intersystems-community/objectscript-docker-template/blob/master/.dockerignore)  - 作成した Docker ファイルにコピーしない不要なホストマシンのファイルをフィルターするために使用できるファイル。 通常、.git や .DS_Store は必須です。 [.gitattributes](https://github.com/intersystems-community/objectscript-docker-template/blob/master/.gitattributes) - git の属性。ソース内の ObjectScript ファイルの行末を統一します。 Windows と Mac/Ubuntu オーナーがリポジトリで共同作業する場合に非常に便利です。 [.gitignore](https://github.com/intersystems-community/objectscript-docker-template/blob/master/.gitignore) - Git で変更履歴を追跡しないファイル。 通常、.DS_Store などの非表示の OS レベルのファイルです。 以上です! リポジトリを Docker 実行可能にし、コラボレーションしやすくするにはどうすればよいでしょうか。   1. [このリポジトリ](https://github.com/intersystems-community/objectscript-docker-template)をクローンします。 2. 以下のファイルをすべてコピーします。 [Dockerfile](https://github.com/intersystems-community/objectscript-docker-template/blob/master/Dockerfile) [docker-compose.yml](https://github.com/intersystems-community/objectscript-docker-template/blob/master/docker-compose.yml) [Installer.cls](https://github.com/intersystems-community/objectscript-docker-template/blob/master/Installer.cls) [iris.script](https://github.com/intersystems-community/objectscript-docker-template/blob/master/iris.script) [settings.json](https://github.com/intersystems-community/objectscript-docker-template/blob/master/.vscode/settings.json "settings.json"){#9f423fcac90bf80939d78b509e9c2dd2-d165a4a3719c56158cd42a4899e791c99338ce73} [.dockerignore](https://github.com/intersystems-community/objectscript-docker-template/blob/master/.dockerignore ".dockerignore"){#f7c5b4068637e2def526f9bbc7200c4e-c292b730421792d809e51f096c25eb859f53b637} [.gitattributes](https://github.com/intersystems-community/objectscript-docker-template/blob/master/.gitattributes ".gitattributes"){#fc723d30b02a4cca7a534518111c1a66-051218936162e5338d54836895e0b651e57973e1} [.gitignore](https://github.com/intersystems-community/objectscript-docker-template/blob/master/.gitignore ".gitignore"){#a084b794bc0759e7a6b77810e01874f2-e6aff5167df2097c253736b40468e7b21e577eeb} 上記をリポジトリにコピーしてください。 [Dockerfile のこの行](https://github.com/intersystems-community/objectscript-docker-template/blob/10f4422c105d5c75111fde16a184a83f5ff86d06/Dockerfile#L15)を IRIS にインポートする ObjectScript のあるリポジトリ内のディレクトリに一致するように変更します(in /src フォルダにある場合は変更しません)。 それだけです。 すべての人(あなた自身も含む)が、新しい IRISAPP ネームスペースでコードをインポートできるようになります。 **プロジェクトの起動方法** IRIS で ObjectScript プロジェクトを実行するためのアルゴリズムは以下の通りです。 1. プロジェクトをローカルに Git clone します。 2. プロジェクトを実行します。 $ docker-compose up -d $ docker-compose exec iris iris session iris Node: 05a09e256d6b, Instance: IRIS USER>zn "IRISAPP" **開発者によるプロジェクトへの貢献方法 ** 1. リポジトリをフォークして、フォークされたリポジトリをローカルに Git clone します。 2. VSCode でフォルダを開きます([Docker](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker) と [ObjectScript](https://marketplace.visualstudio.com/items?itemName=daimor.vscode-objectscript&ssr=false#review-details) の拡張機能が VSCode にインストールされている必要があります)。 3. docker-compose.yml を右クリックし、再起動します。[VSCode ObjectScript](https://openexchange.intersystems.com/package/VSCode-ObjectScript) が自動的に接続され、編集/コンパイル/デバッグできるうようになります。 4. リポジトリに変更をコミット、プッシュ、およびプルリクエストします。 以下は、この仕組みを説明する簡単な Gif です。 ![](/sites/default/files/inline/images/images/launch_and_edit1.gif) 以上です! それでは、コーディングをお楽しみください!  
お知らせ
Rie Tokue · 2024年7月30日

第17回インターシステムズ主催 開発者向けオンラインセミナー「InterSystems IRIS® サーバーとデータの守り方入門」のご案内

ご好評をいただいておりますインターシステムズ開発者向けオンラインセミナー、9月は以下のテーマで開催いたします。 テーマ「InterSystems IRIS® サーバーとデータの守り方入門」 日時:9月6日(金)13:30~14:00 (参加費無料・事前登録制) ご登録はこちらから [概要] はじめはユートピアになると考えられていたサイバー空間にも多様な脅威が出現し、日々変化し続けています。 多くの分野で活用されている IRIS と IRIS for Health、より厳しいセキュリティ要件は避けられない未来とも言えるでしょう。 本セッションではIRISインスタンスと管理するデータを保護する方法について概要をご説明します。 [こんな方にお勧め] IRISの管理機能に興味ある方IRISを使用したソリューションを設計される方 ご多用中とは存じますが、皆様のご参加をお待ち申し上げております!
お知らせ
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 さんに贈られました。 受賞された皆さん、おめでとうございます!また、コンテストにご興味お持ちいただきありがとうございました! 次回のコンテストもご期待ください!
お知らせ
Rie Tokue · 2025年7月17日

インターシステムズ第5回ソリューションウェビナー「~FHIR×OMOP CDMで広がる医療データの価値~InterSystems OMOPのご紹介」

こんにちは。 7月16日~18日に東京ビックサイトで開催された「国際モダンホスピタルショウ」のインターシステムズのブースにて様々なミニセッションを行いました。 その中で弊社製品の最新情報についてご紹介したミニセッションを”モダンホスピタルショウ「おさらいウェビナー」として、2回にわたり、お届けしています。 展示では伝えきれなかった技術や背景、導入効果などをご紹介します。第2回の本ウェビナーでは以下のトピックを取り上げます 日時:9月3日(水)午後1時30分~2時 テーマ:「~FHIR×OMOP CDMで広がる医療データの価値~InterSystems OMOPのご紹介」 参加費無料・事前登録制 ご登録はこちらから 第2回「~FHIR×OMOP CDMで広がる医療データの価値~InterSystems OMOPのご紹介」 【概要】OMOP CDM(Observational Medical Outcomes Partnership Common Data Model)は、医療データの二次利用、特に臨床研究やリアルワールドエビデンスの創出において強力な基盤となる、国際的な標準データモデルです。OMOP CDMの概要をご紹介するとともに、FHIRからOMOP CDMへの変換を実現する「InterSystems OMOP」ソリューションについて、デモを交えてご紹介いたします。 OMOP CDMに関心のある方はもちろん、FHIRデータの出力意義や活用方法について検討されている方も、是非ご参加ください。 【こんな方にお勧め】・医療データの標準化や利活用に関心のある方・医療機関や製薬会社でデータ管理や分析に携わる方・FHIRやOMOP CDMを活用したデータ連携・分析に携わる方 ご多用中とは存じますが、皆様のご参加をお待ち申し上げております。