Ghost Inspector – Teams通知連携

SlackからTeamsに移行して久しい弊社では、CloudWatch AlarmやGhost InspectorのSlack通知のためだけにSlackを起動しているような人がいました。

見落としや業務効率の低下を招くので、Teamsに一本化してやろうというお話。
CloudWatchのTeams連携についてはCloudWatch – Teams通知連携を参照。

2021年3月からTeamsがGhost InspectorとのIntegrationを正式サポートしたので、Teamsでコネクタを構成してGhost Inspectorで通知を設定するだけ。超簡単。
早速Ghost Inspector用のチャネルを作って設定してみました。

1. Teamsのコネクタ設定

チャネル右上のメニューから、コネクタを選択
Ghost Inspectorを検索し、[構成]
Ghost Inspectorのアカウントにサインイン
接続する(通知を受け取りたい)組織を選ぶ
(よくわからなければ、全て接続して問題ない)
チャネル > コネクタ > 構成済み にGhost Inspectorが出ていれば、正常に接続設定が済んでいる。

2. Ghost Inspector通知設定

Ghost Inspector > 右上のアカウント > Settingsを開く > Notifications を開くと、Teamsの通知設定が表示されている。

※Teamsのコネクタ構成の反映には多少時間がかかるようなので、表示されていない場合は少し時間を置いてF5。

Suite Notificationsの設定例
Test Notificationsは受け取らない趣味(うるさいので)

各Test Suite/Testについても、Suite settings/Test settings > Notifications より、通知設定を確認する。
(デフォルトは「Use suite setting」なので問題ないはずだけど念の為。むしろ通知を飛ばさない想定のTestやSuiteは手動でNoにしないと通知が来てしまう)

かわいい

コネクタの設定あれこれ

  • Teamsの複数のチャネルで通知を受け取りたい
    • コネクタの設定はチャネルごとに行います。Ghost Inspectorの接続作業を、それぞれのチャネルで行ってください。Ghost Inspector側でも、通知先はチャネルごとに管理されています。
  • チャネルの通知設定を解除したい
    • 通知を解除したいチャネルのコネクタ > 構成済みから、Ghost Inspectorの構成を削除してください。Ghost Inspector側の通知設定は自動的に削除されます。

CloudWatch – Teams通知連携

SlackからTeamsに移行して久しい弊社では、CloudWatch AlarmやGhost InspectorのSlack通知のためだけにSlackを起動しているような人がいました。

見落としや業務効率の低下を招くので、Teamsに一本化してやろうというお話。
Ghost InspectorのTeams連携についてはGhost Inspector – Teams通知連携を参照。

軽く調べたらWebhookを使えばいいらしい。簡単~~~!!

1. Teamsのコネクタを作成

Slackで言うところのIntegration。

通知を受け取りたいチャネルにて、下記の設定を行う。
通知用のチャネルを作るのが良さそう。

チャネル右上の「・・・」からコネクタを選択
Incoming Webhookを「構成」
適当な名前とアイコンを設定して「作成」
WebhookURLが表示されるのでコピーしておく。

※忘れてしまっても、コネクタ > 構成済み > Incoming Webhook > (構成済みを展開) > 管理 から再度確認できる。

余談

アイコン画像は下記のように6角形に切り抜かれて使用されるため、周囲の余白をいい感じに調整すると気分が良い。

正方形 → アイコン切り抜き 参考画像

2. Teams通知のLambdaを作成

下記のような関数をさっくりと作成。

参考にした記事のほぼそのまま。
コンパクトにしたかったのでいくらか省略し、組み込みのライブラリだけ使うように書き換えた程度。かっこよくはない。

import json
import logging

from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError


HOOK_URL = "(WebhookURLを記載)"

logger = logging.getLogger()
logger.setLevel(logging.INFO)


def lambda_handler(event, context):
    logger.info("Event: " + str(event))
    
    subjet = event['Records'][0]['Sns']['Subject']
    
    message_json = json.loads(event['Records'][0]['Sns']['Message'])
    logger.info("Message: " + str(message_json))

    newStateReason = message_json['NewStateReason']
    newStateValue = message_json['NewStateValue']
    nameSpace = message_json['Trigger']['Namespace']
    metricName = message_json['Trigger']['MetricName']
    alarm_description = message_json['AlarmDescription']

    # Create contents to POST to Microsoft Teams.
    text = [
        newStateReason,
        "\r\n\r\n",
        "**Alarm State:** {0}          **Name Space:**: {1}".format(newStateValue, nameSpace),
        "**Metric:** {0}".format(metricName),
        "\r\n\r\n",
        alarm_description,
        ]

    request_data = {
        'title': subjet,
        'text': '\r\n\r\n'.join(text)
        }

    # POST to Microsoft Teams.
    request = Request(
        HOOK_URL, 
        data=json.dumps(request_data).encode('utf-8'),
        method="POST"
    )

    try:
        with urlopen(request) as response:
            response_body = response.read().decode('utf-8')
            logger.info(response_body)
    except HTTPError as err:
        logger.error(err.code)
    except URLError as err:
        logger.error(err.reason)

3. SNSトピックを作成

既存の通知先を置き換えることになったので、サブスクリプションの置換のみ。

先程のLambda関数用のサブスクリプションを作成

※SNSトピックとの紐付けは、Lambda関数の「トリガー」設定からでも行なえる。(関数の概要 > トリガーを追加 > SNSを選択 > トピックを選択 > [追加])

