VS Code+Docker php開発環境構築でxdebugバージョンにハマる

 phpで作られた既存システムの開発環境を、VS Code+Dockerで再構築していました。
 情報はたくさんWebで見つかるので、構築はそれ程困りませんでしたが、最後のVS Codeからのデバッグ実行でちっとも止まってくれません。

 phpはたまにしか触らないレベルなので、こうなると一気にハマって先に進みません。

 暫く試行錯誤しながら何となくphpinfoを確認していると、どうもxdebugのバージョンが3になっているようです。
 で、xdebug3でWebを探すと案の定、php.iniの記述がこれまで参考にしていたサイトと違う内容になってました。

 ハマった時は落ち着いて状況を確認しないと、無駄な時間が増えてしまいますね。

wordpressのチェックボックスが表示されない

 何時からか忘れましたが、wordpressでチェックボックスを押しても反応が無くなりました。これではチェックされているかが解りません。

 かなり不便なので、いい加減治したいと、何気なくブラウザの開発ツールを見ていたら、チェックボックスを押したタイミングで下記のようなエラーが出ているのを発見。

 あ、以前にセキュリティ対策としてnginxの設定を弄ってましたねえ。それが問題になっているようです。

 nginx.confを見直ししてadd_header Content-Security-Policyのimg-srcにdata:を追加。

 治りましたが、Mozillaのページでは非推奨だって書かれてますね。。

push.jsでWindows10端末に通知してみた

 システム障害時のアラートといった、イベント発生をトリガーに業務対応するようなシーンで、これまでメール受信で対応していましたが、多種のメールに埋もれて気が付けないケースが出てきたという事で、メールに変わる何らかの通知機能は無いかと検討。

 要件としては、対象はWindows10端末のみ、内部的な仕組みな為、外部サービスの使用は不可、イベントはチケットシステムに登録されるので、チケットシステム上に、イベント一覧画面を作成して定期的に画面をリロード、push.jsで通知する形なら、まあ気が付くだろうと試してみました。

 push.js自体の実装自体は簡単で、適当にググってサクッと完成。通知を出したら同じ通知を次は出さないとかは個別に工夫します。

 基本的に通知設定は端末・デバイス側の設定に依存しており、Windows端末ならシステム設定から通知設定をするんですが、それ以外にもブラウザ毎に通知仕様が微妙に異なるようです。FireFoxは通知を複数表示できるが、Chromeは1件だけとか。

 Push.Createコール時にrequireInteraction: trueにした場合、Chromeの通知は閉じるボタンが付き、かなり長時間通知が表示された状態になるようでしたが、Edge(Chromium前?)はそうでもなかったりとか。また、Push.Createのコール時のtimeout設定は、特に効いていないようでした。

 あと、基本的にブラウザが通知を許可してくれるのはlocalhostかhttpsのサイトだけという縛りがありますが、Edgeならhttpサイトでも通知が可能だったのでテストに便利です。

 でも、イベント発生トリガーをメール受信からおきかえられるかは業務利用次第ですね。

粒度問題

 何かシステムを作ろうとなったときによく感じるのが粒度問題です。

 簡単に言うと要件を出す立場の人側は、森を見て木を見ず、開発する立場の人側は木を見て森を見ず、そんな違う立場の間で起きる認識のずれ、コミュニケーションギャップ問題です。前者は対象を大きな範囲で捉えており、1本1本の木々には関心が無かったりします。後者は、個々の木を構成した結果の集合としての森なので、木々の方に着目する傾向があります。たまに木が大好きな前者もいたりはしますが、実は木でも「松」にしか関心が無かったり、、と関心の対象が異なるので話が噛み合わないのは当然です。しかも、当事者はそのような状況になかなか気がつけません。さらに開発工程で担当者が違うような体制の場合、さらに別の面で同じような問題になったりします。

 このような状態が続くと、当たり前ですが、最終的に良い結果にはならないので、早い段階で手を打ちたいですよね。でも、双方の意識を変えるという難しい問題なので、簡単な手はなかなか見つかりません。

 結局、言葉だけで伝えられない事は、一旦紙、ドキュメントという形に落とす意外無いように思います。まずは森である大枠をいろんな角度で対象を分類し、徐々徐々にドリルダウンしていきます。このフェーズの落とし所として意識するのは、そのドキュメントを見る人たちが意識している粒度の粗さと細かさのちょうど真ん中辺りの粒度レベルまでに抑える事です。話が進むにつれてドキュメントに結果をフィードバックし、仕様書的な物に変えていきます。

 人の意識を変えるのは難しいけど、少しずつ対話しながら双方が歩み寄るという、ここで言うところの粒度問題も、長年続く領土問題も平和に解決するには結局同じ方法しか無いないんだろうなあ。
 

