Mackerelでのアラート対応のためのトイルを削減するツール prepalert

この記事はMackerel Advent Calendar 2022KAYAC Advent Calendar 2022 の7日目です。
こんにちは、SREチーム所属の@mashiikeです。

前年の Mackerel Advent Calendar 2021 ではSREにおいて大事なSLO/エラーバジェットをMackerelのメトリックとして投稿するツール shimesaba について話しました。 1年経って、Mackerelを用いたSLI/SLO/エラーバジェットの運用が安定化してくると、次に気になってくるのはトイルだと思います。

cloud.google.com

「トイルとは、手作業、繰り返される、自動化が可能、戦術的、長期的な価値がない、サービスの成長に比例して増加する、といった特徴を持つ作業です。」 トイルの例としては次のようなものがあります。

・割り当てリクエストの処理
・データベース スキーマ変更の適用
・重要性の低いモニタリング アラートの確認
・プレイブックからのコマンドのコピーと貼り付け

ここに挙げたすべての例に共通する特徴は、エンジニアが頭で判断する必要がないということです。

さて、上記の例の中で、Mackerelでのシステム運用に関係するトイルとは、『重要性の低いモニタリング アラートの確認』です。 今回は、アラート対応におけるトイルを削減するためのツール prepalert について話したいと思います。

github.com

アラート対応におけるトイル

冒頭で挙げられたトイル『重要性の低いモニタリング アラートの確認』とは一体どういうことでしょう?
ここで言う『重要度の低い』という言葉はいろいろな解釈があるとは思います。
一つの考え方として『エラーバジェットが削りきれていないような状況でのアラート』や『ユーザーに重大なエラーが出ていないようなアラート』のことを指すと考えられます。
エラーバジェットが削れていたり、すでにユーザーに見える形でエラーが起きている場合、できるだけ早く対応する必要があるため人間が様々な調査を行うことでしょう。
しかしながら、そうでない場合・・・例えば『単発の5xxエラーに関するWarnアラート』のような、起きていることを把握はしたいが一瞬発生しただけでは慌てる必要のないというアラートは運用中フェーズではよくあることでしょう。
そういった、重要度の低いアラートは確認項目が定型化することはよくあると思います。

shimesabaを導入したあるプロダクトでは、SLO:latency として『ALBのレスポンスタイムのp90が700ms以内である』というものを設定しています。
週次のSRE定例で、SLO:latencyのエラーバジェットがどれぐらい削られたのか?いつ削られたのか? というのをMackerelのアラートベースで確認するようにしています。

これらのアラートはSRE的にはエラーバジェットが残っている状況では、それほど焦る必要はなく重要度の低いアラートとなります。
しかし、週次の定例では、ALBやNginxのアクセスログにクエリして、毎回手作業で以下のような確認が行われていました。

  • どのエンドポイントが起因となって発生したのか?
  • 具体的なリクエストの件数は?
  • リファラーはどこなのか?
  • 対象となったリクエストIDは?
  • p90以外のmedianやaverage,max,minなどのレスポンスタイムは?

これらの確認は、トイルでありエンジニアのモチベーションを下げる要因になっていました。
そこで、このトイルを解消するために生み出されたのが prepalert になります。
※ 名前の由来は prepare + alert

トイル削減ツール 『prepalert』

prepalertは何をするツールか?
一言で言えば『アラート対応ために必要な情報を、アラートのメモやグラフアノテーションとして書き出すツール』です。
アーキテクチャーは以下のようになってます。

alertをWebhookとして受け取って、SQSへメッセージを送ります。 送られたSQSメッセージをトリガーにして、workerが起動して、RedshiftへのクエリやS3 Select、Cloudwatch Logs Insightsなどを駆使して関連情報を取得して、アラートのメモやグラフアノテーションとしてMackerelに投稿します。

Terraform等での構築の例として github.com/mashiike/prepalert/lambda がありますので、こちらをご覧いただけるとより詳細がわかると思います。

実際の動作例としては、以下のようになっています。

この例では、各種のログに問い合わせて、その結果をアラートのメモに投稿しています。
その時間帯で、エンドポイントごとのp90が閾値を超えたものを列挙している例です。
prepalertが入る以前は、redash等でクエリした結果を共有していましたが、prepalertが入ることによって自動で情報がアラートに関連付けられるようになりました。
prepalertによって、現在では重要度の低いのアラートの確認がスムーズに行くようになりました。

prepalertの使い方

prepalertの簡単な使い方を紹介します。
Mac,Linuxをお使いの方はbrewコマンドでインストール可能です。

$ brew install mashiike/tap/prepalert

prepalertをインストールしたら、初期のconfigを生成します。

