github.com/m3db/m3@v1.5.0/src/query/graphite/common/context.go (about) 1 // Copyright (c) 2019 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package common 22 23 import ( 24 ctx "context" 25 "sync" 26 "time" 27 28 "github.com/m3db/m3/src/query/graphite/context" 29 "github.com/m3db/m3/src/query/storage" 30 ) 31 32 // contextBase are the real content of a Context, minus the lock so that we 33 // can safely copy a context without violating the rules of go vet. 34 // nolint 35 type contextBase struct { 36 // TimeRangeAdjusted is a boolean indicating whether the time range has an adjustment. 37 TimeRangeAdjusted bool 38 39 // The start time to query against. 40 StartTime time.Time 41 42 // The end time to query against. 43 EndTime time.Time 44 45 // TimeRangeAdjustment is the time range adjustment made to the query. 46 TimeRangeAdjustment TimeRangeAdjustment 47 48 // The underlying engine. 49 Engine QueryEngine 50 51 // Trace records traces. 52 Trace Tracer 53 54 // Timeout indicates whether to use a custom timeout when fetching data, 55 // specify zero to indicate default timeout or a positive value 56 Timeout time.Duration 57 58 // Source is the query source. 59 Source []byte 60 61 // MaxDataPoints is the max datapoints for the query. 62 MaxDataPoints int64 63 64 // FetchOpts are the fetch options to use for the query. 65 FetchOpts *storage.FetchOptions 66 67 parent *Context 68 reqCtx ctx.Context 69 storageContext context.Context 70 } 71 72 // Context is the parameters to a query evaluation. 73 type Context struct { 74 sync.RWMutex 75 contextBase 76 } 77 78 // ContextOptions provides the options to create the context with 79 type ContextOptions struct { 80 Start time.Time 81 End time.Time 82 Engine QueryEngine 83 Timeout time.Duration 84 MaxDataPoints int64 85 FetchOpts *storage.FetchOptions 86 } 87 88 // TimeRangeAdjustment is an applied time range adjustment. 89 type TimeRangeAdjustment struct { 90 OriginalStart time.Time 91 OriginalEnd time.Time 92 ShiftStart time.Duration 93 ShiftEnd time.Duration 94 ExpandStart time.Duration 95 ExpandEnd time.Duration 96 } 97 98 // NewContext creates a new context. 99 func NewContext(options ContextOptions) *Context { 100 return &Context{ 101 contextBase: contextBase{ 102 StartTime: options.Start, 103 EndTime: options.End, 104 Engine: options.Engine, 105 storageContext: context.New(), 106 Timeout: options.Timeout, 107 MaxDataPoints: options.MaxDataPoints, 108 FetchOpts: options.FetchOpts, 109 }, 110 } 111 } 112 113 // TracingEnabled checks whether tracing is enabled for this context. 114 func (c *Context) TracingEnabled() bool { return c.Trace != nil } 115 116 // ChildContextOptions is a set of options to pass when creating a child context. 117 type ChildContextOptions struct { 118 adjustment struct { 119 adjusted bool 120 shiftStart time.Duration 121 shiftEnd time.Duration 122 expandStart time.Duration 123 expandEnd time.Duration 124 } 125 } 126 127 // NewChildContextOptions returns an initialized ChildContextOptions struct. 128 func NewChildContextOptions() ChildContextOptions { 129 return ChildContextOptions{} 130 } 131 132 // AdjustTimeRange will adjust the child context's time range. 133 func (o *ChildContextOptions) AdjustTimeRange( 134 shiftStart, shiftEnd, expandStart, expandEnd time.Duration, 135 ) { 136 if shiftStart == 0 && shiftEnd == 0 && expandStart == 0 && expandEnd == 0 { 137 // Not an adjustment, don't mark "adjusted" true 138 return 139 } 140 o.adjustment.adjusted = true 141 o.adjustment.shiftStart = shiftStart 142 o.adjustment.shiftEnd = shiftEnd 143 o.adjustment.expandStart = expandStart 144 o.adjustment.expandEnd = expandEnd 145 } 146 147 // NewChildContext creates a child context. Child contexts can have any of 148 // their parameters modified, but share the same underlying storage context. 149 func (c *Context) NewChildContext(opts ChildContextOptions) *Context { 150 // create a duplicate of the parent context with an independent lock 151 // (otherwise `go vet` complains due to the -copylock check) 152 c.RLock() 153 child := &Context{ 154 contextBase: c.contextBase, 155 } 156 child.parent = c 157 c.RUnlock() 158 159 origStart, origEnd := child.StartTime, child.EndTime 160 if child.TimeRangeAdjusted { 161 origStart, origEnd = c.TimeRangeAdjustment.OriginalStart, c.TimeRangeAdjustment.OriginalEnd 162 } 163 164 if opts.adjustment.adjusted { 165 child.TimeRangeAdjusted = true 166 child.TimeRangeAdjustment.OriginalStart = origStart 167 child.TimeRangeAdjustment.OriginalEnd = origEnd 168 child.TimeRangeAdjustment.ShiftStart += opts.adjustment.shiftStart 169 child.TimeRangeAdjustment.ShiftEnd += opts.adjustment.shiftEnd 170 child.TimeRangeAdjustment.ExpandStart += opts.adjustment.expandStart 171 child.TimeRangeAdjustment.ExpandEnd += opts.adjustment.expandEnd 172 173 child.StartTime = origStart. 174 Add(child.TimeRangeAdjustment.ShiftStart). 175 Add(-child.TimeRangeAdjustment.ExpandStart) 176 child.EndTime = origEnd. 177 Add(child.TimeRangeAdjustment.ShiftEnd). 178 Add(child.TimeRangeAdjustment.ExpandEnd) 179 } 180 181 child.reqCtx = c.reqCtx 182 return child 183 } 184 185 // Close closes the context 186 func (c *Context) Close() error { 187 if c.parent != nil { 188 // Closing a child context is meaningless. 189 return nil 190 } 191 192 return c.storageContext.Close() 193 } 194 195 // SetRequestContext sets the given context as the request context for this 196 // execution context. This is used for calls to the m3 storage wrapper. 197 func (c *Context) SetRequestContext(reqCtx ctx.Context) { 198 c.Lock() 199 c.reqCtx = reqCtx 200 c.Unlock() 201 } 202 203 // RequestContext will provide the wrapped request context. Used for calls 204 // to m3 storage wrapper. 205 func (c *Context) RequestContext() ctx.Context { 206 c.RLock() 207 r := c.reqCtx 208 c.RUnlock() 209 return r 210 } 211 212 // RegisterCloser registers a new Closer with the context. 213 func (c *Context) RegisterCloser(closer context.Closer) { 214 c.storageContext.RegisterCloser(closer) 215 } 216 217 // AddAsyncTasks adds tracked asynchronous task(s) 218 func (c *Context) AddAsyncTasks(count int) { 219 c.storageContext.AddAsyncTasks(count) 220 } 221 222 // DoneAsyncTask marks a single tracked asynchronous task complete 223 func (c *Context) DoneAsyncTask() { 224 c.storageContext.DoneAsyncTask() 225 } 226 227 // A Trace is tracing information about a function or fetch within a query. 228 type Trace struct { 229 // ActivityName is the name of the activity being traced. 230 ActivityName string 231 232 // Duration is the amount of time it took to execute the activity. 233 Duration time.Duration 234 235 // Inputs are the number of timeseries processed by the trace. 236 Inputs []TraceStats 237 238 // Outputs is the number of timeseries returned by the trace. 239 Outputs TraceStats 240 } 241 242 // TraceStats tracks the number of timeseries used by a trace. 243 type TraceStats struct { 244 NumSeries int // number of timeseries being acted on 245 } 246 247 // A Tracer is used to record a Trace. 248 type Tracer func(t Trace)