matlab-instrument-opentelemetry-tracing について
MATLAB関数にOpenTelemetryトレースを追加するスキルです。MATLABのワークフローを計測する開発者向けに、Spanのライフサイクル、暗黙的な親子コンテキスト、例外記録、属性の規約を示します。
主な機能
- 01処理単位となる関数のSpan作成
- 02親子コンテキストの暗黙的な伝播
- 03例外とSpanステータスの記録
- 04属性とイベントの追加
- 05OpenTelemetryセマンティック規約の適用
活用シーン
- 01複数関数からなるMATLAB処理の追跡
- 02MATLABのファイル・ネットワークI/Oの観測
- 03外部システム呼び出しでのエラー記録
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ matlab/ matlab-agentic-toolkit --skill matlab-instrument-opentelemetry-tracingインストール後、Claude Code で/matlab-instrument-opentelemetry-tracingを入力して読み込まれたか確認します。
同梱ファイルmanifest.yamlreferences/semantic-conventions.md
詳細
OpenTelemetry トレーシングで MATLAB コードを計測する
正しい暗黙的なコンテキスト伝播、RAII ライフサイクル、セマンティック規約を備えた OpenTelemetry トレーススパンを MATLAB 関数に追加します。
前提条件
OpenTelemetry-MATLAB パッケージ(バージョン 1.11.0 以降)がインストールされている必要があります。このパッケージは、このスキル全体で使用する opentelemetry.trace.* 名前空間を提供します。MATLAB R2022b 以降が必要です。
主な関数
| 関数 | 用途 | ツールボックス | 利用可能なバージョン |
|---|---|---|---|
opentelemetry.trace.getTracer | 名前を指定してトレーサーインスタンスを取得する | OpenTelemetry-MATLAB | R2022b |
startSpan | トレーサーから新しいスパンを作成する | OpenTelemetry-MATLAB | R2022b |
makeCurrent | スパンを現在のコンテキストに設定する(暗黙的な親子関係を有効にする) | OpenTelemetry-MATLAB | R2022b |
setAttributes | キーと値のメタデータをスパンに付加する | OpenTelemetry-MATLAB | R2022b |
setStatus | スパンを「Ok」または「Error」としてマークする | OpenTelemetry-MATLAB | R2022b |
recordException | MException をスパンに記録する | OpenTelemetry-MATLAB | R2022b |
addEvent | スパン内にタイムスタンプ付きイベントを記録する | OpenTelemetry-MATLAB | R2022b |
endSpan | 関数の途中でスパンを終了する(ループのみ) | OpenTelemetry-MATLAB | R2022b |
MATLAB API の違い
MATLAB の OpenTelemetry API は、C++、Java、Python の実装と少し異なります。他の言語での一般的な OTel の知識に頼らないでください。関数について不明な場合は、help opentelemetry.trace.Span などを使って、実際に利用できる機能を確認してください。よくある落とし穴:
setAttribute(単数形)は存在しません。setAttributes(複数形)を使用してくださいopentelemetry.trace.StatusCode.Ok/StatusCode.Error列挙型は存在しません。setStatusには文字列"Ok"または"Error"を直接渡してください
使用する場合
- ユーザーが MATLAB コードへのトレーシングまたはスパンの追加を依頼した場合
- ユーザーが OpenTelemetry によるコードの計測を依頼した場合
- ユーザーが可観測性の追加を求めており、その要件にトレーシングが含まれている場合
- ユーザーが関数間の親子スパン関係を求めている場合
使用しない場合
- ユーザーがメトリクスのみ(カウンター、ヒストグラム、ゲージ)を求めている場合 — トレーシングスキルは不要です
- ユーザーがロギングのみ(構造化ログレコード)を求めている場合 — トレーシングスキルは不要です
- ユーザーが TracerProvider/SDK の設定(エクスポーター、サンプラー、リソース)を求めている場合 — これは別のセットアップスクリプトで行います
- ユーザーがネットワーク境界を越えたコンテキスト伝播(HTTP ヘッダーへの注入/HTTP ヘッダーからの抽出)を求めている場合
- ユーザーが
parforループ内の計測を求めている場合 — MATLAB では OTel コンテキストはスレッドセーフではありません
絶対的なルール
これらのルールは他のすべての考慮事項に優先します。いずれかに違反すると、誤った計測になります。
1. 関数シグネチャを変更しない
計測は呼び出し元から見えないものでなければなりません。関数にパラメーター(トレーサー、コンテキスト、スパン)を追加しないでください。戻り値も変更しないでください。各関数は内部で独自のトレーサーを取得します。
tr = opentelemetry.trace.getTracer("tracer_name");
これはグローバルプロバイダーからの低コストな検索であり、リソースの割り当てではありません。
2. スパンは RAII — 関数終了時に endSpan を呼び出さない
MATLAB の Span オブジェクトは C++ の共有ポインターを保持します。スパン変数がスコープを抜けると(関数が戻る、またはエラーがスローされると)、C++ デストラクターが自動的にスパンを終了します。変数が自然にスコープを抜ける前に、関数の途中でスパンを終了する必要がある場合にのみ endSpan を呼び出してください。
3. スコープは RAII — 関数終了時に clear(scope) を呼び出さない
makeCurrent が返す Scope オブジェクトは、スコープを抜けると以前のコンテキストに戻します。変数に代入して、そのライフタイムを制御してください。%#ok<NASGU> プラグマは「未使用変数」の警告を抑制します。この変数は値ではなく、そのライフタイムに意味があるためです。例外:ループ内では、次の反復の前に親コンテキストへ戻すため、clear が必要です(ループパターンを参照)。
4. すべてのスパンで必ず makeCurrent を呼び出す
子関数で作成される子スパンが自動的に子として関連付けられるよう、すべてのスパンをカレントにする必要があります。makeCurrent を使わないと、子スパンは親のないルートスパンになります。
5. startSpan に明示的な「Context」を渡さない
makeCurrent を一貫して使用している場合、startSpan はカレントスパンを自動的に親として取得します。「Context」を明示的に渡すのは冗長で、エラーの原因になります。例外は、カレントスパンとは異なるスパンの子として作成する必要がある場合だけです(まれです)。
6. 必ずスパンのステータスを設定する
スパンを終了する前に、すべてのスパンのステータスを設定する必要があります。
- 成功時は
setStatus(span, "Ok") - 失敗時は
setStatus(span, "Error", message)
明示的なステータスが設定されていないスパンは、トレースビューアーで状態が不明瞭になります。
7. getTracer を直接使用する
tr = opentelemetry.trace.getTracer("tracer_name");
opentelemetry.sdk.trace.TracerProvider() や、opentelemetry.trace.Provider.getTracerProvider() の後に getTracer を呼び出す方法は使用しないでください。上記の1行が正しいエントリーポイントです。
8. 意味のあるドメイン名詞を使った snake_case の属性名を使用する
すべての属性名は小文字でドット区切りにし、各要素内では snake_case を使用する必要があります。名前空間(ドットの左側)には、「total」「numeric」「count」のような一般的な単語ではなく、意味のあるドメイン名詞を使用してください。パターンと例の全容については、以下のセマンティック規約のセクションを参照してください。
ワークフロー
ステップ 1:コードを分析する
以下を特定します。
- エントリーポイント関数(ユーザーが呼び出す最上位の関数)
- 個別の作業単位を表すサブ関数とローカル関数
- I/O 操作(ファイルの読み取り/書き込み、ネットワーク呼び出し、データベース)
- エラーが発生しやすい箇所(ファイル I/O、外部システム、解析)
- トラッキングに値する、計算負荷の高い処理
ステップ 2:トレーサー名を選択する
ファイル名またはそれを含むパッケージから決めます。
processSensorData.m→"processSensorData"+mypackage/analyze.m→"mypackage"
同じワークフロー内のすべての関数で、同じトレーサー名を使用してください。
ステップ 3:各関数に計装を追加する
意味のある作業単位を表すすべての関数に、コアパターンを適用します。些細なヘルパー(5行未満で、I/O がないもの)や、タイトなループ内で何千回も呼び出される関数には計装を追加しないでください。
ステップ 4:必要な箇所にエラー処理を追加する
recordException を使った try-catch は、I/O を実行する関数または外部システムを呼び出す関数にのみ追加します。純粋な計算を try-catch で囲まないでください。
ステップ 5:属性とイベントを追加する
デバッグに役立つ属性(入力サイズ、主要なパラメーター、出力の特性など)を追加します。重要な節目をイベントとして記録します。セマンティック規約に従ってください(references/semantic-conventions.md を参照)。
ステップ 6:検証する
計装したコードを mcp__matlab__evaluate_matlab_code または mcp__matlab__run_matlab_file で実行し、エラーなく動作することを確認します。
コアパターン
計装するすべての関数で使用する、正しいパターンは次のとおりです。
function result = processData(inputData, method)
tr = opentelemetry.trace.getTracer("myService");
span = startSpan(tr, "processData");
scope = makeCurrent(span); %#ok<NASGU>
% --- original function body (unchanged) ---
result = transform(inputData, method);
setStatus(span, "Ok");
end
要点:
- 関数内で
getTracerを呼び出します。引数として渡してはいけません "Context"を指定せずにstartSpanを呼び出します。カレントコンテキストを自動的に継承しますscope = makeCurrent(span)により、このスパンがすべての子スパンの親になります%#ok<NASGU>は誤警告を抑制します。重要なのは scope の有効期間です- 関数が戻る前に
setStatusを呼び出します endSpanは不要です。関数が戻ると RAII によってスパンが終了します
複数関数の例
function results = runPipeline(inputFile)
tr = opentelemetry.trace.getTracer("pipeline");
span = startSpan(tr, "runPipeline");
scope = makeCurrent(span); %#ok<NASGU>
data = loadData(inputFile);
cleaned = cleanData(data);
results = analyze(cleaned);
setStatus(span, "Ok");
end
function data = loadData(filepath)
tr = opentelemetry.trace.getTracer("pipeline");
span = startSpan(tr, "loadData");
scope = makeCurrent(span); %#ok<NASGU>
data = readtable(filepath);
setStatus(span, "Ok");
end
function cleaned = cleanData(data)
tr = opentelemetry.trace.getTracer("pipeline");
span = startSpan(tr, "cleanData");
scope = makeCurrent(span); %#ok<NASGU>
cleaned = rmmissing(data);
setStatus(span, "Ok");
end
function results = analyze(data)
tr = opentelemetry.trace.getTracer("pipeline");
span = startSpan(tr, "analyze");
scope = makeCurrent(span); %#ok<NASGU>
results = summary(data);
setStatus(span, "Ok");
end
各関数は個別にトレーサーを取得し、それぞれ独自のスパンを作成します。親子関係は makeCurrent によって自動的に確立されます。
エラー処理パターン
I/O または外部システム呼び出しを含む関数で使用します。
function data = fetchData(url)
tr = opentelemetry.trace.getTracer("myService");
span = startSpan(tr, "fetchData", SpanKind="client");
scope = makeCurrent(span); %#ok<NASGU>
setAttributes(span, "url.full", url);
try
data = webread(url);
setAttributes(span, "http.response.status_code", 200);
catch ME
recordException(span, ME);
setStatus(span, "Error", ME.message);
rethrow(ME);
end
setStatus(span, "Ok");
end
主なポイント:
recordExceptionは MException 全体(識別子、メッセージ、スタックトレース、原因)を記録しますsetStatus(span, "Error", ...)は、トレースビューアーでスパンをエラーとしてマークしますrethrow(ME)は元のエラーを保持します。再スロー後も、RAII によりスパンは終了しますrecordExceptionとsetStatusの両方が必要です。前者は詳細を記録し、後者は視覚的なインジケーターを設定しますsetStatus(span, "Ok")は try-catch ブロックの後に配置し、tryの中には置かないでください。rethrowは関数を終了するため、成功時にのみ「Ok」に到達します
属性
属性の設定には setAttributes(複数形)を使用してください。存在しない単数形の setAttribute は使用しないでください。
setAttributes(span, "input.rows", height(data), "input.columns", width(data));
スパン作成時にディクショナリを使用することもできます。
span = startSpan(tr, "processData", Attributes=dictionary( ...
["input.file", "input.format"], ...
{filepath, "csv"}));
数値の型キャストは不要です。API はすべての MATLAB 数値型をネイティブに処理します。
イベント
スパン内の重要なマイルストーンをイベントとして記録します。
addEvent(span, "validationComplete", "rows.valid", validCount, "rows.rejected", rejectCount);
SpanKind
SpanKind は、処理にリモート通信が含まれる場合にのみ設定してください。内部処理では設定しないでください(デフォルトは "internal" です)。
| SpanKind | 場合 | MATLAB の例 |
|---|---|---|
"client" | 応答を待つ送信リクエスト | webread、webwrite、ftp、データベースクエリ |
"server" | 受信リクエストの処理 | MATLAB Production Server ハンドラー |
"producer" | 待機せずに処理を開始 | キューへの公開、バッチジョブのキューへの登録 |
"consumer" | producer からの処理を実行 | キューリスナー、バッチワーカー |
span = startSpan(tr, "fetchData", SpanKind="client");
endSpan を使用する場合
endSpan は、関数の途中でスパンを終了する場合、つまり変数が自然にスコープ外になる前にのみ使用してください。
function results = batchProcess(items)
tr = opentelemetry.trace.getTracer("myService");
span = startSpan(tr, "batchProcess");
scope = makeCurrent(span); %#ok<NASGU>
results = cell(numel(items), 1);
for i = 1:numel(items)
itemSpan = startSpan(tr, "processItem");
itemScope = makeCurrent(itemSpan); %#ok<NASGU>
setAttributes(itemSpan, "item.index", i);
results{i} = processOne(items{i});
setStatus(itemSpan, "Ok");
endSpan(itemSpan); % Needed: itemSpan must end each iteration
clear("itemScope"); % Needed: restore parent context before next iteration
end
setStatus(span, "Ok");
end
ループ本体の末尾にある両方の行は必須です。
endSpan(itemSpan)— スパンの計測時間を終了します。これがないと、次の反復で変数が上書きされるまでスパンの継続時間が延びてしまいます(誤った計測時間になります)。clear("itemScope")— 親スパンを現在のコンテキストに戻します。これがないと、次の反復でmakeCurrentを呼び出した際、新しいスパンが親の下の兄弟ではなく、前の反復のスパンの子になり、入れ子のチェーンが作られます(正しいフラットな一覧になりません)。
セマンティック規約
属性名は {object}.{property} のパターンに従う必要があります。
- 小文字を使用し、ドットで区切ります。キャメルケースは使用しないでください
- 各コンポーネント内では snake_case を使用します。
totalPathsではなくtotal_pathsとします - 名前空間には意味のあるドメイン名詞を使用します。ドットの左側の語は、一般的な形容詞や数量詞(
total、numeric、count)ではなく、ドメイン内の具体的なオブジェクト(例:batch、file、result、data)にしてください
| 誤り | 正しい例 | 理由 |
|---|---|---|
batch.totalPaths | batch.total_paths | キャメルケースではなく snake_case |
option.S0 | option.initial_price | 説明的で、小文字 |
numeric.columns | data.numeric_columns | 「data」は意味のあるドメイン名詞ですが、「numeric」はそうではありません |
total.paths | result.total_paths | 「total」はドメイン名詞ではありません |
コード属性、ファイル I/O 属性、HTTP クライアント属性、ドメイン固有のパターンに関する詳しいガイダンスは、references/semantic-conventions.md を参照してください。
よくある間違い
| 間違い | 間違いである理由 | 正しい方法 |
|---|---|---|
| 関数の引数としてトレーサーを渡す | 関数の API が変わり、既存の呼び出し元で問題が発生します | 各関数内で getTracer を呼び出します |
| 関数の引数としてコンテキストを渡す | 関数の API が変わり、計装が見えるようになります | makeCurrent を使用します。子スパンは自動的に継承します |
関数の終了時に endSpan を呼び出す | 冗長です。スパンは RAII によって終了するため、コードが煩雑になります | 削除します。関数の途中でのみ endSpan を使用します |
関数の終了時に clear(scope) を呼び出す | 冗長です。関数が戻るとき、スコープは RAII によってコンテキストを復元します | 削除して、変数をスコープ外に出します。ループ内では clear が必要です。上記のループパターンを参照してください |
startSpan に "Context" を渡す | makeCurrent を使用する場合は冗長で、明示的な結合を生みます | 省略します。startSpan は現在のコンテキストを使用します |
子関数で makeCurrent を省略する | 孫スパンがコンテキストを継承できず、深いトレースが機能しなくなります | すべてのスパンで必ず makeCurrent を呼び出します |
setAttribute(単数形)を使用する | MATLAB OTel API には存在しません | setAttributes(複数形)を使用します |
setStatus を省略する | トレースビューアーでスパンのステータスが曖昧になります | 必ず「Ok」または「Error」を設定します |
OTel コードを if isConfigured で囲む | 不要です。未設定の場合、OTel メソッドは何もしません | ガードを削除し、常に計装します |
TracerProvider() の後に getTracer を使用する | 間接的で、メリットがないのにコードが1行増えます | opentelemetry.trace.getTracer(name) を直接使用します |
属性を int64 にキャストする | 不要です。API は MATLAB のすべての数値型に対応しています | ネイティブの型をそのまま使用します |
計装しないもの
- 簡単なヘルパー関数(5行未満で、I/O を行わないもの)
- きついループ内で何千回も呼び出される関数(オーバーヘッドが発生します)
- 匿名関数またはコールバック(重要な処理を行う場合を除く)
parforブロック内のコード(コンテキストはスレッドセーフではありません)
Copyright 2026 The MathWorks, Inc.