OmniAICreator/Qiita-1.07M huggingface dataset:
GA4 と BigQuery のデータ連携手順

Google Analytics 4（GA4）と Google BigQuery を連携させることで、より詳細なデータ分析が可能になります。本記事では、GA4 から BigQuery へのエクスポートを設定する方法を体系的に解説します。

## 1. GA4 と BigQuery の連携とは？

GA4 では、Google Cloud の BigQuery にデータをエクスポートし、SQL クエリを用いて詳細な分析が可能です。これにより、標準レポートでは取得できないデータの深堀りや、他のデータと組み合わせた分析ができます。

## 2. 連携の前提条件

GA4 と BigQuery を連携するには、以下の条件を満たしている必要があります。

- **GA4 プロパティを所有**していること
- **Google Cloud プロジェクトを作成済み**であること
- **BigQuery の課金設定が完了**していること（無料枠を超えた場合は料金が発生）
- **適切な権限**（編集者または管理者権限）を持っていること

## 3. BigQuery 側の設定

### 3.1 Google Cloud プロジェクトの作成

1. [Google Cloud Console](https://console.cloud.google.com/) にアクセス
2. プロジェクトを作成（または既存のプロジェクトを使用）
3. BigQuery API を有効化

### 3.2 BigQuery の権限設定

GA4 から BigQuery へデータをエクスポートするには、**BigQuery Data Editor** のロールを付与する必要があります。

1. [Google Cloud Console](https://console.cloud.google.com/) で IAM 設定を開く
2. **GA4 のサービスアカウント**（Google Analytics のシステムが自動で使用するアカウント）を探す
3. **BigQuery Data Editor** のロールを付与

## 4. GA4 側の設定

### 4.1 BigQuery へのリンク設定

1. [Google Analytics 管理画面](https://analytics.google.com/) にアクセス
2. **GA4 プロパティ**を選択
3. **[管理] > [BigQuery のリンク]** を開く
4. **[リンクを作成]** をクリック
5. **GCP プロジェクト**を選択（作成済みのプロジェクトを指定）
6. **データのエクスポート頻度**（1日1回 または ストリーミング）を選択
7. **保存して完了**

## 5. BigQuery でのデータ確認

設定完了後、BigQuery のコンソールで `analytics_<プロパティID>` というデータセットが作成されます。

```sql
SELECT *
FROM `プロジェクトID.analytics_プロパティID.events_*`
WHERE event_name = 'purchase'
LIMIT 10;
```

上記のクエリで購入イベントを確認できます。

## 6. 連携後の活用方法

- **詳細なユーザー分析**（セッション時間、エンゲージメント率の深掘り）
- **広告データとの統合**（Google Ads とのデータ統合）
- **ダッシュボード構築**（Looker Studio などと連携）

## 7. まとめ

GA4 と BigQuery を連携することで、より柔軟で高度なデータ分析が可能になります。設定は簡単ですが、権限設定やデータの管理には注意が必要です。

### 関連リンク

- [Google Cloud BigQuery の概要](https://cloud.google.com/bigquery/docs/introduction)
- [BigQuery のクイックスタートガイド](https://cloud.google.com/bigquery/docs/quickstarts)
- [GA4 の BigQuery 連携公式ドキュメント](https://support.google.com/analytics/answer/9268042?hl=ja)
Webdis: Nginx のリバースプロキシーでアクセス

こちらのページを参考にしました。
[NginxでURLエンコードされたパスを含むURLをデコードしないでバックエンドのAPIサーバーにプロキシしたい](https://qiita.com/ko-he-8/items/ccd47c1159ea0a21d66c)

## Webdis の動作確認

```bash
curl http://localhost:7379/KEYS/*
```

```bash
http http://localhost:7379/KEYS/*
```

## Nginx の動作確認

```bash
sudo nginx -t
```

```bash
sudo systemctl status nginx
```

## Nginx の設定変更

```text:/etc/nginx/sites-available/default
server {
	listen 80 default_server;
	listen [::]:80 default_server;

    （省略）

    location /redis/ {
        set $proxy_uri $request_uri;
        if ($request_uri ~ ^/redis(.*)$) {
            set $proxy_uri $1;
        }
        proxy_pass http://127.0.0.1:7379$proxy_uri;
	}
}
```

設定の確認

```bash
sudo nginx -t
```

Nginx の再起動

```bash
sudo systemctl restart nginx
```

## アクセス

```bash
curl http://localhost/redis/KEYS/*
```

```bash
http http://localhost/redis/KEYS/*
```

SCAN を使う場合

```bash
curl http://localhost/redis/scan/0
```

```bash
http http://localhost/redis/scan/0
```
Zabbixが遅かったのでDBの「innodb_buffer_pool_size」を見直した話

# 

Zabbixを利用していて、仕様はそこそこなのにやたら遅い。Webフロントの詰まりや、"Utilization of history syncer processes over 75%"などの警告が出る。

CPUもメモリも優先度余裕あるのに…これ、DB周りが原因かもと詳しく調べてみた。

## 発見したポイント

MariaDBの `innodb_buffer_pool_size` が、なんと **128MB** のまま。これが大問題だった。

## innodb_buffer_pool_size って何者なのか

ざっくり言うと:

> 「InnoDB のデータやインデックスをメモリに保持するためのキャッシュプールの大きさ」

データベースの実態はディスクベース。これをこまめに読み書きするのは非実用的なので、InnoDBは可能な限りメモリにだけ管理させる。

その主役が `innodb_buffer_pool` であり、そのサイズを指定するのが `innodb_buffer_pool_size`。


## 小さいと何が起きるのか

Zabbixの場合、つまり:

- 多数の INSERT (history 系) が DB に飛ぶ
- MariaDBがそれをメモリでうまくさばけない
- ディスクへの直接書きが増える
- 結果、I/O で詰まる

これが「Utilization of history syncer processes over 75%」の原因である可能性大。

## 実際の現場

```bash
# grep StartHistoryPollers /etc/zabbix/zabbix_server.conf
StartHistoryPollers=50

# MariaDB側
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
-> 128MB
```

完全にバランスがおかしい状態。。。


## 解決策

**`innodb_buffer_pool_size` を増やす**
   ```ini
   # /etc/my.cnf
   [mysqld]
   innodb_buffer_pool_size = 4G
   ```
   メモリに余裕があれば 8G もOK

**`StartHistoryPollers` を減らす**
   ```ini
   StartHistoryPollers=12
   ```
DBが受け渡れる範囲に要調整

**`innodb_log_file_size` も見直し**
   ```ini
   innodb_log_file_size = 512M
   ```
   書き込み性能の向上

## まとめ

- Zabbixが遅い時は DB周りも見るべし
- `innodb_buffer_pool_size` は **InnoDBデータベースの性能の要**
- 小さすぎると、いくらCPUやメモリに余裕があっても、Zabbixは遅くなる
- 詰まってるのは「ZabbixではなくMariaDB」かも
Linux(CentOS7)が起動しなくなった(Generating "/run/initramfs/rdsosreport.txt")際の対処

突然の停電でデスクトップPCが強制終了・・・
その後、PC内の仮想PC(CentOS7)が起動しなくなってしまいました。

```
[    2.463483] XFS (dm-0): Internal error XFS_WANT_CORRUPTED_GOTO at line 1635 o
f file fs/xfs/libxfs/xfs_alloc.c.  Caller xfs_free_extent+0xfc/0x130 [xfs]
[    2.465295] XFS (dm-0): Internal error xfs_trans_cancel at line 990 of file f
s/xfs/xfs_trans.c.  Caller xlog_recover_process_efi+0x16b/0x190 [xfs]
[    2.466871] XFS (dm-0): Corruption of in-memory data detected.  Shutting down
 filesystem
[    2.467677] XFS (dm-0): Please umount the filesystem and rectify the problem(
s)
[    2.468373] XFS (dm-0): Failed to recover EFIs

Generating "/run/initramfs/rdsosreport.txt"


Entering emergency mode. Exit the shell to continue.
Type "journalctl" to view system logs.
You might want to save "/run/initramfs/rdsosreport.txt" to a USB stick or /boot
after mounting them and attach it to a bug report.
```
どうやらブート領域のdm-0が破損している様子
以下のコマンドで修正しました
```
:/# xfx_repair -Lv /dev/dm-0
```
無事、起動出来るようになりました！
ネットワーク機器の種類と役割

# ネットワーク機器の種類と役割完全ガイド

## 1. ネットワーク機器の概要
ネットワーク構築に欠かせない機器の種類と特徴をわかりやすく解説します。

## 2. ネットワークアダプター
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3515709/49cb5c79-7709-4777-9a99-634c226104c5.png)


### 2.1 主な役割
- **データ変換**：電気信号とデジタルデータの相互変換（例：スマホの充電器が交流を直流に変換するように）
- **通信管理**：データの一時保管と適切なタイミングでの送信（交通整理員のような役割）
- **プロトコル実装**：通信規則の遵守（国際会議での通訳者のような存在）

### 2.2 主な種類
#### 接続方式別

| 種類 | 使用例 | 特徴 |
|------|--------|------|
| PCI-E | ゲーミングPC | 高速通信可能 |
| USB | ノートPC用 | 持ち運び便利 |


#### 通信速度別
- **1Gbps**：一般的なオフィスネットワーク
- **40Gbps**：データセンター用（新幹線と自転車の速度差のようなもの）



## 3. 信号増幅機器
### 3.1 リピーター
**実用例**：戸建て住宅のWi-Fi中継器

- **長所**：
  - 簡単設置（コンセント差すだけ）
  - 低遅延
  - 低コスト

- **短所**：
  - エラー信号も増幅（コピー機で汚れまで拡大するように）
  - 接続数制限あり

### 3.2 ハブ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3515709/bcd36c2e-12aa-41c5-8a93-c79aaffe6c4c.png)


**イメージ**：昔の電話交換台（全員の会話が筒抜け）

- **特徴**：
  - 全ポートで帯域共有（1本の水道をみんなで共有）
  - 半二重通信（一方通行の橋）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3515709/5649eb66-5a94-43da-876e-1a072bfc9ef6.png)


## 4. インテリジェント接続機器
### 4.1 ブリッジ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3515709/62cb38ef-01a9-4d40-97a4-faadf74fe767.png)


**実例**：マンションの防犯ゲート（許可された住民のみ通過）

- **メリット**：
  - 不要な通信を遮断
  - 異なる規格のネットワークを接続可能

- **デメリット**：
  - 処理に時間がかかる
  - 大規模ネットワーク不向き

### 4.2 スイッチ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3515709/a7c8bbd7-121c-4b2d-ac12-0fd6f71f91a4.png)


**イメージ**：現代の電話交換システム（直接接続）

- **動作原理**：
  1. 住所録作成（MACアドレス学習）
  2. 効率的な配送（宅配便の仕分けセンター）
  3. 不明先は全戸配布（町内会の回覧板）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3515709/39b30c3f-1d4e-4c45-9dc4-163504a1a53d.png)

#### ハブとの比較表


| 特徴            | ハブ              | スイッチ           |
|-----------------|-------------------|-------------------|
| 通信方式        | 全員放送          | 個別配送          |
| 速度            | 最大100Mbps       | 1Gbps～40Gbps    |
| 遅延            | 大きい            | 小さい            |
| 価格            | 安価(3,000円～)   | 高価(10,000円～)  |


## 5. ルーター
**たとえ**：郵便局の仕分けセンター

- **主な機能**：
  - 最適経路選択（カーナビのような経路探索）
  - ブロードキャスト遮断（アパートの各部屋を隔てる壁）
  - セキュリティ機能（門番のような存在）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3515709/6db3ca01-8573-4a99-a8b7-62df89f49be8.png)



### 5.1 代表的な活用例
- **家庭用**：Wi-Fiルーター（複数端末をインターネット接続）
- **企業用**：VPN接続による支店間通信

## 6. 機器比較総まとめ



| 機器       | 対応層 | 分離可能領域 | 速度目安     | 価格帯       |
|------------|--------|--------------|-------------|-------------|
| ハブ       | 物理層 | 衝突ドメイン | 100Mbps     | ～5,000円   |
| スイッチ    | データリンク層 | 衝突ドメイン | 10Gbps      | 10,000円～  |
| ルーター    | ネットワーク層 | ブロードキャストドメイン | 1Gbps      | 5,000円～   |


## 7. 実践的な選び方
1. **家庭用**：ルーター内蔵スイッチ（5,000円程度）
2. **小規模オフィス**：24ポートスイッチ（30,000円程度）
3. **大規模企業**：レイヤ3スイッチ（100,000円～）

**失敗例**：
- 中継器を4台以上接続→通信速度が1/10に低下
- 古いハブを再利用→4K動画が途切れる

ネットワーク機器選びのポイントは「必要な通信速度」と「接続機器数」を正確に把握することです。適切な機器選択で、快適なネットワーク環境を構築しましょう！
AWS アカウント間で DB スナップショットを移行するときにはキー設定に注意

DB がデフォルトキーで暗号化されていると、スナップショットを移行先に共有しても復元できなかった、という話。

ユーザー管理キーの場合の移行方法は記事がたくさんあるので、デフォルトキーが使われている場合の対処だけ紹介。

アカウント閉鎖まで行う時は移行元のスナップショットが消えたりアクセスできなくなったりがあるので、移行先で復元して改めてスナップショットを取っておくのが良い。
そのスナップショットが復元できるところまで確認しておくと盤石

## 要点

デフォルトキーで暗号化されていると移行先で操作できなくなるため、ユーザー管理キーでの暗号化で作り直してから移行した。

## 状況

アカウント閉鎖を前提にデータの保存をしようとしていて、別のアカウントにスナップショットを共有した。
だが、移行先アカウントでは暗号化キーへのアクセス権がなくて復元もコピーもできなかった。

暗号化キーがデフォルトキーだったため、別アカウントへの共有設定ができなかった。

## 解決策

移行元で暗号化キーを変えたデータベースを作成してスナップショットを取り直した。

ユーザー管理キーであれば設定変更が可能で別アカウントとの共有もできるので、キーを変えてDBを作り直した。

1. RDS で、対象DBのスナップショットを作成
2. KMS でユーザー管理キーに移行先アカウントからのアクセス権を付与（ブラウザから作成すると共有アカウントの設定欄があるので、新しく作るとわかりやすい）
3. RDS で、2 のキーを指定してスナップショットを復元
4. 復元した DB のスナップショットを作成
5. 4 のスナップショットを移行先に共有
6. 移行先アカウントでスナップショットを復元して、復元したDBのスナップショットを作成

## キーの指定について

DB スナップショットは DB と同じ暗号化キーを使って作成されるようで、キーの指定ができない。
少なくともブラウザコンソールでは指定できなかった。
【TypeScript】 Parameter Propertieを使ってclass作成を効率化する

# はじめに
TypeScriptのクラス作成を学習していて、`Parameter Properties`という機能を知りました。従来のクラス定義方法と比較し、Parameter Propertiesの利点を備忘録としてまとめます。

# クラス（class）定義作成方法
### フィールド定義＋コンストラクタでフィールドを初期化

クラス内で以下の定義を行います。
・ フィールド
・ コンストラクタ

実際にクラスからオブジェクトを作成する場合（インスタンス化）、引数に値を設定することで作成可能です。

```typescript:todo.ts
export class Todo {
  // フィールド定義
  public id: number;
  public title: string;
  public done: boolean;
  public created_at: string;

  // コンストラクタ
  constructor(id: number,  title: string, done: boolean, created_at: string) {
    this.id = id;
    this.title = title;
    this.done = done;
    this.created_at = created_at;
  }
}

// インスタンス化
const newTodo = new Todo(1, "title", true, "20250330");
console.log('newTodoだよ', newTodo);
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3993509/d69ec94f-e765-41ff-b4d1-3874d5ce0d67.png)

個人的に感じたフィールド定義でクラス定義した場合のメリット・デメリット
メリット：フィールドを最初に定義するので、どの値を定義したクラスかわかりやすい
デメリット：冗長する

### Parameter Propertiesで定義する

コンストラクタの引数に、アクセス修飾子をつけることで、フィールドを自動で定義してくれます。
TypeScriptの`Parameter Properties`という機能を使うことで冗長化しない


```typescript:todo.ts
// クラスの作成
export class Todo {
  constructor(
    public id: number,
    public title: string,
    public done: boolean,
    public created_at: string,
  ){}
}

// インスタンス化
const newTodo = new Todo(1, "title", true, "20250330");
console.log('newTodoだよ', newTodo);
```

# おわりに
`Parameter Properties`の定義方法は最初どういこと？となりました。
使い方を理解した後はこちらのほうが簡潔でわかりやすく記載できるなと感じました。

# 参考

https://typescriptbook.jp/reference/object-oriented/class/fields#%E3%82%B3%E3%83%B3%E3%82%B9%E3%83%88%E3%83%A9%E3%82%AF%E3%82%BF%E3%82%92%E7%94%A8%E3%81%84%E3%81%9F%E3%83%95%E3%82%A3%E3%83%BC%E3%83%AB%E3%83%89%E3%81%AE%E5%88%9D%E6%9C%9F%E5%8C%96

https://www.typescriptlang.org/docs/handbook/2/classes.html#parameter-properties
WORK.COMを有効にしたScratch Orgを作成する

:::note warn
Work.comは廃止されたためScratch Orgも作成できなくなってしまいました。。。
https://help.salesforce.com/s/articleView?id=000391089&type=1
:::

## 事前準備

1. DevHub組織を作成する
    - [Developer Edision](https://www.salesforce.com/form/developer-signup/?d=pb)もしくは本番環境を用意
2. DevHubを有効化
    - 「設定 > Dev Hub」の「Dev Hub を有効化」を有効にする
3. Salesforceプロジェクトフォルダのスクラッチ組織定義ファイル（`config/project-scratch-def.json`）を編集する

### スクラッチ組織定義ファイルの例

```json:project-scratch-def.json
{
  "orgName": "Document System App",
  "country": "JP",
  "edition": "Enterprise",
  "language": "ja",
  "features": [
    "Communities",
    "EnableSetPasswordInApi",
    "PersonAccounts",
    "WorkplaceCommandCenterUser",
    "ForceComPlatform"
  ],
  "settings": {
    "communitiesSettings": {
      "enableNetworksEnabled": true
    },
    "experienceBundleSettings": {
      "enableExperienceBundleMetadata": true
    },
    "languageSettings": {
      "enableTranslationWorkbench": true,
      "enableEndUserLanguages": true
    },
    "lightningExperienceSettings": {
      "enableS1DesktopEnabled": true
    },
    "mobileSettings": {
      "enableS1EncryptedStoragePref2": false
    },
    "surveySettings": {
      "enableSurvey": true
    }
  }
}
```

- [独自のスクラッチ組織定義ファイルを作成する | Developers](https://developer.salesforce.com/docs/atlas.ja-jp.sfdx_dev.meta/sfdx_dev/sfdx_dev_scratch_orgs_def_file.htm)
- [Work.com 開発組織の設定 | Developers](https://developer.salesforce.com/docs/atlas.ja-jp.workdotcom_dev_guide.meta/workdotcom_dev_guide/wdc_cc_setup_dev_org.htm)
- [設定 メタデータAPI  | Developers](https://developer.salesforce.com/docs/atlas.ja-jp.api_meta.meta/api_meta/meta_settings.htm)

## 手順

1. スクラッチオルグの作成
    - `sf org create scratch -d -f config/project-scratch-def.json -a scratch_org_name`
2. スクラッチオルグユーザーのパスワードを生成する
    - `sf org generate password`
3. [WORK.COMインストールサイト](https://install.work.com/products)にアクセスして、スクラッチオルグユーザーのID/PASSを入力し、必要なパッケージをインストールする

:::note
**CLIでパッケージをインストールする方法**
パッケージのインストール後に`sf package installed list`を実行することでPackage VersionIdを確認することができます。
このIDを使用してpackage installを実行することで、CLIからパッケージをインストールできます。
`sf package install --package 04t4R000001lhpCQAQ`

![スクリーンショット 2025-04-01 11.48.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125621/f3bd0c6c-e7a2-4337-810b-626daf2a75c0.png)
:::

## 参考

- [クイックスタート: Salesforce DX | Trailhead](https://trailhead.salesforce.com/ja/content/learn/projects/quick-start-salesforce-dx)
- [スクラッチ組織 | Developers](https://developer.salesforce.com/docs/atlas.ja-jp.sfdx_dev.meta/sfdx_dev/sfdx_dev_scratch_orgs.htm)
- [設定 メタデータAPI | Developers](https://developer.salesforce.com/docs/atlas.ja-jp.api_meta.meta/api_meta/meta_settings.htm)
- [Work.com 開発者ガイド | Developers](https://developer.salesforce.com/docs/atlas.ja-jp.workdotcom_dev_guide.meta/workdotcom_dev_guide/wdc_cc_overview.htm)
- [orgInit.sh | Github](https://github.com/forcedotcom/WorkDotCom-Partners/blob/master/orgInit.sh)
- [Salesforce CLI チートシート | Qiita](https://qiita.com/TaaaZyyy/items/d6780394df2b12dfce64)
2025年人気No.1のNext.jsで、最新ツールとウェブを作る！ | シリーズ総概観

## シリーズの目的
このシリーズは、2025年のウェブ開発トレンドをリードするNext.jsを使って、ゼロから実践的なウェブサイトを構築するプロセスを段階的に解説することを目的としています。初心者から中級者までが、最新技術を活用してモダンなブログサイトを作り上げるスキルを身につけられるよう設計されています。

---

## シリーズの概要
全10エピソードで構成され、基本的な環境設定から機能拡張までを網羅しています。以下は各エピソードの要点です：

### エピソード1: 紹介と環境設定
- Next.jsの概要と2025年のウェブ開発における重要性を理解。
- 開発環境をセットアップし、最初のプロジェクトを作成。

### エピソード2: ルーティングとページの基本
- App Routerを使ったルーティングを習得。
- 静的ページと動的ページを作成し、`Link`でナビゲーションを強化。

### エピソード3: スタイリングの基本
- Tailwind CSSを統合し、デザインを適用。
- 共通レイアウトを`layout.tsx`で構築。

### エピソード4: データ取得とAPIルート
- Server ComponentsやSSG/SSRでデータを取得。
- 自作APIルートを作成し、動的コンテンツを扱う。

### エピソード5: Markdownでブログを構築
- Markdownを使って静的ブログを実装。
- 投稿リストと詳細ページを構築。

### エピソード6: データベースの統合
- Supabaseを導入し、データベースを接続。
- CRUD操作で動的ブログにアップグレード。

### エピソード7: フォームと認証
- `react-hook-form`でフォームを作成。
- NextAuth.jsでGoogleログインを追加し、ページを保護。

### エピソード8: パフォーマンスとSEOの最適化
- `next/image`で画像を最適化。
- メタデータとISRでSEOとパフォーマンスを向上。

### エピソード9: ウェブサイトのデプロイ
- Vercelにプロジェクトをデプロイ。
- カスタムドメインを設定し、公開。

### エピソード10: 機能拡張とメンテナンス
- 検索機能や分析ツールを追加。
- デバッグと長期運用のノウハウを習得。

---

## 学べる技術と成果物
このシリーズを通じて、以下の技術を習得できます：
- **Next.js**: App Router、Server Components、APIルート。
- **スタイリング**: Tailwind CSSで迅速かつモダンなデザイン。
- **データ管理**: MarkdownとSupabaseを使った静的・動的コンテンツ。
- **認証**: NextAuth.jsでセキュアなログイン。
- **最適化**: パフォーマンスとSEOのベストプラクティス。
- **デプロイ**: Vercelでの本番環境公開。

**成果物**：
- 認証付きの動的ブログサイト。
- 検索機能や分析ツールを備えた完成度の高いウェブアプリ。
- カスタムドメインで公開された本番環境。

---

## シリーズの価値
- **実践的**: 単なる理論ではなく、実際に動くウェブサイトを作り上げる。
- **最新技術**: 2025年のトレンド（Next.js 13+、Server Componentsなど）を反映。
- **ステップごとの学習**: 初心者でも無理なく進められる構成。

---

## 各エピソードへのリンク
以下に各エピソードへのリンクをまとめました。ぜひ振り返って復習してください：
- [エピソード1: 紹介と環境設定](https://qiita.com/BNR-Long/items/e9cdf626edb8e46aa4b7)
- [エピソード2: ルーティングとページの基本](https://qiita.com/BNR-Long/items/ab62e7348a5e760d0c54)
- [エピソード3: スタイリングの基本](https://qiita.com/BNR-Long/items/a454b14951a113d96b19)
- [エピソード4: データ取得とAPIルート](https://qiita.com/BNR-Long/items/4ba7d6e30dbc4ec9c46b)
- [エピソード5: Markdownでブログを構築](https://qiita.com/BNR-Long/items/cf70a65eaddf391db876)
- [エピソード6: データベースの統合](https://qiita.com/BNR-Long/items/d56a7d5239a234dfb4f7)
- [エピソード7: フォームと認証](https://qiita.com/BNR-Long/items/784828464026b7cb1f21)
- [エピソード8: パフォーマンスとSEOの最適化](https://qiita.com/BNR-Long/items/c06b1f431e4f8a759e50)
- [エピソード9: ウェブサイトのデプロイ](https://qiita.com/BNR-Long/items/6b956d4901eeb97ae5d3)
- [エピソード10: 機能拡張とメンテナンス](https://qiita.com/BNR-Long/items/6c4a9c08606e1280eea4)

※リンクは後で追加してください。

---

## 最後に
このシリーズは、Next.jsを軸にウェブ開発の全工程を体験する旅でした。学んだスキルを活かして、独自のプロジェクトを立ち上げたり、さらに機能を追加したりしてみてください。2025年のウェブ開発の世界で、あなたのアイデアが輝くことを願っています！

この総概観が役に立ったと思ったら、ぜひ「いいね」を押して、ストックしていただければ嬉しいです！シリーズを振り返りながら、次のステップへ進んでください！
watsonx.ai & watsonx.governanceで3rd partyのLLMによるRAGを評価③

先ず、3rd ParthのLLMによるRAGのための検証データを作成しました。
https://qiita.com/yono1o12/items/01fc190c1facc65b9b76

次に、3rd PartyのLLMに対して、プロンプトテンプレートをWatsonx.governance上でモデル本体から切り離して（detached）登録・評価できるようにしました。
https://qiita.com/yono1o12/items/1299c718dd4d089ef449

今回は、検証データを利用して、watsonx上で3rd partyのLLMよるRAGを検証します。

先ず検証データをダウンロード。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3756172/a49cc1f8-2709-4acf-99ce-acae67f8c24f.png)

Excelで中身確認すると、Context、質問、回答、生成された回答の４つが含まれた検証データであることを確認できる（UTF-8なので文字化けしているのはスルーでOK）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3756172/b259232e-c689-4bb7-ad59-570b61a3cccf.png)

作成したプロンプトテンプレートからEvalute（検証）へ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3756172/bbba3c98-ec81-4ece-b45d-4b8353906cbe.png)

Questionにquestion、Contextにcontext、プロンプトテンプレートの引数をそれぞれ選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3756172/cdbe5b36-ceba-400e-90cc-5bda7332128e.png)

検証データをUploadして、検証データの列名をそれぞれ選択。参照出力は検証データのなかにあるAnswer（正解となる回答）を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3756172/5f8d5a60-ed19-4a94-8bbb-1cc95228f4a3.png)

評価を開始。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3756172/e2798238-de1c-46f8-bafe-a8698f530578.png)

しばし待つ。。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3756172/5f5858f2-2792-4021-939d-37642a756898.png)

かんりょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3756172/3ec05ae9-70d7-4e05-91c6-657de6336d5c.png)
watsonx.ai & watsonx.governanceで3rd partyのLLMによるRAGを評価②

以下で、3rd ParthのLLMによるRAGのための検証データを作成しました。
https://qiita.com/yono1o12/items/01fc190c1facc65b9b76

次に、3rd PartyのLLMに対して、プロンプトテンプレートをWatsonx.governance上でモデル本体から切り離して（detached）登録・評価できるようにします。これにより、プロンプトの品質やリスクを、LLM本体とは独立してチェック・改善できるようになります。detachはwatsonx.ai/Watson Studioで以下を実行すればOKです。尚、以下はOpenShift上にインストールされたwatsonx.aiで実施していますが、SaaSのwatsonx.aiもCloudPakforDataConfig()の以外は同じ手順で可能なはずです。


```python
!pip install --upgrade ibm-aigov-facts-client | tail -n 1
```

```python
AZURE_OPENAI_ENDPOINT = "<INPUT YOUR AZURE_OPENAI_ENDPOINT>"
AZURE_OPENAI_DEPLOYMENT_NAME = "<INPUT YOUR AZURE_OPENAI_DEPLOYMENT_NAME>"
```

```python
CPD_URL = "<INPUT YOUR CPD_URL>"
CPD_USERNAME = "<INPUT YOUR CPD_USERNAME>"
CPD_API_KEY = "<INPUT YOUR CPD_API_KEY>"
```

```python
import os

PROJECT_ID = os.environ.get('PROJECT_ID')
print(PROJECT_ID)
```

```python
from ibm_aigov_facts_client import (
    AIGovFactsClient, CloudPakforDataConfig,
    DetachedPromptTemplate, PromptTemplate
)
from ibm_aigov_facts_client.utils.enums import Task

creds = CloudPakforDataConfig(
    service_url=CPD_URL,
    username=CPD_USERNAME,
    api_key=CPD_API_KEY
)
facts_client = AIGovFactsClient(
    cloud_pak_for_data_configs=creds,
    container_id=PROJECT_ID,
    container_type="project",
    disable_tracing=True
)
```

```python
PROMPT_TEMPLATE = """# System:
Answer the question based on the context.

# Context:
{context}

# Question
{question}

# Answer:
""".strip()
```

```python
detached_information = DetachedPromptTemplate(
    prompt_id="detached-aoai-prompt",
    model_id=f"azure/{AZURE_OPENAI_DEPLOYMENT_NAME}",
    model_provider="Azure OpenAI",
    model_name="GPT-3.5-turbo",
    model_url=AZURE_OPENAI_ENDPOINT,
    prompt_url="prompt_url",
    prompt_additional_info={"model_owner": "Microsoft", "model_version": "gpt-3.5-turbo-1106"}
)
```

```python
prompt_name = "Detached prompt for Azure OpenAI GPT-3.5-turbo TEST2"
prompt_description = "A detached prompt for RAG using Azure OpenAI's GPT-3.5-turbo model TEST2"

# define parameters for PromptTemplate
prompt_template = PromptTemplate(
    input=PROMPT_TEMPLATE,
    prompt_variables={"context": "", "question": ""},
)
pta_details = facts_client.assets.create_detached_prompt(
    model_id=f"azure/{AZURE_OPENAI_DEPLOYMENT_NAME}",
    task_id="retrieval_augmented_generation",
    name=prompt_name,
    description=prompt_description,
    prompt_details=prompt_template,
    detached_information=detached_information
)
project_pta_id = pta_details.to_dict()["asset_id"]
print(f"Detached Prompt template ID: '{project_pta_id}'")
```

watsonx.aiのプロジェクトで切り離されたプロンプトテンプレートが作成されていればOkです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3756172/ac8ccafb-ec53-487b-97cd-222bfad4f81d.png)
Knowledge Base RAGアプリケーションの技術解説

## 概要

このサンプルコードは、Streamlitを使ったRAG（Retrieval Augmented Generation）アプリケーションの実装例です。RAGとは、LLMの回答生成を外部知識で拡張する手法で、より正確で信頼性の高い回答を得るために活用されています。

## アーキテクチャ

![RAGの概念図]

1. **ユーザーからの入力**
   - Streamlit UIから質問を受付
   - 使用するLLMモデル（Claude 3 SonnetまたはHaiku）を選択

2. **知識検索（Retrieval）**
   - Amazon Knowledge Basesから関連ドキュメントを検索
   - ハイブリッド検索（ベクトル + キーワード）で上位30件を取得

3. **コンテキスト拡張プロンプト生成（Augmentation）**
   - 検索結果を「context」としてプロンプトに挿入
   - 検索結果がない場合の回答方法も指定

4. **回答生成（Generation）**
   - Amazon Bedrockを通じてClaude 3モデルに問い合わせ
   - 検索結果を参考にした回答を生成

## 主要コンポーネント

### 1. UI層 (Streamlit)
```python
st.title("Knowledge base RAGアプリケーションサンプル")
use_model = st.selectbox("使用するモデルを選択してください",("Sonnet","Haiku"))
user_input = st.text_input("質問")
send_button = st.button("送信")
```

### 2. レトリーバー (Amazon Knowledge Bases)
```python
retriever = AmazonKnowledgeBasesRetriever(
    knowledge_base_id="XXXXXXXXXX",
    retrieval_config={
        "vectorSearchConfiguration": {
            "numberOfResults": 30, 
            "overrideSearchType": "HYBRID"
        }
    }
)
```

### 3. LLM (Claude 3 via Amazon Bedrock)
```python
LLM = ChatBedrock(model_id=modelId, model_kwargs={"temperature": 0, "max_tokens": 4000})
```

### 4. RAGチェーン (LangChain)
```python
chain = {"context": retriever, "question": RunnablePassthrough()} | prompt | LLM | StrOutputParser()
```

## 技術的ポイント

1. **ハイブリッド検索**
   - ベクトル検索（意味的類似性）とキーワード検索（構文的一致）を組み合わせて検索精度を向上

2. **プロンプトエンジニアリング**
   - システムプロンプトで明確な指示を与え、知識ベースの情報と一般知識を区別

3. **パラメータチューニング**
   - temperature=0で決定論的な回答を生成（再現性向上）
   - 最大トークン数や検索結果数の適切な設定

4. **LangChainパイプライン**
   - 複数のコンポーネントを統合したシンプルなデータフロー
   - `|` 演算子を使用した直感的なチェーン構築

## 拡張ポイント

- 検索結果のフィルタリングやリランキング
- 回答品質の評価メカニズム
- ユーザーフィードバックの取り込み
- 多言語対応
【ChatGPT＋4o Image Generation】で画像をはめ込む方法です。


　どうも、カーブミラーです。

　今回は、4o Image Generationで画像をはめ込む方法です。

:::note info
本記事は、ChatGPT（Plus版）
で行なっております。
画像はあります。　あしからず。
:::
　ChatGPT等の動作状況を知らせる
　　OpenAIのステータスページ。
　　　[OpenAIステータス](https://status.openai.com/)
***
　こちらも載せますね。
　　[ChatGPTが使えない？ログインできない・反応しない原因やエラー時の対処法を解説](https://aismiley.co.jp/ai_news/chatgpt-error-resolution-explanation/)
***
　まずは、ニュースです。

　サムがポストしました。
　　[サム・アルトマンポスト](https://x.com/sama/status/1906771292390666325?t=nNN1UdZct9uAeTBkZqcLPw&s=19)

***（ChatGPT）***
ChatGPTのローンチ（26か月前）は、僕がこれまで見た中でも最もクレイジーでバイラルな瞬間の一つだった。
当時、最初の5日間で100万人のユーザーが増えたんだ。

でも今は、たった1時間で100万人が増えてる。
***

　次もサムです。
　　[サム・アルトマンポスト](https://x.com/sama/status/1906867488320843823?t=FbKrWwewvGAOABUlzeu9yw&s=19)

***（ChatGPT）***
ChatGPTイメージ・ジェネレーションがすべての無料ユーザーにロールアウトされました！
***

　それって、
　　GPUがさらに溶けるって話では？

　というか、
　　ただでさえ、
　　　生成速度が遅くなっていて
　　　　制限で描画できなくなっている
　　　　　のに、負荷を増やす！？

　DALL-Eも
　　描画失敗しやすくなってて
　　　困りものなんだけど……。

***
　では、【本題】です。

　今回は、
　　4o Image Generationで
　　　画像をはめ込む方法です。

　画像をはめ込む、
　　それはDALL-E3と
　　　CodeI nterpreterを
　　　　使っても大変なことでした。

　でも
　　4o Image Generationなら
　　　簡単にできます。

　手順は以下のとおり。
　❶はめ込む画像をアップロード
　❷下記Promptを入力
```Text:スマホ画面に画像をはめ込むPrompt
スマホ画面をこちらに見せてくる着物姿の若く美しい日本人女性。スマホ画面には画像をはめ込んで。
```
　❸送信。

　はい、出来上がり。
![ChatGPT Image 2025年3月27日 10_05_18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/66d2483d-a305-48a3-a3f8-530e5ee183b4.png)

　ポイントは
　「スマホ画面には画像をはめ込んで」
　　という部分ですね。

　ほかの
　　ところは
　　　それぞれで変えてください。

　また、
　　“スマホ”を
　　　“パソコン”や“テレビ”にしても
　　　　同様の結果を得られます。

　スマホが傾いてても
　　はめ込んで、その角度にして
　　　くれますので、
　　　　何も心配ありません。

　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
2025年人気No.1のNext.jsで、最新ツールとウェブを作る！ | エピソード9 ウェブサイトのデプロイ

## 目標
- Next.jsプロジェクトを本番環境にデプロイする方法を学ぶ。
- Vercelを使って簡単に公開する。
- カスタムドメインを設定する。
- デプロイ後の管理と更新を確認する。

---

## 1. デプロイの準備
プロジェクトをデプロイする前に、いくつかの確認を行います。

### 手順：
1. **コードの確認**：
   - `npm run build`を実行し、エラーなくビルドできることを確認。
2. **環境変数の設定**：
   - `.env.local`の内容を整理（Supabaseキー、NextAuth設定など）。
   - 例：
     ```
     SUPABASE_URL=あなたのSupabase URL
     SUPABASE_KEY=あなたのSupabase anon key
     GOOGLE_CLIENT_ID=あなたのGoogleクライアントID
     GOOGLE_CLIENT_SECRET=あなたのGoogleクライアントシークレット
     NEXTAUTH_URL=https://your-domain.vercel.app
     NEXTAUTH_SECRET=ランダムな文字列
     ```
3. **依存関係の確認**：
   - `package.json`に必要なライブラリがすべて記載されていることを確認。

---

## 2. Vercelへのデプロイ
VercelはNext.jsに最適化されたホスティングプラットフォームです。

### 手順：
1. **Vercel CLIのインストール**：
   ```
   npm install -g vercel
   ```
2. **ログイン**：
   ```
   vercel login
   ```
   - ブラウザでVercelアカウントにログイン。
3. **デプロイ実行**：
   - プロジェクトルートで以下を実行：
     ```
     vercel
     ```
   - 初回はプロジェクト名や設定を聞かれます（デフォルトでOK）。
4. **環境変数の設定**：
   - Vercelダッシュボード（またはCLI）で`.env.local`の内容を「Environment Variables」に追加。
   - 例：
     ```
     vercel env add SUPABASE_URL
     ```

**確認**：
- デプロイ後、提供されたURL（例：`https://your-project.vercel.app`）でサイトが動作するか確認。

---

## 3. カスタムドメインの設定
独自ドメインを追加して、プロフェッショナルな見た目にします。

### 手順：
1. **ドメインの取得**：
   - お名前.comやGoogle Domainsなどでドメインを購入（例：`myblog2025.com`）。
2. **Vercelにドメインを追加**：
   - Vercelダッシュボードのプロジェクトで「Domains」タブを開く。
   - ドメインを入力（例：`myblog2025.com`）。
3. **DNS設定**：
   - ドメイン管理画面で、Vercelが指示するDNSレコード（通常はAレコード）を追加。
   - 例：
     ```
     Type: A
     Host: @
     Value: 76.76.21.21 (VercelのIP)
     ```
4. **SSLの自動設定**：
   - Vercelが自動でSSL証明書を発行。

**確認**：
- `https://myblog2025.com`でサイトが表示されるか確認。

---

## 4. デプロイ後の管理と更新
公開後もサイトを維持・更新します。

### 手順：
1. **コードの更新**：
   - ローカルで変更を加えた後、`vercel --prod`で再デプロイ。
2. **プレビュー**：
   - 本番環境に影響を与えずにプレビューURLで確認：
     ```
     vercel
     ```
3. **ログの確認**：
   - Vercelダッシュボードの「Logs」タブでエラーやリクエストを確認。

---

## 実践：公開されたブログ
- **デプロイ**：Vercelにプロジェクトをアップロード。
- **ドメイン**：カスタムドメインを設定。
- **動作確認**：投稿追加やログインが正しく動作するかテスト。

**ヒント**：
- Vercelの無料枠で十分ですが、トラフィックが増えたらプランを検討。

---

## エピソード9の終了
- Next.jsプロジェクトをVercelにデプロイしました。
- カスタムドメインで公開し、管理方法を学びました。

**次回のエピソード**：機能を拡張し、長期的なメンテナンスのコツを学びます。

---

この記事が役に立ったと思ったら、ぜひ「いいね」を押して、ストックしていただければ嬉しいです！次回のエピソードもお楽しみに！
GitHub Copilotとは

# 目次
- [1. はじめに](#1-はじめに)
- [2. 対応環境](#2-対応環境)
- [3. 基本機能](#3-基本機能)
- [4. キーボードショートカット（Visual Studio Code の例）](#4-キーボードショートカットvisual-studio-code-の例)
- [5. GitHub Copilot Chat の活用方法](#5-github-copilot-chat-の活用方法)
  - [5-1. Slash コマンド](#5-1-slash-コマンド)
  - [5-2. チャット変数](#5-2-チャット変数)
  - [5-3. チャット参加者（エージェント）](#5-3-チャット参加者エージェント)
- [6. 主なコマンド一覧](#6-主なコマンド一覧)
- [7. ベストプラクティス](#7-ベストプラクティス)

## 1. はじめに
GitHub Copilot は、GitHub と OpenAI が共同で開発した AI ペアプログラマーです。
コードの自動補完、関数やクラスの生成、テストコードの提案、さらには自然言語でのコード説明など、開発作業を効率化する多彩な機能を備えています。

## 2. 対応環境
- IDE サポート：
  - Visual Studio Code
  - Visual Studio
  - Neovim
  - JetBrains IDEs
  - Xcode、Web ブラウザ版など

## 3. 基本機能
- コード補完 (Ghost Text)：
タイプ中にコードの提案が表示され、Tab キーで採用、Esc キーでキャンセル。
- インラインチャット：
コード中の疑問や補足をその場で質問できる機能（Ctrl+I）。
- Copilot Chat：
より大規模な対話や詳細な説明、コードの修正提案をチャット形式で受けられる。
- テスト・ドキュメント生成：
選択したコードブロックに対して単体テストやドキュメントコメントを自動生成。

## 4. キーボードショートカット（Visual Studio Code の例）
- Tab → 提案全体を受け入れる
- Esc → 提案を拒否する
- Ctrl + → → 単語単位で提案を受け入れる
- Ctrl + Enter → 補完パネルを開く
- Ctrl + I → インラインチャットを開始する
- Ctrl + Shift + I → クイックチャット（短い質問用）を開始する

## 5. GitHub Copilot Chat の活用方法
### 5-1. Slash コマンド
チャット入力時に「/」を入力することで、よく使う操作を短いコマンドで呼び出せます。
- /clear → 現在のチャット履歴をクリアして新規セッションを開始
- /explain → アクティブなコードの動作や目的を説明
- /fix → 選択中のコードの問題点を修正する提案を表示
- /tests → 単体テストを自動生成
- /new → 新しいプロジェクトやファイルのスキャフォールディングを開始

### 5-2. チャット変数
入力に特定のコンテキストを付加するため、先頭に「#」を使います。
- #file → 現在のファイル内容をコンテキストに追加
- #selection → 選択中のコードを付加
- #function / #class / #block → 対象となる関数、クラス、コードブロックを含む

### 5-3. チャット参加者（エージェント）
質問に特化した専門家のようなエージェントを指定できます。
- @workspace → プロジェクト全体の文脈で質問する
- @vscode → VS Code 固有の操作や設定について質問する
- @terminal → ターミナルやシェルコマンドの問題解決に活用
- @github → GitHub 関連の問い合わせ（例：プルリクエスト、コミット情報など）
- @azure → Azure 関連の質問に対応（※現在プレビュー中）

## 6. 主なコマンド一覧
| コマンド | 説明 |
|---------|------|
| /clear | チャット履歴をクリアし、新しいセッションを開始 |
| /explain | 選択中のコードの動作・意図を説明 |
| /fix | コードの問題点やエラーを修正する提案を生成 |
| /fixTestFailure | 失敗しているテストの原因を探り、修正案を提案 |
| /tests | 単体テストの自動生成 |
| /new | 新規プロジェクト／ファイルのスキャフォールディング開始 |
| /doc | ドキュメントコメントの自動生成 |
| /optimize | 選択中のコードの実行時間やパフォーマンス改善提案を生成 |

また、コマンドパレット（Ctrl+Shift+P）からも「GitHub Copilot: …」コマンドで各種操作が可能です。

## 7. ベストプラクティス
- コンテキストの提供：
コード中に適切なコメントや関数名を用意し、Copilot に十分な情報を与えることで、より精度の高い提案が得られます。
- 生成コードのレビュー：
AIが出す提案はあくまで補助です。必ず自分の目で内容を確認し、必要に応じて修正してください。
- 段階的な依頼：
複雑な機能は一度に頼まず、細かく分割して依頼することで、より正確なコードが生成されます。
- 反復的な対話：
チャット機能を活用し、返答に対してさらに具体的な質問や改善依頼をすることで、最適なソリューションを得られます。
- 最新のアップデート確認：
GitHub Copilot は多モデル対応（GPT-4o、Claude 3.5、Gemini など）やマルチファイル編集など、日々進化しています。公式発表やドキュメントを定期的にチェックしてください。
MQTT: 受信したデータを Redis に入れる

BROKER は  localhost
TOPIC は /topic/register
です。

## プログラム

```py:subscribe_redis.py
#! /usr/bin/python
#
#	subscribe_redis.py
#
#						Mar/31/2025
#
# ------------------------------------------------------------------
import sys
import json
import paho.mqtt.subscribe as subscribe
import redis

# ------------------------------------------------------------------
def redis_write_proc(key,value):
#
	sys.stderr.write("*** redis_write_proc ***\n")
	rr = redis.Redis(host='localhost', port=6379, db=0)
	rr.set(key, value)
# ------------------------------------------------------------------
def on_message_print(client, userdata, message):
	print("%s %s" % (message.topic, message.payload))
	json_str = message.payload
	unit_aa = json.loads(json_str)
	cpid = unit_aa['cpid']
	version = unit_aa['version']
	print(cpid)
	print(version)
	key = "cpid:" + cpid
	redis_write_proc(key,version)
#
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
broker = 'localhost'
port = 1883
topic = '/topic/register'
#
#
subscribe.callback(on_message_print, topic, hostname=broker, userdata={"message_count": 0})
#
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

## テスト用スクリプト

```bash
#
BROKER="localhost"
TOPIC="/topic/register"
#
echo $BROKER
message="{\"cpid\": \"A1B2C3D9\",\"version\": \"2025-3-31 AM 11:09\"}"
mosquitto_pub -d -m "${message}" \
    -h  $BROKER \
    --topic $TOPIC
#
```

## Systemd でプログラムを動かす

プログラムを
/usr/local/subscribe に置く

サービスの作成

```text:subscribe_redis.service
[Unit]
Description = start up mqtt_client subscribe_redis

[Service]
WorkingDirectory=/var/tmp/subscribe_redis
ExecStart=/usr/local/subscribe/subscribe_redis.py
Type=simple

[Install]
WantedBy=default.target
```

作業用の Directory を作成

```bash
mkdir /var/tmp/subscribe_redis
```

起動

```bash
sudo systemctl start subscribe_redis
```

起動の確認

```bash
sudo systemctl status subscribe_redis
```
Railsのヘルパーメソッドとは？基本と便利な使い方

## 1. ヘルパーメソッドとは？

Railsのヘルパーメソッドは、ビュー（View）での処理を簡潔に書くためのメソッドです。
たとえば、日付のフォーマット変換やリンクの作成を簡単に記述でき、コードの可読性を向上させます。

::: note
###### なぜヘルパーメソッドを使うのか？
1\. ビューのコードをスッキリさせる（ロジックを減らし、見やすくする）
2\. 共通処理をまとめて再利用できる（DRY原則に従う)
3\. Railsが提供する便利なメソッドを活用できる
:::
## 2. よく使われるヘルパーメソッド

#### ① link_to（リンクを作成する）

\<a>タグを簡単に生成できます。

~~~erb:
<%= link_to "ホームへ戻る", root_path %>
~~~

URLだけでなく、オプションを追加することでCSSクラスの適用やデータ属性の追加も可能です。

~~~erb
<%= link_to "詳細を見る", article_path(@article), class: "btn btn-primary" %>
~~~

#### ② image_tag（画像を表示する）

画像タグを簡単に生成できます。
~~~erb:
<%= image_tag "logo.png", alt: "サイトのロゴ", class: "logo" %>
~~~

#### ③ form_with（フォームを作成する）

Railsでは、フォームの作成もヘルパーメソッドを使うと簡単になります。
~~~erb:
<%= form_with(model: @user, local: true) do |f| %>
  <%= f.label :name %>
  <%= f.text_field :name %>
  <%= f.submit "送信" %>
<% end %>
~~~

#### ④ number_to_currency（通貨フォーマットに変換する）

数値を通貨の形式に変換できます。
~~~erb:
<%= number_to_currency(1000) %>  # => ¥1,000
~~~

オプションを指定すれば、通貨の種類を変更することも可能です。
~~~erb:
<%= number_to_currency(1000, unit: "$", delimiter: ",", precision: 2) %>  
# => $1,000.00
~~~
#### ⑤ time_ago_in_words（○○前を表示する）

投稿時間などを「◯◯前」に変換できます。

~~~erb:
<%= time_ago_in_words(@article.created_at) %> 前
~~~

## 3. カスタムヘルパーを作成する

Railsでは、独自のヘルパーメソッドも作成できます。
例えば、文字数を制限して「…」をつけるメソッドを作りたい場合：

#### ① app/helpers/application_helper.rb にメソッドを定義

~~~ruby:
module ApplicationHelper
  def truncate_text(text, length = 30)
    text.length > length ? "#{text[0, length]}..." : text
  end
end
~~~
#### ② ビューで使用する
~~~erb:
<%= truncate_text(@article.title, 20) %>
~~~
Lambdaのコード管理とdeployについて

# 課題を感じていた構成
- Lambda関数のGoで書かれたコードを全てterraformで管理
- 同じリポジトリにterraform管理するディレクトリ(teffagrunt)とアプリケーションディレクトリ(server)がある
- アプリケーション(server配下)はGoで実装している
- Lambdaの関数もGoで実装している

# この構成で運用しづらかったこと
- teffarormの中にアプリケーションのコードがある違和感
- テストがやりづらい
    - localで動かすにはLambda特有の`handler関数` を都度localで動く形に置き換えが必要
    - terraform管理配下にコードがあることでアプリケーションディレクトリ配下の共通処理やライブラリが使えない
    - テストがやりづらい。アプリケーションディレクトリ配下にあるものはtestDBを使うようにしているがこれが使えない。


# 改善
- Lambda(Goのコード)は、アプリケーションディレクトリに移動し、terraformではインフラのみ管理する形に変更する
    - アプリケーションディレクトリに移動することで以下が可能になる
        - モジュールの再利用
        - テスト機構の再利用(testDBなど)
- デプロイ時はこれまで通りterraformで実施
    - main.tfの中でビルド対象のファイルを指定してzipを読み込めればOK



参考にした記事
https://dev.classmethod.jp/articles/deploy-golang-lambda-function-with-terraform/

# ASIS

```
├── server/
│   ├── controller/
│   ~
├── terragrunt/
│   ├── envs/
│   ├── modules/
│       └── lambda
│             └─lambda_logic/ # (ここにGoのコードがあるのが運用しづらくしてい)
│               └──db.go 
│               └──go.mod
│               └──go.sum
│               └──main.go

```


main.tf (build部分抜粋)
```
# 必要なモジュールをbuildする
resource "terraform_data" "build_lambda" {

  provisioner "local-exec" {
    command = <<EOT
      # Set the target OS and architecture
      cd ${path.module}/lambda
      GOOS=linux GOARCH=amd64 go build -o bootstrap main.go db.go

      # Check if the build was successful
      if [ $? -ne 0 ]; then
        echo "Go build failed!"
        exit 1
      fi
    EOT
  }

  # 毎回ビルドする
  triggers_replace = [
    timestamp()
  ]
}
```


# TOBE

```
├── server/
│   ├── controller/
│   ~
│   └── lambda/
│          └── main.tf
│          └── xxxxx/ # (lambda関数Aで使用するgoのコード群)
│                 ├── main.go
│                 ├── go.mod
│                 ├── go.sum
│                 └── db.go  # (ここに移動。テストもしやすくなる)
├── terragrunt/
│   ├── envs/
│   │   ├── dev/
│   │   ├── prod/
│   ├── modules/
│   │   └── lambda_xxxxx/
│       └── main.tf  # Lambda や IAM の作成のみを定義

```


main.tf
Goソースがあるディレクトリに移動する部分だけ変更
```
# --------------------------------------------------
# 1) Lambdaビルド (Goソースをコンパイル)
# --------------------------------------------------
# 必要なモジュールをbuildする
resource "terraform_data" "build_lambda" {

  provisioner "local-exec" {
    command = <<EOT
      # Set the target OS and architecture

      # ここを変更するだけ!!
      # server/lambdas/xxxxx ディレクトリに移動
      cd ${path.root}/../../server/lambdas/xxxxx
      
      GOOS=linux GOARCH=amd64 go build -o bootstrap main.go db.go

      # Check if the build was successful
      if [ $? -ne 0 ]; then
        echo "Go build failed!"
        exit 1
      fi
    EOT
  }

  # 毎回ビルドする
  triggers_replace = [
    timestamp()
  ]
}
```
parse_url() 関数

個人的にメモとしてまとめる

## parse_url() の役割
parse_url() は、URLを解析して スキーム（プロトコル）、ホスト（ドメイン）、パス、クエリなど の情報を配列として取得できます。

具体例
``` php
$url = "https://hogehoge.com/path/to/page?query=123";
$parsed_url = parse_url($url);

print_r($parsed_url);
```

結果
```
Array ( 
[scheme] => https 
[host] => hogehoge.com 
[path] => /path/to/page 
[query] => query=123 
)
```

### parse_url() の戻り値
parse_url($url) は、以下のようなキーを持つ 連想配列 を返します（存在しない部分は省略されます）。

キー ($parsed_url['キー名'])  | 内容
------------- | -------------
scheme  | http または https（プロトコル）
host  | hogehoge.com （ドメイン）
port  | 80 や 443 など（省略されることもある）
user  | user（認証情報のユーザー名）
pass  | password（認証情報のパスワード）
path  | query=123（クエリパラメータ）
fragment  | section1（URLの #section1 部分）


### componentとは
PHP_URL_SCHEME、 PHP_URL_HOST、PHP_URL_PORT、 PHP_URL_USER、PHP_URL_PASS、 PHP_URL_PATH、PHP_URL_QUERY あるいは PHP_URL_FRAGMENT のうちのいずれかを指定し、 特定の URL コンポーネントのみを文字列 (PHP_URL_PORT を指定した場合だけは整数値) で取得するようにします。

componentを入れた場合

```php
<?php
$url = 'http://username:password@hostname:9090/path?arg=value#anchor';

var_dump(parse_url($url));
var_dump(parse_url($url, PHP_URL_SCHEME));
var_dump(parse_url($url, PHP_URL_USER));
var_dump(parse_url($url, PHP_URL_PASS));
var_dump(parse_url($url, PHP_URL_HOST));
var_dump(parse_url($url, PHP_URL_PORT));
var_dump(parse_url($url, PHP_URL_PATH));
var_dump(parse_url($url, PHP_URL_QUERY));
var_dump(parse_url($url, PHP_URL_FRAGMENT));
?>
```
結果

```php
array(8) {
  ["scheme"]=>
  string(4) "http"
  ["host"]=>
  string(8) "hostname"
  ["port"]=>
  int(9090)
  ["user"]=>
  string(8) "username"
  ["pass"]=>
  string(8) "password"
  ["path"]=>
  string(5) "/path"
  ["query"]=>
  string(9) "arg=value"
  ["fragment"]=>
  string(6) "anchor"
}
string(4) "http"
string(8) "username"
string(8) "password"
string(8) "hostname"
int(9090)
string(5) "/path"
string(9) "arg=value"
string(6) "anchor"
```


こちらを活用すればparse_url($url) で host 部分を取得して
host部分が仕様のものと異なればNotFoundにリダイレクトしたり、何かと使用する場面はありそうですね。

参考
https://www.php.net/manual/ja/function.parse-url.php
Angular GuardとServiceについて

# GuardとServiceについて

今回はAngularにおけるGuardとServiceについて概要を説明する。

![図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935725/7b9c5540-3b74-42c3-b86d-29b8ad8216cd.png)

## Service
- **コンポーネント間でデータを共有するために使用される**
- APIとの通信やデータの管理、ビジネスロジックを分離する目的でも利用される

## Guard
- 特定の条件を満たさないとルート遷移を許可しないようにする仕組み
- コンポーネントが生成される前（ルート遷移前）に実行されるため、不正なアクセスを防ぐことができる
- CanActivate 以外にも、CanDeactivate, CanLoad などのガードがあり、用途に応じて異なる動作を実装できる

### CanActivate
- `CanActivate` は、ユーザーがルートにアクセスできるかどうかを制御する

### CanDeactivate
- `CanDeactivate` は、ユーザーがページを離れる前に確認処理を行うガード
【PowerApps】タイマーコントロールを用いたユーザに依存せず関数を実行する方法

本記事ではタイマーコントロールを利用するに至った経緯や利用手順についてまとめます。

## 結論
タイマーコントロールを利用することでユーザが画面を開き、設定した式をミリ秒単位で実行することができます。

## 利用するに至った背景
変数内の値を変更する関数をonStart,onVisible,onClickなどのユーザの動きに依存するプロパティ以外で関数を実行する方法を探しました。

## タイマーコントロールのメリット・デメリット
メリット
1.時間単位で実行できるため、ユーザの動きに依存しない
2.簡単に繰り返し実行が可能

デメリット
1.ユーザがアプリを利用している（タイマーコントロールを設定した画面上を開いている）時しか実行されない
2.画面ごとに設定する必要がある

## 設定方法
![スクリーンショット 2025-03-28 121937.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3914487/db541ffc-d071-4fa2-82a0-e33d945d6dc6.png)
![スクリーンショット 2025-03-28 122451.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3914487/f6d53189-4908-47be-a523-4da1593cc70c.png)
1.挿入し、タイマーと検索し、選択する
2.追加されたタイマーコントロールのプロパティを設定する
3.テキストラベルを配置する

## 実装例 数秒ごとに現在時刻を変数に取得する
<font color="#ff0000">タイマーコントロールに設定したプロパティと式</font>
Duration     : 1000（ミリ秒）
AutoStart    : true
OnTimerEnd   : Set(現在時刻,Now())
               //現在時刻変数を用意し、Now関数取得した現在時刻を挿入
Start        : true
Visible      : false
Repeat       : true

<font color="#ff0000">テキストラベルに設定したプロパティと式</font>
Text      : 現在時刻


実装画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3914487/c0b6a121-4cca-4b1f-ae0a-206d1af2365b.png)
図のようにテキストラベルに時計のような役割を持たせるようなことができた。


## まとめ
今回はユーザの挙動に依存せず実行することを狙い、タイマーコントロールを利用しました！ユーザに依存しないといいつつ、ユーザがアプリを利用しているときだけ実行できる仕組みなので依存してない？という声は無視します...
この仕組みであればより能動的に分岐を作ることができ、ユーザに配慮した機能を作成することにつながると思っています。ぜひご活用ください。


<font color="#ff0000">以下主要プロパティ</font>
Duration     : タイマーの値何秒ごとに実行するか指定する
AutoStart    : (true/false)タイマーを自動的に開始する
OnTimerEnd   : タイマーが停止したときに式を実行する
OnTimerStart : タイマーが実行されたときに式を実行する
Start        : (true/false)タイマーを開始するか指定する
Visible      : (true/false)タイマーを視覚的に表示するか指定する
【Rails】Railsのセッション固定とセッションハイジャックを防ぐ方法

# はじめに

こんにちは。アメリカに住みながら独学でエンジニアを目指しているTairaです。

Railsのアプリケーション開発において、セキュリティ対策は必須で、セッション固定攻撃とセッションハイジャック攻撃の対策について記事にしたいと思います。

## 1. セッション固定攻撃とは？

セッション固定攻撃（Session Fixation Attack）とは、攻撃者が特定のセッションIDをユーザーに意図的に使わせ、そのセッションIDでログインさせることでユーザーのセッションを奪う攻撃手法です。

### 対策方法：reset_session

Railsでは、`reset_session` メソッドを使うことで、この攻撃を防ぐことができます。これは、現在のセッションIDを無効にし、新しいセッションIDを発行するものです。

```ruby
# パスワード変更やログイン成功時に使う
reset_session
```

- ユーザーがログインに成功したときや、パスワード変更後にこのコードを実行することで安全性を高めます。

## 2. セッションハイジャックとは？

セッションハイジャックとは、攻撃者がユーザーのCookie（特に永続的なセッション認証情報）を盗み、そのCookieを使って正規ユーザーになりすます攻撃です。

### 対策方法：remember_digestを無効化

Railsで永続セッションを使う場合、一般的には以下のようにCookieとデータベースのremember_digestを利用して実装します。

- Cookieにはremember_tokenを保存
- DBにはremember_digestを保存
- ログイン時に両者を比較してユーザーを認証

もし攻撃者がremember_tokenを盗んだ場合、サーバー上のremember_digestを削除することで攻撃者の永続セッションを無効にできます。

```ruby
# user.rb

def forget
  update_attribute(:remember_digest, nil)
end

# パスワード変更時のコントローラなどで呼び出す
@user.forget
```

この方法を使えば、攻撃者が取得済みの永続セッション情報が無効になるため、セッションハイジャックを防ぐことができます。

## まとめ

Railsアプリケーションでは、

- セッション固定攻撃には `reset_session`
- セッションハイジャックには `remember_digest` の無効化（`@user.forget`）

という2つの手法を使い分け、組み合わせることで安全なセッション管理を実現できます。
watsonx.ai & watsonx.governanceで3rd partyのLLMによるRAGを評価①

先ず、watsonx.ai/watson studioでcontext、質問、回答、生成された回答(generated_text)を含む検証データを作成。以下では、[neural-bridge/rag-dataset-12000](https://huggingface.co/datasets/neural-bridge/rag-dataset-12000)のContextと質問より回答を生成して、検証データを作成している。

```python
!pip install --upgrade openai azure-identity
```

```python
from datasets import load_dataset

ds = load_dataset("neural-bridge/rag-dataset-12000")
ds
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3756172/a916de24-05cc-41bb-a20f-91ad56f22af6.png)

```python
import pandas as pd

df = pd.DataFrame(ds['test']).head(n=10)
df
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3756172/f24518b7-4567-411f-b366-606c70c7f189.png)


```python
AZURE_OPENAI_ENDPOINT = "<INPUT YOUR AZURE_OPENAI_ENDPOINT>"
AZURE_OPENAI_DEPLOYMENT_NAME = "<INPUT YOUR AZURE_OPENAI_DEPLOYMENT_NAME>"
AZURE_CLIENT_ID = "<INPUT YOUR AZURE_CLIENT_ID>"
AZURE_CLIENT_SECRET = "<INPUT YOUR AZURE_CLIENT_SECRET>"
AZURE_TENANT_ID = "<INPUT YOUR AZURE_TENANT_ID>"
```

```python
PROMPT_TEMPLATE = """# System:
Answer the question based on the context.

# Context:
{context}

# Question
{question}

# Answer:
""".strip()
```

```python
import os
from azure.identity import ClientSecretCredential, get_bearer_token_provider

scope = "https://cognitiveservices.azure.com/.default"
credential = ClientSecretCredential(
    tenant_id=os.environ.get('AZURE_TENANT_ID', AZURE_TENANT_ID),
    client_id=os.environ.get('AZURE_CLIENT_ID' ,AZURE_CLIENT_ID),
    client_secret=os.environ.get('AZURE_CLIENT_SECRET', AZURE_CLIENT_SECRET)
)
azure_ad_token_provider = get_bearer_token_provider(credential, scope)
```

```python
from openai import AzureOpenAI

client = AzureOpenAI(
    azure_endpoint=os.environ.get('AZURE_OPENAI_ENDPOINT', AZURE_OPENAI_ENDPOINT),
    api_version="2024-02-15-preview",
    azure_ad_token_provider=azure_ad_token_provider
)
```

```python
tmp = []
max_tokens = 4096
for index, row in df.iterrows():
    print(index)
    context = row['context']
    question = row['question']
    response = client.chat.completions.create(
        model=os.environ.get('AZURE_OPENAI_DEPLOYMENT_NAME', AZURE_OPENAI_DEPLOYMENT_NAME),
        messages=[{"role": "user", "content": PROMPT_TEMPLATE.format(context=context, question=question)}],
        max_tokens=max_tokens
    )
    tmp.append(response.choices[0].message.content)
```

```python
tmp
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3756172/70a3e0fc-7ae5-4e30-aaf3-c6f571ffe173.png)

```python
df['generated_text'] = tmp
df
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3756172/d47541f1-4a9a-41b0-a020-ef811904b36a.png)


```python
from ibm_watson_studio_lib import access_project_or_space

wslib = access_project_or_space({'token':TOKEN})
df.to_csv("test.csv", index=False)
res = wslib.upload_file("test.csv", overwrite=True)
print(res)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3756172/840db2d8-dc3d-4676-9745-bf138b81e5e5.png)
GoogleスプレッドシートでR1C1参照を活用した条件付き書式のテクニック

# はじめのはじめに
本文はすべて我が配下、ChatGPTに出力させたものです。検証も面倒でメモ程度に出力したものですので眉唾で見てください。

## はじめに

GoogleスプレッドシートやExcelで作業する際、「特定の条件に合致するセルをハイライトしたい」というニーズはよくあります。今回は、別の領域の値を参照して条件付き書式を適用する高度なテクニックを紹介します。特に、R1C1参照方式とINDIRECT関数を組み合わせた方法は、大量のデータを扱う際に非常に便利です。

## 課題の例

例えば次のような状況を考えてみましょう：

- メインデータはF2:AR147に存在する
- 変更情報はAS2:CE147に記録されている（変更がある場合は「変更」と表示）
- F2:AR147の各セルに対応するAS2:CE147のセルに「変更」がある場合、そのF2:AR147のセルをハイライトしたい

## 解決方法：INDIRECT関数とR1C1参照を使った条件付き書式

この課題は、条件付き書式と以下の数式を使うことで簡単に解決できます：

```
=INDIRECT("R"&ROW()&"C"&(COLUMN()+39), FALSE) = "変更"
```

### 数式の解説

この数式は非常にパワフルですが、分解して理解する必要があります：

1. `ROW()` - 現在のセルの行番号を返します
2. `COLUMN()` - 現在のセルの列番号を返します
3. `COLUMN()+39` - 現在の列から39列右の列番号を計算します（例：F列(6)からAS列(45)への移動）
4. `"R"&ROW()&"C"&(COLUMN()+39)` - R1C1形式のセル参照を文字列として構築します
5. `INDIRECT(..., FALSE)` - 構築した文字列をセル参照として評価します（FALSEはR1C1形式を指定）
6. `= "変更"` - 参照先のセルの値が「変更」と等しいかをチェックします

### 具体的な適用例

F列からAR列までのセルは、それぞれAS列からCE列の対応するセルを参照します：
- F列 → AS列（+39列）
- G列 → AT列（+39列）
- ...
- AR列 → CE列（+39列）

## 条件付き書式の設定手順

1. F2:AR147の範囲を選択します
2. 「書式」→「条件付き書式」を選択
3. 「条件の種類」で「カスタム数式」を選択
4. 数式欄に `=INDIRECT("R"&ROW()&"C"&(COLUMN()+39), FALSE) = "変更"` を入力
5. 書式設定（背景色など）を選択
6. 「完了」をクリック

## このテクニックの応用と利点

### 応用例
- データ検証：入力値が別の場所にある許容範囲内かをチェック
- 複数条件：複数の列の値を組み合わせて条件を構築
- 動的参照：シート内の位置に依存せず、相対的な位置関係で条件を記述

### 利点
- VBAやGoogle Apps Scriptを使わずに実装可能
- セルの変更に即座に反応する
- 大量のセルに一度に適用できる
- 数式の再利用が簡単

## 注意点

- 数式内の「+39」という数値は、参照先のセルが何列離れているかによって調整が必要です
- シートの構造を変更（列の挿入・削除など）すると、調整が必要になる場合があります
- 大量のセルに条件付き書式を適用すると、スプレッドシートのパフォーマンスが低下する可能性があります

## まとめ

INDIRECTとR1C1参照を組み合わせた条件付き書式は、スプレッドシートの高度な機能を活用した効率的な方法です。この手法を使えば、複雑な条件での書式設定も簡単に実現できます。ぜひ皆さんのスプレッドシート作業に取り入れてみてください。

## 参考情報
- [INDIRECT関数の公式ドキュメント](https://support.google.com/docs/answer/3093377)
- [条件付き書式の使い方](https://support.google.com/docs/answer/78413)
- [R1C1参照スタイルについて](https://support.microsoft.com/ja-jp/office/excel-%E3%81%AE%E5%8F%82%E7%85%A7%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E3%82%92-a1-%E3%81%8B%E3%82%89-r1c1-%E3%81%AB%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B-3e0ba1fa-c893-49da-b741-32bd23c7ce5c)
24時間動くdiscord BOT を作ろう！

# 概要
本記事は、webアプリをデプロイし、かつ、discordのBOTを24時間動作させる内容となっています。 

:::note info
この記事は、前回の続きとなっています。
前回記事「100MBまでの動画をdiscordに送信できるBOTを作る」も是非読んでください！！
https://qiita.com/yonuma28/items/3a49659774c408367e58
:::
webアプリのデプロイとdiscord BOTの起動はrender上で行っています。renderの詳細は下記記事をご覧ください。
https://qiita.com/tks_00/items/73cf04c225e5f6113cd8

## render と UptimeRobot
今回使用しているrenderですが、フリープランですと画面を閉じると一定時間でサービスがスリープ状態に入ってしまいます。そのため、定期的にrenderにリクエストを送ることでスリープ状態を回避します。
定期的なリクエストは、`UptimeRobot`というサービスを使用します。
https://dashboard.uptimerobot.com

## やり方
では、どのようにして24時間BOTを動作させるのかを見ていきましょう。
まずは、エンドポイントを作成します。
```python
@app.route('/keep_alive', methods=['GET'])
def keep_alive():
    return jsonify({'message': 'Alive'}), 200
```
これにより、`URL/keep_alive`にてHTTP/GET リクエストを受け取ることが出来ます。
次に、このエンドポイントを利用して、外部から定期的にリクエストを送信する仕組みを作ります。今回は、UptimeRobotを使用して指定した間隔でこのエンドポイントにリクエストを送信します。これにより、サーバーがアイドル状態にならず、常に稼働し続けることが可能になります。
### UptimeRobot
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654841/e115d92d-9004-43c0-8203-6157b5c9ced3.png)

ログインしたら、New monitorをクリックします。すると、以下の画面が開きますので、作成したエンドポイントを入力したら完了です。これで、5分おきに `/keep_alive` にリクエストが入り、BOTを24時間起動することが出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654841/bf0c52c1-066f-4edf-9da3-8b83202f708e.png)

:::note info
入力するURLは、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654841/029cfd76-d6f8-410c-8802-1e5471cb08ba.png)
ここで表示されているURLの後ろに、`/keep_alive` を付けたものになります。
:::

## 終わりに
簡単にdiscord BOTを24時間動作させる方法をご紹介しました。良き開発ライフを。