Commit 9be51d24 by lichenggang

init

parents
# Binaries for programs and plugins
*.exe
*.dll
*.so
*.dylib
*.idea
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with IDE
*.out
.log
logs
.bat
.exe
.project
.sh
.vscode
debug
*.test
*.pyc
tmp
package main
import "code"
const (
Directory = "E:\\project\\see_log\\" // directory of the log
TestPort = 9998
)
// example
func main() {
code.See(Directory, TestPort)
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>seelog</title>
<link rel="shortcut icon" href="http://www.eiguo.cn/favicon.ico" type="image/x-icon" />
<!-- <link href="http://cdn.90so.net/layui/2.3.0/css/layui.css" rel="stylesheet" media="screen"> -->
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/html2canvas/0.5.0-beta4/html2canvas.min.js"></script>
<!-- <script src="http://cdn.90so.net/layui/2.3.0/layui.js"></script> -->
<script>
var out = true
var filterText = ""
function connect (){
var ws = new WebSocket("ws://"+ window.location.host +"/ws");
ws.onmessage = function(e) {
console.log(filterText)
if (out && (filterText == "" || e.data.indexOf(filterText) != -1)){
$('#log').append("<pre style='color: white;font-size: 15px'>"+ e.data +"</pre>").scrollTop($('#log')[0].scrollHeight)
}
};
ws.onclose = function () {
$('#status').css("background-color","red").text("链接断开")
reConnect()
}
ws.onopen = function () {
$('#status').css("background-color","chartreuse").text("连接成功")
}
ws.onerror = function (e) {
$('#status').css("background-color","red").text("链接断开")
}
}
function reConnect(){
setTimeout(function(){
connect();
},1000);
}
connect()
$(function () {
// 暂停
$('#pause').click(function () {
out = !out
if (out){
$(this).text('暂停').css("background-color","")
}else{
$(this).text('已暂停').css("background-color","red")
}
})
// 清屏
$('#clear').click(function () {
$('#log').empty()
})
// 截屏
$('#cut').click(function () {
printPhoto("log")
})
// 过滤
$('#filter').on('input',function () {
filterText = $('#filter').val()
})
})
// 截屏
function printPhoto(tab){
html2canvas(document.querySelector("#"+tab)).then(canvas => {
// 图片导出为 png 格式
var type = 'png';
var imgData = canvas.toDataURL(type);
var _fixType = function(type) {
type = type.toLowerCase().replace(/jpg/i, 'jpeg');
var r = type.match(/png|jpeg|bmp|gif/)[0];
return 'image/' + r;
};
// 加工image data,替换mime type
imgData = imgData.replace(_fixType(type),'image/octet-stream');
//console.log(imgData);
var saveFile = function(data, filename){
var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
save_link.href = data;
save_link.download = filename;
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
save_link.dispatchEvent(event);
};
// 下载后的文件名
var filename = 'seelog'+ '.' + type;
// download
saveFile(imgData,filename);
});
}
</script>
</head>
<body>
<header>
<h2 id="title">实时查看日志信息 &nbsp;<button id="status" style="background-color: darkorange">正在连接...</button></h2>
<div class="tool">
<button id="pause">暂停</button>
<button id="clear">清屏</button>
<button id="cut">截图</button>
<span style="padding:1px;border:1px ; background:#FFF"><button style="width: auto">过滤</button><input id="filter" type="text"></span>
</div>
</header>
<div id="log"></div>
</body>
<style>
body {
margin-left: 2%
}
#title {
}
#log {
width:96%;
height: 800px;
background-color:#181818;
border: 1px #ccc solid;
overflow-y: scroll;
margin-top: 10px;
padding-left: 12px;
float: left;
}
.tool button {
height: 30px;
width: 100px;
font-size: medium;
}
input {
background-color: lightyellow;
color: black;
font-size: medium;
position:absolute;
height: 25px;
}
</style>
</html>
\ No newline at end of file
package code
import (
"log"
"os"
"time"
)
// 监控日志文件
func monitor(filePath string) {
defer func() {
if err := recover(); err != nil {
log.Printf("[seelog] error:%+v", err)
}
}()
var fileInfo os.FileInfo
var err error
for i := 1; i <= 10; i++ {
fileInfo, err = os.Stat(filePath)
if err != nil {
log.Printf("[seelog] error:%v", err.Error())
continue
}
break
}
offset := fileInfo.Size()
for {
fileInfo, err = os.Stat(filePath)
if err != nil {
log.Printf("[seelog] error:%v", err.Error())
continue
}
newOffset := fileInfo.Size()
if offset < newOffset {
msg := make([]byte, newOffset-offset)
file, err := os.Open(filePath)
if err != nil {
log.Printf("[seelog] error:%v", err.Error())
continue
}
_, err = file.Seek(offset, 0)
if err != nil {
log.Printf("[seelog] error:%v", err.Error())
}
_, err = file.Read(msg)
if err != nil {
log.Printf("[seelog] error:%v", err.Error())
}
manager.broadcast <- msg
offset = newOffset
file.Close()
}
offset = newOffset
time.Sleep(200 * time.Millisecond)
}
}
package code
import (
"log"
"sync"
)
// 启动seelog
func See(filePath string, port int) {
var wg sync.WaitGroup
wg.Add(1)
// 检查参数
if !checkParam(filePath, port) {
return
}
//开启socket管理器
go manager.start()
go server(port, filePath)
wg.Wait()
}
// 参数验证
func checkParam(filePath string, port int) bool {
if filePath == "" {
log.Println("filePath 不可为空")
return false
}
if port == 0 {
log.Println("port 不可为空")
return false
}
return true
}
package code
import (
"bytes"
"fmt"
"golang.org/x/net/websocket"
"html/template"
"log"
"net/http"
"net/url"
"os"
"path/filepath"
"strconv"
"strings"
"time"
)
// 开启 httpServer
func server(port int, directory string) {
defer func() {
if err := recover(); err != nil {
log.Printf("[seelog] error:%+v", err)
}
}()
file_map := make(map[string]struct{})
// 返回页面
//http.HandleFunc("/log",page)
http.HandleFunc("/log", func(w http.ResponseWriter, r *http.Request) {
fileli := make(map[string]struct{})
filepath.Walk(directory, func(path string, info os.FileInfo, err error) error {
tmp := strings.Split(path, "\\") //todo linux下需要改动
filename := tmp[len(tmp)-1]
if strings.Contains(path, ".log") {
fileli[filename] = struct{}{}
}
return nil
})
queryform, err := url.ParseQuery(r.URL.RawQuery)
if err != nil {
log.Fatal(err)
}
li_filename := queryform["filename"]
filename := li_filename[0]
if _, ok := fileli[filename]; ok {
} else {
var ct bytes.Buffer
ct.WriteString("<script>alert(\"File not exist: ")
ct.WriteString(filename)
ct.WriteString("\")</script>")
w.Write([]byte(ct.String()))
return
}
// 监控文件
if _, ok := file_map[filename]; ok {
fmt.Printf("%s 已经被监控\n", filename)
} else {
go monitor(directory + filename)
file_map[filename] = struct{}{}
}
fmt.Println(filename)
w.Header().Set("Content-Type", "text/html")
w.WriteHeader(200)
t, err := template.ParseFiles("src/templates/page.html")
if err != nil {
log.Println("err:", err)
return
}
t.Execute(w, nil)
})
// socket链接
http.Handle("/ws", websocket.Handler(genConn))
// 测试
http.HandleFunc("/test", func(writer http.ResponseWriter, request *http.Request) {
t, err := template.ParseFiles("index.html")
if err != nil {
log.Println(err)
}
t.Execute(writer, nil)
})
var bt bytes.Buffer
bt.WriteString("127.0.0.1:")
bt.WriteString(strconv.Itoa(port))
http.ListenAndServe(bt.String(), nil)
//log.Fatal()
}
// 创建client对象
func genConn(ws *websocket.Conn) {
client := &client{time.Now().String(), ws, make(chan []byte, 1024)}
manager.register <- client
go client.read()
client.write()
}
package code
import (
"fmt"
"golang.org/x/net/websocket"
"log"
"os"
"time"
)
// websocket客户端
type client struct {
id string
socket *websocket.Conn
send chan []byte
}
// 客户端管理
type clientManager struct {
clients map[*client]bool
broadcast chan []byte
register chan *client
unregister chan *client
}
var manager = clientManager{
broadcast: make(chan []byte),
register: make(chan *client),
unregister: make(chan *client),
clients: make(map[*client]bool),
}
func (manager *clientManager) start() {
defer func() {
if err := recover(); err != nil {
log.Printf("[seelog] error:%+v", err)
}
}()
for {
select {
case conn := <-manager.register:
manager.clients[conn] = true
fmt.Printf("A client connect, current clients count is %d \n", len(manager.clients))
case conn := <-manager.unregister:
if _, ok := manager.clients[conn]; ok {
close(conn.send)
delete(manager.clients, conn)
fmt.Printf("A client disconnect, current clients count is %d \n", len(manager.clients))
}
case message := <-manager.broadcast:
for conn := range manager.clients {
select {
case conn.send <- message:
default:
close(conn.send)
delete(manager.clients, conn)
}
}
}
}
}
func (c *client) write() {
//defer func() {
// manager.unregister <- c
// c.socket.Close()
//}()
for {
select {
case message, ok := <-c.send:
if !ok {
c.socket.WriteClose(1)
return
}
c.socket.Write(message)
}
}
}
func (c *client) read() {
defer func() {
manager.unregister <- c
}()
//
for {
var reply string
if err := websocket.Message.Receive(c.socket, &reply); err != nil {
fmt.Println("Error! Can't receive message...")
break
}
if reply != "heart" {
manager.unregister <- c
c.socket.Close()
} else {
fmt.Println("heart package...")
}
reply = ""
//time.Sleep(2000 * time.Millisecond)
//jsonMessage, _ := json.Marshal(&Message{Sender: c.id, Content: string(message)})
//manager.broadcast <- jsonMessage
}
}
func (c *client) monitor(filePath string) {
defer func() {
if err := recover(); err != nil {
log.Printf("[seelog] error:%+v", err)
}
}()
var fileInfo os.FileInfo
var err error
for i := 1; i <= 10; i++ {
fileInfo, err = os.Stat(filePath)
if err != nil {
log.Printf("[seelog] error:%v", err.Error())
continue
}
break
}
offset := fileInfo.Size()
for {
fileInfo, err = os.Stat(filePath)
if err != nil {
log.Printf("[seelog] error:%v", err.Error())
continue
}
newOffset := fileInfo.Size()
if offset < newOffset {
msg := make([]byte, newOffset-offset)
file, err := os.Open(filePath)
if err != nil {
log.Printf("[seelog] error:%v", err.Error())
continue
}
_, err = file.Seek(offset, 0)
if err != nil {
log.Printf("[seelog] error:%v", err.Error())
}
_, err = file.Read(msg)
if err != nil {
log.Printf("[seelog] error:%v", err.Error())
}
manager.broadcast <- msg
offset = newOffset
file.Close()
}
offset = newOffset
time.Sleep(200 * time.Millisecond)
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>seelog</title>
<link rel="shortcut icon" href="http://www.eiguo.cn/favicon.ico" type="image/x-icon" />
<!-- <link href="http://cdn.90so.net/layui/2.3.0/css/layui.css" rel="stylesheet" media="screen"> -->
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/html2canvas/0.5.0-beta4/html2canvas.min.js"></script>
<!-- <script src="http://cdn.90so.net/layui/2.3.0/layui.js"></script> -->
<script>
var out = true
var filterText = ""
function connect (){
var ws = new WebSocket("ws://"+ window.location.host +"/ws");
ws.onmessage = function(e) {
console.log(filterText)
if (out && (filterText == "" || e.data.indexOf(filterText) != -1)){
$('#log').append("<pre style='color: white;font-size: 15px'>"+ e.data +"</pre>").scrollTop($('#log')[0].scrollHeight)
}
};
ws.onclose = function () {
$('#status').css("background-color","red").text("链接断开")
reConnect()
}
ws.onopen = function () {
$('#status').css("background-color","chartreuse").text("连接成功")
}
ws.onerror = function (e) {
$('#status').css("background-color","red").text("链接断开")
}
// function send_heart() {
// ws.send("heart")
// }
// setInterval(send_heart, 10000)
}
function reConnect(){
setTimeout(function(){
connect();
},1000);
}
connect()
$(function () {
// 暂停
$('#pause').click(function () {
out = !out
if (out){
$(this).text('暂停').css("background-color","")
}else{
$(this).text('已暂停').css("background-color","red")
}
})
// 清屏
$('#clear').click(function () {
$('#log').empty()
})
// 截屏
$('#cut').click(function () {
printPhoto("log")
})
// 过滤
$('#filter').on('input',function () {
filterText = $('#filter').val()
})
})
// 截屏
function printPhoto(tab){
html2canvas(document.querySelector("#"+tab)).then(canvas => {
// 图片导出为 png 格式
var type = 'png';
var imgData = canvas.toDataURL(type);
var _fixType = function(type) {
type = type.toLowerCase().replace(/jpg/i, 'jpeg');
var r = type.match(/png|jpeg|bmp|gif/)[0];
return 'image/' + r;
};
// 加工image data,替换mime type
imgData = imgData.replace(_fixType(type),'image/octet-stream');
//console.log(imgData);
var saveFile = function(data, filename){
var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
save_link.href = data;
save_link.download = filename;
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
save_link.dispatchEvent(event);
};
// 下载后的文件名
var filename = 'seelog'+ '.' + type;
// download
saveFile(imgData,filename);
});
}
</script>
</head>
<body>
<header>
<h2 id="title">实时查看日志信息 &nbsp;<button id="status" style="background-color: darkorange">正在连接...</button></h2>
<div class="tool">
<button id="pause">暂停</button>
<button id="clear">清屏</button>
<button id="cut">截图</button>
<span style="padding:1px;border:1px ; background:#FFF"><button style="width: auto">过滤</button><input id="filter" type="text"></span>
</div>
</header>
<div id="log"></div>
</body>
<style>
body {
margin-left: 2%
}
#title {
}
#log {
width:96%;
height: 800px;
background-color:#181818;
border: 1px #ccc solid;
overflow-y: scroll;
margin-top: 10px;
padding-left: 12px;
float: left;
}
.tool button {
height: 30px;
width: 100px;
font-size: medium;
}
input {
background-color: lightyellow;
color: black;
font-size: medium;
position:absolute;
height: 25px;
}
</style>
</html>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment