github.com/rajeev159/opa@v0.45.0/topdown/lineage/lineage.go (about) 1 // Copyright 2019 The OPA Authors. All rights reserved. 2 // Use of this source code is governed by an Apache2 3 // license that can be found in the LICENSE file. 4 5 package lineage 6 7 import ( 8 "github.com/open-policy-agent/opa/topdown" 9 ) 10 11 // Notes returns a filtered trace that contains Note events and context to 12 // understand where the Note was emitted. 13 func Notes(trace []*topdown.Event) []*topdown.Event { 14 return Filter(trace, func(event *topdown.Event) bool { 15 return event.Op == topdown.NoteOp 16 }) 17 } 18 19 // Fails returns a filtered trace that contains Fail events and context to 20 // understand where the Fail occurred. 21 func Fails(trace []*topdown.Event) []*topdown.Event { 22 return Filter(trace, func(event *topdown.Event) bool { 23 return event.Op == topdown.FailOp 24 }) 25 } 26 27 // Filter will filter a given trace using the specified filter function. The 28 // filtering function should return true for events that should be kept, false 29 // for events that should be filtered out. 30 func Filter(trace []*topdown.Event, filter func(*topdown.Event) bool) (result []*topdown.Event) { 31 32 qids := map[uint64]*topdown.Event{} 33 34 for _, event := range trace { 35 36 if filter(event) { 37 // Path will end with the Note event. 38 path := []*topdown.Event{event} 39 40 // Construct path of recorded Enter/Redo events that lead to the 41 // Note event. The path is constructed in reverse order by iterating 42 // backwards through the Enter/Redo events from the Note event. 43 curr := qids[event.QueryID] 44 var prev *topdown.Event 45 46 for curr != nil && curr != prev { 47 path = append(path, curr) 48 prev = curr 49 curr = qids[curr.ParentID] 50 } 51 52 // Add the path to the result, reversing it in the process. 53 for i := len(path) - 1; i >= 0; i-- { 54 result = append(result, path[i]) 55 } 56 57 qids = map[uint64]*topdown.Event{} 58 } 59 60 if event.Op == topdown.EnterOp || event.Op == topdown.RedoOp { 61 if event.HasRule() || event.HasBody() { 62 qids[event.QueryID] = event 63 } 64 } 65 } 66 67 return result 68 }