私と私の猫の他は誰でも隠し事を持っている

野良プログラマ発、日々のアウトプット

AWS SNS のメッセージ属性とフィルターで、配信をオプトイン・アウトする

運用中のシステムから、警報やエラーの類を AWS SNS 経由で関係者に通知するというユースケースは割とありがちだと思います。そんな時、内容の重要度等に応じて配信先を選択するにはどうしたら良いか? という件について。

結論から言うと、メッセージ送信の際に件名・本文の他に属性(この場合だと重要度)を付与してやり、当該トピックに登録されたサブスクリプションのフィルターポリシーの設定に従って通知をオン・オフする、というやり方になります。

docs.aws.amazon.com

例として、「警報(Warning)」と「エラー(Error)」の二種類を持つシステムアラートを、SNS トピック MySystemAlert から配信するものします。この配信に際して、サービス運用者 staff@abc.def にはエラーだけを、技術担当者 engineer@abc.def には両方を通知したい場合は、両者をトピックにサブスクリプション登録した後、フィルターポリシーを以下のように設定します。

サービス運用者 staff@abc.def

{
   "alert_level": ["error"]
}

技術担当者 engineer@abc.def

{
   "alert_level": ["warning", "error"]
}

あとはトピックへのメッセージ送信の際に、下記のようにメッセージ属性を付与してやれば OK。ここでは alert_level が error なので、両者のサブスクリプションに配信されることになります。

aws sns publish --topic-arn <トピック MySystemAlert の ARN> --subject 'エラーが発生しました!!' --message 'これはテストです。無視して下さい。' --message-attributes '{"alert_level":{"DataType":"String","StringValue":"error"}}'

尚、サブスクリプションが Lambda 関数の場合は、メッセージ属性はパラメタ event.Records[].Sns.MessageAttributes.<属性名>.Value からアクセスできるので、これを使ってより細かいコントロールも可能になりますね。

2022年第1四半期 プライムビデオで観た音楽系コンテンツ

今年1〜3月にアマプラで観た音楽系コンテンツの所感というかメモでつ。ネタバレ御免につきご注意を。

インサイド・ルーウィン・デイヴィス 名もなき男の歌(字幕版)

ボブ・ディランも憧れたという伝説的なフォーク SSW、デイヴ・ヴァン・ロンクの自伝をベースにした、売れないフォークシンガーのダメダメな数日を描いた疑似伝記映画。シカゴへの往復はロードムービーふう。ピーター・ポール&マリーやブラザーズ・フォーみたいな登場人物や、ラストシーンでのボブ・ディラン(のような人)登場が胸アツでつ。オスカー・アイザック歌うまい、キャリー・マリガンはビッチでキュート、猫かわいい。コーエン兄弟の「オー、ブラザー!」も観てみたくなりました。

音楽

毎日ヒマを持て余しているヤンキー高校生トリオが思いつきでバンド「古武道」(ベース+ベース+ドラムw)結成、紆余曲折(のようなモノ)を経て地元のロックフェスに立つまでのアニメ映画。とにかく劇中の音楽が「ちゃんとして」ます。例えば実写映画版の「ベック」がコユキの凄さを無音にすることでしか表現できなかったのに対し、本作はちゃんと音を作っていて、それがまた実際素晴らしい。カンを想起させるハンマービートな古武道、批評眼的視座に優れていて演奏テクニックも備えているはっぴいえんどな「古美術」、その他ロック好きにアピールする記号が満載。以前から評判は聞こえてはいましたが、マジで傑作ッス。

ブランカとギター弾き(字幕版)

マニラのスラムで路上生活する孤児の少女と、同じく宿無し盲目路上ギター弾きじいさんが出会い、旅をしながら絆を深めていくロードムービー。ストーリーは正直ピンと来なかったけど、映像的にはフィリピンの街並みが目に美味しかったです。サイデル・ガブテロ演じる少女が歌ったのは「カリノサ」というフィリピン民謡(歌詞は現代ふうにリライトされてる)らしいけど、リズムといい節回しといいペルーのフォルクローレに通じるようであり、興味深かったです。

サンセット・ストリップ ロックンロールの生誕地 (字幕版)

LA の歓楽街、サンセット・ストリップの小史ドキュメンタリー映画(2013年米公開)。ウィスキー・ア・ゴーゴーやロキシーシアターといった有名ライブハウスの名前は知ってても、それらが密集するこの数km程のエリアがカウンターカルチャーのシンボル的な存在だったというのは初めて認識しました。元々はセレブが集う退廃色の濃い夜の社交場だったのが、'60年代からユースカルチャーにシフトして「セックス・ドラッグ・ロックンロール」タウンに変貌。そして'80年代末にオルタネイティヴの台頭でロックが過去の遺物となるとともに衰退して行った、ということですかね。当時のライブ映像が盛り込んである訳でなく、太ってシワだらけになった往年のロックスター達が未練たっぷりに懐古したりステージ(リバイバルフェスか何か?)でイケイケに振る舞う姿が痛々しい。ジョニー・デップキアヌ・リーヴスらが華を添えてなければ、結構物悲しい作品で終わったかもですねー。

という訳で、前回まで半年ペースで纏めてましたがボリューム的に大変なので、四半期毎に書くことにしました。まだまだウォッチリストはパンパンなのでネタが尽きそうにありません。

はてなブログで UA と GA4 を併用する

このブログでは開設以来 Google アナリティクスでアクセス集計してきましたが、アナリティクスのコンソールで最近こんな表示が。

f:id:mariyudu:20220402104009p:plain

従来のアナリティクス(ユニーバサルアナリティクス、以下 UA)が、次世代の「Google アナリティクス4」(以下 GA4)に代替わりするので、UA は 2023年7月からデータ収集できなくなるよ、ってことですね。UA で蓄積されたデータを GA4 に移行することは出来ないっぽいので、暫くの間は UA と同時に GA4 でもトラッキングして GA4 側にじゅうぶんデータが溜まった時点でスイッチするのが良さげです。じゃあ、それをはてなブログで設定するにはどうすんの? ってのが今日のお題。既に移行先の GA4 アカウントとプロパティは取得済み、また Google タグマネージャーは使っていない、という前提で読んで下さい。

従来はブログ設定の「詳細設定」で UA のトラッキング ID を設定して、トラッキングを行ってきました(下図)。

f:id:mariyudu:20220402104037p:plain

これにより、自分でトラッキングコードを書かなくともはてなブログがトラッキングコードを生成してくれていた訳ですね。けれど、ここで GA4 のトラッキング ID を追加するような設定には対応していないみたいです。さて、どうするか… 少し調べた結果、はてなブログのトラッキングコード生成機能を使うのを止めて、自分でトラッキングコードを書く」のが手っ取り早かったです。上記の「Google Analytics 埋め込み」にセットしたトラッキング ID を削除し、そのずっと下のほうにある「head 要素にメタデータを追加」に、トラッキングコードを書きます(下図)。

f:id:mariyudu:20220402104053p:plain

ラッキングコードは GA4 で発行したものの最後に、gtag() パラメータに UA のトラッキング ID を指定した行を追加するかたちになります。この設定を一週間前に行いましたが、UA と GA4 の両方でトラッキングデータが蓄積されているようです。

Heroku でシンプルな PHP サイトを作る

ここしばらく、レンタルサーバ中心で開発・提供してきた個人サイトの数々を整理統合する作業をしてます。その一環で、とある PHP 製サイトを Heroku の無料プランに移行してみることにしました。公式のチュートリアルに従って手順を学んだのですが、Silex アプリのボイラープレートを git clone して作業を進めるというのはブラックボックスっぽいというか、いまいち理解に繋がる感じがしなかったので、フレームワーク頼りではなく古典的なスクリプトレットのサイト開発を手作業でひとつずつ進めるやりかたにブレイクダウンしてみました。「Heroku アプリを作る」件だけにフォーカスしたいので、下記を前提にしています。

  • Heroku アカウントを持っている。
  • ローカル環境に Heroku CLIPHP、Composer、Git がインストールされており、使える状態になっている。またそれらについての最低限の知識を持っている。

さて、Heroku で PHP サイトを構築するには、ざっくり言って下記要件が必要なようです。

  • サイトのドキュメントルートとなるディレクトリを作り、そこのプログラムを配置する。
  • モジュールやライブラリの類は Composer で用意する。
  • Heroku のコンテナに指示をする Procfile というファイルが必要。
  • 一式は Git リポジトリ化されており、リモートリポジトリは Heroku を指している。

これらをステップ・バイ・ステップで手作業してみます。macOS 等の Unix 系 OS を対象とした記述になっていますので、Windows の方は適宜読み替えて下さい。まず、ローカル環境の適当な場所にプロジェクトディレクトリを構築。

mkdir -p heroku-php-site/web
cd heroku-php-site/

Heroku のコンテナで使われるモジュールを Composer でインストール。

composer require --dev heroku/heroku-buildpack-php

これで、composer.json, composer.lock, vendor/ が出来ていれば OK。次に PHP アプリファイルを作成。シンプルに phpinfo() を実行するだけのページ1枚だけです。

cat << EOS > web/index.php
<?php
phpinfo();
EOS

Procfile を作成します。

cat << EOS > Procfile
web: vendor/bin/heroku-php-apache2 web/
EOS

Git 管理から外すファイル・ディレクトリも明記。

cat << EOS > .gitignore
vendor/
.env
EOS

これで一式が揃ったので、ビルトインサーバで動作確認。

php -S 0.0.0.0:8080 -t web

ブラウザで http://localhost:8080/ を開き、phpinfo() 出力が表示されていれば OK。

以上でアプリ開発(笑)が完了したので、ここから Heroku にデプロイする手順に入ります。Git ローカルリポジトリを作成。ブランチはデフォルトのまま main が良いようなので、古い git を使っている方はご用心。

git init
git add .
git commit -m "最初のコミット"

事前にブラウザで Heroku ダッシュボード( https://dashboard.heroku.com/ )にログインしておいてから、下記手順でアプリをデプロイします。heroku create の際にはアプリ名を指定しないとランダムな名称が付与されるので、ここでは my-simple-php としておきます。

heroku login
heroku create my-simple-php
git push heroku main

これでデプロイが完了したので、ブラウザで動作確認してみます。

heroku open

ローカルの時と同様、https://my-simple-php.herokuapp.comphpinfo() 出力が表示されていれば OK。

以上です。あとは必要に応じてプログラムを改修し、git push heroku main でデプロイという繰り返しになります。

うたほんくん、シーズン2突入しました

かれこれ20年くらい運営しているちょっとしたサービスをリニューアルしました。

utahon.mariyudu.net

「うたほんくん」という、ウクレレコードフォーム付きの歌詞カードを生成するサービスなんですが、リニューアル後はこんな感じです↓。

f:id:mariyudu:20220312135900p:plain
歌詞を書いてコードを埋め込みプレビューしてみると…
f:id:mariyudu:20220312135941p:plain
コードフォーム付き歌詞カードのできあがり♫

従来版は全面的にサーバサイドで動作するウェブアプリケーションでしたが、これを SPA 志向なアーキテクチャに変更して Node.js で全部書き直しました。技術的なトピックは以下のとおりです。

  • 一式を Nuxt.js(2.15)上で Static 生成。
  • U/I は Vuetify(2.6)を採用。
  • コードフォーム画像は SVG で提供(従来は ImageMagick でビットマップ生成)。
  • サービスタイトルのフォントはヤマナカデザインワークス様のバナナスリップを利用。
  • コードフォーム画像中の音楽記号には、stixfonts の STIXTwoMath-Regular.woff2 を利用。

20年前のリリース当初は Perl CGIXBM 画像を生成するという古式ゆかしい構造だったのが CGIRuby で書き直し、さらに PHP + ImageMagick に… とそれなりに変遷してきたサービスですが、今回はアーキテクチャごと見直したこともあり「シーズン2」としましたw

ここ10年くらいは放置状態で忘れ去られた感がありましたが、復活の手応えがあるようならギター版や移調機能等、付け加えてみたいアイディアはあるので、ご愛顧よろしくねっ。

2021年下半期 プライムビデオで観た音楽系コンテンツ

上半期に続き、無事シリーズ化できそうで何よりですw 相変わらずネタバレ御免な内容なので、ご注意を。

オーケストラの少女(字幕版)

1937年作。失業中のトロンボーン奏者の娘が、父とその仲間達を救う為、オーケストラ結成のスポンサー探しを、ひいては有名指揮者に初舞台の指揮を頼み込んで成功させるまでの音楽喜劇。フィラデルフィア管弦楽団とその指揮者レオポルド・ストコフスキーが実名で登場してます。

I Am The Blues アイ・アム・ザ・ブルース(字幕版)

ミシシッピルイジアナで、今でもジュークジョイントでライブサーキットしている老ブルースミュージシャン達のドキュメンタリー。予め知っていた名前はバーバラ・リン等の数人だけだったので、それ程興奮しながら観たという感じじゃなかったけど、伝説的なミュージシャン達が生存している間にこういう記録がなされて多くの人が楽しんでいるってのは善き哉。

プラハモーツァルト 誘惑のマスカレード(字幕版)

モーツァルトプラハに滞在して「ドン・ジョヴァンニ」を書いたという史実をベースにした、制作秘話的フィクション。イケメンなモーツァルトがヒーローよろしく難事件をバババンと解決! 的な爽快エンタメかと思ったら、優男なだけで全く無力だし切れ者そうに見えた悪役男爵は只のスケベオヤジだしと、何とも盛り上がらないままエンディングという印象。

クラーク・シスターズ -First Ladies Of Gospel-

1970〜80年代に活躍した5姉妹ゴスペルグループの伝記映画。星一徹みあるスパルタ母ちゃんと娘たちの確執、グラミー賞獲得による教会と衝突、デニスとトウィンキーの相次ぐ脱退、晩年の再結成等が描かれます。芸能界を生き抜くって本当に大変…

トミー HDリマスター版 (字幕版)

ロックが未だ拡張期だった時代ならではの八方破れな意欲が眩しいでつ。一度くらいは観てると思ってたんだけど、こんな映画だったっけ? という妙な新鮮さがw 筋を深読みするよりは、全員が元気だったフーのメンバーが観られることが嬉しい。エルトン、ティナ・ターナー、クラプトンとゲストも豪華だったんだなぁ。

かげきしょうじょ!! [全13話]

天然系のギフテッド少女が宝塚ライクな歌劇団の養成学校に入学して成長していく群像青春劇。イマドキな軽妙さと小気味良いテンポ感で安心して観られる反面、記憶には残らないかなぁと言ったら意地悪でしょうか。

フレディ・マーキュリー:キング・オブ・クイーン(字幕版)

今まで観てきたフレディドキュメンタリーとさほど変わらない印象。この制作元、同じ取材ソースを元に複数コンテンツを便乗乱造してるのでは、と思いたくなる焦点感の薄さでした。

ブルーノート・レコード ジャズを超えて(字幕版)

ブルーノート・レコードの復興から現在に至るドキュメンタリー。黄金時代がどれだけ凄かったかとイキるのではなく、ヒップホップを取り込み、ノラ・ジョーンズで新市場を開拓してと、変貌して行くように見えてもファウンダー(アルフレッド・ライオンとフランシス・ウルフ)の精神性がそのまま現在でも生きているってのが主旨でしょうか。好感が持てる構成でした。

じっくりと映画を観る精神的な余裕がなかなか無くて、TV アニメばかり観てた一年だったような気がするけど、振り返ってみると音楽モノはそれなりに観てますな。そんな訳で、今年もよろしくお願いします。

Step Functions を PHP プログラムから実行する

最近、AWS Step Functions を使ってみたのですが、これが中々面白い。ステートマシンというワークフローを定義して、予め作っておいた Lambda 関数群を順に実行して出力値を次の関数に渡したり、分岐・ループ、並列実行等もできちゃう。Lambda 関数を Unix コマンドになぞらえると Step Functions はシェルスクリプトですな。単純な機能の Lambda 関数を組み合わせて複雑な処理が可能になるので、バッチ処理的なユースケースでサーバレス化が捗りそうです。

そんな便利な Step Functions ですが、ステートマシンの作り方等は他に解説がいくらでもあるので、今回は作ったステートマシンを PHP プロうグラムから実行する話。単純な要件だけど、コードサンプルが意外に見つからなかったもので。

以下、ステートマシンを非同期に実行開始して、1秒毎に状態取得・出力するという例です。AWS SDK for PHP 3 が必要なので、下記スクリプトのある場所で composer require aws/aws-sdk-php してある前提です。

<?php
require_once('./vendor/autoload.php');

define('AWS_ACCESS_KEY', <あなたのアクセスキー>);
define('AWS_SECRET_ACCESS_KEY', <あなたのシークレットアクセスキー>);
define('AWS_REGION', <リージョン>);
define('STATEMACHINE_ARN', <あなたのステートマシンのARN>);

// Step Functions クライアント生成
$credentials = new Aws\Credentials\Credentials(AWS_ACCESS_KEY, AWS_SECRET_ACCESS_KEY);
$sfn = new Aws\Sfn\SfnClient([
	'region' => AWS_REGION,
	'version'  => 'latest',
	'credentials' => $credentials
]);

// ステートマシンの実行を開始
$input = [
	"var1" => "a",
	"var2" => "b",
	"var3" => "c",
];
$result = $sfn->startExecution([
	'stateMachineArn' => STATEMACHINE_ARN,
	'input' => json_encode($input)
]);
$executionArn = $result['executionArn'];

// 実行状態を監視しつつ終了まで待つ
for ($events=[],$expire=time() + 60; time() < $expire;) {
	sleep(1);
	// 実行状態を取得
	$result = $sfn->describeExecution([
		'executionArn' => $executionArn
	]);
	$status = $result['status'];
	// イベント履歴を取得
	$result = $sfn->getExecutionHistory([
		'executionArn' => $executionArn
	]);
	// 発生したイベントを表示
	$newEvents = array_slice($result['events'], count($events));
	foreach ($newEvents as $newEvent) {
		printf("[%d] %s\n", $newEvent['id'], $newEvent['type']);
	}
	$events = $result['events'];
	if ($status != 'RUNNING') {
		break;
	}
}

Lambda 関数の内部でもプログレスを DynamoDB 等に出力するようにすれば、より詳しい監視が可能になるかも。逆にそこまで詳しく状態把握する必要がなければ、startExecution() を startSyncExecution() にすると簡単に同期処理できます。