/
buffer.go
95 lines (78 loc) · 1.99 KB
/
buffer.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
// Copyright 2017 The OPA Authors. All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.
package server
import (
"sync"
"time"
"github.com/open-policy-agent/opa/metrics"
"github.com/open-policy-agent/opa/topdown"
)
// Buffer defines an interface that the server can call to push diagnostic
// information about policy decisions. Buffers must be able to handle
// concurrent calls.
type Buffer interface {
// Push adds the given Info into the buffer.
Push(*Info)
// Iter iterates over the buffer, from oldest present Info to newest. It should
// call fn on each Info.
Iter(fn func(*Info))
}
// buffer stores diagnostic information.
type buffer struct {
ring []*Info
size int
start int // The index of the next item to pop.
end int // The index where the next item will be inserted.
sync.Mutex
}
// NewBoundedBuffer creates a new Buffer with maximum size n. NewBoundedBuffer
// will panic if n is not positive.
func NewBoundedBuffer(n int) Buffer {
if n <= 0 {
panic("size must be greater than 0")
}
return &buffer{ring: make([]*Info, n, n)}
}
func (b *buffer) Push(i *Info) {
b.Lock()
defer b.Unlock()
b.ring[b.end] = i
b.end = (b.end + 1) % len(b.ring)
switch b.size {
case len(b.ring): // We erased something, move the start up.
b.start = (b.start + 1) % len(b.ring)
default:
b.size++
}
}
func (b *buffer) Iter(fn func(*Info)) {
b.Lock()
defer b.Unlock()
i := b.start
for j := 0; j < b.size; j++ {
fn(b.ring[i])
i = (i + 1) % len(b.ring)
}
}
// Info contains information describing a policy decision.
type Info struct {
DecisionID string
RemoteAddr string
Query string
Timestamp time.Time
Input interface{}
Results *interface{}
Error error
Metrics metrics.Metrics
Trace []*topdown.Event
}
type diagSettings struct {
on bool
explain bool
}
var (
diagsOff = diagSettings{}
diagsOn = diagSettings{on: true}
diagsAll = diagSettings{on: true, explain: true}
)