このエントリーは、ふぃーるどのーつおよび錬金術MeetUpとのタイアップ記事です。
技術書典のWebサイトにはサークルチェックという機能があり、サークル参加者は マイページで自分のサークルへのチェック数を知ることができます。
本エントリーでは、技術書典のサークル被チェック数を取得してMackerelにメトリック投稿する バッチ処理をAzure Functions上でTypeScriptを用いて構築します。
なぜTypeScriptかというと、Javaプログラマーは型がないとろくなプログラムがかけないからです。...という話を第二十一回 Azureもくもく会 @ 品川 - connpassのLTでしたら主宰の@kingkinoさんに「C#でいいじゃない」とつっこまれました。いやそうでもあるし、Azure Functions上でJava っていう手もありますが。
サンプルコード
ソースコードは、以下で公開しています。
https://github.com/azusa/circlecheck-mackerel
なお、このコードはえるきちさん(@erukiti)がerukiti/techbookfest-circle-botで公開している、「技術書典4向けの被サークルチェック数をSlackに垂れ流すbot」が元になっています。
用意するもの
関数を作成する
「Azure CLI で初めての関数を作成する」を参考にして関数を作成します。
# コンソール出力のメッセージに従って https://microsoft.com/devicelogin にアクセスしてコードを入力する az login # リソースグループの作成 az group create --name myResourceGroup --location japaneast az storage account create --name startazurefunction --location japaneast --resource-group myResourceGroup --sku Standard_LRS # Fuction App を作成する az functionapp create --resource-group myResourceGroup --consumption-plan-location japaneast --name fieldnotesjpfunction --storage-account startazurefunction
なおaz functionapp create
の実行時に以下のようなエラーメッセージが表示されたときは--name
で指定するApp名が既に取得されているので、ぶつからない名前にしてください。
Operation failed with status: 'Not Found'. Details: 404 Client Error: Not Found for url: https://management.azure.com/subscriptions/***/resourceGroups/myResourceGroup/providers/Microsoft.Web/sites/startazurefunction?api-version=2016-08-01
# Azure Functions Core Tools をインストールする npm install -g azure-functions-core-tools@core # ひな形を作成する func init MyFunctionProj cd MyFunctionProj # JavaScriptで関数のひな形を作成する func new --language JavaScript --template TimerTrigger --name TimerTriggerJS cd TimerTriggerJS
TimeTriggerJSディレクトリー配下にpackge.json
を作成します。postinstall
で行っていることについては後述します。
{ "name": "azurefunctions-typescript-startup", "version": "1.0.0", "main": "index.js", "license": "MIT", "devDependencies": { "tslint": "^5.9.1", "tslint-config-prettier": "^1.10.0", "tslint-plugin-prettier": "^1.3.0", "typescript": "^2.8.1" }, "scripts": { "postinstall": "npm install -g typescript && tsc" } }
# ライブラリーをインストールする npm install # tsconfig.jsonを作成する tsc --init
tsconfig.jsonの設定を記述します。
{ "compilerOptions": { "target": "ES2015", "module": "commonjs", "lib": [ "es2015" ], "sourceMap": true, "strict": true, }, "exclude": [ "node_modules" ] }
index.jsをindex.tsにリネームし、中の記述を以下の通りなおします。
export async function run (context: any, myTimer: any) { const timeStamp = new Date().toISOString(); if(myTimer.isPastDue) { context.log('JavaScript is running late!'); } context.log('JavaScript timer trigger function ran!', timeStamp); context.done(); };
# コンパイルが通るか確認 tsc
デプロイの設定をする
ここまでの過程をpushしたものが次にあります。
Azure Functions の継続的なデプロイ | Microsoft Docsに従い、GitHubとの連携設定を行います。設定は、関数の「プラットフォーム機能」の「展開オプション」から行います。
なお、メニューを展開していくと画面が横に果てしなく長くなりますが、これがAzure流なのでしょう。多分。
デプロイ時にtscコマンドが実行されるようにする
ここまでの設定で、Gitのリモートレポジトリーにコードをpushした時にAzure Functionsにコードが連携され、npm install
で依存ライブラリーのインストールが行われるようになっています。
TypeScriptの場合は、このタイミングで、TypeScriptからJavaScriptへのコンパイルを行う必要があります。
Azure Fucntionsの場合はnpm install
のタイミングで行うことになるので、postinstall
のタイミングでTypeScriptのインストールとtsc
コマンドの実行を行うよう、package.json
を記述することになります。
postinstall
のタイミングで、グローバルへのnpmパッケージのインストールを行うのはnpmのお作法からははずれますが、やむを得ないという感じです。
timerTriggerの注意点
timeTriggerの設定はfunction.jsonで行いますが、この際の注意点は、CRON書式の一番左が秒だということ です。
UNIXのCRONのつもりで毎時実行しようとして0 * * * * *
と書くと、毎分実行されることになります。(なりました)
バッチ処理の記述
以上の仕組みをもとにした、バッチ処理の実装は、以下の通りです。
MackerelのAPIを使用して、POSTする部分の処理は、以下の通りです。
const sendToMackerel = async checkedCount => { const opt = { method: 'POST', uri: 'https://api.mackerelio.com/api/v0/services/techbookfest/tsdb', body: JSON.stringify([{ name: "circleCheck", time: Math.floor(new Date().getTime() / 1000), value: checkedCount }]), headers: { 'content-type': 'application/json', 'X-Api-Key': apiKey }, resolveWithFullResponse: true } await rp(opt) }
スクリプトが参照する環境変数の設定は、「プラットフォーム機能」の「アプリケーション設定」から行います。
余談ですが、他のXaaSサービスの設定画面にあるような、「パラメーターをマスクする機能」ってないんですかね...
取得するメトリック
以上の設定を行ってFunction Appを実行すると、以下の様なメトリックが取得できます。*1
おわりに
上記のバッチ処理は、4/22に開催される技術書典4で、サークル「ふぃーるどのーつ」の新刊「Mackerelではじめるお手軽サーバー監視」のサービスメトリックの事例として実装したものです。同書ではプラグイン開発による対象メトリックの追加やCRONによるバッチ処理のロギングと監視など、Mackerelの活用事例を豊富に取り上げています。
*1:Mackerelのグラフ共有機能を使用しています