Compare commits

..
6 Commits
Author SHA1 Message Date
Akizon 9dd09731bd Merge pull request #100 from komari-monitor/dev
feat: 补全相关日志记录
2025-07-04 00:47:00 +08:00
Akizon77 963c829164 feat: 添加重试机制以增强消息发送的可靠性 2025-07-04 00:45:43 +08:00
Akizon77 d01fafbf0f feat: 更新终端相关日志记录 2025-07-04 00:42:50 +08:00
Akizon77 729db05346 feat: 增强cloudflared运行时日志记录,添加错误处理和成功退出日志 2025-07-04 00:35:25 +08:00
Akizon 70dc06a761 Merge pull request #90 from komari-monitor/dev
docs: 更新 Agent 开发指南
2025-07-01 22:40:38 +08:00
Akizon77 be059b7aa3 feat: 更新 Agent 开发指南 2025-07-01 22:39:36 +08:00
7 changed files with 77 additions and 107 deletions

No files matched your search

+3 -43
View File
@@ -78,7 +78,7 @@ Komari 是一款轻量级的自托管服务器监控工具,旨在提供简单
这个坑晚点再填吧 ヽ( ̄ω ̄( ̄ω ̄〃)ゝ
## 客户端 Agent 开发指南
这个坑晚点再填吧 (o゜▽゜)o☆
[Komari Agent 信息上报与事件处理文档](https://komari-monitor.github.io/komari-document/dev/agent.html)
## 贡献
欢迎提交 Issue 或 Pull Request!
@@ -87,46 +87,6 @@ Komari 是一款轻量级的自托管服务器监控工具,旨在提供简单
- 感谢我自己能这么闲
- 广告位招租喵
## 引用
- [gorm.io](https://gorm.io/)
- [spf13/cobra](https://github.com/spf13/cobra)
- [oschwald/maxminddb-golang](https://github.com/oschwald/maxminddb-golang)
- [gorilla/websocket](https://github.com/gorilla/websocket)
- [google/uuid](https://github.com/google/uuid)
- [gin-gonic/gin](https://github.com/gin-gonic/gin)
- [UserExistsError/conpty](https://github.com/UserExistsError/conpty)
- [creack/pty](https://github.com/creack/pty)
- [rhysd/go-github-selfupdate](https://github.com/rhysd/go-github-selfupdate)
- [shirou/gopsutil](https://github.com/shirou/gopsutil)
## 许可证
[MIT License](LICENSE)
## 截图
![PixPin_2025-06-07_15-28-30](https://github.com/user-attachments/assets/edce5694-c6c8-4647-bc11-8b27105fd55c)
![PixPin_2025-06-07_15-28-49](https://github.com/user-attachments/assets/23b58032-211a-4b59-b444-c8267606a0bb)
![PixPin_2025-06-07_15-29-05](https://github.com/user-attachments/assets/f4325d4d-fa69-41c6-9251-19f530476e65)
![PixPin_2025-06-07_15-30-05](https://github.com/user-attachments/assets/69be38f6-6681-4afb-9a04-965d39b7fcc2)
![PixPin_2025-06-07_15-30-46](https://github.com/user-attachments/assets/01d84dd1-3c81-4424-a041-7dbc2ae5822e)
## 碎碎念
### 我为什么做Komari?
起因: [求推荐系统监控软件](https://www.nodeseek.com/post-133745-1)
> @古xx斯
> 哪吒?
> > 数据至少保存15天
> @sxxu
> 怕不是做梦的预算
> @Vxxn
> prometheus加grafana
> > 部署太麻烦
没有合适的,最近刚好时间稍微多了一些,就搓了 komari.
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=komari-monitor/komari&type=Date)](https://www.star-history.com/#komari-monitor/komari&Date)
+5 -4
View File
@@ -23,10 +23,11 @@ var (
)
type TerminalSession struct {
UUID string
UserUUID string
Browser *websocket.Conn
Agent *websocket.Conn
UUID string
UserUUID string
Browser *websocket.Conn
Agent *websocket.Conn
RequesterIp string
}
var TerminalSessionsMutex = &sync.Mutex{}
+8 -7
View File
@@ -41,10 +41,11 @@ func RequestTerminal(c *gin.Context) {
// 新建一个终端连接
id := utils.GenerateRandomString(32)
session := &TerminalSession{
UserUUID: user_uuid.(string),
UUID: uuid,
Browser: conn,
Agent: nil,
UserUUID: user_uuid.(string),
UUID: uuid,
Browser: conn,
Agent: nil,
RequesterIp: c.ClientIP(),
}
TerminalSessionsMutex.Lock()
@@ -95,7 +96,7 @@ func RequestTerminal(c *gin.Context) {
}
TerminalSessionsMutex.Unlock()
})
logOperation.Log(c.ClientIP(), user_uuid.(string), "request, terminal id:"+id+",client:"+session.UUID, "terminal")
//logOperation.Log(c.ClientIP(), user_uuid.(string), "request, terminal id:"+id+",client:"+session.UUID, "terminal")
}
func ForwardTerminal(id string) {
@@ -104,7 +105,7 @@ func ForwardTerminal(id string) {
if !exists || session == nil || session.Agent == nil || session.Browser == nil {
return
}
logOperation.Log("", session.UserUUID, "established, terminal id:"+id, "terminal")
logOperation.Log(session.RequesterIp, session.UserUUID, "established, terminal id:"+id, "terminal")
established_time := time.Now()
errChan := make(chan error, 1)
@@ -161,7 +162,7 @@ func ForwardTerminal(id string) {
session.Browser.Close()
}
disconnect_time := time.Now()
logOperation.Log("", session.UserUUID, "disconnected, terminal id:"+id+", duration:"+disconnect_time.Sub(established_time).String(), "terminal")
logOperation.Log(session.RequesterIp, session.UserUUID, "disconnected, terminal id:"+id+", duration:"+disconnect_time.Sub(established_time).String(), "terminal")
TerminalSessionsMutex.Lock()
delete(TerminalSessions, id)
TerminalSessionsMutex.Unlock()
+8 -2
View File
@@ -124,6 +124,14 @@ func RunCloudflared() error {
log.Printf("[cloudflared] %s", scanner.Text())
}
}()
go func() {
if err := cmd.Wait(); err != nil {
log.Printf("cloudflared exited with error: %v", err)
} else {
log.Println("cloudflared exited successfully")
}
os.Exit(1)
}()
log.Println("cloudflared started")
return nil
}
@@ -137,7 +145,5 @@ func Kill() {
log.Println("cloudflared killed")
}
cloudflaredCmd = nil
} else {
log.Println("cloudflared is not running")
}
}
+2 -2
View File
@@ -117,13 +117,13 @@ func GetGeoInfo(ip net.IP) (*GeoInfo, error) {
cacheKey := providerName + ":" + ip.String()
if cachedInfo, found := geoCache.Get(cacheKey); found {
log.Println("GeoIP cache hit for", cacheKey)
//log.Println("GeoIP cache hit for", cacheKey)
return cachedInfo.(*GeoInfo), nil
}
info, err := CurrentProvider.GetGeoInfo(ip)
if err == nil && info != nil {
log.Println("GeoIP cache miss for", cacheKey)
//log.Println("GeoIP cache miss for", cacheKey)
geoCache.Set(cacheKey, info, cache.DefaultExpiration)
}
return info, err
+11 -1
View File
@@ -2,6 +2,7 @@ package messageSender
import (
"github.com/komari-monitor/komari/database/config"
"github.com/komari-monitor/komari/database/logOperation"
)
var CurrentProvider MessageSender
@@ -34,5 +35,14 @@ type MessageSender interface {
}
func SendTextMessage(message string, title string) error {
return CurrentProvider.SendTextMessage(message, title)
var err error
for i := 0; i < 3; i++ {
err = CurrentProvider.SendTextMessage(message, title)
if err == nil {
logOperation.Log("", "", "Message sent: "+title, "info")
return nil
}
}
logOperation.Log("", "", "Failed to send message after 3 attempts: "+err.Error(), "error")
return err
}
+40 -48
View File
@@ -21,52 +21,44 @@ func (t *TelegramMessageSender) SendTextMessage(message, title string) error {
fullMessage = fmt.Sprintf("<b>%s</b>\n%s", title, message)
}
var lastErr error
for i := 0; i < 3; i++ { // Retry mechanism
conf, err := config.Get()
if err != nil {
lastErr = err
continue
}
if fullMessage == "" {
return errors.New("telegram is disabled or message is empty") // Assuming disabled if message is empty
}
endpoint := conf.TelegramEndpoint + conf.TelegramBotToken + "/sendMessage"
data := url.Values{}
data.Set("chat_id", conf.TelegramChatID)
data.Set("text", fullMessage)
data.Set("parse_mode", "HTML") // Use HTML for basic formatting if title is present
resp, err := http.PostForm(endpoint, data)
if err != nil {
lastErr = fmt.Errorf("failed to send message: %v", err)
continue
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
lastErr = fmt.Errorf("telegram API returned non-OK status: %d", resp.StatusCode)
continue
}
var result struct {
Ok bool `json:"ok"`
Description string `json:"description"`
}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
lastErr = err
continue
}
if !result.Ok {
lastErr = fmt.Errorf("telegram API error: %s", result.Description)
continue
}
return nil
var err error
conf, err := config.Get()
if err != nil {
return err
}
return lastErr
}
if fullMessage == "" {
return errors.New("message is empty")
}
endpoint := conf.TelegramEndpoint + conf.TelegramBotToken + "/sendMessage"
data := url.Values{}
data.Set("chat_id", conf.TelegramChatID)
data.Set("text", fullMessage)
data.Set("parse_mode", "HTML")
resp, err := http.PostForm(endpoint, data)
if err != nil {
return fmt.Errorf("failed to send message: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("telegram API returned non-OK status: %d", resp.StatusCode)
}
var result struct {
Ok bool `json:"ok"`
Description string `json:"description"`
}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return err
}
if !result.Ok {
return fmt.Errorf("telegram API error: %s", result.Description)
}
return nil
}