Java Azure FunctionsでApplication Insightsにカスタムメトリックを送る―分散トレーシング“Recommended”をBicepだけで自動化する完全ガイド

Azure Functions(Linux/Java 17)から Application Insights にカスタム メトリックやトレースを送るうえで、ポータルを一切触らず Bicep だけで “Collection Level = Recommended” に相当する分散トレーシング設定を有効化する方法を、最小構成から運用の勘所までまとめました。既存の Application Insights 再利用パターンと新規作成パターンの双方を網羅し、確認手順・KQL・コード例まで一気通貫で解説します。

目次

質問の要点と結論

  • 課題:Java 17 の Azure Functions(Linux, Java)で、Application Insights にカスタム メトリック/トレースを送信したい。ポータル操作なし(Bicep のみ)で “Collection Level = Recommended” を有効化したい。既存の Application Insights を使い回す Bicep も知りたい。
  • 結論(最短の答え):
    • Application Insights リソース側に CollectionLevel を設定する必要はありません。(Bicep では Unknown property 警告。削除して問題なし)
    • Function App 側で Java agent を有効化し、アプリ設定 APPLICATIONINSIGHTS_PREVIEW_FEATURES=recommended を指定すれば、“Collection Level = Recommended” 相当がオンになります。
    • 既存の Application Insights をexisting リソース参照でリンクし、APPLICATIONINSIGHTS_CONNECTION_STRING を Function App に渡します。

Bicep の基本方針(なぜこうするのか)

“コレクション レベル”は Application Insights リソースのプロパティではなく、アプリケーション プラットフォーム側のテレメトリ収集挙動(Java agent の有効化と動作モード)で決まります。Bicep で行うことは次の 2 点だけです。

  1. Function App に Java agent をアタッチ(App Service 上の自動アタッチ機能を使う)
  2. プレビュー機能を “recommended” で有効化(追加収集や推奨インストルメンテーションをオン)

この設計により、ポータルで「Application Insights を有効化」や「コレクション レベル変更」といった個別操作は不要になります。

最少構成:既存の Application Insights をリンクする Bicep

すでに運用中の Application Insights を再利用する最小テンプレートです。ポイントは existing 参照と Function App へのアプリ設定、そしてリンク用タグです。

@description('既存 Application Insights 名')
param appInsightsName string
@description('Function App 名')
param functionAppName string
param location string = resourceGroup().location

// 既存 Application Insights を参照
resource existingAI 'Microsoft.Insights/components@2020-02-02' existing = {
  name: appInsightsName
}

// Function App 本体
resource functionApp 'Microsoft.Web/sites@2022-09-01' = {
  name:  functionAppName
  location: location
  kind: 'functionapp,linux,java'
  identity: { type: 'SystemAssigned' }
  properties: {
    httpsOnly: true
    siteConfig: {
      appSettings: [
        { name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
          value: existingAI.properties.ConnectionString }
        { name: 'APPLICATIONINSIGHTS_ENABLE_AGENT'       value: 'true' }
        { name: 'APPLICATIONINSIGHTS_PREVIEW_FEATURES'   value: 'recommended' }
        { name: 'APPLICATIONINSIGHTS_PROFILERFEATURE_VERSION' value: '1.0.0' }
        { name: 'FUNCTIONS_WORKER_RUNTIME'               value: 'java' }
        { name: 'FUNCTIONS_EXTENSION_VERSION'            value: '~4' }
        // Linux の Java ランタイム指定(推奨)
        { name: 'JAVA_VERSION'                           value: '17' }
      ]
      // Linux の明示指定をする場合は以下も(必要時のみ)
      // linuxFxVersion: 'Java|17'
    }
  }
  // Portal の関連付け表示用(運用時に便利)
  tags: { 'hidden-link:${existingAI.id}': 'Resource' }
}
  • APPLICATIONINSIGHTS_PREVIEW_FEATURES=recommended が“Collection Level = Recommended”同等のキー設定です。
  • existing を付けないと既存 AI の再利用にならず、新規作成されてしまう点に注意。
  • Linux/Java では kind: 'functionapp,linux,java' を明示し、必要に応じて linuxFxVersion で Java 17 を固定化します。