$ prepalert init
Which Mackerel service do you use to post graph annotations?: dev
Which SQS Queue do you use?: dev-prepalert

Try running the following two commands in a separate terminal:

$ prepalert --config . --mackerel-apikey <your Mackerel api key> run --mode webhook
$ prepalert --config . --mackerel-apikey <your Mackerel api key> run --mode worker

When performing a local operating environment, request the following

$ cat event.json | curl -d @- -H "Content-Type: application/json" http://localhost:8080

Have fun prepalert.

Mackerelのgraph annotationを投稿するサービスやSQSのQueue名を聞かれるので入力します。
コンソール上では、ローカルで動かす場合の方法が書かれています。
実際に使う場合はAWS Cloud上に構築することになります。

生成されたconfigを見てみましょう。コメントアウトされてる部分を取り除くとこのような感じになっています。

config.hcl

// Composition of the entire prepalert
prepalert {
  required_version = ">=v0.8.0"
  sqs_queue_name   = "dev-prepalert"
  service          = "dev"

}

rule "simple" {
  alert {
    any       = true
    on_opened = true
    on_closed = false
  }
  information           = "How do you respond to alerts?"
  update_alert_memo     = true
  max_alert_memo_size   = 10000 //If the size of the memo exceeds 10KB, a part of the memo will be omitted. This setting can be changed from 100Bytes ~ 80KB.
  post_graph_annotation = false
}

ある特定のアラートについて、失敗等のリカバリやクエリチェック向けで用意してる exec コマンドを使ってみましょう。

$ export MACKEREL_APIKEY=<your Mackerel API key (writable)>
$ prepalert --config . exec <alert_id>                              
2022/12/01 17:39:07 [info] try get sqs queue url: dev-prepalert
2022/12/01 17:39:07 [info][-] match rule `simple`
2022/12/01 17:39:07 [info][-] update alert memo: alert_id=<alert_id>  
2022/12/01 17:39:08 [info][-] 1 rules match

コレを実行すると、対象のアラートのメモが以下のようになります。

この設定の状態で、AWS Cloud上に構築して、Mackerelのwebhookを設定すると、すべてのアラートのメモに How do you respond to alerts? という固定の文字列が設定されるようになります。

このままでも、アラート対応の手順書等をメモに入れる使い方ができますが、より実用的な例を示します。 監視のIDが4xxxxxxxxxxであるアラートが来た際に、アラートの発生30分前から現在までの間の時刻について、ALBのログをS3 Select経由でクエリし、5xxのリクエストの情報をアラートのメモに残す設定です。

config.hcl

prepalert {
  required_version = ">=v0.8.0"
  sqs_queue_name   = "dev-prepalert"
  service          = "dev"
}

query_runner "s3_select" "default" {
  region = "ap-northeast-1"
}

query "alb_5xx_logs" {
  runner            = query_runner.s3_select.default
  bucket_name       = "logs-example-com"
  object_key_prefix = "external-alb/AWSLogs/123456789012/elasticloadbalancing/ap-northeast-1/${strftime("%Y/%m/%d", runtime.event.alert.opened_at)}/"
  compression_type  = "GZIP"
  csv {
    field_delimiter  = " "
    record_delimiter = "\n"
  }
  expression        = templatefile("get_alb_5xx_log.sql", { runtime = runtime })
}

rule "alb_5xx" {
  alert {
    monitor_id = "4xxxxxxxxxx"
    on_opened  = true
    on_closed  = false 
  }
  queries = [
    query.alb_5xx_logs,
  ]
  information = <<EOT
下記のALBのログを確認しましょう。
ALBログの読み方は、https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/load-balancer-access-logs.html を参照してください。"actions_executed""waf-failed"の場合は、error_reasonで詳細を確認しWAFConnectionTimeout の場合は "AWS WAF への接続がタイムアウトした"ことを意味します。AWS WAFのSLAは99.95%でよく出る上に深刻ではない可能性が高いので単発の場合は一旦放念しましょう。

それ以外で、気になる場合は詳細調査を行いましょう。
${runtime.query_result.alb_5xx_logs.json_lines}
EOT

  update_alert_memo     = true
  max_alert_memo_size   = 80000
  post_graph_annotation = true
}

get_alb_5xx_log.sql

SELECT
    s._1 as "type"
    ,s._2 as "time"
    ,s._3 as "elb"
    ,s._4 as "client_port"
    ,s._5 as "target_port"
    ,s._6 as "request_processing_time"
    ,s._7 as "target_processing_time"
    ,s._8 as "response_processing_time"
    ,s._9 as "elb_status_code"
    ,s._10 as "target_status_code"
    ,s._11 as "received_bytes"
    ,s._12 as "sent_bytes"
    ,s._13 as "request"
    ,s._14 as "user_agent"
    ,s._15 as "ssl_cipher"
    ,s._16 as "ssl_protocol"
    ,s._17 as "target_group_arn"
    ,s._18 as "trace_id"
    ,s._19 as "domain_name"
    ,s._20 as "chosen_cert_arn"
    ,s._21 as "matched_rule_priority"
    ,s._22 as "request_creation_time"
    ,s._23 as "actions_executed"
    ,s._24 as "redirect_url"
    ,s._25 as "error_reason"
    ,s._26 as "target_port_list"
    ,s._27 as "target_status_code_list"
    ,s._28 as "classification"
    ,s._29 as "classification_reason"
FROM s3object s
WHERE TO_TIMESTAMP(s._2) >= DATE_ADD(minute,-30,TO_TIMESTAMP('${strftime_in_zone("%Y-%m-%dT%H:%M:%SZ","UTC",runtime.event.alert.opened_at)}'))
AND TO_TIMESTAMP(s._2) <= TO_TIMESTAMP('${strftime_in_zone("%Y-%m-%dT%H:%M:%SZ","UTC",runtime.event.alert.closed_at)}')
AND cast(s._9 as INT) >= 500

このように、query_runnerとqueryという設定を追加すると、prepalertは設定された内容に従い情報を取得します。 そして、 ${runtime.query_result.<query_name>.json_lines} というような形で、参照してメモにその結果を埋め込むことが可能になります。

prepalertにはまだ紹介できていない機能もありますが、大まかにはこのような動きをするツールとなっております。

おわりに

prepalertはアラート対応で必要となる情報をMackerelに集約するために生まれたトイル削減ツールです。 アラート確認のために、RedshiftへのクエリやS3 Select、Cloudwatch Logs Insightsに定型のクエリを実行している場合は、是非使用を検討してみてください。
いつか皆様のSREの活動の役に立てれば幸いです。

カヤックではサービスの信頼性を追求するエンジニアも募集しています

hubspot.kayac.com

アーケード筐体奮闘記~アーケード筐体でPCゲームを遊べるようにした話~

はじめに

この記事はTech KAYAC Advent Calendar 2022の6日目の記事です。

こんにちは、OC事業部その他配属の橋本と申します。普段は専門部隊の手が届かないところにヘルプで入ってよしなにすることを仕事としているのですが、その仕事のうちの一つに「アーケード筐体をPCと繋いでよしなにゲームできるようにしておいて」という無茶ぶり仕事があったので、その時の奮闘を今回ブログとして供養したいと思います。

筐体について

今回動かす筐体はこちらになります。

今回動かす筐体 多分BLASTCITY
SEGAのBLAST CITYだと思いますが、僕も細かい仕様はよく知りません。なんせインターネットが発達する前の代物です。しかも非売品。ろくな資料は見つけられませんでした。 さて、コイツの大まかな構成ですが、ものすごくザックリ言うと筐体の中にモニターとコントローラが入っていて、これらをよしなにPCと接続することができればミッションコンプリートです。 やってることはPS5やswitchをとモニターを接続して遊ぶのと一緒です。こう聞くと簡単そうですね。

コントローラーを繋ぐ

まずは簡単なほうからいきましょう アーケードコントローラー(以下アケコン)とPCを繋ぐのに必要な作業は以下の2つです

①アケコンとPCを接続する

②アケコンの入力をPCの入力に変換する

①について

アケコンの端子はJamma規格という規格にのっとって作られたものになります。

Jammaハーネス 逆に差すと大変

まずコイツをキーボード入力に変換するための変換器が必要となります。 これはamazonで「Jamma USB変換」とかで調べると出てくるものを買えばいいです。日本製のものはないので中国製のものを買いました。

中国製なので、取説はもちろんありません。 ただあまり難しいことはなく、基盤の金色の所に筐体から伸びているJammaハーネスを差せばよいだけです。向きを間違えると基盤が大破するので、それだけ気を付けましょう。

②について

これはWindowsの場合はJoyToKeyというシェアウェアを使うことで解決できます。

joytokey.net

Macでも似たようなソフトは確認しているので、Macでやりたいよって人はググればでてくると思います。 JoyToKeyをインストールしたら、筐体のボタン1つ1つにキーボード操作を割りふることができるので、モニターを接続した後ポチポチ設定していきましょう。

JoyToKeyの設定。アケコンのボタンとキーボード入力を1:1に対応させることができる

JoytoKeyについてはただのソフトウェアの使い方になるので、省略します。詳しくは公式HPなりを参照してください。

モニターとの接続について

これでコントローラとPCを接続することができました。 後はモニターとPCを接続すればゲームができます!やったね! 筐体の映像端子はVGAです。こいつをHDMI to VGA変換ケーブルを使ってPCと接続すれば完成!!!!!

…… …… ……

とはいかないんですよね。残念ながら。 ここからが長い長い旅路の始まりです。(おそらく読者の多くもここまでは順調な方が多いのではないでしょうか…)

水平走査周波数のチューニング

まずPCから出力される映像とモニター側で表示できる映像をすり合わせる必要があります。この時キーになるのが水平走査周波数というものです。

水平走査周波数とは

水平走査周波数とは、テレビ受像機やディスプレイ装置のように電気的に像を表示面に投影する装置において、単位時間あたりに表示する走査線(横線、ライン)の数。
水平走査周波数(水平同期周波数)とは - 意味をわかりやすく - IT用語辞典 e-Words

とのこと。 まあネットゲームをよくやる人には馴染み深いFPSのご親戚みたいなもんだと思っていれば大丈夫です。

この水平走査周波数は対応する周波数がモニターによって違うので、まずこれを確認します(ここで、筐体の仕様が分からないので響きました。) 調べてみると今回使用した筐体のモニターはこの水平走査周波数を、スイッチで15Hzと24kHzと31Hzに切り替えることができることが判明したので、このスイッチを探し、「31Hz」に設定します。(現在発売されている多くのPCは25kHz以下の水平走査周波数の映像を出力することができません。)

水平走査周波数を変えるスイッチ。比較的新しい筐体は31kHzに対応している。

筐体の種類によっては15kHzや24kHzしか受け付けないモニターもあります。その時は残念ですが、PCとモニターの間にダウンスキャンコンバータを挟む必要があります。お手元の筐体をご確認ください(もしかしたら15kHzを出力できるグラフィックボードもあるのかもしれませんが…)

PCの映像出力を調整する。

次にPCの映像出力を調整します。 Windowsで水平走査周波数やリフレッシュレートについて細かい調整をするにはグラフィックボードが必要になるので、最初はMacのSwitchResXというシェアウェアを使って接続してみました。 結果…

規格通り出力しているが映像が安定しない
なぜか砂嵐が起きるという結果に…

水平走査周波数もリフレッシュレートも完璧に合わせているはずなのになぜか砂嵐が起きます(いまだに原因不明です) MacとHDMIケーブルをつなぐためのハブが問題なのか、そもそもMacのパワーが足りていないのか…とにかくMacだとうまくいかなかったので、会社からグラボ付きのwindowsPCを借りて再挑戦。

今度は G-GEAR「VIVE Ready PC」ゴールドモデル

www.tsukumo.co.jp

を使いました。

グラボの設定から 水平走査周波数:31kHz リフレッシュレート:62Hz(60ではないんですね、これが) に設定

結果は……

無事映像が安定した。やったね
無事安定して映像を出すことに成功しました。やったね

メインモニターを繋ぐ。

これでモニター、コントローラーともに設定できました!PCにゲームを入れて、ボタンを設定するだけでゲームができます・・・! ともいかないんですね・・・ハイ

このアーケード筐体のモニター、なんと「メインモニターにした瞬間、落ちます」 どうしてだと思います?どうしてなんでしょうね。

ということでメインモニターを繋いでおかないといけません。 今回はメインモニターとしてこちらのUSB小型モニターを繋ぎました。 社員様がたまたま保有していたモニターをお借りしたので、細かい仕様などはしりません。 適当にアマゾンなどでUSBモニターをポチって頂ければと思います。

今回メインモニタとして利用したモニター
これでぱっと見は筐体のモニターがメインモニターとして動いているように見えます。

ホントのホントに終わり

これで終わりです。あとはマウスとキーボードを使って遊びたいゲームを起動し、筐体のモニターに映し、JoyToKeyを使ってボタンの設定をすれば遊ぶことができます。 フルスクリーンでゲームがしたい場合はSteamのビッグピクチャーモードなどを利用すると良いと思いますが、今回は省略します。 興味のある人は調べてみてください。

最後に今この筐体は弊社の会議棟オフィス「ありがとう」のオープンスペースにて、稼働中です。弊社社員が開発した「UnrealSumou」というゲームができます。 ゲーム自体は無償で配布中ですので興味のある方は是非インストールしてみてください。

mobile.twitter.com

github.com

また鎌倉付近にお住まいの方は是非一度生の筐体で遊んでいただければ、僕の苦労も報われますので是非遊びに来てください。1回100クルッポで遊べます。

では。