實時日誌瀏覽,通俗點來說就是跑到服務器上tail -f xxxx,然後盯着屏幕,看着它不斷的打日誌。當應用被部署在一臺服務器的時候,tail一下的確也可以解決問題了,但是隨着應用部署的服務器數量越來越多,服務器上的各類日誌數量的不斷增長,勢必就會造成日誌文件的瀏覽非常的不便。頻繁切換終端的窗口,切換切換着甚至自己都忘記究竟在哪臺服務器上,看的是那份日誌文件了。
今天看到一篇有關於log.io的文章,上傳送門《想實時 tail 多臺機器上面的日誌?試試 Log.io 或者 Sumo Logic 的新功能》,突然發現這個軟件正好就能解決小型團隊最容易碰到的實時日誌瀏覽的問題
Log.IO能做什麼
這個軟件的功能非常簡單,對的,非常簡單!不像Zabbix一樣具備非常多的隱藏技能,安裝過程非常簡單,
npm install -g log.io --user "root"
//啓動server
log.io-server
//修改一下配置,主要改服務器信息和日誌路徑
vi ~/.log.io/harvester.conf
//啓動採集器
log.io-harvester
//訪問頁面
http://localhost:28778
他就提供了一個看實時日誌的界面(原諒我突然就開啓了吐槽模式,你這會不會也太簡單了一點),不過總的來說,問題還是能解決的,左側的菜單思路是節點->應用名這樣的模式,這個倒是挺正派的,一個節點底下會有多份不同的日誌(話說作者不知道有沒考慮過給節點分個組呢),右側的就是應用了,勾選的日誌信息都會在這裏展現出來,其實單服務器的話倒是沒什麼問題,但是多服務器,刷日誌又刷的快的情況下,這個界面就會看的眼花繚亂了。
Log.IO源碼分析
站在巨人的肩膀上(有現成的就拿來抄)的思想是我一直所堅持的(這纔是生產力啊!ヽ( ^∀^)ノ),先看整體架構,直接上官方架構圖
做法是通過Harvester進行日誌採集,通過TCP送到Server,然後Server通過WebSocket送到web頁面上面。
Harvester的運轉方式
記錄指定日誌文件的Current Position,然後監控日誌文件的變化(NodeJS本身就挺多這樣的庫的),每當發生Change事件之後,往下讀文件
把變更的文件通過一定的格式採用TCP協議送到Server端
+log|web_server|my_server01|info|this is log messages
Server的運作方式
Server在接受到Harvester送來的的信息之後,把字符串變成LogObject、LogStream、LogNode等一系列對象
通過Socket.IO這個庫把日誌信息往外送,Socket.IO這個庫倒是挺簡單易用的,上個官網例子
var io = require('socket.io')(80);
var cfg = require('./config.json');
var tw = require('node-tweet-stream')(cfg);
tw.track('socket.io');
tw.track('javascript');
tw.on('tweet', function(tweet){
io.emit('tweet', tweet);
});
Web
Web的開發上倒是挺中規中矩的,採用比較流行的Express,然後通過WebSocket接收完數據之後就把對應的數據顯示在頁面上
一些想法
Log.IO這個應用代碼量非常的少,這種易讀性使得這個程序非常適合拿來改造(比起讀Kibana那界面的原源碼,這簡直就是天堂T_T),所以,不由的就產生了一些想法
對Harvester的一些想法
按照Harvester的運作方式來看,我認爲完全可以不採用log.io的Harvester,而直接採用類似Rsyslog這樣的大多數操作系統上都存在的日誌收集工具就可以了,免去Agent部署升級的煩惱。不然還不知道會不會碰上Agent性能不穩定搞掛服務器呢
對Server的一些想法
既然是WebSocket,那麼是不是可以採用類似在Nginx上加WebSocket擴展之類的做法來把Server替換掉呢?
log.io是不是能夠集成到ELK這類日誌搜索軟件裏面,作爲輔助功能存在呢?日誌先送到ES或者是一些其他地方,然後再通過一些Transfer程序把日誌送到Server
對Web的一些想法
Web這種操作上的東西,應各業務場景(個人品味。。。)不同會有比較大的差別,假如是我設計這個功能的原型,我會希望頁面上能有這樣的功能。
- 實時日誌按照時間分屏展示;
- 能夠在界面上輸入關鍵字,然後對關鍵字日誌高亮,方便排查問題;
- 再多一個業務模塊的分組,方便對整組業務模塊的服務器進行過濾;
- 根據提供的關鍵字信息,只展示具備關鍵字的日誌行(類似tail -f xxx|grep 這樣的功能);