フル構成:Log Analytics + Application Insights を新規作成してリンク

新規にワークスペース連携の Application Insights を用意するテンプレートです。再利用パターンとの違いは AI/LAW の生成とリンクだけで、Function App 側の設定は同じです。

@description('リソースのベース名(接頭辞)')
param baseName string
@description('デプロイ先ロケーション')
param location string = resourceGroup().location

var laName  = '${baseName}-law'
var aiName  = '${baseName}-ai'
var funcApp = '${baseName}-func'

resource la 'Microsoft.OperationalInsights/workspaces@2022-10-01' = {
  name: laName
  location: location
  properties: {
    retentionInDays: 30
    features: {
      enableLogAccessUsingOnlyResourcePermissions: true
    }
  }
}

resource ai 'Microsoft.Insights/components@2020-02-02' = {
  name: aiName
  location: location
  kind: 'web'
  properties: {
    Application_Type: 'web'
    WorkspaceResourceId: la.id
  }
}

resource plan 'Microsoft.Web/serverfarms@2022-09-01' = {
  name: '${baseName}-plan'
  location: location
  kind: 'functionapp'
  sku: {
    name: 'Y1'
    tier: 'Dynamic' // Consumption
  }
}

resource func 'Microsoft.Web/sites@2022-09-01' = {
  name: funcApp
  location: location
  kind: 'functionapp,linux,java'
  identity: { type: 'SystemAssigned' }
  properties: {
    serverFarmId: plan.id
    httpsOnly: true
    siteConfig: {
      linuxFxVersion: 'Java|17'
      appSettings: [
        { name: 'FUNCTIONS_EXTENSION_VERSION'            value: '~4' }
        { name: 'FUNCTIONS_WORKER_RUNTIME'               value: 'java' }
        { name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'  value: ai.properties.ConnectionString }
        { name: 'APPLICATIONINSIGHTS_ENABLE_AGENT'       value: 'true' }
        { name: 'APPLICATIONINSIGHTS_PREVIEW_FEATURES'   value: 'recommended' }
        { name: 'APPLICATIONINSIGHTS_PROFILERFEATURE_VERSION' value: '1.0.0' }
        { name: 'JAVA_VERSION'                           value: '17' }
        // ビルド成果物の配布方式に応じて
        // { name: 'WEBSITE_RUN_FROM_PACKAGE'               value: '1' }
      ]
    }
  }
  tags: {
    'hidden-link:${ai.id}': 'Resource'
    'hidden-link:${la.id}': 'Resource'
  }
}

パラメータ ファイル例(.bicepparam)

using 'main.bicep'

param baseName = 'demoapp-jp'
param location = 'Japan East' 

デプロイ コマンド例(Azure CLI)

az deployment group create \
  --resource-group <rg-name> \
  --template-file main.bicep \
  --parameters main.bicepparam

アプリ設定(Application Settings)完全版チェックリスト

キー必須 / 任意推奨値説明
APPLICATIONINSIGHTS_CONNECTION_STRING必須AI の接続文字列既存/新規 AI を問わず Connection String を設定。InstrumentationKey より接続文字列の使用を推奨。
APPLICATIONINSIGHTS_ENABLE_AGENT必須trueJava agent の自動アタッチを有効化。分散トレーシングや依存関係収集のベースとなる。
APPLICATIONINSIGHTS_PREVIEW_FEATURES必須recommended“Collection Level = Recommended” 相当をオン。綴りは 小文字のみで厳密に。
APPLICATIONINSIGHTS_PROFILERFEATURE_VERSION任意1.0.0Profiler 機能の有効化に関連。組織ポリシーに合わせて使用。
APPLICATIONINSIGHTS_ROLE_NAME任意例:my-funcAI の cloud_RoleName に反映。複数 Function App を 1 つの AI に集約する場合に可視性が向上。
FUNCTIONS_WORKER_RUNTIME必須javaFunctions ランタイムの種類。
FUNCTIONS_EXTENSION_VERSION必須~4Functions のメジャー バージョン。
JAVA_VERSION推奨17Java の実行バージョンを明示。Linux の場合は linuxFxVersion: 'Java|17' の指定も可。

ネットワーク/セキュリティの注意点

Function App から Application Insights への送信はアウトバウンド HTTPS を前提とします。VNet 経由や NSG 制限を行う場合は、以下の先を遮断しないようにします。

用途ドメイン(例)備考
テレメトリ取り込み接続文字列の IngestionEndpoint のホスト名(例:*.in.applicationinsights.azure.com)地域によりエンドポイントが異なるため、接続文字列の値を参照。
後方互換(旧来エンドポイント)dc.services.visualstudio.com古いエージェント/SDK 互換のために記載。新規は上段の地域エンドポイントが基本。
ライブ メトリクス等(AI ライブ機能関連のドメイン)組織要件に応じて開放を検討。不要なら閉じても可。

動作確認(KQL サンプル)

デプロイ直後は数分待つとテレメトリが到達します。次の Kusto クエリで “recommended” 相当の収集が効いているかを確認します。

// トレース(アプリログ)
traces
| where cloud_RoleName == "my-func" // APPLICATIONINSIGHTS_ROLE_NAME を設定した場合
| where timestamp > ago(30m)
| sort by timestamp desc

// 依存関係(HTTP 呼び出し・DB 等のオートインストルメンテーション)
dependencies
| where cloud_RoleName == "my-func"
| where timestamp > ago(30m)
| summarize count() by type, success

// カスタム メトリック(後述コード例で送信した名前に合わせる)
customMetrics
| where name == "orders.processed"
| summarize total = sum(value), dcount(cloud_RoleInstance) by bin(timestamp, 5m)
| order by timestamp desc 

アプリからのカスタム メトリック送信(Java)

OpenTelemetry API(Java agent 併用)

Application Insights の Java agent は内部で OpenTelemetry を利用します。アプリ側は OTel API を使ってメトリック/トレースを生成すると、エージェント経由で AI へ輸送されます(追加の接続設定は不要)。

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.api.metrics.LongCounter;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;

public class MetricsExample {
private static final Meter meter =
GlobalOpenTelemetry.get().getMeter("com.example.func");

private static final LongCounter ordersProcessed =
meter.counterBuilder("orders.processed")
.setDescription("Number of processed orders")
.setUnit("1")
.build();

public static void track(String region) {
ordersProcessed.add(1, Attributes.of(AttributeKey.stringKey("region"), region));
}
} 
  • GlobalOpenTelemetry を使うことで、Azure 側のエージェント設定をそのまま活用できます。
  • メトリック名は lowercase.with.dots など機械可読な命名を推奨。ディメンションは Attributes に付与します。

TelemetryClient(Application Insights Java SDK)

エージェントと併用して、従来の SDK で明示的に送る方法です。既存資産の移行にも向きます。

import com.microsoft.applicationinsights.TelemetryClient;
import com.microsoft.applicationinsights.TelemetryConfiguration;
import com.microsoft.applicationinsights.telemetry.MetricTelemetry;
import java.util.HashMap;
import java.util.Map;

public class AiClassicExample {
private static final TelemetryClient client;

static {
TelemetryConfiguration cfg = TelemetryConfiguration.createDefault();
cfg.setConnectionString(System.getenv("APPLICATIONINSIGHTS_CONNECTION_STRING"));
client = new TelemetryClient(cfg);
}

public static void trackOrder(double amount, String region) {
MetricTelemetry metric = new MetricTelemetry("orders.amount", amount);
Map props = new HashMap<>();
props.put("region", region);
client.trackMetric(metric);
client.trackEvent("order.completed", props, null);
client.flush();
}
} 

Micrometer(Spring ベースのユースケース)

Spring Boot を Functions で使う場合は Micrometer を経由すると、カウンタやタイマの定義が容易です。エージェントが有効なら OTel 経由で AI に流れます。

// 例:アプリ起動時にカウンタを登録し、ハンドラでインクリメント
Counter counter = Counter.builder("orders.processed")
  .description("Number of processed orders")
  .register(Metrics.globalRegistry);

public void handle(...) {
counter.increment();
} 

運用ノウハウ(プラン/性能/コスト)

観点推奨・注意点
プラン選定消費(Consumption)は低頻度ジョブやバーストに強い一方、コールドスタート時に Java agent の初期化で数秒遅延が出ることがあります。低レイテンシ要件なら Premium(EP)を検討。
サンプリング既定の確率サンプリングでコスト抑制。高負荷時はサンプリングを前提にダッシュボードを設計し、重大アラート用データはメトリック中心に。
ロール名の粒度APPLICATIONINSIGHTS_ROLE_NAME をサービス単位で付与し、ダッシュボード・アラートのスコープを明瞭化。
ログ保持Log Analytics の保持日数(例:30 日)をワークロードに合わせて調整。Long-term 保持はアーカイブを活用。

よくあるハマりどころ(チェックリスト)

項目確認内容
接続文字列APPLICATIONINSIGHTS_CONNECTION_STRING が意図した AIを指すか(ステージ/本番の取り違え注意)。
プレビュー機能値は厳密に recommended(小文字のみ)。Recommended は無効。
ネットワーク制限VNet/NSG で IngestionEndpoint への 443 を開放。古い構成では dc.services.visualstudio.com も許可。
Java ランタイムJava 11/17 は AI Java agent 対応済み。ランタイムの明示固定(linuxFxVersion)でズレを防止。
AI 側プロパティApplication Insights リソースに CollectionLevel のようなプロパティを作らない(Unknown property)。
既存 AI の再利用existing 修飾子を付与。ないと新規作成される。

運用で効く設計パターン(Bicep の作法)

  • 接続先の切り替えはパラメータ化:AI 名や Connection String を stage(dev/stg/prod) で差し替え。
  • タグで資産追跡:hidden-link:<resourceId> だけでなく、owner、costCenter、environment を付与。
  • アプリ設定はモジュール化:appSettings を配列変数でまとめ、ワークロード固有のキーのみ差し替え。
  • フェイルセーフ:AI 未到達時もアプリが落ちない前提(送信失敗はリトライ/バックオフ)。

Windows(参考)との違い

Windows プランでも考え方は同じです。主な違いは以下の通りです。

観点Linux(本記事)Windows(参考)
kind / ランタイム'functionapp,linux,java' / linuxFxVersion: 'Java|17''functionapp' / siteConfig.javaVersion: '17'
Java agentAPPLICATIONINSIGHTS_ENABLE_AGENT=true同様に有効化
ファイルシステム読み取り専用(Run From Package)推奨同様だが一部ツール差異あり

アラート/可観測性テンプレートのたたき台

“recommended” を有効化したら、以下の指標でまずアラート化しておくと運用が安定します。

  • 失敗率:requests | summarize failureRate = 100.0 * (sumif(itemCount, success==false) / sum(itemCount))
  • 外形監視:Functions のトリガー別に遅延・エラー割合を可視化。
  • 重要メトリック:ビジネス カウンタ(例:orders.processed)の急減・急増検知。

トラブルシュート手順

  1. AI 到達確認:上記 KQL で直近 30 分の traces/dependencies を確認。ゼロ件ならネットワーク/接続文字列を再確認。
  2. アプリ設定の反映:再デプロイ後に Function App のリスタートを実施。設定のタイプミス(大文字混入)に注意。
  3. エージェント衝突:独自の OTel SDK 初期化とエージェントの二重初期化が競合しないかを確認。基本は GlobalOpenTelemetry を利用。
  4. サンプリング影響:トレースはサンプリングで間引かれるため、メトリックは必ず送る設計にして可観測性を担保。

まとめ

“Collection Level = Recommended” を Bicep だけで成立させる鍵は、Function App に Java agent を有効化し、APPLICATIONINSIGHTS_PREVIEW_FEATURES=recommended を指定することです。Application Insights リソース側に CollectionLevel のような設定は不要で、既存インスタンスも existing 参照で安全に再利用できます。この記事のテンプレートとチェックリスト、KQL・コード例まで含めて適用すれば、ポータル操作なしで Java Functions の分散トレーシングとカスタム メトリック収集を“推奨レベル”で有効化し、運用の初期セットを自動化できます。

付録:デプロイ後の自己診断コマンド

# Function App のアプリ設定を確認(誤字の洗い出し)
az webapp config appsettings list \
  --name <func-name> \
  --resource-group <rg-name> \
  --query "[?name=='APPLICATIONINSIGHTS_PREVIEW_FEATURES' || name=='APPLICATIONINSIGHTS_ENABLE_AGENT' || name=='APPLICATIONINSIGHTS_CONNECTION_STRING']"

# Java ランタイムの確認(Linux)

az webapp show 
--name  --resource-group  
--query "siteConfig.linuxFxVersion" 

付録:Bicep スニペット集(再利用可)

既存 AI をパラメータ化して読み込むモジュール

param aiName string

resource ai 'Microsoft.Insights/components@2020-02-02' existing = {
name: aiName
}

output aiConnectionString string = ai.properties.ConnectionString
output aiId string = ai.id 

Function App のアプリ設定配列を共通化

param connectionString string
param javaVersion string = '17'

var baseAppSettings = [
{ name: 'FUNCTIONS_EXTENSION_VERSION'            value: '~4' }
{ name: 'FUNCTIONS_WORKER_RUNTIME'               value: 'java' }
{ name: 'JAVA_VERSION'                           value: javaVersion }
{ name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'  value: connectionString }
{ name: 'APPLICATIONINSIGHTS_ENABLE_AGENT'       value: 'true' }
{ name: 'APPLICATIONINSIGHTS_PREVIEW_FEATURES'   value: 'recommended' }
] 

付録:Functions の Java ハンドラでの計測例

public class MyFunction {
  @FunctionName("OrderProcessor")
  public HttpResponseMessage run(
      @HttpTrigger(name = "req", methods = {HttpMethod.POST}, authLevel = AuthorizationLevel.FUNCTION)
      HttpRequestMessage<Optional<String>> request,
      final ExecutionContext context) {


// OpenTelemetry を使ったカウンタ
MetricsExample.track("jp-east");

// 従来 SDK での補助的なイベント
AiClassicExample.trackOrder(42.0, "jp-east");

return request.createResponseBuilder(HttpStatus.OK)
              .body("ok")
              .build();


}
} 

Q&A

  • Q: ポータルで「Application Insights をオン」にする操作は不要ですか?
    A: はい。Bicep で接続文字列と agent 設定を入れれば十分です。ポータル操作は省略できます。
  • Q: 既存 AI と新規 AI をステージで切り替えたい。
    A: existing 参照/新規作成をモジュール化し、環境パラメータで分岐させるのが安全です。
  • Q: カスタム メトリックが customMetrics に出ない。
    A: エージェント起動直後は到達まで数分かかります。サンプリングはメトリックには通常適用されませんが、間違いがないか KQL で確認し、名前・単位・ディメンションの綴りを再点検してください。
  • Q: コストを抑えたい。
    A: メトリック中心の監視(少量のトレース)/サンプリング活用/保持期間の最適化で効果が出ます。

短い再掲:この記事の要点

  • Application Insights に CollectionLevel は不要。Bicep で指定しない。
  • Function App 側で APPLICATIONINSIGHTS_ENABLE_AGENT=true と APPLICATIONINSIGHTS_PREVIEW_FEATURES=recommended。
  • 既存 AI は existing 参照で安全に再利用。
  • OpenTelemetry API/TelemetryClient/Micrometer いずれのコードパスでもカスタム メトリック送信可能。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次