Parse events transforms raw events into events. It does analyze and verify per-event-type arguments.
(rawEvents []rawEvent)
| 151 | // Parse events transforms raw events into events. |
| 152 | // It does analyze and verify per-event-type arguments. |
| 153 | func parseEvents(rawEvents []rawEvent) (events []*Event, err error) { |
| 154 | var ticksPerSec, lastSeq, lastTs int64 |
| 155 | var lastG, timerGoid uint64 |
| 156 | var lastP int |
| 157 | lastGs := make(map[int]uint64) // last goroutine running on P |
| 158 | stacks := make(map[uint64][]*Frame) |
| 159 | for _, raw := range rawEvents { |
| 160 | if raw.typ == EvNone || raw.typ >= EvCount { |
| 161 | err = fmt.Errorf("unknown event type %v at offset 0x%x", raw.typ, raw.off) |
| 162 | return |
| 163 | } |
| 164 | desc := EventDescriptions[raw.typ] |
| 165 | if desc.Name == "" { |
| 166 | err = fmt.Errorf("missing description for event type %v", raw.typ) |
| 167 | return |
| 168 | } |
| 169 | if raw.typ != EvStack { |
| 170 | narg := len(desc.Args) |
| 171 | if desc.Stack { |
| 172 | narg++ |
| 173 | } |
| 174 | if raw.typ != EvBatch && raw.typ != EvFrequency && raw.typ != EvTimerGoroutine { |
| 175 | narg++ // sequence number |
| 176 | narg++ // timestamp |
| 177 | } |
| 178 | if len(raw.args) != narg { |
| 179 | err = fmt.Errorf("%v has wrong number of arguments at offset 0x%x: want %v, got %v", |
| 180 | desc.Name, raw.off, narg, len(raw.args)) |
| 181 | return |
| 182 | } |
| 183 | } |
| 184 | switch raw.typ { |
| 185 | case EvBatch: |
| 186 | lastGs[lastP] = lastG |
| 187 | lastP = int(raw.args[0]) |
| 188 | lastG = lastGs[lastP] |
| 189 | lastSeq = int64(raw.args[1]) |
| 190 | lastTs = int64(raw.args[2]) |
| 191 | case EvFrequency: |
| 192 | ticksPerSec = int64(raw.args[0]) |
| 193 | if ticksPerSec <= 0 { |
| 194 | // The most likely cause for this is tick skew on different CPUs. |
| 195 | // For example, solaris/amd64 seems to have wildly different |
| 196 | // ticks on different CPUs. |
| 197 | err = ErrTimeOrder |
| 198 | return |
| 199 | } |
| 200 | case EvTimerGoroutine: |
| 201 | timerGoid = raw.args[0] |
| 202 | case EvStack: |
| 203 | if len(raw.args) < 2 { |
| 204 | err = fmt.Errorf("EvStack has wrong number of arguments at offset 0x%x: want at least 2, got %v", |
| 205 | raw.off, len(raw.args)) |
| 206 | return |
| 207 | } |
| 208 | size := raw.args[1] |
| 209 | if size > 1000 { |
| 210 | err = fmt.Errorf("EvStack has bad number of frames at offset 0x%x: %v", |