Skip to content

読み上げ文字数の集計#38

Merged
MORIMORI0317 merged 7 commits into
TeamFelNull:developfrom
yuu1111:feat/tts-count-metrics
May 20, 2026
Merged

読み上げ文字数の集計#38
MORIMORI0317 merged 7 commits into
TeamFelNull:developfrom
yuu1111:feat/tts-count-metrics

Conversation

@yuu1111
Copy link
Copy Markdown
Contributor

@yuu1111 yuu1111 commented May 7, 2026

Summary

Discord議論 (MG / MORIMORI0317) で出ていた「Bot稼働状況・読み上げ量」要件のうち、集計部分の実装

  • Bot/サーバー単位 + 日次 + ボイス別 で読み上げ文字数とメッセージ数をDBに集計
  • SQLite/MySQL双方でアトミックUPSERT (同時書き込みでロストしない)
  • Bot所有者向け /stat コマンド (today/week/all/server)
  • 統計機能を独立コンフィグ・独立DBに分離 (MORIMORI0317 さんのレビュー反映)

カウント単位は 辞書適用 + read_limitカット後に音声合成APIへ渡した最終テキストの String.length() (UTF-16)。外部API課金との相関が高く、計測コストもゼロ。厳密モーラ数は別途検討余地あり。

Prometheusメトリクス公開は本PRから分離しました。本PRがマージされた後、後続PRで対応します (MORIMORI0317 さんの依頼に基づく)。退避ブランチ: feat/tts-prometheus

レビュー反映 (追加対応)

MORIMORI0317 さんのレビュー (Discord, ER図 + config 案) を踏まえて以下を実装:

  1. 独立コンフィグstatistics.enable / statistics.data_base を新設 (本体DBコンフィグと同構造)
  2. DB分離 — 保存先を save_data.db から statistics_data.db (または独立MySQLスキーマ) に分離。本体DAOから tts_count_data を完全削除
  3. パッケージ集約dev.felnull.itts.core.statistics を新設して関連コードを全て集約
  4. ボイス別集計tts_count_datavoice_type_id / voice_category_id FK を追加、voice_type_key / voice_category_key テーブル新設

未リリース機能のため破壊的変更で対応。本体DB側のスキーマには一切変更なし。

新パッケージ構成

core/.../statistics/
├── StatisticsConfig.java
├── StatisticsManager.java          # ライフサイクル管理 (enable=false で no-op)
├── TTSCountRecorder.java           # voice 引数対応
├── TTSCountRecord.java             # voice フィールド追加
├── repository/
│   ├── StatisticsRepository.java
│   ├── StatisticsRepoErrorListener.java
│   └── impl/StatisticsRepositoryImpl.java
└── dao/
    ├── StatisticsDAO.java
    ├── StatisticsDAOFactory.java
    └── impl/{SQLite,MySQL,Base}StatisticsDAO.java + StatisticsDAOFactoryImpl.java

コンフィグ例

"statistics": {
  // 集計を有効にするかどうか
  "enable": true,
  // 統計データの保存先
  "data_base": {
    "type": "sqlite",  // または "mysql"
    "host": "",
    "port": 0,
    "database_name": "",
    "user": "",
    "password": ""
  }
}

主な追加・変更ファイル

  • 新規パッケージ core.statistics.* 配下一式 (DAO / Repository / Manager / Recorder / Config)
  • Config#getStatisticsConfig() 追加 + selfhost/ConfigImpl に JSON5 マッピング追加
  • VoiceAudioSchedulerrecorder.record(..., voice, ...) に変更
  • StatCommandStatisticsManager 経由に切替、無効時は「統計機能は無効になっています」を返す
  • 本体 DAO / SQLiteDAO / MySQLDAO / DataRepository(Impl) から TTSCount 関連を全削除
  • テスト TTSCountStatisticsTest を新パッケージに移動 + ボイス対応

検証

  • ./gradlew clean build (checkstyle 含めて成功)
  • ./gradlew :core:test --tests "*.statistics.*" (8並列スレッド × 50回 incrementCount でロスト無し、ボイス別集計確認)
  • ./gradlew :selfhost:shadowJar