4. CloudWatch アラームを作成

既存のアラームの通知先を変えただけなので詳細は省略。

アラームのアクションとして通知先に先程のSNSトピックを指定する。

5. 動作確認

適当にしきい値を下げてアラーム状態にしてみると、コネクタ設定をしたチャネルにて、下記のような投稿が確認できた。

実は設定したのが4月なので、そのときのスクショ
(投稿者の名称が手順と異なるのはそのため)

課題

Teamsは現状、Webhookによる投稿でチャネル通知(Slackの@channel的なメンション)が使えないらしく、アラーム通知に気付きにくいという問題がある。

今後に期待……

参考

非同期で外部ファイルを読み込み、マップ表示速度を上げる


ODINの立案された配送計画の表示の部分(solveVRPResult)でマップの読み込み速度が遅いという問題がありました。
具体的には、ルートと配送先が多数設定されているとそれぞれをマップ上に表示する外部ファイルの読み込みなどに時間がかかっていました。

そこで、asyncまたdeferを活用して非同期で読み込むことで、表示速度を上げるということを試みました。

async・・・読み込み開始は非同期、読み込みが完了したらすぐに実行(script要素の実行順が保証されないので依存関係のあるscript要素はうまくいかなくなるかも)
defer・・・読み込み開始は非同期、読み込みが完了してもすぐには実行せず、DOMツリーの構築が完了してから実行

それぞれの外部ファイルの内容を検証したところ、読み込まれる順番が重要だということがわかりました。
しかし、deferでやってもそこまで速度が改善されず、なんとか全てasyncを使いつつ読み込む順番を工夫することで高速化を図りました。

結果としては、それぞれの読み込み速度と読み込むべき順番を考慮し、
①Mapboxのinitialize
②各ルートの緯度経度のデコード
③各ルートを異なる色の線として描画
③マップ表示範囲の調整
④SVGマーカーなどマーカー類の表示
といったような順序になりました。

また、ファイル内でのコードの順番(どこに呼び出し内容を書くか)というのも速度に影響していました。
HTML→JavaScript(外部ファイル呼び出し、JS処理)
としていたのを
JavaScript(外部ファイル呼び出し)→HTML→JavaScript(JS処理)
と変更しました。

<link rel="stylesheet" href="{$smarty.const.TEMPLATE_URL}templates/css/select2.min.css">
<link rel="stylesheet" href="{$smarty.const.TEMPLATE_URL}templates/css/jsgantt.css">

<script async src="templates/js/mapbox/initializeMapbox.js"></script>
<script async src="templates/js/mapbox/makeVrpResultFestureData.js"></script>
<script async src="templates/js/utils.js"></script>
<script async src="templates/js/decodePathLngLat.js"></script>
<script async src="templates/js/mapbox/addLine.js"></script>
<script async src="templates/js/mapbox/resizeToFit.js" ></script>
<script async src="{$smarty.const.OPEN_LAYERS}"></script>
<script async src="templates/js/error_check.js"></script>
<script async src="templates/js/mapbox/addSvgMarker.js"></script>
<script async src="templates/js/mapbox/addSymbolMarker.js"></script>
<script async src="templates/js/mapbox/addPopup.js"></script>
    
<h1>{$smarty.const.DELIVERY_PLAN_CRATE}</h1>
{include file='route_optimizer/flow_and_status.html'}

...

変数名や関数名を英文に近い表現にして可読性を上げる



変数名やプロパティ名はどのような名前がいいのか色々調べたら、
英文を意識してコードを書くと可読性向上につながるという内容を発見して、そういう命名もありかと思いました。

たとえば、boolean型の変数名またメソッド名は、YesかNoで答えられるような三人称単数現在形の動詞にします。
そうすると、if文と組み合わせたときに読んですぐに意味が分かりやすいです。

class Driver{

 public bool $hasEntered; //配送先エリアに入ったかどうか

 public function sendNotificationWhenHavingEntered(){

  if($this->hasEntered == true){
   sendNotification();
  }

 }

...

関数の引数についても、以下のように英文を意識することができるようです。

name($user, '山田太郎');

name A B.(AにBと名付ける)ですね。
ちょっとこの例は単純ですが、こういったように引数の順番など少しずつ考慮することで可読性も少しずつ上がっていくような気がしました。

Android CPUの動作をモニターする

時に、Androidの開発でCPUがどれぐらい使われてるかな~

とかモニタリングしたい時があります。

CPUやネットワークを使う動きは、バッテリーを消耗するからモニタリングしたいとか、CPUを動作させるようなプログラムがちゃんと意図したとおりに定期的に動作しているか、などを確認することができます。

やり方はとってもカンタン!です。

1.AndroidStudioの下にある「Profiler」というタブをクリックするか、[View] > [Tool Windows] > [Profiler] を選択でProfilerを開きます。

2.動作を確認したいアプリをRunします。

そんだけ。

Profilerの画面に、下記のようにCPUとかメモリとか、ネットワーク利用とか、バッテリ使用量が出てきます。便利!

停止するときは、赤い■ボタンを押します。

CPUの行をクリックすると、CPUがどのように使われているかが一覧の画面より詳しくわかります。

どのスレッドがいつ発生しているかとかもわかりますね。

ライブラリを組み込んでいるときは、ライブラリのスレッドの動作も出てきます。

画面をタップして違う画面に遷移したりしていろいろ計測できますので、やってみてください!

公式は下記です。

https://developer.android.com/studio/profile/cpu-profiler?hl=ja