LoginSignup
11
12

More than 5 years have passed since last update.

AWS Lambda でパフォーマンス監視

Posted at

サイトのパフォーマンスを監視するために、定期的にスクレイピングをしようと思い、
サーバーを立てるのも面倒なのでAWSのLambdaでしのごうとしたら意外と大変だったのでメモ

要約

  • Nodejsが古い(v0.10.36)
  • seleniumは使わないで、child_processから直接phantomjs(最新: v2.1.1)起動
  • performance API には頼らない
  • 金があるならNewRelic

Nodejsが古い

最初はSeleniumでやればすぐにできるだろうと考えていたのですが、
Lambdaで使用できるNode.jsは0.10.36と古く、Seleniumではサポート対象外です。

selenium-webdriverのバージョンを2.44.0ぐらいにすると動かせますが、phantomjsとの相性が悪いようで、
seleniumからphantomjsを実行しようとすると、サーバーとつながらない旨のエラーをはいてきます。
おそらくphantomjsのバージョンがあっていないのだと思いますが、どのバージョンが正しいか見つけるのが面倒だったので、
直接phantomjsを起動しました。

Phantomjsでperformance API

phantomjsでも、performance APIはサポートされていますが、
performance.timingがないため、情報が片手落ちです。

そのため、onResourceRequestedを使用して、開始時のリクエストなど、必要な情報を取得します。
また、mark()もないため、 new Date().getTime()で代用します。

Lambdaにアップロードする

これをまとめると、

Phantomjsを起動するLmbda用関数を作成します。
以下、抜粋なので、これだけでは動きませんが雰囲気はわかると思います。

index.js
exports.handler = function(event, context) {
  var childProcess = require('child_process');

  function callPhantom(callback) {
    var childArgs = ["script.js"]

    process.env['LD_WARN'] = 'true';
    console.log("calling...");
    childProcess.exec("./phantomjs ./script.js", function(err, stdout) {
      console.log("stdout", stdout);
      console.log("err", err);
      context.done(err, stdout)
    });
  }

  console.log("start");
  callPhantom(function() {
    console.log("finish");
    context.done();
  });
};

phantomjsに渡すファイルでは、
開始時間などperformance.timingでとれるような情報を取得しつつ
phantomjs内で実行された情報も取得します。

script.js
phantom.onError = function(msg, trace) {
  console.log("error", msg);
  var result = {"msg": msg};
  console.error(JSON.stringify(result));
  phantom.exit(1);
};

page.onResourceRequested = function(requestData, networkRequest) {
  //stop GA access not to affect user
  if(/.*google-analytics.*/.test(requestData.url)) {
    networkRequest.abort();
    return;
  }
};

resTime = {};
reqTime = {};
realAccessUrl= "http://www.example.com";

page.onResourceReceived = function(response) {
  if (response.stage === "start") {
    //ほしい情報もろもろを取得する
    if(response.url == realAccessUrl) {
      resTime['page_request_start'] = response.time.getTime();
      reqTime[response.id] = "page_response_end";
    }
  } else if(response.stage == "end") {
    if (response.id in reqTime) {
      resTime[reqTime[response.id]] = response.time.getTime();
    }
  }
};

function onPageReady() {
  var result = page.evaluate(function() {
    return JSON.stringify(PerformanceMonitor.getResult());
  });

  var times = JSON.parse(result);
  times["page_request_start"] = resTime["page_request_start"];

  var elapseTimes = {};
  var keys = Object.keys(times);
  var startTime = resTime['page_request_start'];
  for(var i = 0; i < keys.length; i++) {
    var key = keys[i];
    elapseTimes[key] = times[key] - startTime;
  }

  var phantomResult = {
    "elapseTimes": elapseTimes
  };

  console.log(JSON.stringify(phantomResult));
  phantom.exit();
}

パフォーマンス計測用に、サイトに埋め込むjsファイルです。
performance.mark()がないので、Date.getTime()を使用し、
Cookieで計測するかどうかを決定しています。

performanmce.js
document.PerformanceMonitor = new function() {
  var performanceResults = {};

  this.mark = function(name) {
    if(isMonitorable == false) return;

    var markName = markPrefix + name;
    //performance.mark(markName);
    if (performanceResults[markName] == undefined || performanceResults[markName] == null) {
      performanceResults[markName] = new Date().getTime();
    }
  };

  this.getResult = function() {
    if(isMonitorable == false) return {};

    return performanceResults;
  };

  var isMonitorable = false;

  initIsMonitorable();
  function initIsMonitorable() {
    isMonitorable = /monitor_enable=true[;\s]?/.test(document.cookie);
  }
}()

npmモジュールは以下

package.json
 "devDependencies": {
    "phantomjs": "2.1.3",
    "phantom-url": "1.0.0"
  }

Uploadする

上をまとめてzipにしてアップロードします。
ただ、30MB近くになるので、ブラウザからアップロードしようとすると偶に失敗します。
ただ、境界に近かったのか、

npmをseleniumからphantomjsに変えたところ失敗する確率が大きく減りました。

New Relicを使う

簡単だと思って気軽にやってみたら、意外と面倒だったのでNew Relic のSynthesisを使うと良いかもしれません。
簡単に試したところ、seleniumも、performance APIも動いたので、手軽だと思います

11
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
12