Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability for query storage to provide unconsolidated blocks #929

Merged
merged 4 commits into from
Oct 1, 2018

Conversation

nikunjgit
Copy link
Contributor

@nikunjgit nikunjgit commented Sep 21, 2018

No description provided.

@@ -36,6 +36,11 @@ type columnBlock struct {
seriesMeta []SeriesMeta
}

// Unconsolidated returns the unconlidated version for the block
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/unconlidated/unconsolidated

@@ -36,6 +36,11 @@ type columnBlock struct {
seriesMeta []SeriesMeta
}

// Unconsolidated returns the unconlidated version for the block
func (c *columnBlock) Unconsolidated() (UnconsolidatedBlock, error) {
return nil, fmt.Errorf("unconslidated block not support for block, meta: %s", c.meta)
Copy link
Collaborator

@benraskin92 benraskin92 Sep 21, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reword error and check spelling

@@ -47,6 +47,11 @@ func NewScalar(val float64, bounds models.Bounds) Block {
}
}

// Unconsolidated returns the unconlidated version for the block
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comments as above

return len(s.datapoints)
}

// Consolidated conslidates the series
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/conslidates/consolidates

}

// Type assertion
var _ ConsolidationFunc = TakeLast
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this needed for exactly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to ensure TakeLast actually implements ConsolidationFunc. I guess i can remove it since multiSeriesBlock Consolidate will throw a compilation error if TakeLast doesn't implement it

@@ -145,6 +145,23 @@ type lazyBlock struct {
processedBlock block.Block
}

// Unconsolidated returns the unconlidated version for the block
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/unconlidated/unconsolidated

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/for the block/of the block

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we use "for the block" in most other places.

return f.processedBlock.Unconsolidated()
}

err := f.process()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if err := f.process(); err != nil {
   return nil, err
}

