検索

クリアフィルター
記事
Megumi Kakechi · 2023年5月8日

ヘルスモニタでのチェック頻度およびアラート通知条件の確認と変更方法

これは InterSystems FAQ サイトの記事です。 InterSystems IRIS では、柔軟でユーザ拡張可能な監視ツールである「システムモニタ」をお使いいただくことが可能です。 システムモニタには、以下の3つのインスタンス監視ツールがあります。 システムモニタ:システムの状態およびリソースを監視・固定パラメータに基づいて通知 (アラートおよび警告) を生成 ヘルスモニタ:主要なシステムメトリックおよびユーザ定義メトリックをサンプリング&ユーザ変更可能パラメータおよび規定の通常値と比較し、該当しきい値を超えた場合に通知を生成 アプリケーションモニタ:重要なシステムメトリックをサンプリング&ユーザが作成したアラート定義を使用して評価 messages.logに、以下のようなログが記録される場合があります。 [SYSTEM MONITOR] DBLatency(c:\xxx\) Warning: DBLatency = 1510 ( Warnvalue is 1000).※このメッセージの意味については こちらの記事 をご覧ください。 このメッセージはシステムモニタのインスタンス監視ツールであるヘルスモニタにより出力されています。システムモニタは色々なリソースの使用状況を監視する機能です。メッセージ中のDBLatency は、データベースの読み取り I/O 速度(ディスク I/O 応答速度)を監視し出力しているものです。 ご参考ドキュメントIRIS ヘルス・モニタ このシステムモニタよりコンソールログへメッセージが出力されますが、メッセージの重要度が 0 のものは、インフォメーションのメッセージになります。 センサオブジェクトで設定された最大値や警告値を超えた場合は、メッセージの重要度が 1 Warning , 2 Alert のものを出力します。 Alertの場合:ある期間のセンサの読み取り値が 3 回連続してセンサの最大値を上回った場合にアラート (深刻度 2 の通知) を生成Warningの場合:ある期間のセンサの読み取り値が 5 回連続してセンサの警告値を上回った場合にワーニング (深刻度 1 の通知) を生成 ヘルスモニタのセンサーオブジェクトの設定(最大値等の変更)は、^%SYSMONMGR ユーティリティを使用して行えます。※システムモニタのセンサオブジェクト設定は固定パラメータであるため変更はできません。 変更例) DBLatencyのログ出力のしきい値を、 Alert (深刻度 2 の通知):3000 から 4000 へ Warning (深刻度 1 の通知):1000 から 2000 へに変更します。 センサオブジェクトの設定を行う前に システムモニタを停止する必要があります。 %SYS>do ^%SYSMONMGR 1) Start/Stop System Monitor 2) Set System Monitor Options 3) Configure System Monitor Classes 4) View System Monitor State 5) Manage Application Monitor 6) Manage Health Monitor 7) View System Data 8) Exit Option? 1 1) Start System Monitor 2) Stop System Monitor 3) Exit Option? 2 Stopping System Monitor... System Monitor stopped 1) Start System Monitor 2) Stop System Monitor 3) Exit Option? センサオブジェクトのしきい値の変更を行います。 %SYS>do ^%SYSMONMGR 1) Start/Stop System Monitor 2) Set System Monitor Options 3) Configure System Monitor Classes 4) View System Monitor State 5) Manage Application Monitor 6) Manage Health Monitor 7) View System Data 8) Exit Option? 6 1) Enable/Disable Health Monitor 2) View Alerts Records 3) Configure Health Monitor Classes 4) Set Health Monitor Options 5) Exit Option? 3 1) Activate/Deactivate Rules 2) Configure Periods 3) Configure Charts 4) Edit Sensor Objects 5) Reset Defaults 6) Exit Option? 4 1) List Sensor Objects 2) Edit Sensor Object 3) Exit Option? 2 Sensor? ? Num Sensor Threshold : 9) DBLatency 10) DBReads 11) DBWrites 12) DiskPercentFull : Sensor? 9 DBLatency Base? 1000 => Alert Value? 3000 => 4000 <-- Alert(2) メッセージ出力レベルを 4000 に変更 Setting Max Multiplier and Warn Multiplier to 0. Enter a Warn Value Warn Value? 1000 => 2000 <-- Warming(1) メッセージ出力レベルを 2000 に変更 Sensor object DBLatency updated. Base 750 MaxMult 0 AlertValue 4000 WarnMult 0 WarnValue 2000 1) List Sensor Objects 2) Edit Sensor Object 3) Exit Option? <-- このあと全て <Enter> で抜ける システムモニタを再開することで、設定したセンサオブジェクトの値が有効になります。 %SYS>do ^%SYSMONMGR 1) Start/Stop System Monitor : Option? 1 1) Start System Monitor 2) Stop System Monitor 3) Exit Option? 1 Starting System Monitor... System Monitor started 1) Start System Monitor 2) Stop System Monitor 3) Exit Option? <-- このあと全て <Enter> で抜ける ※変更可能なセンサオブジェクトの一覧は こちら をご覧ください。 Caché 用に作成された資料になりますが、以下で^%SYSMONMGRユーティリティについて詳しく説明をしています(IRISでも根本機能は同じです)。ぜひ参考になさってください。モニタリングツールによるシステム監視(P.8~)
記事
Toshihiko Minamoto · 2021年8月3日

IRIS と Python でチャットボットを作成する

![画像](https://raw.githubusercontent.com/renatobanzai/iris-python-covid19/master/img/chatbot.gif) # IRIS と Python でチャットボットを作成する この記事では、InterSystems IRIS データベースを Python と統合して自然言語処理(NLP)の機械学習モデルを提供する方法を説明します。 ### Python を使用する理由 世界的に広く採用され使用されている Python には素晴らしいコミュニティがあり、様々なアプリケーションをデプロイするためのアクセラレータ/ライブラリが豊富に提供されています。 関心のある方は https://www.python.org/about/apps/ をご覧ください。 ### IRIS のグローバル ^globals について学び始めると、型にはまらないデータモデルに素早くデータを取り込む手法として使用することに慣れてきました。 そのため、最初は ^globals を使用してトレーニングデータと会話を保存し、チャットボットの動作をログに記録することにします。 ### 自然言語処理 自然言語処理(NLP)は、人間の言語から意味を読み取って理解する能力を機械に与える AI のテーマです。 ご想像のとおりあまり単純ではありませんが、この広大で魅力的な分野で最初の一歩を踏み出す方法を説明します。 ### デモ - 試してみましょう チャットボットアプリケーションをデモとしてデプロイしています: [http://iris-python-suite.eastus.cloudapp.azure.com:8080](http://iris-python-suite.eastus.cloudapp.azure.com:8080) ### どのように動作しますか? ### 機械学習 まず、機械学習には、一般的なソフトウェア開発とは異なるパラダイムがあることを知っておきましょう。 分かりにくい要点は、機械学習モデルの開発サイクルです。 **完全な説明ではありません** 標準的なアプリケーション開発サイクルは次のようになっています。 コードの開発 -> テスト(開発データを使用)-> デプロイ(実際のデータを使用) そして、機械学習では、コード自体に同じ価値がありません。 責任はデータと共有されています! つまり、データがなければ、実際のデータもないということです。 これは、実行される最終的なコードは、開発コンセプトと使用されるデータのマージによって生成されるためです。 したがって、機械学習アプリケーションのサイクルは次のようになっています。 モデルの開発(トレーニング)と実データ -> 検証 -> この結果(モデル)をデプロイ ### モデルをトレーニングするには モデルをトレーニングするにはたくさんの手法があり、それぞれのケースと目的には大きな学習曲線が伴います。 ここでは、いくつかの手法をカプセル化して、トレーニング方法と事前処理済みのトレーニングデータを提供する [ChatterBot](https://github.com/gunthercox/ChatterBot) ライブラリを使用し、結果に焦点を当てやすくしています。 ### 事前学習のモデル言語とカスタムモデル 基本的な会話型チャットボットを作成するにはこれを使用することができます。 チャットボットをトレーニングするためのすべてのデータがニーズを完全に満たすように作成することもできますが、短時間で作成するのは困難です。 このプロジェクトでは、会話のベースとして en_core_web_sm を使用し、[フォーム](http://iris-python-suite.eastus.cloudapp.azure.com/chatbot-training-data)を使って作成できるカスタムトレーニングデータとマージします。 ### 基本アーキテクチャ ![画像](https://raw.githubusercontent.com/renatobanzai/iris-python-covid19/master/img/chatbot_diagram.png) ### Python で使用したもの このアプリケーション環境では、Python 3.7 と以下のモジュールを使用します。 - PyYAML=1.0.0 - chatterbot>=1.0.0 - chatterbot-corpus>=1.2.0 - SQLAlchemy>=1.2 - ./nativeAPI_wheel/irisnative-1.0.0-cp34-abi3-linux_x86_64.whl ### プロジェクト構造 このプロジェクトは理解しやすい単純な構造になっています。 メインのフォルダには、最も重要な 3 つのサブフォルダがあります。 - ./app: すべての**アプリケーションコード**とインストール構成が含まれます。 - ./iris: アプリケーションをサービングする **InterSystems IRIS dockerfile** が含まれます。 - ./data: **ボリューム**によってホストをコンテナー環境にリンクします。 ### アプリケーション構造 ./app ディレクトリには、以下のファイルが含まれます。 - chatbot.py: Web アプリケーションの実装が含まれます。 - iris_python_suite.py: IRIS Native API によって IRIS データベースや Python と使用する、アクセラレータを持つクラスです。 ### データベース構造 このアプリケーションでは、InterSystems IRIS をリポジトリとして使用します。使用されるグローバルは以下のとおりです。 - ^chatbot.training.data: 質疑応答の形式で、すべてのカスタムトレーニングデータを保存します。 - ^chatbot.conversation: すべての会話ペイロードを保存します。 - ^chatbot.training.isupdated: トレーニングパイプラインを制御します。 ### ほかのソリューションの製品 全会話のレポートは作成しませんでしたが、私のグローバルグラフビューアを使用すれば、問題なく会話を追跡することができます。 ![画像](https://raw.githubusercontent.com/renatobanzai/iris-python-covid19/master/img/conversations.png) ## 自分でアプリケーションを実行する ### 前提条件 * git * docker と docker-compose(docker のメモリ設定を 4 GB 以上に増加してください) * 環境のターミナルへのアクセス ### 手順 docker-compose を使って、すべてのピースと構成を備えた 1 つの環境を簡単に起動できます。iris-python-covid19 フォルダに移動し、次のように入力します。 ``` $ docker compose build $ docker compose up ``` ### コンテナの推定起動時間 初回実行時は、画像や依存関係をダウンロードするためのインターネット接続に依存します。 15 分以上かかる場合は、おそらく何らかの問題が発生しているので、こちらにご連絡ください。 2 回目以降はパフォーマンスが向上し、2 分もかかりません。 ### すべてが万全である場合 しばらくしたら、ブラウザを開いて次のアドレスに移動します。 トレーニングデータのフォーム ``` http://localhost:8050/chatbot-training-data ``` チャットボット ``` http://localhost:8080 ``` ### IRIS 管理ポータルの確認 この時点では、USER ネームスペースを使用しています。 ``` http://localhost:9092 user: _SYSTEM pass: theansweris42 ``` ### この記事が役に立った場合、またはコンテンツを気に入った場合は、投票してください。 このアプリケーションは、Open Exchange コンテストに現在参加中です。こちら(https://openexchange.intersystems.com/contest/current)から私のアプリケーション「**iris-python-suite**」に投票してください。
記事
Mihoko Iijima · 2022年2月4日

Embedded Python 試してみました

開発者の皆さん、Python好きの皆さん、こんにちは! ドキュメントをみながら IRIS 2021.2 に追加された Embedded Python を試してみました! IRIS にログインしてるのに Pythonシェルに切り替えできて Python のコードが書けたり、Python で import iris するだけで SQL を実行できたりグローバルを操作できるので、おぉ!✨という感じです。 ぜひ、みなさんも体感してみてください! では早速。 まず、IRISにログインします。Windows ならターミナルを開きます。Windows 以外は以下実行します。 IRIS のインストール方法を確認されたい方は、【はじめての InterSystems IRIS】セルフラーニングビデオ:基本その1:InterSystems IRIS Community Edition をインストールしてみよう!をチェックしてみてください! iris session iris iris session の引数はインストール時指定のインスタンス名(構成名)です。インスタンス名が不明な場合は iris list を打つと確認できます。以下の例の場合は IRIS がインスタンス名です。 irisowner@dc47786c4ca9:~$ iris list Configuration 'IRIS' (default) directory: /usr/irissys/ versionid: 2021.2.0.649.0 datadir: /data/config/ conf file: iris.cpf (SuperServer port = 1972, WebServer = 52773) status: running, since Fri Feb 4 10:32:13 2022 state: warn product: InterSystems IRISHealth irisowner@dc47786c4ca9:~$ IRIS にログインした状態で Python シェルに切り替えてみましょう。 USER>do ##class(%SYS.Python).Shell() Python 3.8.10 (default, Sep 28 2021, 16:10:42) [GCC 9.3.0] on linux Type quit() or Ctrl-D to exit this shell. >>> print("こんにちは!") こんにちは! >>> Python 書けますね! 次、IRIS にSample.Person クラスがあるとします。後でSQLも実行したいので、永続クラスとして定義してあるとします。 Class Sample.Person Extends %Persistent { Property Name As %String; Property Email As %String; } クラス定義を作成するのが面倒な場合は、以下 CREATE 文を実行でも大丈夫です。 CREATE TABLE Sample.Person (Name VARCHAR(50), Email VARCHAR(50)) メモ:CREATE文の場合、列を記述した順序で列番号が付与されますが、クラス定義はオブジェクト指向の考えに基づいて定義されるため、カラム番号の考えがありません。そのため、SELECT * FROM *** をしたときの表示順が異なる場合があります。 では、この Sample.Person に対して Python シェル上でインスタンスを作成して、保存してみたいと思います! まず最初に、IRISの操作をしたいときは、 import iris をします。​​​ >>> import iris >>> p=iris.cls("Sample.Person")._New() >>> p.Name="山田太郎" >>> p.Email="taro@mail.com" >>> status=p._Save() >>> print(status) 1 インポートした iris モジュールの cls()メソッドにクラス名を指定し、_New() メソッドでインスタンスを生成します。インスタンスに値を入れて保存するときは _Save() メソッドを実行します。 IRIS内の構文に似てますね。 👉 set p=##class(Sample.Person).%New() 保存は set status=p.%Save() では、ちゃんとデータが入っているかSQLで確認しましょう! >>> rs=iris.sql.exec("SELECT Name,Email from Sample.Person") >>> for idx,row in enumerate(rs): ... print(f"[{idx}]:{row}") ... [0]:['山田太郎', 'taro@mail.com'] >>> iris.sql.exec(”実行したいSQL文”) を指定して SQL を実行しています。実行結果(例では変数 rs)はリストで返るので、enumerate()関数を使ってFOR文で中身を取り出しています。 引数がある場合は、iris.sql.prepare() メソッドを利用します。引数の置き換え記号は ? を指定します。 >>> stmt=iris.sql.prepare("SELECT Name,Email from Sample.Person where ID<?") >>> rs=stmt.execute(2) >>> for idx,row in enumerate(rs): ... print(f"[{idx}]:{row}") ... [0]:['山田太郎', 'taro@mail.com'] >>> 今度は、INSERT文を実行して一人増やしてみます。 >>> rs=iris.sql.exec("INSERT INTO Sample.Person (Name,Email) VALUES('鈴木花子','hana@mail.com')") SQLで登録を確認します。 >>> rs=iris.sql.exec("SELECT Name,Email from Sample.Person") >>> for idx,row in enumerate(rs): ... print(f"[{idx}]:{row}") ... [0]:['山田太郎', 'taro@mail.com'] [1]:['鈴木花子', 'hana@mail.com'] >>> 2件目もちゃんと登録できました。 今度は、2件目の花子さんをオブジェクトの文法を使ってオープンして名前を変更して保存します。 >>> hanako=iris.cls("Sample.Person")._OpenId(2) >>> hanako.Name '鈴木花子' >>> hanako.Name="HANAKO" >>> hanako._Save() 1 また SQL で確認してみましょう。 >>> rs=iris.sql.exec("SELECT Name,Email from Sample.Person") >>> for idx,row in enumerate(rs): ... print(f"[{idx}]:{row}") ... [0]:['山田太郎', 'taro@mail.com'] [1]:['HANAKO', 'hana@mail.com'] >>> ローマ字に変わりましたね!Pyhon で IRIS の ObjectScript と同じことができました! では、次に、クラス定義にメソッドを追加します。最初は ObjectScript で書いたものを呼び出してみます。 ClassMethod CreateEmail(uid As %String) As %String { return uid_"@mail.com" } では Python から実行してみます。 >>> iris.cls("Sample.Person").CreateEmail("hanahana") 'hanahana@mail.com' >>> ​​​できましたー! 次、クラス定義にPythonでメソッドのコードを書いてみましょう!(そうなんです。書けちゃうんです。[ Language = python ] を付けたらできるんです!) Method PythonPrint() [ Language = python ] { print("\nあなたの名前は:" + self.Name + " メールは:"+self.Email) } インスタンスメソッドなので、今オープンしている花子さんのデータを表示してみます。 >>> hanako.PythonPrint() あなたの名前は:HANAKO メールは:hana@mail.com >>> 動きましたねー! では、次はグローバルに挑戦です。この記事で紹介した人物相関をグローバルで表現してみようの例を使います。 >>> glo=iris.gref("^Relation") >>> glo["Eren"]="主人公エレン" >>> glo["Eren","Armin"]="" >>> glo["Eren","Mikasa"]="" >>> glo["Eren","Zeke"]="" >>> glo["Armin"]="エレンの幼馴染(エレン)" >>> glo["Mikasa"]="エレンの幼馴染(ミカサ)" >>> glo["Zeke"]="エレンの異母兄弟" >>> iris.gref() メソッドを使用してグローバルの参照を変数に設定しています。例では、前で設定したグローバル変数 ^Relation の参照を取得するため引数に "^Relation" を指定してます。 グローバルの参照を利用して、IRIS内の操作と同様に値を設定したり、サブスクリプトにデータを入れたり、好きなように操作できます。 値を参照したい場合は、こんな感じです。 >>> glo["Eren"] '主人公エレン' >>> 次は、登場人物 エレン のお友達を探してみましょう。 友達情報は、^Relation("Eren") の第2サブスクリプトを探せばよいのですが、Python でも $Order() 関数のイメージのまま記述できます。(import iris を実行した後の記述から書いています) >>> glo=iris.gref("^Relation") >>> sub="" >>> while True: ... sub=glo.order(["Eren",sub]) ... if (sub==None): ... break ... print(sub) ... Armin Mikasa Zeke >>> 無事、Python からもグローバル変数の第2サブスクリプトに設定したエレンのお友達が見つかりました。 いかがでしたでしょうか。 今回は、IRIS にログインした状態で Python を実行する方法を中心に試してみました。(IRIS にログインして Python シェルを起動して IRIS のテーブルやグローバルを操作しました。) 次は、Python のプログラムを IRIS から実行する方法などご紹介する予定です。お楽しみに~ なお、ドキュメントにいろんなパタンのサンプルコードが掲載されています。 記事より前に試された方!ぜひ感想やこんなコード動かせたよ!の情報をお寄せください!お待ちしてます!
記事
Toshihiko Minamoto · 2022年6月2日

プログラムでミラーをセットアップする方法

コミュニティの皆さん、こんにちは。 今までにミラーリング環境をセットアップされたことはありますか? プライベートネットワーク、仮想 IP アドレス、および SSL 構成を設定したことはありますか? この作業を何度か繰り返すと、証明書の生成や各 IRIS インスタンスの構成にはたくさんの手動による作業が必要で、時間がかかる作業であることに気づきました。 頻繁にこの作業を行わなければならない方にとっては、面倒な作業です。 たとえば、品質管理チームでは、新しいバージョンのアプリケーションをテストするたびに、新しい環境を作成しなければならないでしょう。 サポートチームであれば、複雑な問題を再現する環境を作成しなくてはならないかもしれません。 となれば、こういった環境を素早く作成できるツールが絶対に必要です。 この記事では、以下を使用するミラー環境のセットアップ例を紹介します。 - アービター - プライマリ - バックアップフェイルオーバーメンバー - 読み書きレポート非同期メンバー - ノード間でジャーナルを転送するための SSL 構成 - ミラー用のプライベートネットワーク - 仮想 IP アドレス - ミラーリングされたデータベース ![ネットワークスキーマ](https://raw.githubusercontent.com/lscalese/iris-mirroring-samples/master/img/net-schema.png) 一見すると、ちょっと複雑であり、たくさんのコードが必要なように見えますが、ご心配いりません。 OpenExchange には、ほとんどの操作を簡単に実行できるライブラリがあります。 この記事では、プロセスをニーズに適合させる方法を例示することを目的としていますが、セキュリティ事項においてはベストプラクティスガイドではありません。 では、ここで使用するサンプルを作成しましょう。 ### ツールとライブラリ - [PKI-script](https://openexchange.intersystems.com/package/PKI-Script): 公開鍵基盤(PKI)は、自己署名された証明書を生成して権限サーバーを得られるようにする、IRIS に統合された機能です。 [Pete Greskoff の素晴らしい記事](https://community.intersystems.com/post/creating-ssl-enabled-mirror-intersystems-iris-using-public-key-infrastructure-pki)によると、PKI Script ライブラリは、すべての操作をプログラムで実行し、管理ポータルでのあらゆる手動操作を回避することを目標としています。 このライブラリには、ミラーリング用のユーティリティメソッドが含まれますが、 証明書がすでにある場合は、PKI-Script の代わりにその証明書を使用できます。 - [config-api](https://openexchange.intersystems.com/package/Config-API): このライブラリは、IRIS の構成に使用されます。 ミラーリング構成は、バージョン 1.1.0 以来サポートされています。 このライブラリの使用方法については詳しく説明しません。 これについてはいくつかの記事がすでに公開されていますので、 [そちら](https://community.intersystems.com/post/environment-setup-config-api)をご覧ください。 手短に言えば、config-api は IRIS テンプレート構成ファイル(JSON 形式)の作成と読み込みを簡単に行うために使用されます。 - [ZPM](https://openexchange.intersystems.com/package/ObjectScript-Package-Manager) - Docker ### GitHub ページ すべての必要なリソースは、[iris-mirroring-samples リポジトリ](https://github.com/lscalese/iris-mirroring-samples/)にあります。 ### システムの準備 既存のリポジトリをクローンします。 ```bash git clone https://github.com/lscalese/iris-mirroring-samples cd iris-mirroring-samples ``` リポジトリをクローンする代わりにサンプルを新規作成する場合は、新しいディレクトリと、`backup` と `config-files` というサブカテゴリを作成します。 [irissession.sh](https://raw.githubusercontent.com/lscalese/iris-mirroring-samples/master/session.sh) をダウンロードします。 ``` mkdir -p iris-mirroring-samples/backup iris-mirroring-samples/config-files cd iris-mirroring-samples wget -O session.sh https://raw.githubusercontent.com/lscalese/iris-mirroring-samples/master/session.sh ``` 後で「アクセス拒否」の問題が発生しないように、`irisowner` グループと `irisowner` ユーザーを作成し、バックアップディレクトリのグループを `irisowner` に変更する必要があります。 ```bash sudo useradd --uid 51773 --user-group irisowner sudo groupmod --gid 51773 irisowner sudo chgrp irisowner ./backup ``` このディレクトリは、最初のミラーメンバーをセットアップした後に、他のノードとデータベースバックアップを共有するためのボリュームとして使用されます。 ### IRIS ライセンスを取得する IRIS Community エディションでは、ミラーリングを使用できません。 有効な IRIS コンテナーライセンスをまだお持ちでない場合は、資格情報を使用して [Worldwide Response Center(WRC)](https://wrc.intersystems.com)にお問い合わせください。 「アクション」-->「オンライン配布」、次に「評価」ボタンをクリックし、「評価ライセンス」を選択してフォームに入力します。 ライセンスファイルの `iris.key` をこのディレクトリにコピーします。 ### InterSystems Containers Registry にログインする 便宜上、InterSystems Containers Registry(ICR)を使用して、Docker イメージをプルします。 Docker ログイン\\パスワードが不明な場合は、WRC 資格情報を使用して [SSO.UI.User.ApplicationTokens.cls](https://login.intersystems.com/login/SSO.UI.User.ApplicationTokens.cls) にアクセスすると、ICR トークンを取得できます。 ```bash docker login -u="YourWRCLogin" -p="YourICRToken" containers.intersystems.com ``` ### `myappdata` データベースとグローバルマッピングを作成する ここでは実際には `myappdata` データベースの作成を行いませんが、Docker ビルド時にそれを作成するように構成を準備します。 そのためには、JSON 形式で単純なファイルを作成します。IRIS インスタンスに読み込むには config-api ライブラリが使用されます。 [config-files/simple-config.json](https://github.com/lscalese/iris-mirroring-samples/blob/master/config-files/simple-config.json) ファイルを作成します。 ```json { "Defaults":{ "DBDATADIR" : "${MGRDIR}myappdata/", "DBDATANAME" : "MYAPPDATA" }, "SYS.Databases":{ "${DBDATADIR}" : {} }, "Databases":{ "${DBDATANAME}" : { "Directory" : "${DBDATADIR}" } }, "MapGlobals":{ "USER": [{ "Name" : "demo.*", "Database" : "${DBDATANAME}" }] }, "Security.Services" : { "%Service_Mirror" : { /* このインスタンスのミラーサービスを有効にします */ "Enabled" : true } } } ``` この構成ファイルを使用すると、デフォルトの設定で新しいデータベースを作成し、USER ネームスペースに `demo.*` というグローバルマッピングを指定できます。 [config-api](https://openexchange.intersystems.com/package/config-api) 構成ファイルの機能に関する詳細については、関連する[記事](https://community.intersystems.com/post/environment-setup-config-api)または [GitHub ページ](https://community.intersystems.com/post/environment-setup-config-api)をご覧ください。 ### Docker ファイル Docker ファイルは既存の [Docker テンプレート](https://github.com/intersystems-community/objectscript-docker-template)を基盤としていますが、作業ディレクトリの作成、仮想 IP を使用するためのツールのインストール、ZPM のインストールなどを行うように変更する必要があります。 IRIS イメージは、すべてのミラーメンバーで同一です。 ミラーリングは、ロール(最初のメンバー、フェイルオーバーバックアップ、または読み書きレポート)に応じて正しい構成を使って開始するコンテナにセットアップされます。 以下の Dockerfile のコメントをご覧ください。 ```Dockerfile ARG IMAGE=containers.intersystems.com/intersystems/iris:2021.1.0.215.0 # WRC からイメージをダウンロードする必要はありません。 イメージはビルド時に ICR からプルされます。 FROM $IMAGE USER root # COPY session.sh / COPY iris.key /usr/irissys/mgr/iris.key # /opt/demo を作業ディレクトリとし、構成ファイルやその他のインストールファイルをそこに保存します。 # arping コマンドを得るために、iputils-arping をインストールします。 仮想 IP の構成に必要です。 # 最新の ZPM バージョンをダウンロードします(ZPM は Communty エディションにのみ含まれます)。 RUN mkdir /opt/demo && \ chown ${ISC_PACKAGE_MGRUSER}:${ISC_PACKAGE_IRISGROUP} /opt/demo && \ chmod 666 /usr/irissys/mgr/iris.key && \ apt-get update && apt-get install iputils-arping && \ wget -O /opt/demo/zpm.xml https://pm.community.intersystems.com/packages/zpm/latest/installer USER ${ISC_PACKAGE_MGRUSER} WORKDIR /opt/demo # デフォルトミラーのロールを master に設定します。 # これはランタイム時に docker-compose ファイルでオーバーライドされます(最初のインスタンス、バックアップ、およびレポートのマスター) ARG IRIS_MIRROR_ROLE=master # config-files ディレクトリの内容を /opt/demo にコピーします。 # 現時点では、データベースとグローバルマッピングをセットアップする simple-config のみを作成しました。 # この記事の後の方で、ミラーのセットアップを行う他の構成ファイルを追加します。 ADD config-files . SHELL [ "/session.sh" ] # ZPM をインストールします。 # ZPM を使用して、config-api と pki-script をインストールします。 # 以下の操作を行うために、config-api を使って simple-config.json ファイルを読み込みます。 # - 「myappdata」データベースを作成する # - 「myappdata」データベースのグローバル「demo.*」の「USER」ネームスペースにグローバルマッピングを追加する # 基本的に、ここが、ObjectScript アプリケーションをインストールするエントリポイントです。 # このサンプルでは、simple-config.json を読み込んで、単純なデータベースとグローバルマッピングを作成します。 RUN \ Do $SYSTEM.OBJ.Load("/opt/demo/zpm.xml", "ck") \ zpm "install config-api" \ zpm "install pki-script" \ Set sc = ##class(Api.Config.Services.Loader).Load("/opt/demo/simple-config.json") # ミラー初期化スクリプトをコピーします。 COPY init_mirror.sh / # 起動後のスクリプト実行して、ミラーリングを構成します。 # init_mirror.sh の内容は、この記事の後の方で記述されます。 CMD ["-a", "/init_mirror.sh"] ``` ### IRIS イメージをビルドする Dockerfile の準備ができたので、イメージをビルドできます。 ``` docker build --no-cache --tag mirror-demo:latest . ``` このイメージは、プライマリ、バックアップ、およびレポートノードの実行に使用されます。 ### 最初のミラーメンバー構成ファイルを準備する config-api ライブラリではミラーの構成が可能であるため、最初のミラーメンバー専用の構成ファイル `config-files/mirror-master.json` を作成する必要があります。 便宜上、コメントは直接 JSON に記述されています。 [コメントなしの mirror-master.json はこちら](https://raw.githubusercontent.com/lscalese/iris-mirroring-samples/master/config-files/mirror-master.json)からダウンロードできます。 すべての IP アドレスは、`Docker-compose` ファイルのあるノードにそれぞれ割り当てられます。 ```json { "Defaults":{ /* すべての変数を含むセクション */ "MirrorName" : "Demo", /* ミラー名 */ "ArbiterNode" : "172.16.238.10|2188", /* アービターノードの IP アドレスとポート */ "VirtualAddress" : "172.16.238.100/24", /* 仮想 IP アドレス */ "VirtualAddressInterface" : "eth0", /* 仮想 IP アドレスに使用されるネットワークインターフェース */ "MirrorAddress" : "172.16.220.20", /* プライベートミラーネットワーク内のこのノードの IP アドレス */ "AgentAddress" : "172.16.238.20", /* このノードの IP アドレス(Agent は同じマシンにインストールされています) */ "SystemName" : "master", /* ミラー内のこのインスタンスの名前 */ "DBDir" : "${MGRDIR}myappdata/", /* Demo ミラーい追加するデータベースディレクトリ */ "DBName" : "MYAPPDATA" /* ミラー内のデータベース名 */ }, "SYS.MirrorMaster" : { "${MirrorName}" : { "Config" : { "Name" : "${MirrorName}", "SystemName" : "${SystemName}", "UseSSL" : true, "ArbiterNode" : "${ArbiterNode}", "VirtualAddress" : "${VirtualAddress}", "VirtualAddressInterface" : "${VirtualAddressInterface}", "MirrorAddress": "${MirrorAddress}", "AgentAddress": "${AgentAddress}" }, "Databases" : [{ /* ミラーに追加するデータベースのリスト */ "Directory" : "${DBDir}", "MirrorDBName" : "${DBName}" }], "SSLInfo" : { /* SSL 構成、証明書は PKI で生成されます */ "CAFile" : "/usr/irissys/mgr/CAServer/CA_Server.cer", "CertificateFile" : "/usr/irissys/mgr/master_client.cer", "PrivateKeyFile" : "/usr/irissys/mgr/master_client.key", "PrivateKeyPassword" : "", "PrivateKeyType" : "2" } } } } ``` ### フェイルオーバーミラーメンバー構成ファイルを準備する フェイルオーバーバックアップメンバーの `config-files/mirror-backup.json` 構成ファイルを作成します。 最初のメンバーに似ています。 ```json { "Defaults":{ /* すべての変数を含むセクション */ "MirrorName" : "Demo", /* 参加するミラー */ "AgentAddress" : "172.16.238.20", /* 最初のミラーメンバーの Agent IP アドレス */ "SystemName" : "backup", /* ミラー内のこのインスタンス名 */ "PrimaryInstanceName" : "IRIS", /* 最初のミラーメンバーの IRIS インスタンス名 */ "VirtualAddressInterface" : "eth0", /* 仮想 IP アドレスに使用されるネットワークインターフェース */ "DBDir" : "${MGRDIR}myappdata/", /* ミラーの DB */ "MirrorAddress" : "172.16.220.30" /* プライベートネットワーク内のこのノードの IP アドレス */ }, "SYS.MirrorFailOver" : { "${MirrorName}" : { "Config": { "Name" : "${MirrorName}", "SystemName" : "${SystemName}", "InstanceName" : "${PrimaryInstanceName}", "AgentAddress" : "${AgentAddress}", "AgentPort" : "2188", "AsyncMember" : false, "AsyncMemberType" : "" }, "Databases" : [{ "Directory" : "${DBDir}" }], "LocalInfo" : { "VirtualAddressInterface" : "${VirtualAddressInterface}", "MirrorAddress": "${MirrorAddress}" }, "SSLInfo" : { "CAFile" : "/usr/irissys/mgr/CA_Server.cer", "CertificateFile" : "/usr/irissys/mgr/backup_client.cer", "PrivateKeyFile" : "/usr/irissys/mgr/backup_client.key", "PrivateKeyPassword" : "", "PrivateKeyType" : "2" } } } } ``` ### 読み書き非同期メンバー構成ファイルを準備する フェイルオーバー構成ファイルに非常に良く似ています。 違いは、`AsyncMember`、`AsyncMemberType`、および `MirrorAddress` の値です。 `./config-files/mirror-report.json` ファイルを作成します。 ```json { "Defaults":{ "MirrorName" : "Demo", "AgentAddress" : "172.16.238.20", "SystemName" : "report", "PrimaryInstanceName" : "IRIS", "VirtualAddressInterface" : "eth0", "DBDir" : "${MGRDIR}myappdata/", "MirrorAddress" : "172.16.220.40" }, "SYS.MirrorFailOver" : { "${MirrorName}" : { "Config": { "Name" : "${MirrorName}", "SystemName" : "${SystemName}", "InstanceName" : "${PrimaryInstanceName}", "AgentAddress" : "${AgentAddress}", "AgentPort" : "2188", "AsyncMember" : true, "AsyncMemberType" : "rw" }, "Databases" : [{ "Directory" : "${DBDir}" }], "LocalInfo" : { "VirtualAddressInterface" : "${VirtualAddressInterface}", "MirrorAddress": "${MirrorAddress}" }, "SSLInfo" : { "CAFile" : "/usr/irissys/mgr/CA_Server.cer", "CertificateFile" : "/usr/irissys/mgr/report_client.cer", "PrivateKeyFile" : "/usr/irissys/mgr/report_client.key", "PrivateKeyPassword" : "", "PrivateKeyType" : "2" } } } } ``` ### IRIS ノードを構成して証明書を生成する すべての構成ファイルの準備が整いました! [Dockerfile](https://github.com/lscalese/iris-mirroring-samples/blob/master/Dockerfile) の最後の行は、`CMD ["-a", "/init_mirror.sh"]` です。 次に、証明書を生成して、関連する構成ファイルで各 IRIS ノードをセットアップするこのスクリプトを記述する必要があります。 以下のこのスクリプトでわかるように、証明書を生成するためのコードはいたって単純です。 * マスターの場合は、`Do ##class(lscalese.pki.Utils).MirrorMaster(,"",,,,"backup,report")` とします。 PKI サーバー、PKI クライアント、証明書のリクエストの構成、検証を待機、証明書の取得、以降のノード別のリクエストを 5 分間自動的に検証、を行います。 自動的に受け入れられるリクエストは、ホストの `backup` と `report` に制限されます。 * バックアップとレポートノードの場合は、`Do ##class(lscalese.pki.Utils).MirrorBackup("${PKISERVER}","")` とします。 PKI クライアントを構成、証明書をリクエスト、検証を待機、証明書を取得、を行います。 ```bash #!/bin/bash # ミラーをテストするために使用されるデータベース。 DATABASE=/usr/irissys/mgr/myappdata # ディレクトリには、他のノードでリストアするための、マスターがバックアップした myappdata が含まれます。 BACKUP_FOLDER=/opt/backup # マスターノード用の config-api JSON 形式のミラー構成ファイル。 MASTER_CONFIG=/opt/demo/mirror-master.json # フェイルオーバーとバックアップノード用の config-api JSON 形式のミラー構成ファイル。 BACKUP_CONFIG=/opt/demo/mirror-backup.json # レポートと非同期ノード用の config-api JSON 形式のミラー構成ファイル。 REPORT_CONFIG=/opt/demo/mirror-report.json # ミラー名... MIRROR_NAME=DEMO # ミラーメンバーのリスト。 MIRROR_MEMBERS=BACKUP,REPORT # PKI サーバーのホスト:ポート(PKI サーバーはマスターインスタンスにインストールされます) PKISERVER=master:52773 # マスターで実行。 # このインスタンスの公開鍵基盤サーバーを構成し、SSL を使用してミラーを構成するための証明書を生成します。 # https://community.intersystems.com/post/creating-ssl-enabled-mirror-intersystems-iris-using-public-key-infrastructure-pki に記載された記事と # https://openexchange.intersystems.com/package/PKI-Script の関連ツールをご覧ください。 # config-api と /opt/demo/simple-config.json ファイルを使用して、マイナー構成を読み込みます。 # 「backup」と「report」という他のメンバーのミラーへの参加を自動的に許可するジョブを開始します(最大 600 秒の遅延でポータル管理の手動検証を回避します)。 master() { rm -rf $BACKUP_FOLDER/IRIS.DAT iris session $ISC_PACKAGE_INSTANCENAME -U %SYS
記事
Mihoko Iijima · 2020年12月20日

揮発性テーブルのビットマップ・インデックスの圧縮(維持管理)方法

これは InterSystems FAQ サイトの記事です 揮発性テーブル(多数のINSERT、DELETEが行われるテーブル)では、ビットマップ・インデックス用ストレージは徐々に効率が低下する可能性があります。 例えば、以下の定義からなるデータが数千件あり、一定期間保持した後 TRUNCATE TABLE で一括削除を行うオペレーションが繰り返し行われているとします。 Class MyWork.MonthData Extends (%Persistent, %Populate) { /// 満足度 Property Satisfaction As %String(VALUELIST = ",満足,やや満足,やや不満,不満,"); /// 年齢 Property Age As %Integer(MAXVAL = 70, MINVAL = 20); Index AgeIdx On Age [ Type = bitmap ]; } INSERT によってできたビットマップ・インデックスのストレージのイメージ(一部)は以下の通りです。 【INSERT時】 ^MyWork.MonthDataI("AgeIdx",20,1) = $zwc(401,120,4,75,102,10,<省略> 958)/*$bit(5,76,103,107・・・ ^MyWork.MonthDataI("AgeIdx",21,1) = $zwc(407,121,29,178,251,2<省略>,732,772,898,960)/*$bit(3・・・ ^MyWork.MonthDataI("AgeIdx",22,1) = $zwc(402,96,5,57,74,164,<省略>,0,4)/*$bit(20,63,77,92,10・・・ ^MyWork.MonthDataI("AgeIdx",23,1) = $zwc(133,116)_$c(0,0,8,0<省略>,64,0,4)/*$bit(20,63,77,92・・・ ^MyWork.MonthDataI("AgeIdx",25,1) = $zwc(404,119,105,155,235<省略>,947)/*$bit(106,156,236,30・・・ ^MyWork.MonthDataI("AgeIdx",26,1) = $zwc(128,119)_$c(0,0,0,2,<省略>,0,128)/*$bit(26,80,115,1・・・  <以下省略> TRUNCATE TABLE でデータを一括削除した場合、レコードデータは消えますがビットマップ・インデックス用ストレージの一部が残ります(イメージ)。 【TRUNCATE後】 ^MyWork.MonthDataI("AgeIdx",20,1) = $zwc(145,120)/*$bit()*/ ^MyWork.MonthDataI("AgeIdx",21,1) = $zwc(151,121)/*$bit()*/ ^MyWork.MonthDataI("AgeIdx",22,1) = $zwc(146,96)/*$bit()*/ ^MyWork.MonthDataI("AgeIdx",23,1) = $zwc(133,116)_$c(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,・・・ ^MyWork.MonthDataI("AgeIdx",24,1) = $zwc(131,125)_$c(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,・・・ ^MyWork.MonthDataI("AgeIdx",25,1) = $zwc(148,119)/*$bit()*/ ^MyWork.MonthDataI("AgeIdx",26,1) = $zwc(128,119)_$c(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,・・・  <以下省略> このように、繰り返し行われるデータの入れ直しによりビットマップ・インデックス用ストレージに不要な情報が残ったり、一括更新作業で効率が低下するようなストレージになった場合、%SYS.Maint.Bitmap クラスのOneClass()、Namespace() メソッドを使用してビットマップ・インデックスを圧縮(維持管理)し、最適な効率に復元することができます。 実行例は以下の通りです。 // 第1引数:クラス名 // 第2引数:ジャーナルに記録しない:1/記録する:0 // 第3引数:実行結果の画面表示あり:1/表示なし:0 >set st=##class(%SYS.Maint.Bitmap).OneClass("MyWork.MonthData",1.1) Class: MyWork.MonthData Start Time: 2017-06-21 15:34:54 Global: ^MyWork.MonthDataI("$MonthData")was compressed: 96.15% Old Size: 0.000(MB) New Size: 0.000(MB) Global: ^MyWork.MonthDataI("AgeIdx")was compressed: 61.09% Old Size: 0.004(MB) New Size: 0.002(MB) Compression time in seconds: 0 Namespace() メソッドはネームスペース全体のビットマップ・インデックスの圧縮を行います。 詳細は下記クラスリファレンスをご参照ください。 クラスリファレンス(%SYS.Maint.Bitmap.Namespace())【IRIS】クラスリファレンス(%SYS.Maint.Bitmap.Namespace())
記事
Megumi Kakechi · 2021年4月23日

インターシステムズの技術の優位性について

これは InterSystems FAQ サイトの記事です。 アプリケーションに求められる要件は日々複雑化しています。 しかし、複雑化するからといって開発のスピードおよび実行時のスピードが遅くなることは許されません。 複雑な要件を満たすために現在主流の手法ではソフトウェアスタック上の様々な部品(ミドルウェア、ライブラリ、フレームワークなど)を組み合わせる方法を取ります。 この方法は、様々なものを学習するための時間、それらを連携する方法、経年で様々なものが進化していくことに伴って各部品間の関係性が変化するためにそれらを維持管理していくための手間など様々な付帯的な作業が必要です。 結果として本来行いたいことに集中して取り組む前に付随する作業に忙殺されることになり開発生産性があがりません。しかも実行時にも様々な部分が連携するためのオーバーヘッドを避けることができず期待する性能を確保することも困難になります。 一方インターシステムズのプラットフォームには上記要件を満たすのに必要十分な機能がひとつの首尾一貫した形で提供されており上記の様な手間がほとんど必要ありません。 さらにこのプラットフォームにはインターシステムズ独自の高性能、スケーラビリティの高いデータベースエンジンが内蔵されており様々なデータ処理を効率良く高速に処理します。 結果として本来行いたい作業に集中でき、アプリケーションを素早く開発でき、完成したアプリケーションは期待通りの性能を発揮します。 以下の記事もあわせてご覧ください。 【FAQ】ブレークスルーアプリケーションとはどのようなものですか? 【FAQ】インターシステムズという会社を簡単に説明してください。
記事
Mihoko Iijima · 2021年6月28日

クラス定義でプロパティ名を変更するとそれまで参照できていたデータが参照できなくなる/参照時にエラーが発生する場合の対処方法

これは InterSystems FAQ サイトの記事です。 クラス定義の Property 定義文の名称を直接変更した場合、内部的には 元のプロパティを削除し、新しいプロパティを追加 したことになります。 このため、すでにデータを格納している永続クラスのプロパティ名をエディタで直接変更した場合、元のプロパティで設定されていた値にはアクセスができなくなります(新しいデータの格納位置が割り当てられます)。 また、変更したプロパティが必須(非ヌル)に指定されていた場合、データが存在しないために参照時にエラーが発生します。 以下の図は、左画面が変更前の状態、右画面がプロパティ名を変更してコンパイルを行った状態です。 基本的に、このような操作を行う場合は、あらかじめデータをエクスポートし、データの削除を行い、クラス定義の変更を行ってから、データを再インポートする方法が安全です。 または、スタジオのメニューの クラス > リファクタ > 名前変更 を利用してプロパティ名を変更します。(リファクタの名前変更メニューにより、クラス定義内のストレージやメソッド定義に対して、一括でプロパティ名を変更できます。) 変更対象のクラス定義を開き、修正したいプロパティ名を選択し、スタジオのメニューの クラス > リファクタ > 名前変更 を選択します。 変更対象の場所を目で確認しながら変更を許可することができます。変更を行った後は、クラス定義のコンパイルを行います。 VSCode または、リファクタメニューがない古いバージョンのスタジオでは、プロパティ名を修正した後、手動でストレージ定義を変更します。 方法:ストレージの定義で、新しいプロパティが元のプロパティと同じ格納位置をポイントするように手動で調整します。 詳細は、以下の通りです。 補足:<Value name="2"> の番号(例は2)は、システムにより任意の数が設定されます。
記事
Hiroshi Sato · 2022年10月14日

CachéでCache Directエミュレータを使っているアプリケーションをIRISのCache Directエミュレータに書き換える方法

IRISでは.Net Binding機能が非推奨になったため、VisM.OCXの置き換えのために用意していたCaché版Cache Directエミュレータ(.Net Binding機能を使用していたため)の使用も非推奨となりました。そこでIRISのNative API機能を使用して書き換えたものを作成し、OpenExchange(以下のFAQトピックを参照してください)に登録しています。 FAQのトピック Caché版Cache Directエミュレータを使っているアプリケーションをIRISに移行するためには、IRIS用のCache Directエミュレータに置き換えて、アプリケーションのコードをいくつか書き換える必要があります。 内容は、それぞれのプロジェクトに含まれるコンソールアプリケーションサンプル(consoleApp.cs)を比較することで大体理解できると思いますが、以下にその手順について説明します。 1. IRISの.Net Native API用のdllの参照設定を追加します。 Visual Studioのプロジェクト設定から参照の追加を選び、以下のファイルを追加してください。 c:\InterSystems\IRIS\dev\dotnet\bin\v4.6.2InterSystems.Data.IRISClient.dll 2. using句 Caché版の場合は、以下のusing句が使われていると思います。 using InterSystems.Data.CacheClient;using InterSystems.Data.CacheTypes; IRISでは、以下の様に変更します。 using InterSystems.Data.IRISClient;using InterSystems.Data.IRISClient.ADO; 3. 接続処理およびインスタンスの生成 Caché版の場合は、以下のような記述で接続、インスタンス生成処理を行っていると思います。 cacheDirectWapper cdw = new cacheDirectWapper("Server = localhost; Log File=cprovider.log;Port=1972; Namespace=USER; Password = SYS; User ID = _system;"); IRIS版でも同じ処理で接続、インスタンス生成できます。 IRIS版では先にIRISへの接続を確立後、その接続オブジェクトを使用して接続する方法もサポートしています。 IRISConnection irisconn = new IRISConnection();irisconn.ConnectionString = "Server = localhost; Log File=cprovider.log;Port=1972; Namespace=USER; Password = SYS; User ID = _system;";irisconn.Open();cacheDirectWapper cdw = new cacheDirectWapper(irisconn); 4. プロパティの参照 Caché版の場合には、.Net Bindingの仕様の制約によって、プロパティやメソッドの参照は、以下の様に2段階(.を2つ使用)になっていました。 cdw.cd.P0 = "ABC;DEF;GHI"; IRIS版の場合は、そのような制約がないので、直接1つの.で参照できるようになりました。 cdw.P0 = "ABC;DEF;GHI";
記事
Megumi Kakechi · 2020年9月27日

コンソールログに出力される「Pausing users because the Write Daemon has not shown...」のエラーについて

これはInterSystems FAQ サイトの記事です。コンソールログ(message.log/cconsole.log)に、以下のようなログが出力される場合があります。 MM/DD/YY-hh:mm:ss:sss (pid) 2 CP: Pausing users because the Write Daemon has not shown signs of activity for xxx seconds. Users will resume if Write Daemon completes a pass or writes to disk (wdpass=yyyy). このメッセージは、コントロールプロセスが出力しています。このプロセスは、ライトデーモン(WriteDaemon)等の主要なシステムプロセスを監視しています。 この監視にて、ディスクI/O 負荷が上がったことなどにより、ライトデーモンの書き込み処理が一定期間(xxx秒間)進んでいない場合、データベースキャッシュ上にダーティなバッファが増えるのを抑制する為に、ユーザプロセスのデータベースへの書き込みアクセスをサスペンドします。このメッセージ出力後、ライトデーモンの活動が復帰するまでユーザプロセスの書き込みアクセスは待ち状態になります(ハング状態になります)。その際、アプリケーションの応答時間への影響が発生します。 ただし、ディスクI/O 負荷が軽減し、ライトデーモンの処理が進行した場合は、以下のメッセージが記録されます。 MM/DD/YY-hh:mm:ss:sss (pid) 0 Write Daemon has show signs of activity, allowing users to proceed この場合は、事象は一時的なものであり問題はありません。 上記の回復を示すメッセージが出力されていない場合は、ライトデーモンの書き込み処理は何らかの原因でハング状態にあったと考えられます。 1つの原因として、ライトデーモンのデータベースファイルへのアクセスが、セキュリティソフトによってブロックされたことが挙げられます。その場合は、インストールフォルダ以下のすべてのファイル(サブフォルダ―も含む)、およびすべてのデータベースファイル、ジャーナルファイルをスキャン対象から外してください。 また、データベースの破損の可能性もありますので、その場合は整合性チェックを行うことを推奨します。
記事
Henrique Dias · 2020年10月8日

概要 npm-iris

npm-iris とは何ですか? N.P.Mは "No Project Mess "の略です。 N.P.M.は、InterSystems IRISとBootstrap 4を使用したプロジェクト&タスク管理アプリです。 No Project Messは、シンプルで直感的なプロジェクトとタスクの管理ソフトウェアで、開発者や中小企業が日々の複雑な問題を軽減できるように作成されています。 スプレッドシート、カンバン、カレンダー、ガントチャートなど、タスクのためのさまざまなビューを提供しています。 なぜでしょうか? 異なるチームで仕事をしていると、あなたは異なるツールを好む人々の存在に気づくでしょう。 だから、多くの場合、あなたはプロジェクトのためのガントチャート、別のためのカンバン、他の紙の上のリストを使用しているでしょう... N.P.M.を使うとこういった煩わしさから解放されます。 あなたやあなたのチームがどのような表示を好むかは関係ありません。 表示はクリックだけで変更することが出来ます。 特徴 初期設定 プロジェクト 利用者 タスク : タスクの作成と管理 スケジューラ : タスクのカレンダー表示 カンバン : カンバンスタイルでタスクを管理する ガント : ガントチャートを使用して、締め切り、マイルストーン、進捗状況を確認できます。 新機能・改善のためのロードマップ OAuth2認証 プロジェクト/チーム/ユーザー別のセキュリティ タイムトラッキング カスタムカレンダー(祝日) 添付ファイルのサポート AppS.RESTフレームワークを活用 Vue.js版 ホームダッシュボードでtodoリストの進捗を確認することができます。 ここでソフトウェアを試すことができます!!!http://npm-iris.eastus.cloudapp.azure.com:52773/npm/home.csp あなたがソフトウェアを気に入って、私があなたの投票に値すると思うなら、npm-irisに投票してください! https://openexchange.intersystems.com/contest/current Henriqueさん、ありがとうございます。 シンプルで見やすいですね!また、ユーザがそれぞれ見やすい画面を選択できるというのも良いと思いました Toshihikoさん、どうもありがとうございました。
記事
Shintaro Kaminaka · 2021年4月15日

IRIS for Health上でFHIRリポジトリ+OAuth2認可サーバ/リソースサーバ構成を構築するパート4(代行認証編)

開発者の皆さん、こんにちは。 以前の[記事](https://jp.community.intersystems.com/node/481321)でIRIS for Health上でFHIRリポジトリを構築し、OAuth2認証を構成する方法をご紹介しました。 この代行認証編では、IRIS for HealthのFHIRリポジトリに組み込まれた認証機能ではなく、IRISの代行認証機能+ZAUTHENTICATEルーチンを使用して認証を行う方法をご紹介します。 前回記事でご紹介したように、標準のFHIRリポジトリの認証機構では、アクセストークンの発行先を追加するためのAudienceの指定(aud=https://~) や、アクセストークンだけではなくベーシック認証の情報を送付するなどの対応が必要でした。 スクラッチでFHIRクライアントを開発するのではなく、既成の製品やアプリケーションからアクセスする場合、上記のような処理の実装ができないことがあるかもしれません。 そのような場合には、この代行認証+ZAUTHENTICATEルーチンを使用して、カスタマイズした認証の仕組みを構築することができます。 ## この記事に含まれる情報のドキュメントについて この記事で記載されている情報はIRIS for Healthのドキュメントにも含まれている内容をわかりやすく再構成したものです。 [RESTサービスの保護:RESTアプリケーションおよびOAuth2.0](https://docs.intersystems.com/irisforhealth20201/csp/docbookj/Doc.View.cls?KEY=GREST_securing#GREST_oauth2) [OAuth 2.0 クライアントとしての InterSystems IRIS Web アプリケーションの使用法](https://docs.intersystems.com/irisforhealth20201/csp/docbookj/DocBook.UI.Page.cls?KEY=GOAUTH_client) ## 代行認証を有効にする まず使用しているIRIS環境で「代行認証」機能を有効にし、アクセスするFHIRリポジトリの「Webアプリケーション設定」で「代行認証」機能を使える用に構成します。 ### 認証/ウェブセッションオプション画面 まずシステムとして「代行認証」が使用できるように構成します。 管理ポータルの システム管理→セキュリティ→システム・セキュリティ→認証/ウェブセッションオプション と進み、「代行認証を許可」をチェックします。 「代行認証によるOS認証を許可」ではありませんのでご注意ください。 ![image](/sites/default/files/inline/images/iris_oauth2_part3_ss1.jpg) ### %Service_WebGatewayサービス 画面 次に、CSPゲートウェイを経由したWebのアクセスに対して、「代行認証」が有効になるよう構成します。 管理ポータルの システム管理→セキュリティ→サービス と進み、「%Service_WebGateway」をクリックして、許可された認証方法の「代行」にチェックがついていることを確認します。もしチェックされていなければ、チェックして保存を実行してください。 ![image](/sites/default/files/inline/images/iris_oauth2_part3_ss2.jpg) ### FHIRリポジトリの ウェブアプリケーションの編集 画面 最後に、アクセスするFHIRリポジトリの ウェブ・アプリケーションの編集画面で「代行認証」を有効にします。 管理ポータルの システム管理→セキュリティ→アプリケーション→ウェブ・アプリケーション と進み、該当のFHIRリポジトリアプリケーションを選択します。 特に変更をしていなければ、/csp/healthshare/\/fhir/r4 となっています。 この画面で、セキュリティの設定:許可された認証方法の「代行」をチェックして保存します。 ![image](/sites/default/files/inline/images/iris_oauth2_part3_ss3.jpg) これで、「代行認証」を利用する準備はOKです。次は、実際に代行認証のためのロジックが記載されたZAUTHENTICATEルーチンを用意します。 ## ZAUTHETICATEルーチンの入手とインポート ZAUTHENTICATEルーチンのサンプルはInterSystemsのGitHubで公開されています。 [GitHub:Samples-Security](https://github.com/intersystems/Samples-Security/) この記事ではここで紹介されているREST.ZAUTHENTICATE.macルーチンを利用します。 GitHubのREADMEに記載されているこのルーチンの説明をここにも転載します。 * `REST.ZAUTHENTICATE.mac` is another sample routine that demonstrates how to authenticate a REST application using OAuth 2.0. To use this sample: 1. Configure the resource server containing the REST application as an OAuth 2.0 resource server. 2. Copy this routine to the %SYS namespace as ZAUTHENTICATE.mac. 3. Modify value of applicationName in ZAUTHENTICATE.mac. 4. Allow delegated authentication for %Service.CSP. 5. Make sure that the web application for the REST application is using delegated authentication. この記事では、先に手順の4.,5.を済ませているので、ルーチンのインポートを実施しましょう。 (上記READMEでは、%Service.CSPと記載されていますが、現在は%Service_WebGatewayになっています。) GitHubからルーチンをダウンロードしてインポートするか、あるいは、この[リンク](https://github.com/intersystems/Samples-Security/blob/master/rtn/REST.ZAUTHENTICATE.mac)から直接ルーチンを表示し、中身をStudioやVS Codeのエディタを使ってコピーしてZAUTHENTICATEルーチンをつくることもできます。**%SYS**ネームスペースに作成します。 (**注意**:2021/4/16時点ではこのルーチンをスタジオからインポートするとエラーが発生してしまいます。お手数ですが、ファイルの中身をコピーしてZAUTHENTICATEルーチンを作成する方法で回避してください。) ZAUTHENTICATEルーチンを作成したら、applicationNameを変更します。これは前回の記事で記載したOAuth2クライアントアプリケーションの **クライアント構成** 画面で作成した「アプリケーション名」を指定します。 ![image](/sites/default/files/inline/images/iris_oauth2_part3_ss4.jpg) ここでは前回の記事にならい「FHIRResource」としています。コードの一部を紹介します。 ``` // Usually you will need to modify at least the roles to be assigned. set roles="%DB_DEFAULT,%Operator" $$$SysLog(3,"OAuth2","[ZAUTHENTICATE]","ServiceName="_ServiceName_", Username="_Username_", roles="_roles) // MUST BE MODIFIED FOR EACH INSTANCE WHICH USES OAuth 2.0 for REST. // The application name used to define the authorization server to this resource server. set applicationName="FHIRResource" set loginSuccessful=0 set errorText="" ``` コードを変更したらコンパイルを実行します。 このZAUTHENTICATEルーチンで重要なのは以下のコード部分です。 GetAccessTokenFromRequestメソッドを使用してHTTPリクエストからアクセストークンを取り出し、ValidateJWTメソッドを使用してValidationを実施し正しいアクセストークンであることを確認しています。 ``` // This ZAUTHENTICATE routine will support OAuth 2.0 based // delegated authentication for subclasses of %CSP.REST. set accessToken=##class(%SYS.OAuth2.AccessToken).GetAccessTokenFromRequest(.sc) // Check if authorized. // if the access token is not a JWT, we would need to validate the access token // using another means such as the introspection or userinfo endpoint. if $$$ISOK(sc) { set valid=##class(%SYS.OAuth2.Validation).ValidateJWT(applicationName,accessToken,,,.jsonObject,,.sc) } ``` ## POSTMANからのテスト それでは前回同様、RESTクライアントツールのPOSTMANからテストしてみましょう。 前回同様、まずはアクセストークンを取得します。 前回とは異なり、Auth URLにaudパラメータを追加する必要はありません。トークンを取得できたら、「Use Token」ボタンをクリックし、そのトークンを使用できるようにします。 次は、FHIRリポジトリへのアクセスです。今回は前回と異なり、ベーシック認証と組み合わせる必要はありませんので、そのままFHIRリポジトリにアクセスするRESTのURLのみを入力し、実行します。 FHIRリソースが取得できたら成功です。 ### 2020.4以降の対応 IRIS for Health 2020.4ではこちらの[記事](https://jp.community.intersystems.com/node/493246)に掲載したように、FHIRリポジトリ上でアクセストークンのスコープ情報がチェックされるようになりました。 このため、セキュリティ用件にも依存しますが、ZAUTHENTICATEルーチンで必ずしもアクセストークンのValidationチェックを行う必要はありません。 これまでこのシリーズで紹介してきましたように、IRIS for HealthがOAuth2認可サーバの役割も兼ねている場合、2020.4上で動かす最も単純な方法は、ZAUTHENTICATEルーチンのGetCredentialsラベルで、アクセストークンを取得する際にも指定したIRISパスワードユーザを返すようにすることです。 例:アクセストークンを取得した際のユーザと ![image](/sites/default/files/inline/images/iris_oauth2_part3_ss5.jpg) 同じユーザを返すようにする。(このdaikoユーザには%All権限を与えています) ``` GetCredentials(ServiceName,Namespace,Username,Password,Credentials) Public { if ServiceName="%Service_WebGateway" { // Supply user name and password for authentication via a subclass of %CSP.REST set Username="daiko" set Password="xxxxx" } quit $$$OK } ``` こちらの[代行認証に関するドキュメント](https://docs.intersystems.com/irisforhealth20201/csp/docbookj/Doc.View.cls?KEY=GCAS_delegated#GCAS_delegated_zauthgetcreds)に記載があるように、GetCredentialsラベルで実在するIRISパスワードユーザが返された場合はそのユーザに認証が行われるため、ZAUTHENTICATEルーチンで実行されていたアクセストークンのValidationチェックのロジックは実施されなくなります。 ただし、アクセストークンの検証はその後FHIRリポジトリ上で実施されるため不正なアクセストークンでアクセスしたりすることはできません。 なお、2020.4では、スコープのチェックやAudience情報のチェックも行われるため、このバージョンの代行認証では aud=https://~ の情報の追加や適切なスコープ指定も必要になります。 テストとしてはこの方法で動作を確認することができると思いますが、もちろん実際のアプリケーションで実装する場合は、より複雑な状況を考慮に入れる必要があるでしょう。例えば、アクセスするユーザごとに異なるIRISパスワードユーザをもつケースもあれば、そもそもアクセストークンの発行元であOAuth2認可サーバが、IRISではなく他のサービスである可能性もあります。後者のようなケースでは、このZAUTHENTICATEルーチン上で代行ユーザを作成する必要があり、さらにそのユーザ名はアクセストークン内のユーザ情報(sub)と一致する必要があります。 残念ながらこの記事でそれらの状況をすべてカバーすることはできませんが、この記事に記載されている情報がIRIS for HealthのFHIRリポジトリを活用したセキュアなアプリケーション構築の一助となれば幸いです。
記事
Mihoko Iijima · 2020年10月22日

VSCode を使ってみよう!

皆さんこんにちは!Virtual Summit ご覧いただけていますでしょうか。 Virtual Summit で VSCode の ObjectScript 用エクステンションバージョン1.0 のリリースが👏正式発表👏されましたので、さっそく利用方法を投稿してみました。 来週の技術セッションではさらに詳しい説明があると思いますので、ご登録がまだの方は、ぜひご登録ください!(ご登録いただくとオンデマンド配信でいつでもセッションのビデオを視聴できます。機械翻訳ではありますがビデオには日本語字幕が付いています。) この記事では、以下の操作方法をご紹介します。 ObjectScript用エクステンションのインストール方法 サーバへ接続する クラス定義を作ってみる ルーチンを作ってみる デバッグを実行してみる 操作前の準備 VSCodeのインストール を行います。 インストール後、VSCode で作成するクラス定義(*.cls)やルーチン(*.mac や *.inc)用ファイルを配置するためのワークスペース(作業環境)用フォルダを作成します。作成が終わったら VSCode を開き、[File > Open Folder...] から作成したフォルダを選択します。 1、ObjectScript用エクステンションのインストール エクステンションのアイコン をクリックし「InterSystems」で検索し と をインストールします。 インストールが完了すると のアイコンが左端に表示されます。 2、サーバへ接続する メニューから File > Preferences > Settings (macOS では Code > Preferences > Settings) を選択して、VS Code Settings Editor を開きます。 検索欄に、objectscript を記入し(下図 赤〇)設定を絞り込み、検索欄すぐ下にある [Workspace] を選択します。 [Objectscript:conn] の下にある [Edit in settings.json] (上図 青〇)をクリックします。 開いたワークスペースのフォルダ以下に [.vscode] フォルダが用意され、settings.json が作成されます。 この settings.json は開いているワークスペースに対するサーバ接続情報の設定ファイルになります。”objectscript.conn”: {} の中に接続したいサーバ情報を記入すると、接続が行えます。設定するパラメータは入力候補が出ます。 図例のイメージで、接続したい IRIS のホスト名(host)、Webサーバポート番号(port)、ネームスペース(ns)、ユーザ名(username)、パスワード(password)を設定し、"active" : true を設定し保存します(Ctrl + s で保存できます)。 記述例は以下の通りです(コピーしてご利用ください)。 { "objectscript.conn": { "active": true, "host":"localhost", "port": 52773, "ns":"USER", "username": "_system", "password": "SYS" } } 接続できると、VSCode左下にある接続状態が、Connected になります。 最新情報を確認する場合は、上図赤枠をクリックしすると、VSCode画面上部中央に以下メニューが表示されます。 メニューの [Refresh Connection] をクリックして最新情報をご確認ください。 この他にも、複数インスタンスへ接続切り替えが簡単に行える、InterSystems Server Manager の機能を利用した記述方法もあります。 前述の方法と異なる点は、settings.json にパスワードを記入しません。 また、”intersystems.servers" に接続するサーバ情報を定義し、"objectscript.conn" の "server" に”intersystems.servers" で定義したサーバ名を指定します。 初回接続時、パスワードを指定するように入力欄(下図赤枠)が表示されます。パスワードを入力すると接続できます。 複数のインスタンスに対して接続情報を登録する場合の settings.json の記述例は以下の通りです。 { "objectscript.conn": { "server": "test", "active": true, "ns": "USER" }, "intersystems.servers": { "test": { "webServer": { "scheme": "http", "host": "localhost", "port": 52773 }, "username": "_SYSTEM" }, "hs":{ "webServer": { "scheme": "http", "host": "localhost", "port":52776 }, "username": "_SYSTEM" } } } サーバ側でパスワードを変更した場合など、VSCode上に登録されたパスワードをクリアするためには、コマンドパレットを利用してクリアできます。 VSCodeのメニューバーから [View > Command Palette...] を選択し、[InterSystems Server Manager: Clear key chain] を選択します。どの接続情報のパスワードをクリアするか表示されるので、接続名を選択してクリアします。 接続完了後、 をクリックすると、サーバ内のクラス/ルーチン/インクルードファイルなどの情報を確認できます。 サーバ情報は読み取り専用の為、VSCode 上で編集したい場合は、ソースコードを右クリックし「Export」を選択します。 Export選択後、ワークスペース > src  以下にソースコードがコピーされます。 ※システムコードは上書きしないようにご注意ください。 3、クラス定義を作ってみる 早速、クラス定義を作成し、HelloWorld! の文字列を出力するメソッドを作ります。 をクリックし、ワークスペースに戻ります。 開いたワークスペースに、パッケージ名と同名のフォルダを用意します。例では、Test としています。 定義例) Class Test.Class1{ ClassMethod Hello(){ write "Hello world! こんにちは!"} } [Ctrl + スペース] を押すと以下のような入力候補が出ます。 コードの作成が完了したら、Ctrl + s で保存+コンパイルを行います。(Outputウィンドウを表示しておくとコンパイル結果が確認できます。) ターミナルを起動し、クラスメソッドの実行を試します。 USER>do ##class(Test.Class1).Hello()Hello world! こんにちは!USER> メモ:コンテナやLinux上のIRISに対しては、iris session インスタンス名 でIRISにログインできます。 例) irisowner@0c6e3bc48ff6:~$ iris session IRIS ノード: 0c6e3bc48ff6 インスタンス: IRIS USER> 4、ルーチンを作ってみる ルーチンの作成についての注意事項は、橋本さんに投稿いただいたこちらの記事がとても参考になります。ぜひご参照ください。 ワークスペース以下にルーチン用ファイルを作成します。拡張子は mac とします。 ルーチンでも [Ctrl + スペース] を押すと入力候補が表示されます。 ルーチン実行例は以下の通りです。 USER>do hello^First()こんにちは、ルーチンですUSER> 5、デバッグの実行 クラス定義の場合、以下のようにメソッドの前に [Debug this method] と表示されます。 ObjectScript のコードをデバッグするためには、launch.json ファイルを作成し、デバッグ内容を定義しておく必要があります。 クラス定義の場合、メソッド名の上に [Debug this method] と表示されるので、ここをクリックすると以下の指示が出てきます。 (ルーチン作成の場合は、ワークスペース内に launch.json を作成すれば大丈夫です) デバッグ用エクステンションのアイコン をクリックしてワークスペースからデバッグ用ウィンドウに切り替えます。 [create a launch.json file.] をクリックすると、以下のように環境選択が表示されるので [ObjectScript Debug] を選択します(以下赤枠)。 launch.json の雛形ファイルが開きます。 name は デバッグ名で、下図の赤枠のように表示されます。 デバッグ対象のコードを program に設定します。 (ルーチンをデバッグする場合は、ワークスペースにある .vscode フォルダの下に launch.json を作成し、program に実行したいルーチンを指定します。) 設定内容例は以下の通りです(コピーしてご利用ください)。 { // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "type": "objectscript", "request": "launch", "name": "Debugテスト", "program": "##class(Test.Class1).Hello()" } ] } 設定が完了したら launch.json を保存し、デバッグを開始します。
記事
Toshihiko Minamoto · 2022年4月21日

ObjectScript Package Manager のユニットテストとテストカバレッジ

この記事では、ObjectScript Package Manager( を参照)を使用して、ユニットテストを実行するためのプロセスを説明します。テストカバレッジ測定( を使用)も含まれます。 ## ObjectScript でのユニットテスト ObjectScript でユニットテストを記述する方法については、素晴らしいドキュメントがすでに存在するため、ここでは繰り返しません。 ユニットテストのチュートリアルは、こちらをご覧ください: ユニットテストは、「/tests」など、ソースツリーの別の場所に含めるのがベストプラクティスです。 InterSystems 内では、デファクトスタンダードとして、/internal/testing/unit_tests/ を使用しています。テストは社内用/非配布用であり、ユニットテスト以外の種類のテストもあるため、これが意に適うためではありますが、単純なオープンソースプロジェクトでは、多少複雑になるかもしれません。 InterSystems の一部の GitHub リポジトリでは、この構造が使用されています。 ワークフローの観点では、VSCode では非常に簡単に行えます。ディレクトリを作成して、そこにクラスを配置するだけです。 より旧式のサーバー中心型のソース管理アプローチ(Studio で使用されているアプローチ)の場合、このパッケージを適切にマッピングする必要があります。このアプローチは、ソース管理拡張機能ごとに異なります。 ユニットテストクラスの命名規則の観点では、個人的には以下を気に入っています(私の所属するグループにおいてはベストプラクティスです)。 UnitTest.<テストされるパッケージ/クラス>[.<テストされるメソッド/機能>] たとえば、MyApplication.SomeClass クラスのメソッド Foo のユニットテストであれば、ユニットテストクラスは UnitTest.MyApplication.SomeClass.Foo と名付けられます。一方で、クラス全体のテストであれば、単に UnitTest.MyApplication.SomeClass となります。 ## ObjectScript Package Manager でのユニットテスト ObjectScript Package Manager でユニットテストを認識させるのは簡単です! 以下のように、module.xml に行を 1 つ追加するだけです( から抜粋。Open Exchange の @Peter.Steiwer による優れた数学パッケージのフォークです。これは単純なサンプルとして使用しています)。 `` ` ...` ` ` `` 上記は次のように解釈します。 * ユニットテストは、モジュールのルート配下にある「tests」ディレクトリにあります。 * ユニットテストは「UnitTest.Math」パッケージにあります。 テストされるクラスは「Math」パッケージに含まれるため、合理的です。 * ユニットテストは、パッケージライフサイクルの「test」フェーズで実行します。 (テストが実行できる「verify」フェーズもありますが、これについては後日お話しします。) ### ユニットテストの実行 上記で説明されたとおりにユニットテストを定義したら、Package Manager でそれを実行するための非常に便利なツールを使用することができます。 %UnitTest.Manager と同じように ^UnitTestRoot などを設定することも可能ですが、特に同じ環境で複数のプロジェクトの作業を行っている場合には、次のオプションを使用する方がはるかに簡単だと思います。 このすべては、上記にリストされている objectscript-math リポジトリのクローンを作成してから `zpm "load /path/to/cloned/repo/"` で読み込むか、「objectscript-math」を自分のパッケージ名(とテスト名)に入れ替えて独自のパッケージで実行することができます。 モジュールを再読み込みしてからすべてのユニットテストを実行する: `zpm "objectscript-math test"` ユニットテストのみを実行する(再読み込みなし): `zpm "objectscript-math test -only"` ユニットテストのみを実行し(再読み込みなし)、詳細出力を取得する: `zpm "objectscript-math test -only -verbose"` 再読み込みを行わずに特定のテストスイート(テストのディレクトリ、この場合は UnitTest/Math/Utils のすべてのテスト)のみを実行し、詳細出力を取得する: `zpm "objectscript-math test -only -verbose -DUnitTest.Suite=UnitTest.Math.Utils"` 再読み込みを行わずに特定のテストケース(この場合は UnitTest.Math.Utils.TestValidateRange)のみを実行し、詳細出力を取得する: `zpm "objectscript-math test -only -verbose -DUnitTest.Case=UnitTest.Math.Utils.TestValidateRange"` または、1 つのテストメソッドに存在する問題を解決するだけである場合は、以下のようにします。 `zpm "objectscript-math test -only -verbose -DUnitTest.Case=UnitTest.Math.Utils.TestValidateRange -DUnitTest.Method=TestpValueNull"` ObjectScript Package Manager を使ったテストカバレッジ測定 ユニットテストがあっても、それがうまく機能するのかを知るにはどうすればよいのでしょうか。 テストカバレッジを測定するだけでは、この疑問に完全に答えることはできませんが、少なくとも役には立ちます。 このことについては、2018 年の Global Summit でお話ししました。https://youtu.be/nUSeGHwN5pc をご覧ください。 最初に行うべきことは、テストカバレッジパッケージをインストールすることです。 `zpm "install testcoverage"` これには ObjectScript Package Manager によるインストール/実行は不要であることに注意してください。詳しくは、Open Exchange をご覧ください: とは言っても、ObjectScript Package Manager も使用するのであれば、テストカバレッジツールを最大限に活用することができます。 テストを実行する前に、テストでカバーしたいクラス/ルーチンを指定する必要があります。 非常に大型のコードベース(HealthShare など)においては、プロジェクト内のすべてのファイルに使用するテストカバレッジを測定して収集してしまうと、システムに装備されている以上のメモリが必要となる場合があるため、このステップは重要です。 (具体的には、行単位モニターの gmheap です。) ファイルのリストは、ユニットテストのルート内の coverage.list というファイルに出力されます。つまり、ユニットテストの別のサブディレクトリ(スイート)にそれぞれのリストが格納されるため、テストスイートが実行する間、追跡されるクラス/ルーチンがオーバーライドされます。 objectscript-math を使った単純な例については、 をご覧ください。[テストツールのユーザーガイド](https://github.com/intersystems/TestCoverage#user-guide)ではさらに詳しく説明されています。 テストカバレッジ測定を有効にしてユニットテストを実行する場合、コマンドにはもう 1 つ引数を追加します。テストを実行するために、%UnitTest.Manager の代わりに TestCoverage.Manager が使用することを指定するのです。 `zpm "objectscript-math test -only -DUnitTest.ManagerClass=TestCoverage.Manager"` 出力には、詳細モードでなくても、ユニットテストでカバーされたクラス/ルーチンの行と一部の集計された統計情報を確認できる URL が含まれます。 ## 今後の内容 このすべてのプロセスを CI で自動化してはどうでしょうか。 ユニットテストの結果とカバレッジのスコア/差をレポートするにはどうすればよいでしょうか。 こういったことも、実現可能です! Docker、Travis CI、および codecov.io を使用した簡単な例について、 をご覧ください。将来、いくつかの異なるアプローチを説明する記事を書く予定です。
記事
Mihoko Iijima · 2023年4月4日

PythonからNativeAPIを利用してIRISに接続する AWS Lambda関数を作成するまでの流れ

開発者の皆さん、こんにちは。 Python Native APIを利用すると、IRISにあるグローバル変数の参照/更新をPythonから行えたり、メソッドやルーチンをPythonから実行することができます。 この記事では「AWS Lambda の IRIS Python Native API IRIS」の記事を参考に、NativeAPIを利用してPythonからIRISに接続するAWS Lambda関数を作成する流れで必要となる、レイヤー作成と関数用コードの作成例をご紹介します。 ※ 事前にAWSのEC2インスタンス(Ubuntu 20.04を選択)にIRISをインストールした環境を用意した状態からの例でご紹介します。 「AWS Lambda の IRIS Python Native API IRIS」の記事では、レイヤーとコードをまとめたZipを用意してLambda関数を作成していますがこの記事ではレイヤーとコード用Zipをそれぞれ用意して作成する流れでご紹介します。 NativeAPIについて詳しくは、「【はじめての InterSystems IRIS】セルフラーニングビデオ:アクセス編:Python の NativeAPI に挑戦」をご参照ください。 AWS Lambda関数のレイヤー作成、関数作成の流れは、別の記事:「PyODBC経由でIRISに接続するAWS Lambda関数を作成するまでの流れ」 と同様のため、この記事では詳細な作成手順について割愛しています。詳細な流れは記事をご参照ください。 以下の流れでご紹介します。 Native API レイヤー用Zipの作成 サンプルのクラス定義のインポート 関数の作成とテスト実行 CloudformationのYAML例 例で使用しているコード一式はこちらにあります👉https://github.com/Intersystems-jp/iris-native-lambda 1. Native API レイヤー用Zipの作成 Native API用モジュールのレイヤーを以下の手順で作成します。 レイヤー作成用の任意ディレクトリを用意し、その下に python ディレクトリを用意します。 mkdir python cd python wget https://github.com/intersystems/quickstarts-python/raw/master/Solutions/nativeAPI_wheel/irisnative-1.0.0-cp34-abi3-linux_x86_64.whl unzip irisnative-1.0.0-cp34-abi3-linux_x86_64.whl cd .. zip -r9 ../iris_native_lambda.zip * この流れで作成したZipの例:iris_native_lambda.zip 2.サンプルのクラス定義のインポート Native APIでは、IRIS内のメソッドやルーチンをPythonから実行できるのでサンプルでは Test.Utils に用意したメソッドを実行しています。 Pythonのサンプルスクリプト:index.pyを試す場合は事前にインポートしてください。 インポートは管理ポータルから、またはVSCodeから、またはUtils.clsをIRISをインストールした環境に転送後、ユーティリティからインポートすることができます。 管理ポータルからインポートする場合 http://IPアドレス:52773/csp/sys/UtilHome.csp にアクセスし、システムエクスプローラ→クラス→ネームスペース:USER→インポートボタン をクリックします。 Utils.clsをファイルに指定してインポートを行ってください。 VSCodeを利用する場合 VSCodeにObjectScriptエクステンションをインストール後、IRISに接続しUtils.cls保存します(Ctrl+S)。 詳細は VSCode を使ってみよう!をご参照ください。 Utils.clsをIRISをインストールした環境に転送後、ユーティリティからインポートする場合 Utils.cls を /usr/irissys/mgr/user ディレクトリに配置した状態での実行例です。 IRISにログインします(USERネームスペースにログインしています)。 iris session IRIS インポート用ユーティリティを利用してインポートを実施します。 do $system.OBJ.Load("/usr/irissys/mgr/user/Utils.cls","ck") 実行例は以下の通りです。 USER>do $system.OBJ.Load("/usr/irissys/mgr/user/Utils.cls","ck") Load started on 03/27/2023 09:36:21 Loading file /usr/irissys/mgr/user/Utils.cls as udl Compiling class Test.Utils Compiling routine Test.Utils.1 Load finished successfully. USER> インポートしたクラス:Test.Utilsには以下のクラスメソッドが用意されています。(全メソッド、JSON文字列を戻り値で返すように作成しています) メソッド名 内容 Hello() IRISのバージョンと実行時の日付時刻を戻り値で返します。 CreateDummyTbl() テスト実行に使用するTest.Personテーブルの作成とサンプルデータ(2レコード)を作成します。 GetPerson() Test.PersonテーブルのSELECTの結果を返します。 CreateDummyGlo() Pythonからグローバル変数の操作例に使用するサンプルグローバル ^KION を作成します。 3. 関数の作成とテスト実行 1.Native API レイヤー用Zipの作成 の手順で作成したレイヤー用Zip:iris_native_lambda.zipと、Pythonスクリプトのサンプルコード:index.py と 接続情報を記載するファイル:connection.config をZipにしたファイル:iris_native_code.zipを利用してAWS Lambda関数を作成します。 Lambda 関数作成とテスト実行の流れついては、開発者コミュニティの記事:PyODBC経由でIRISに接続するAWS Lambda関数を作成するまでの流れ:(6) レイヤーの作成以降をご参照ください。 確認:IRISへの接続情報について サンプルのpythonスクリプト:index.py では、以下いずれかの方法でIRISに接続できるように記述しています。 環境変数を使用する場合 index.pyには、lambda関数作成時に設定する環境変数を利用するように記述しています(19~23行目) 。 なお、環境変数は、Lambda関数登録後、画面で追加/変更できます。 connection.config を使用する index.py の10行目と12~16行目のコメントを外し19~23行目をコメント化して利用します。接続するIRISの情報に合わせて connection.config を変更してください。 メモ:Lambda関数に設定する環境変数例は以下の通りです。 テスト実行の引数例 ※引数に指定するJSONのプロパティに指定が不要な場合は、"none" を設定してください。 TestlUtilsクラスのHello()メソッドを実行する場合の引数例 { "method": "Hello", "function":"none", "args": "none" } 以下のような戻り値が返ります。 "{\"message\":\"こんにちは!今の時間は:2023年3月27日 10:16:05です\",\"status\":1,\"payload\":\"IRIS for UNIX (Ubuntu Server 20.04 LTS for x86-64) 2022.1.2 (Build 574U) Fri Jan 13 2023 15:03:40 EST\"}" Test.Personテーブルの作成とダミーデータの登録する場合の引数例 (TestlUtilsクラスのCreateDummyTbl()メソッドを実行する場合) { "method": "CreateDummyTbl", "function":"none", "args": "none" } 以下の戻り値が返ります。 "{\"Message\":\"登録完了\"}" Test.PersonテーブルのSELECTの結果を取得する場合の引数例 (Test.UtilsクラスのGetPetPerson()メソッド実行する場合) { "method": "GetPerson", "function":"none", "args": "none" } 以下の戻り値が返ります。 "[{\"Name\":\"山田\",\"Email\":\"taro@mail.com\"},{\"Name\":\"斉藤\",\"Email\":\"saito@mail.com\"}]" ^KIONグローバル変数を設定する例 (Test.UtilsクラスのCreateDummyGlo()メソッドを実行する場合の引数例) { "method": "CreateDummyGlo", "function":"none", "args": "none" } 以下の戻り値が返ります。 "{\"Message\":\"登録完了\"}" index.pyのFunctionを動かす例 (^KION全データ取得する get_globaldata()関数を実行する例) { "method":"none", "function":"getglobal", "args":"none" } 以下の戻り値が返ります。 "[[\"久留米\", 14, 19], [\"大阪\", 12, 18], [\"奈良\", 10, 18], [\"愛知\", 13, 15], [\"新潟\", 6, 12], [\"東京\", 14, 19], [\"沖縄\", 21, 26]]" index.pyのFunctionを動かす例 (^KIONにデータを追加するset_kiondata()関数を実行する場合の引数例) { "method":"none", "function": "setglobal", "args": {"area":"長野","min":5,"max":10} } 正しくデータ登録できたかどうかは、get_globaldata()関数を再度実行すると確認できます。 以下、get_globaldata()関数を再実行した場合の戻り値の例です。 "[[\"久留米\", 14, 19], [\"大阪\", 12, 18], [\"奈良\", 10, 18], [\"愛知\", 13, 15], [\"新潟\", 6, 12], [\"東京\", 14, 19], [\"沖縄\", 21, 26], [\"長野\", 5, 10]]" 4. CloudformationのYAML例 例:cloudformation.yml 実行の流れについては、「[PyODBC経由でIRISに接続するAWS Lambda関数を作成するまでの流れ]の」3. 1,2の流れをCloudformationで行う例と同様です。
記事
Hiroshi Sato · 2020年10月5日

Caché .Net BindingアプリケーションをIRISの.Net Native APIを利用して書き換える方法(その3)

ここで紹介するサンプルは、以下のGitHubから入手可能です。 IRIS .Netサンプル jpegファイルを読んで、IRISデータベースに格納するサンプル 上記GitHub上のinsertbinary\insertbinary\binread.csというファイル名です。 処理内容は、ファイルシステム上のjpeg形式のファイルを読み込んで、BLOB形式でIRISデータベースに格納します。 Caché ではADO.NET Managed Providerを使用して実装していましたが、それをIRISのInterSystems Managed Provider for .NETを使用して書き換えました。(名前が変わっていますが、ADO.NETに関しては、機能はほとんど同じです) 従って、厳密に言うと.Net Native APIを使用していませんが、コネクションオブジェクトの使用方法は共通なので、この部分は、Native APIを使用していると言うこともできます。 Caché での実装は、以下の通りです。 // binread.csusing System;using System.IO;CacheCommand spCache;CacheConnection cnCache;CacheDataAdapter daCache;CacheTransaction txCache=null;DataSet dsCache;DataTable dtCache;DataRow drCache;class BinaryRead { static void Main(string[] args) { //存在するファイルを指定する FileStream fs = new FileStream( @"c:\temp\picture\xxx.jpeg", FileMode.Open, FileAccess.Read) int fileSize = (int)fs.Length; // ファイルのサイズ byte[] buf = new byte[fileSize]; // データ格納用配列 int readSize; // Readメソッドで読み込んだバイト数 int remain = fileSize; // 読み込むべき残りのバイト数 int bufPos = 0; // データ格納用配列内の追加位置 readSize = fs.Read(buf, 0, fs.Length) string cacheConnectString = "Server = localhost;Port=1972;Namespace=User;Password=SYS;User ID = _SYSTEM;"; cnCache = new CacheConnection(cacheConnectString); cnCache.Open(); spCache = new CacheCommand("Insert into MyApp.Person2(Name, Picture) Values(?, ?)", cnCache, txCache); CacheParameter pName = new CacheParameter(); pName.ParameterName = "Name"; pName.CacheDbType = CacheDbType.NVarChar; pName.Direction = ParameterDirection.Input; pName.Value = "Hoge Hoge; CacheParameter pPicture = new CacheParameter(); pDOB.ParameterName = "Picture"; pName.CacheDbType = CacheDbType.LONGVARBINARY; pDOB.Direction = ParameterDirection.Input; pDOB.Value = buf; spCache.ExecuteNonQuery(); fs.Dispose(); cnCache.close(); }} IRISで書き換えたソースは以下の通りです。 // binread.csusing System;using System.IO;using System.Data;using InterSystems.Data.IRISClient;using InterSystems.Data.IRISClient.ADO;namespace binaryfileread { class binaryfileread { [STAThread] static void Main(string[] args) { IRISCommand spIRIS; IRISConnection cnIRIS; IRISTransaction txIRIS = null; //存在するファイルを指定する FileStream fs = new FileStream( @"c:\temp\test.jpeg", FileMode.Open, FileAccess.Read); int fileSize = (int)fs.Length; // ファイルのサイズ byte[] buf = new byte[fileSize]; // データ格納用配列 long readSize; // Readメソッドで読み込んだバイト数 int remain = fileSize; // 読み込むべき残りのバイト数 readSize = fs.Read(buf, 0, (int)fs.Length); string IRISConnectString = "Server = localhost;Port=1972;Namespace=User;Password=SYS;User ID = _SYSTEM;"; cnIRIS = new IRISConnection(IRISConnectString); cnIRIS.Open(); spIRIS = new IRISCommand("Insert into MyApp.Person2(Name, Picture) Values(?, ?)", cnIRIS, txIRIS); IRISParameter pName = new IRISParameter(); pName.ParameterName = "Name"; pName.IRISDbType = IRISDbType.NVarChar; pName.Direction = ParameterDirection.Input; pName.Value = "Hoge Hoge"; spIRIS.Parameters.Add(pName); IRISParameter pPicture = new IRISParameter(); pPicture.ParameterName = "Picture"; pPicture.IRISDbType = IRISDbType.LongVarBinary; pPicture.Direction = ParameterDirection.Input; pPicture.Value = buf; spIRIS.Parameters.Add(pPicture); spIRIS.ExecuteNonQuery(); fs.Dispose(); cnIRIS.Close(); } }} CachéとIRISでは、ADO.NETに関しては、関数等の名前がCacheからIRISに変更になっているという違いがあります。 参照の変更 まず以前の参照を削除します。 Visual Studioのソリューションエクスプローラーの所で参照をクリックします。 表示されるInterSystems.Data.CacheClientを削除します。(右クリックして削除を選ぶ) 次にプロジェクトメニューから参照の追加をクリックして、以下の2つのファイルを選択します。(プロジェクトの.Net Frameworkバージョンに合わせて、それに対応するファイルを選択する以下の例は、v4.5を選択) c:\InterSystems\IRIS\dev\dotnet\bin\v4.5 InterSystems.Data.IRISClient.dll jpegファイルを読んで、フォーム上にそのjpegファイルの内容を表示するサンプル 上記GitHub上の\VBImage\VBImage\Forms1.vbというファイル名です。 処理内容は、ファイルシステム上のjpeg形式のファイルを読み込んで、VB.NETのフォーム上のPictureオブジェクトとして表示します。 Caché では.NET Managed Providerの.Net Bindingを使用して実装していましたが、それをIRISの.Net Native APIをを使用して書き換えました。 Caché での実装は以下の通りです。 Imports InterSystems.Data.CacheClientImports InterSystems.Data.CacheTypesImports System.DrawingPublic Class Form1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim cn As CacheConnection cn = New CacheConnection("Server=127.0.0.1;Port=1972;Namespace=User;Username=_system;Password=SYS") cn.Open() Dim img As System.IO.FileStream img = New System.IO.FileStream("C:\temp\test.jpg", System.IO.FileMode.Open, IO.FileAccess.Read) Dim f As User.Fax ' NEW ----------- f = New User.Fax(cn) img.CopyTo(f.pic) f.memo = "abcde" f.Save() f.Dispose() MsgBox("Done!") cn.Close() End Sub  Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click Dim cn As CacheConnection cn = New CacheConnection("Server=127.0.0.1;Port=1972;Namespace=User;Username=_system;Password=SYS") cn.Open() Dim f As User.Fax f = User.Fax.OpenId(cn, 1) PictureBox1.Image = Image.FromStream(f.pic) cn.Close() End SubEnd Class IRISで書き換えたソースです。 Imports InterSystems.Data.IRISClientImports InterSystems.Data.IRISClient.ADOImports System.DrawingImports System.IOPublic Class Form1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim cn As IRISConnection cn = New IRISConnection("Server=127.0.0.1;Port=1972;Namespace=User;Username=_system;Password=SYS") cn.Open() Dim iris As IRIS Dim irisobject As IRISObject Dim memstream As New MemoryStream Dim str As String Dim buf As Byte() Dim pic As IRISObject iris = IRIS.CreateIRIS(cn) irisobject = iris.ClassMethodObject("User.Fax", "%New") Dim img As System.IO.FileStream img = New System.IO.FileStream("C:\temp\test.jpg", System.IO.FileMode.Open, IO.FileAccess.Read) buf = New Byte(img.Length) {} img.Read(buf, 0, img.Length) str = System.Text.Encoding.GetEncoding("ISO-8859-1").GetString(buf) pic = irisobject.GetObject("pic") pic.InvokeVoid("Write", str) irisobject.InvokeIRISStatusCode("%Save") 'Dim f As User.Fax ' NEW ----------- 'f = New User.Fax(cn) 'img.CopyTo(f.pic) 'f.memo = "abcde" 'f.Save() 'f.Dispose() MsgBox("Done!") cn.Close() End Sub Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click Dim cn As IRISConnection Dim iris As IRIS Dim irisobject As IRISObject Dim pic As IRISObject Dim memorystream As New MemoryStream Dim buf As Byte() Dim str As String Dim len As Long cn = New IRISConnection("Server=127.0.0.1;Port=1972;Namespace=User;Username=_system;Password=SYS") cn.Open() iris = IRIS.CreateIRIS(cn) irisobject = iris.ClassMethodObject("User.Fax", "%OpenId", 1) pic = irisobject.GetObject("pic") len = pic.InvokeLong("SizeGet") str = pic.InvokeString("Read", len) buf = System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(str) memorystream.Write(buf, 0, len) PictureBox1.Image = Image.FromStream(MemoryStream) cn.Close() End SubEnd Class 良くコードを見るとわかりますが、IRIS版のほうが処理がかなり長くなっています。 結論を言うとこのケースはIRIS .Net Native APIを使用して書き換えるのは得策ではありません。ADO.NETを使用したほうが簡単に処理できます。 上記GitHub上の\VBImageADO配下にADO.NETで書き換えたサンプルも用意しましたので、ご参考下さい。