Visual Studio CodeのAzure App Service拡張のリモートエラーの通知機能が良かった話

Visual Studio CodeのAzure App Service拡張のリモートエラーの通知機能が良かった話

Clock Icon2022.03.19

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

いわさです。

先日、AzureでApp ServiceからAzure Functionsを呼び出す以下の構成のシンプルなアプリケーションを作成していました。

凡ミスでAzureへデプロイすると動かなくなる問題が起きたのですが、Visual Studio CodeのApp Service拡張機能のおかげですぐに問題に気づけて「ありがてぇ...」となったので共有しておきます。

ローカルで動くけどApp Serviceにアップロードすると動かなくなるアプリ

事前に、Azure FunctionsへHTTPトリガーのものをデプロイしておきます。

$ curl http://localhost:3000/hoge
This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.

Node.js (Express) のWebアプリケーションからFunctionsをHTTP POSTしてレスポンスするだけのアプリケーションを作成します。

npx express-generator myExpressApp --view pug
npm install

Functionsを呼び出さないhoge1と、Functionsを呼び出すhoge2を作成しました。

const router = require("express").Router();

router.get("/", async (req, res, next) => {
    res.send("hoge1");
});

module.exports = router;
const router = require("express").Router();

router.get("/", async (req, res, next) => {
  var request = require('request');
  var options ={
     url: "https://iwasa0319func.azurewebsites.net/api/simplehttpreqres",
     headers: {
      "content-type": "application/json"
    },
  };
  request.post(options, function(error, response, body) {
      res.send(body);
  });
});

module.exports = router;
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var hoge1Router = require('./routes/hoge1');
var hoge2Router = require('./routes/hoge2');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/hoge1', hoge1Router);
app.use('/hoge2', hoge2Router);
:

ローカルは動く

一度ローカル実行してみました。
ローカルでは動作確認出来ました。

$ npm start

$ curl http://localhost:3000/hoge1
hoge1

$ curl http://localhost:3000/hoge2
This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.

AzureだとFunctions呼び出すとタイムアウト

ローカルで動作確認出来たのでAzure App Serviceへデプロイします。
Visual Studio Code(VSCode)を使って開発していたので、VSCodeのApp Service拡張機能をインストールしてこちらを使ってデプロイします。

Azureへの認証を行った状態で、WebApp作成してデプロイ操作をするだけで良いのです。便利すぎる。

デプロイ出来たので、リクエストを送信してみましょう。

$ curl https://iwasa0319nodejs.azurewebsites.net/hoge1
hoge1
$ curl https://iwasa0319nodejs.azurewebsites.net/hoge2

hoge2の応答が返ってこないですね。おかしい。

エラー確認

ぼーっとしててすぐ気づけなかったのですが、開きっぱなしにしていたVSCodeの右下に何か出ていました。

"iwasa0319nodejs" reported a critical error: Cannot find module 'request'

DetailsからAzureポータルの問題の診断と解決->アプリケーションログへ遷移し、エラー詳細情報や発生タイミングを確認することが出来ます。

アッ...

requstモジュールインポートした記憶がないことに気づきました。ローカルはグローバルで動いていたようです。

$ npm install request
$ cat package.json
{
  "name": "myexpressapp",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "cookie-parser": "~1.4.4",
    "debug": "~2.6.9",
    "express": "~4.16.1",
    "http-errors": "~1.6.3",
    "morgan": "~1.9.1",
    "pug": "2.0.0-beta11",
    "request": "^2.88.2"
  }
}

再度デプロイし、もう一度リクエストを送信してみましょう。

$ curl https://iwasa0319nodejs.azurewebsites.net/hoge1
hoge1

$ curl https://iwasa0319nodejs.azurewebsites.net/hoge2
This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.

今度は成功しました。

さいごに

動かなかった原因などは大したことではなかったのですが、ブラウザリクエストやcurlで応答待ちの間にいち早く問題点を指摘してくれたのはこのVisual Studio Codeでした。
特に指定もしてなかったのですがリモート環境のアプリケーションログからすぐに問題点を通知してくれてとても助かりました。

App Serviceの拡張機能すごいなと思ってGitHubのWikiをみていたのですが、Node.jsであればApp Service上でのリモートデバッグも対応しているようですね。次回のトラブルシューティング時にはこの機能も使ってみたいと思いました。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.