Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

關於一些記錄的 counter. #263

Open
chhsiao1981 opened this issue Jul 29, 2021 · 17 comments
Open

關於一些記錄的 counter. #263

chhsiao1981 opened this issue Jul 29, 2021 · 17 comments
Assignees
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@chhsiao1981
Copy link
Collaborator

Is your feature request related to a problem? Please describe.
關於一些記錄的 counter.

Describe the solution you'd like
使用 redis 來記錄 counter.

Describe alternatives you've considered

Additional context

@chhsiao1981
Copy link
Collaborator Author

chhsiao1981 commented Jul 29, 2021

可以加上 prometheus 的 exporter

https://github.com/prometheus/client_golang

@chhsiao1981 chhsiao1981 added enhancement New feature or request help wanted Extra attention is needed labels Jul 29, 2021
@tingyuchang
Copy link
Collaborator

請問有哪些資料需要呢?目前有想到的大概有:在線人數,人氣,推文數等,可能會需要把這些數據相關的 api 一起完成或是修改。
這個 issue 要建立 redis 連線的參數,如果要做的話,我會一併把 docker-compose 那邊一起建立起來

@chhsiao1981
Copy link
Collaborator Author

這個好像有分兩種~
一種是給 frontend 看到的數字 (在線人數 / 人氣)

"給 frontend 看到的數字" 很 tricky~
by 板的數字目前應該會是每隔一段時間 (10 mins) 讓 mongo aggregate 最近 10 分鐘有摸過板 / 摸過 api 的.
又或者是可能可以想想其他方式拿到數字.
然後就 cache 到 redis 裡.

redis 有類似的 code.
docker-compose 裡也已經有 redis 囉~

key 的 convention 是 [prefix]:[key]
(lock 的 prefix 是 lock. counter 的 prefix 就 counter 吧~)

https://github.com/Ptt-official-app/go-openbbsmiddleware/blob/main/schema/lock.go

https://github.com/Ptt-official-app/go-openbbsmiddleware/blob/main/schema/init.go#L224

https://github.com/Ptt-official-app/go-openbbsmiddleware/blob/main/docker/docker-compose.yaml#L23

另外一種是偏給系統和後台紀錄.
(api 的 count, login fail 的 count, 其他特殊 event 的 count)

最近發現 prometheus 很容易就可以搞定這件事:
https://github.com/prometheus/client_golang
https://prometheus.io/docs/guides/go-application/

@tingyuchang
Copy link
Collaborator

ok 我明白了,第一種給 frontend 用的 count-cache 我先想看看生成的機制以及移除(invalidation) ,第二種的話,我對 prometheus 不熟,我先玩看看他是怎麼運作的,再來討論需要觀察的數據是哪些

@tingyuchang
Copy link
Collaborator

在線人數:key -> [count:active-USERID] value -> [lastAPICallTime] ,需要統計的時候就用 redis 的 key pattern ('keys', 'count:active-*') 這個是 O(N) ,應該不會算慢,不過這樣對 redis 的負擔有點高,也許我們可以再設定一個 Key-Value 定時統計上述的數字,讓 API 直接讀取這個數字就好,每一個 active-user 的 invalidation 可以有兩種做法,一個是設 expried 讓 redis 自動刪除,或是排成定時去掃 lastAPICallTime 已經超過某一個範圍的 active-user,這兩種方法都要能夠更新 active-user 的 lastAPICallTime ,可以在某些常用的 api 加入這個規則,或是給一隻 api 讓 frontend 去呼叫。
另外這邊只有統計 go-openmiddleware 的人數 c-pttbbs 要額外從 go-pttbbs 去拿才行

@tingyuchang
Copy link
Collaborator

Prometheus 的部分我研究之後,它可以很容易紀錄這些資料

  1. Counter: API 的呼叫數量、錯誤失敗的次數、任務執行的次數,只能增加或歸零
  2. Gauge: 可以增減的數字,拿來紀錄狀態:cpu, memory, go-routine 的數量等等
  3. Histogram & Summary: 可以做為統計數據的資料,像是 avg, mean, mid 等,所以可以拿來計算 request duration, response size 等需要一定數量的資料才有意義的數據

