Two new utilities written in Go.
[xonotic/xonstat.git] / xonstat / util / xs_parselog.go
1 package main
2
3 import "bufio"
4 import "flag"
5 import "fmt"
6 import "os"
7 import "strings"
8
9 /* xs_parselog parses a standard XonStat log and breaks it down into
10    individual requests which are then saved into files. The file format
11    is <game type>_<match_id>.txt, so one can easily identify which type
12    of request the file contains and which one it is (the match_id is the
13    'I' line in the actual request).
14
15    There is also the ability to extract a specific match as well as to
16    anonymize the hashkeys in the requests to prevent exposing player data
17    unnecessarily. */
18 func main() {
19   var fn = flag.String("file", "xonstat.log", "XonStat log file name")
20   var target_match_id = flag.String("match", "", "the specific match_id (I line) to extract from the log")
21   var anonymize = flag.Bool("anonymize", false, "whether or not to anonymize player hashkeys")
22   flag.Parse()
23
24   f, err := os.Open(*fn)
25   if err != nil {
26     fmt.Println("Issue opening file")
27     os.Exit(1)
28   }
29   defer f.Close()
30
31   r := bufio.NewReader(f)
32
33   var inreq bool
34   var match_id string
35   var game_type_cd string
36   lines := make([]string, 0, 100)
37   hashkeys := make(map[string] int, 500)
38   max_player_id := 0
39
40   line, err := r.ReadString('\n')
41   for err == nil {
42     switch {
43       case strings.Contains(line, "BEGIN REQUEST BODY"):
44         inreq = true
45       case strings.Contains(line, "END REQUEST BODY"):
46         if *target_match_id == "" || match_id == *target_match_id {
47           create_match_file(game_type_cd, match_id, lines)
48         }
49         inreq = false
50         lines = make([]string, 0, 100)
51       case inreq:
52         if *anonymize && line[0] == 'P' {
53           if line[2:5] != "bot" && line[2:8] != "player" {
54             hashkey := line[2:len(line)-1]
55             if _, ok := hashkeys[hashkey]; !ok {
56               hashkeys[hashkey] = max_player_id
57               max_player_id = max_player_id + 1
58             }
59             line = fmt.Sprintf("P %d\n", hashkeys[hashkey])
60           }
61         }
62         if line[0] == 'I' {
63           match_id = line[2:len(line)-1]
64         }
65         if line[0] == 'G' {
66           game_type_cd = line[2:len(line)-1]
67         }
68         lines = append(lines, line)
69     }
70
71     line, err = r.ReadString('\n')
72   }
73 }
74
75
76 func create_match_file(game_type_cd string, match_id string, body []string) {
77   fn := fmt.Sprintf("%s_%s.txt", game_type_cd, match_id)
78   f_raw, err := os.Create(fn)
79   if err != nil {
80     fmt.Printf("Error creating match_id %s.\n", match_id)
81   }
82   defer f_raw.Close()
83
84   f := bufio.NewWriter(f_raw)
85   for _, v := range body {
86     fmt.Fprint(f, v)
87   }
88   f.Flush()
89 }