SpringBootでZabbixAPIを使ってみる

 Zabbixの作業を自動化したいという事で、ZabbixAPIを使ってみました。対象のZabbixは3.2とちょっと古めのようですが、API自体はあまりバージョンは気にしなくてよさそうでした。ドキュメントが充実しているので助かります。

認証後、2件のホストを指定してホスト情報を取ってくるテストを書いてみました。

で、こんな感じで戻ってきます。

hosts: [{“hostid”:”10387″,”host”:”server01″,”name”:”server01_DB”},{“hostid”:”10388″,”host”:”server02″,”name”:”server02_DB”}]

問題無く使えそうなので、要件を整理してから実装してみます。

プログラムは紙に書かない

 最近、地元の図書館で見かけてたまたま借りたのですが、「ペーパレス時代の紙の価値を知る」という本を読みました。

 認知科学?の実験結果報告部分が多く、途中かなり斜め読みになりましたが、紙の本を読むほうが読解が深い、手でページをめくる動作の優位性等、紙の本には電子書籍に対する優位性がまだあり、電子書籍だけでなくPC等含めた電子デバイスとは用途によって使い分けるのがよいだろう的な内容でした。

 確かに筆者も図書館にたまに行くくらいなので、紙の本は気持ち集中して読みやすいような気がしますし、Kindlewhitepaperを持ってはいるけど、最近は殆ど手を付けてなかったりなので、紙派といえばそうかもしれません。

 とはいえ、数千年ある紙の本の歴史をここ20年くらいしか経ていない電子書籍が超えるのは時期尚早なだけで、将来的には置き換わるとは思います。あと100年くらいたてばですが。

 最も、既に紙の本より電子メディアに慣れた世代が大きくなれば、もっと早い段階で置き換わる可能性もあるかもしれません。最終的には個々人の慣れの問題だと思います。主に紙の本と紙のノートをベースに学習してきた世代と、電子デバイス前提の世代間の優位性なんて、時間を掛ければ測れるのかどうかも怪しいものだし、重要なのは中身のコンテンツで、メディアそのものでもありません。教育の現場では過去の実績が乏しい方式に短時間でドラスティックな変革をするのは難しいですよね。でも、筆者のような昭和生まれ世代が受けてきた教育が、当時としても、まあ多少なりともベターだったんだろうとは思いますが、今の時代ならベターどころかただの時代遅れになっている可能性は十分あります。

 本の話になると一番の問題は、世界的に汎用的で共通した紙メディアを、1企業が開発した電子書籍が置き換えていくという所な気がします。ページ操作等含め、紙レベルで世界的に共通仕様の本のようなフォーマットが電子デバイスで実現できるかというと、、なさそうです。

 書くという要素については、例えばプログラムを今の時代に紙に書いている人は居ないでしょう。結局ファイルにならないと動きませんし。書いた後の活用、または一度書いたものの変更しやすさ等、こちらは既に大部分の作業が紙からPC等の電子デバイスに置き換わっているのが現状では無いでしょうか。

 ただ、マウスでウインドウを操作するような時間は結構無駄なので、特に2画面以上使ってる時にマウスで画面を跨いで行ったり来たりするのは、もうちょっとスムーズな操作は無いものでしょうか。

Webixでイベントを実装する

 今作っているWebのUIに、前回使ったw2uiをまた使おうかと思いましたが、今回対象のUIが他のWebサイトから遷移する前提なので、w2uiでは遷移元のWebサイト画面との違和感が強く、別のJavascriptUIフレームワークを探してみたら、Webixを発見。
 
 すっきりした見た目で違和感なさそうなので、今回はWebixを使ってみることにします。
 
 こちらのサイトに概要が書かれているのでとても参考になりました。

 で、UIの形は出来てきたので、イベントの実装をどうやるのかとドキュメントを見ていくと、ボタンのようなUI Controlでは、下記のようにidを指定してイベントを実装するようです。

ドキュメントが充実しているので、とても助かります。

SpringBoot ファイルアップロードでエラーが出る

 前にSpringBootで作ったWebアプリで、たまにファイルアップロードエラーが出ているとの事でログを確認。

 こんなログが吐かれています。

2020-08-03 16:31:28.826 ERROR org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/xx].[dispatcherServlet] Servlet.service() for servlet [dispatcherServlet] in context with path [/xx] threw exception [Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet request; nested exception is java.io.IOException: The temporary upload location [/tmp/tomcat.1401623156062740234.8080/work/Tomcat/xx/xx] is not valid] with root cause
java.io.IOException: The temporary upload location [/tmp/tomcat.1401623156062740234.8080/work/Tomcat/xx/xx] is not valid

 同事象のコチラを参考にテンポラリの場所を変えてみたのですが、開発端末のWindowsだと、どうも設定した値はデフォルトのテンポラリディレクトリの中に指定したディレクトリに出力しようとしてやっぱりエラーになるような感じでした。

 で、次にコチラを参考にspring.http.multipart.locationとして設定したところ、エラーは解消したようなのですが、非推奨になっています。。

 最後に実行環境のEC2にデプロイしたところ、spring.servlet.multipart.locationで指定してちゃんと動きました。アップロード後にtmpファイルは自動的に浄化されています。

 OSで違うなんて微妙な感じです。。

postgresで履歴テーブルから1時間毎の集計をSQLで取得する

 metabaseでpostgresデータを可視化するようにした所、履歴データが格納されているテーブルから1時間毎の集計を取りたいって事で、SQL1発で出来るんかいなと試行錯誤。

 今回の履歴テーブルはtimestamp型で開始時間と終了時間がセットされていて、誰が何をいつからいつまで実施していたかが記録されている、ような形になっています。これを1時間単位でその時間帯にどのくらい実施していたかをサマリたいという内容です。

具体的にはこんな感じでデータがあります。

selet * from xx_history ;

id, start_time, end_time, user_id, task_id
10, 2020-07-27 16:15:23, 2020-07-27 18:17:43, 432, 2
11, 2020-07-27 18:43:54, 2020-07-27 19:02:04, 154, 4
12, 2020-07-27 19:14:52, 2020-07-27 19:45:21, 432, 5
13, 2020-07-27 19:02:15, 2020-07-27 19:42:53, 154, 4

 これを下記のように1時間毎に時間を合計するような形で抽出したいという事になります。

時間範囲(XX時台), 合計時間
2020-07-27 16:00, 00:44:37
2020-07-27 17:00, 01:00:00
2020-07-27 18:00, 00:33:49
2020-07-27 19:00, 01:13:11

 履歴テーブルの開始時間と終了時間に対して、その時間帯が該当するのは、下記4つのパターンがあり、それぞれ時間の取り方が変わってくるのも面倒なトコロです。

・開始時間と終了時間がその時間範囲内
 → 開始時間から終了時間までの時間
・開始時間が時間範囲より過去だが、終了時間が時間範囲内
 → その時間範囲の開始時刻から終了時間までの時間
・開始時間が時間範囲内だが、終了時間は時間範囲より未来
 → 開始時間からその時間範囲の終了時刻までの時間
・開始時間は時間範囲より過去で、終了時間が時間範囲より未来
 → 1時間固定

 調べているとコチラを発見、postgresにはgenerate_seriesという便利なものがあるようです。

 generate_seriesで1時間毎のレコードを一定期間分生成出来るようなので、履歴テーブルとJoinしてSQLを作ります。

 whereとCaseの条件は一緒なので、Whereの方はもっとコストをかけない条件に見直しした方がよいですね。
 実際はもっと複雑な形になるのですが、とりあえずSQL1発で出来そうな感じです。

「Twilio」で電話をかけてみた

自動で電話をかけたいな。
という話で、Twilioをトライアルしてみました。
要件としては架電して相手に日本語で要件を連絡、通話できたかを判定して・・・というところです。

Twilioにアカウントを作成し、ダッシュボードで電話番号を取得します。
DOCを参照しながら、とりあえず試すだけなので、Javaで適当に書いていきます。
基本的なところは、下記を参考にさせて頂きました。

SMSの発信や電話をかけるところまでは特に問題ありませんでしたが、上記サイトの内容とは現時点で変わっているのか、なかなか日本語を喋ってくれません。
あと、トライアル着信の「アカウントをアップグレードしてね」文句の後に何か押さなくてはいけないというのも暫くして気が付きました。。

どうしたら日本語を喋ってくれるのかと、ドキュメントを見ながらaliceとかを試してみたりしましたが、何かゴニョゴニョ言ってるけど何を言っているのか不明。。
結果的にダッシュボード左メニューのサービス→Programmable Voice→TwiML→テキスト音声変換のText-to-Speechという所に日本語はMizukiだと書いてあったので、やってみるとやっと喋ってくれました。ありがとうMizukiさん。

あと、TwiMLをインターネット上のURLからPOSTで取得できるようにしておく、という謎の制約もかなり厄介だったのですが、こちらも結果的に下記のようにすると必須では無かったようです。

とりあえず要件は満たせそうです。
通話判定はもっとケースが必要ですし、判定待ちをもっとましな形にしたいところですが、トライアルなのでここまで。

ランニングコストがOKになって実際に導入すると決まったら、もうちょっと調べないとですね。

カテゴリー: Java