Test plan

  • statistics.enable: true + sqlite で起動 → statistics_data.db が生成される
  • Discord で発話 → tts_count_data に bot/server/voice/date/count が記録される
  • bot_key / server_key / voice_type_key / voice_category_key が正しく FK 解決されている
  • save_data.db 側に tts_count_data存在しない こと
  • /stat today /stat week /stat all /stat server 表示確認
  • statistics.enable: false で再起動 → 統計DBが生成されず /stat が無効化メッセージを返す
  • type: "mysql" (ITTS_STATISTICS スキーマ) で再度上記確認

留意点

  • カウントは UTF-16 の String.length()。要件で言及された「ひらがな1文字=1モーラ」厳密値ではない近似
  • 日付境界はUTC固定
  • Prometheus公開は別PRで対応 (退避ブランチ feat/tts-prometheus に実装済み)
  • 破壊的変更: 既存の save_data.dbtts_count_data がある場合は手動で対処が必要 (未リリース機能のため許容)

yuu1111 added 4 commits May 8, 2026 05:41
Bot/サーバー単位 + 日次で読み上げ文字数とメッセージ数をDBに集計記録する。
SQLite/MySQL双方でアトミックUPSERTにより同時書き込みでもロストしない。

- 新規テーブル tts_count_data (bot_id, server_id, target_date 単位)
- TTSCountRecorder で読み上げ確定時に非同期記録
- Micrometer Prometheus レジストリで /metrics エンドポイント公開
  (デフォルト 127.0.0.1:9095, 設定で無効化可)
- /stat コマンド (today/week/all/server) で Bot 所有者向けに集計表示
- 起動時に DB 累計値を Counter に注入し再起動後も整合
- server_id = 0 をBot全体合計の予約値とし、server_id IS NULLの分岐を削除
  unique制約とON CONFLICT/ON DUPLICATE KEY UPDATE単一クエリに統一しrace conditionを解消
- /stat week でメッセージ数も表示
- TTSCountData#getRecord を追加し、StatCommand での2重SELECTを解消
- 起動時のCounter累計注入を削除 (Prometheusのrate計算を狂わせるため)
- MetricsRegistry の getOrCreate{Char,Message}Counter を共通化
- DataRepositoryImpl の sum 系ボイラープレートをwithConnectionヘルパで集約
- botId解決を getBot().getBotId() に統一
- RELATIVE_TIME_FORMAT を BaseCommand に集約
- PrometheusHttpExposer に固定スレッドプールを設定し詰まりを回避
- MetricsRegistryをinterface化しPrometheus実装とNoOp実装を分離
  メトリクス無効時もnon-nullになり呼び出し側のnullチェックを削除
- ITTSRuntimeUseにgetTTSCountRecorder/getMetricsRegistryのdefaultを追加
  VoiceAudioSchedulerのITTSRuntime.getInstance()プルを既存パターンに統一
- ITTSRuntime#initMetricsを生成と起動に限定し、シャットダウンフック登録を
  registerShutdownHooksに分離
集計機能のマージ後に別PRで対応する方針のため、
Prometheus関連の実装を本PRから取り除く

- core/metrics配下を削除
- MetricsConfigを削除
- ITTSRuntime/Use・Config・selfhost ConfigImplから参照を除去
- Micrometer依存を削除
- TTSCountRecorderはDB書き込みのみに簡略化
@yuu1111 yuu1111 changed the title 読み上げ文字数の集計とPrometheusメトリクス公開 読み上げ文字数の集計 May 7, 2026
@yuu1111 yuu1111 mentioned this pull request May 7, 2026
6 tasks
yuu1111 added 3 commits May 9, 2026 19:14
- core.statistics パッケージを新設し、TTSCount 関連を集約
- statistics.enable / statistics.data_base コンフィグを追加
- 保存先を save_data.db から statistics_data.db (または独立MySQLスキーマ) に分離
- 集計粒度にボイス別 (voice_type / voice_category) を追加
- 本体 DAO/Repository から TTSCount 関連を全削除
@yuu1111 yuu1111 force-pushed the feat/tts-count-metrics branch from 32eb81a to ce4f0f9 Compare May 17, 2026 11:31
@yuu1111 yuu1111 marked this pull request as ready for review May 18, 2026 11:03
@MORIMORI0317 MORIMORI0317 merged commit 628e280 into TeamFelNull:develop May 20, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants