-
Notifications
You must be signed in to change notification settings - Fork 0
/
log.go
165 lines (148 loc) · 3.75 KB
/
log.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
package LogAnalysis
import (
"bytes"
"encoding/json"
"log"
"strconv"
"strings"
"sync"
"time"
)
type LogData struct {
SessionID int `json:"session_id"`
ID int `json:"id"`
SeqNumber int `json:"seq_number"`
Method string `json:"method"`
Timestamp time.Time `json:"timestamp"`
Headers map[string]string `json:"headers"`
Payload interface{} `json:"payload"`
ExtraData string `json:"extra_data"`
}
// 模式
type Mode struct {
//序列
OrderList string
//统计有几个Session用了这个模式
SessionList []int
//通过相同的Mode
Sum int
}
// 方法调用序列模式包含的方法个数可以调整
const step = 2
var (
//统计
SessionMark map[int][]LogData
//作为模式计算的下表
MethodName []string
ModeMark map[string]Mode
Mutex sync.Mutex
)
func init() {
SessionMark = make(map[int][]LogData, 0)
ModeMark = make(map[string]Mode, 0)
}
func LogGetChan(lineChan chan []byte, endIndex int, sy *sync.WaitGroup) {
defer sy.Done()
for {
select {
case val, _ := <-lineChan:
//这个line记得这样写深复制,不能再翻同样的低级错误
line := make([]byte, len(val))
copy(line, val)
if bytes.Equal(line, []byte{'E', 'O', 'F'}) {
endIndex--
if endIndex == 0 {
return
}
continue
}
var _log LogData
err := json.Unmarshal(line, &_log)
if err != nil {
//log.Println(string(line))
log.Println("Unmarshal is fault : ", err)
continue
}
Mutex.Lock()
//数据装载
if _, ok := SessionMark[_log.SessionID]; ok {
SessionMark[_log.SessionID] = append(SessionMark[_log.SessionID], _log)
} else {
SessionMark[_log.SessionID] = []LogData{_log}
}
if !isHavedMethod(_log.Method) {
MethodName = append(MethodName, _log.Method)
}
Mutex.Unlock()
}
}
//数据导入结束,开始做数据汇总
}
func analysis() {
//先map一下方法
for SessionId, data := range SessionMark {
//最后一位也算进step 里面 所以要-1
for i := 0; i < len(data)-step+1; i++ {
//开始具体走
orderList := ""
for j := 0; j < step; j++ {
//如果用数字来优化感觉如果 method>0 要处理一下,肯定比字符串要好不少的
orderList += strconv.Itoa(getMethodId(data[i+j].Method))
}
if val, ok := ModeMark[orderList]; ok {
val.Sum++
//不要重复的
var repeat bool
for i := 0; i < len(val.SessionList); i++ {
if val.SessionList[i] == SessionId {
repeat = true
break
}
}
if !repeat {
val.SessionList = append(val.SessionList, SessionId)
}
ModeMark[orderList] = val
} else {
ModeMark[orderList] = Mode{OrderList: orderList, Sum: 1, SessionList: []int{SessionId}}
}
}
}
Max := 0
var MaxResult []string
log.Println("一共会话有:", len(SessionMark))
for _, mode := range ModeMark {
result := make([]string, 0)
for _, i := range mode.OrderList {
result = append(result, MethodName[i-'0'])
}
str := strings.Join(result, "->")
if mode.Sum > Max {
MaxResult = []string{str}
Max = mode.Sum
} else if mode.Sum == Max {
MaxResult = append(MaxResult, str)
}
log.Println("该模式:", str, "出现了:", mode.Sum, "次", "并且再 session id :", mode.SessionList, "出现过")
}
log.Println("一共会话有:", len(SessionMark))
log.Println("一共匹配模式有:", len(ModeMark))
log.Println("最大匹配的模式是:", strings.Join(MaxResult, ","), "次数为:", Max)
}
func getMethodId(method string) int {
for i := 0; i < len(MethodName); i++ {
if MethodName[i] == method {
return i
}
}
return -1
}
func isHavedMethod(method string) (Pass bool) {
for _, i2 := range MethodName {
if i2 == method {
Pass = true
break
}
}
return
}