sum := 0.0
for _, n := range f {
for _, n := range vals {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}

func (c *consolidatedBlock) Unconsolidated() (block.UnconsolidatedBlock, error) {
return nil, fmt.Errorf("unconsolidated blocks are not supported")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errors.New("unconsolidated blocks are not supported")

return c.unconsolidated.Close()
}

type consolidateStepIter struct {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consolidatedStepIter?

return c.unconsolidated.Meta()
}

type consolidateSeriesIter struct {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consolidatedSeriesIter?

@@ -47,6 +47,11 @@ func NewScalar(val float64, bounds models.Bounds) Block {
}
}

// Unconsolidated returns the unconlidated version for the block
func (b *Scalar) Unconsolidated() (UnconsolidatedBlock, error) {
return nil, fmt.Errorf("unconslidated block not support for block, meta: %s", b.meta)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be a notImplemented error, since scalars should be fine to have unconsolidated

return UnconsolidatedSeries{datapoints: datapoints, Meta: meta}
}

// DatapointsAtStep returns the raw datapoints at a step index
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: DatapointAtStep returns the raw datapoint at a step index

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's returning multiple datapoints ?


// DatapointsAtStep returns the raw datapoints at a step index
func (s UnconsolidatedSeries) DatapointsAtStep(idx int) ts.Datapoints {
return s.datapoints[idx]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should perform bound checks

)

// Block represents a group of series across a time bound
type Block interface {
// Unconsolidated returns the unconsolidated version of the block
Unconsolidated() (UnconsolidatedBlock, error)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe rather than error it could return a bool to indicate if it can be unconsolidated?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even for things which can support unconsolidated, you can still get an error. So we need an error here neverthless. I like this over having a bool so that clients don't check 2 things

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit weird; you may want to continue and do something different if you can't consolidate because you errored vs your block being unable to block, but that could be changed later if necessary

func seriesValuesToDatapoints(values []float64, bounds models.Bounds) ts.Datapoints {
dps := make(ts.Datapoints, len(values))
for i, v := range values {
t, _ := bounds.TimeForIndex(i)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need the second arg here otherwise you'll have a nil timestamp

Copy link
Contributor Author

@nikunjgit nikunjgit Sep 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was assuming we'd just provide values within bounds for tests. Didn't want each test to check for error. A better approach i suppose it for tests to pass in testing.T object but that requires too many changes and didn't look very useful

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad didn't catch these were test utilities

// SeriesMeta returns the metadata for each series in the block
SeriesMeta() []SeriesMeta
// Meta returns the metadata for the block
Meta() Metadata
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can roll these into a single interface and share that with StepIter

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, might be a good idea to pull

		// SeriesMeta returns the metadata for each series in the block
	SeriesMeta() []SeriesMeta
	// Meta returns the metadata for the block
	Meta() Metadata

into a single interface since a lot of these use them

dps := seriesValuesToDatapoints(values, bounds)
seriesList[i] = ts.NewSeries(meta[i].Name, dps, meta[i].Tags)
}
b, _ := storage.NewMultiSeriesBlock(seriesList, &storage.FetchQuery{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: newline

* THE SOFTWARE.
*/

package storage
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: rename to consolidated.go

return c.unconsolidated.Close()
}

type consolidateStepIter struct {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: rename to consolidatedStepIter

return c.unconsolidated.Meta()
}

type consolidateSeriesIter struct {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: rename to consolidatedSeriesIter

for i, values := range seriesValues {
dps := seriesValuesToDatapoints(values, bounds)
seriesList[i] = ts.NewSeries(meta[i].Name, dps, meta[i].Tags)
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: newline


// Aligned returns values aligned to given bounds.
func (d Datapoints) Aligned(bounds models.Bounds) []Datapoints {
numDatapoints := len(d)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

d.Len()?

}

// Aligned returns values aligned to given bounds.
func (d Datapoints) Aligned(bounds models.Bounds) []Datapoints {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to Align?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arnikola wanted it AlignToBounds. Is that better ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Early bird gets the worm @benraskin92 😜

@codecov
Copy link

codecov bot commented Sep 24, 2018

Codecov Report

Merging #929 into master will decrease coverage by 21.94%.
The diff coverage is 0%.

Impacted file tree graph

@@             Coverage Diff             @@
##           master     #929       +/-   ##
===========================================
- Coverage   77.82%   55.88%   -21.95%     
===========================================
  Files         411      408        -3     
  Lines       34516    34377      -139     
===========================================
- Hits        26863    19212     -7651     
- Misses       5778    13374     +7596     
+ Partials     1875     1791       -84
Flag Coverage Δ
#dbnode 69.67% <ø> (-11.72%) ⬇️
#m3ninx 54.14% <ø> (-21.12%) ⬇️
#query 0% <0%> (-64.36%) ⬇️
#x 38.88% <ø> (-45.84%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 918ee35...1320a86. Read the comment docs.

@@ -36,6 +36,11 @@ type columnBlock struct {
seriesMeta []SeriesMeta
}

// Unconsolidated returns the unconsolidated version for the block
func (c *columnBlock) Unconsolidated() (UnconsolidatedBlock, error) {
return nil, fmt.Errorf("unconsolidated view not support for block, meta: %s", c.meta)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/support/supported

func (m multiSeriesBlock) Consolidate() (block.Block, error) {
return &consolidatedBlock{
unconsolidated: m,
consolidationFunc: block.TakeLast,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll use a different consolidation func in the future, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prometheus only has gauges so TakeLast is only reasonable option. Yeah, we would probably have different once we have different types.

@@ -47,6 +47,11 @@ func NewScalar(val float64, bounds models.Bounds) Block {
}
}

// Unconsolidated returns the unconsolidated version for the block
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit ...of the block

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ben had the same comment. We use "for the block" almost everywhere

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's grammatically correct almost everywhere, just not here 😛

return math.NaN()
}

return values[len(values)-1].Value
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might need to be a little more complex; rather than taking the last value it should take the last non-NaN value

select {
case <-sigChan:
case <-interruptCh:
var interruptErr error
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might need to rebase?

func (b *fixedResolutionValues) AlignToBounds(_ models.Bounds) []Datapoints {
values := make([]Datapoints, len(b.values))
for i := 0; i < b.Len(); i++ {
values[i] = Datapoints{b.DatapointAt(i)}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe

stepSize := bound.StepSize()
...
Datapoints{
 Timestamp: bound.Start().Add(time.Duration(i) * stepSize)
 Value: b.DatapointAt(i)
}

?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a little cleaner since Datapoint already does this logic

}

// Consolidated consolidates the series
func (s UnconsolidatedSeries) Consolidated(consolidationFunc ConsolidationFunc) Series {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: rename to Consolidate?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's just talking about a view. Maybe we already have it cached and don't really consolidate.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like Consolidate

@@ -36,6 +36,11 @@ type columnBlock struct {
seriesMeta []SeriesMeta
}

// Unconsolidated returns the unconsolidated version for the block
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: of the block

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we use for the block at most places. Can do a search and replace in a separate diff

return math.NaN()
}

allNaNs := true
result := 0.0
prev := values[0]
prev := datapoints[0].Value
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any chance these can be nil?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we already have a length check ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean datapoints[0] could be nil, so you might hit NPE when you call .Value

func seriesValuesToDatapoints(values []float64, bounds models.Bounds) ts.Datapoints {
dps := make(ts.Datapoints, len(values))
for i, v := range values {
t, _ := bounds.TimeForIndex(i)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad didn't catch these were test utilities

"github.com/m3db/m3/src/query/block"
)

type consolidatedBlock struct {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: consolidatedBlock is a bit of a weird name for something containing an unconsolidated block and a consolidation block

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it doesn't have consolidation block just a consolidatationFunc

dpIdx := 0
for i := 0; i < steps; i++ {
startIdx := dpIdx
t, _ := bounds.TimeForIndex(i)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then might be a bit better to do the calculation here explicitly to avoid the overhead of the bounds checking in .TimeForIndex()?

@@ -20,6 +20,10 @@

package block

import (
"github.com/m3db/m3/src/query/ts"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you use "github.com/m3db/m3/src/dbnode/ts" and delete this one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we want to avoid any dbnode things especially coupling their series representation with ours. We'd probably move anything m3db related within ts/m3db and localize it there

// TakeLast is a consolidation function which takes the last datapoint which has non nan value
func TakeLast(values ts.Datapoints) float64 {
for i := len(values) - 1; i >= 0; i-- {
if !math.IsNaN(values[i].Value) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}

m.consolidated = consolidated

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: newline


// AlignToBounds returns values aligned to given bounds.
func (d Datapoints) AlignToBounds(bounds models.Bounds) []Datapoints {
numDatapoints := d.Len()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe put these in a var()?

var ( 
  numDatapoints = d.Len()
  steps = bounds.Steps()
  stepValues = make([]Datapoints, steps)
  dpIdx = 0
  stepSize = bounds.StepSize
  t = bounds.Start
)

dpIdx := 0
stepSize := bounds.StepSize
t := bounds.Start
for i := 0; i < steps; i++ {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: newline

@@ -98,6 +138,17 @@ func (b *fixedResolutionValues) DatapointAt(point int) Datapoint {
}
}

// AlignToBounds returns values aligned to given bounds.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kind of weird to call this AlignToBounds, but you just disregard the bounds..

Copy link
Collaborator

@benraskin92 benraskin92 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple nits, but LGTM

* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This license text comment should be // prefixed per line like the other .go files.

Copy link
Collaborator

@arnikola arnikola left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ran this on a preprod host and the missing metrics we were seeing on master are resolved :)

Fix lint

Remove unused mock

Revert "Remove unused mock"

This reverts commit 2ad6e95.

Update mock
@nikunjgit nikunjgit merged commit 5b31831 into master Oct 1, 2018
@nikunjgit nikunjgit deleted the unconsolidatedBlock branch October 1, 2018 16:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants