🔍
Next.jsのログをApplication Insightsに送る
Next.js のログを Application Insights の trace に送るのでハマったので手順をメモ
コードはここに置いてある
前提
- App Service から Application Insights へ
- App Service は Docker イメージ利用
- Next.js
- ロガーは winston
手順
Azure のリソースを作成する
次のような感じでリソースを定義して、terraform applyする。
注意点として、App Service の環境変数にはAPPLICATIONINSIGHTS_CONNECTION_STRINGを設定しておく。
main.tf
app_settings = {
APPLICATIONINSIGHTS_CONNECTION_STRING = azurerm_application_insights.this.connection_string
}
Next.js のコードを書く
必要なライブラリを追加する
npm install @azure/monitor-opentelemetry @opentelemetry/winston-transport winston
instrumentation.tsで Azure Monitor の初期設定をする
instrumentation.ts
import { useAzureMonitor } from "@azure/monitor-opentelemetry";
export function register() {
console.log("Registering Azure Monitor instrumentation...");
// eslint-disable-next-line react-hooks/rules-of-hooks
useAzureMonitor();
console.log("Azure Monitor instrumentation registered successfully.");
}
どこでも良いが、今回はpage.tsxでログを出すことにする
page.tsx
import winston from "winston";
import { OpenTelemetryTransportV3 } from "@opentelemetry/winston-transport";
export const dynamic = "force-dynamic";
const logger = winston.createLogger({
transports: [
new winston.transports.Console(),
new OpenTelemetryTransportV3({}),
],
});
export default function Home() {
logger.info("ほげほげ");
...
イメージを push する
特別変なことはしていないが、流れをメモ
az login
az acr login --name registryappinextjs
docker build -t registryappinextjs.azurecr.io/app --platform=linux/amd64 .
docker push registryappinextjs.azurecr.io/app
動作確認
イメージを更新するために、App Service を再起動して...

App Service にアクセスする

念の為、App Service のログストリームにログが表示されていることを確認して...

Application Insights に trace が表示されているはず。反映まで少しラグがあるので注意

ハマったところ
Next.js の middleware を使っている場合
middleware.tsが配置されていると、Edge Runtime での処理が走る(instrumentation.tsにも波及する)
useAzureMonitorの処理は Node.js Runtime でしか動作しないので、Edge Runtime ではエラーとなる。
に記載の通り、NEXT_RUNTIMEによる分岐を挟む必要が出てくる。
instrumentation.ts
export async function register() {
if (process.env.NEXT_RUNTIME === "nodejs") {
await import("./instrumentation-node");
}
}
instrumentation-node.ts
import { useAzureMonitor } from "@azure/monitor-opentelemetry";
console.log("Registering Azure Monitor instrumentation...");
// eslint-disable-next-line react-hooks/rules-of-hooks
useAzureMonitor();
console.log("Azure Monitor instrumentation registered successfully.");
instrumentationOptionsで winston を enable にしても trace は出力されない
.NET、Java、Node.js、Python アプリケーション用の Azure Monitor OpenTelemetry を追加および変更するに記載されているinstrumentationOptionsを利用して次のように設定しても trace は出力されない。
instrumentation.ts
import { useAzureMonitor } from "@azure/monitor-opentelemetry";
export function register() {
console.log("Registering Azure Monitor instrumentation...");
// eslint-disable-next-line react-hooks/rules-of-hooks
useAzureMonitor({
instrumentationOptions: {
winston: {
enabled: true,
}
}
});
console.log("Azure Monitor instrumentation registered successfully.");
}
参考
Discussion