@chhsiao1981
Copy link
Collaborator Author

  1. 在線人數: 會是固定一段時間 (每分鐘或是每 10 mins) update 一次. update 結果放在 redis 裡.
    (所以 redis 裡只會有 1 個數字)
    update 的 source 可以從 mongo 拿到 go-openbbsmiddleware 和 go-pttbbs 拿到 c-pttbbs 的人數.
  2. 我們應該是只需要記我們自己想要用的 counter 就好囉~ prometheus go lib 就內建自動幫我們紀錄 system-level 的數字.
    histogram / summary 是 prometheus 自己內部的運作結果. 通常會直接用 grafana 呈現出來.

@tingyuchang tingyuchang self-assigned this Nov 8, 2021
@tingyuchang
Copy link
Collaborator

tingyuchang commented Nov 8, 2021

在線人數:ok 沒問題,那就改成從 mongo aggregate active api users,以及從 go-pttbbs 拿人數,加總之後寫入 redis ,這一個動作會寫入 cronjob 定期執行。
Prometheus: 目前看起來可以先搜集

  1. api 的呼叫次數
  2. api return error 的次數

使用 gin 的 middleware 應該可以比較簡單解決這個需求,有看到 opensource 或是自己寫應該也不複雜~

@tingyuchang
Copy link
Collaborator

我先從 active users 開始做,目前看了 db 裡面的 collection ,應該可以用 user_read_article user_read_board 兩個來完成 openbbsmiddle 這一端的上線人數。

btw 水球系統那邊未來應該有打算串 websocket ?也許那時候直接算 connecting client 的數量就好了~

@chhsiao1981
Copy link
Collaborator Author

剛剛想到是有可能 user_read_articleuser_read_board 重複算到~
是可以再開一個 collection 是 user_visit.
然後就 Update({UserID}, {UpdateNanoTS, Action})

然後就可以 Count({UpdateNanoTS > now - 10 mins})

@tingyuchang
Copy link
Collaborator

好,那我再建一個新的 collection: user_visit: user_id, update_nano_ts

@tingyuchang
Copy link
Collaborator

Screen Shot 2021-11-25 at 2 30 54 PM

  1. action 的部分先用 url 代替
  2. user_visit record 我的想法是一個 user 只會有一筆資料,會透過每一次的 api 呼叫來更新 user_visit 的內容

@chhsiao1981
Copy link
Collaborator Author

@tingyuchang

非常感謝!
大致上是 userVisit.Update({user_id: "matt"}, {Action: [url], UpdateNanoTS: 1234567890000000000}) 應該就可以囉~
(好像其實 action 還有 POST / GET 的區別~. 看看是否要加上 method)

@tingyuchang
Copy link
Collaborator

tingyuchang commented Nov 26, 2021

好,我會加上 method,另外我有注意到你的格式是
({user_id: "matt"}, {Action: [url], UpdateNanoTS: 1234567890000000000})
請問跟目前 document 的 json format 比
({user_id: "matt", Action: [url], UpdateNanoTS: 1234567890000000000})

是希望 user 獨立出一個 struct 嗎?

@chhsiao1981
Copy link
Collaborator Author

@tingyuchang

並不是喔~

Update 包含著 filter 和 update 的部分.

其中 {user_id: "meet"} 是 filter 的部分.
{Action: [url], UpdateNanoTS: 1234567890000000000} 是 update 的部分.

https://github.com/Ptt-official-app/go-openbbsmiddleware/blob/main/db/collection.go#L200

@tingyuchang
Copy link
Collaborator

喔喔,是我誤會了XD

@tingyuchang
Copy link
Collaborator

目前剩下的部分:

  1. 看板的在線人數
  2. Prometheus
  3. 其他待補充

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants