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

[query] Fix time() function in binary comparisons #1888

Merged
merged 6 commits into from
Aug 22, 2019
Merged

Conversation

arnikola
Copy link
Collaborator

What this PR does / why we need it:
Fixes #1878

@arnikola arnikola changed the title Arnikola/time fix [query] Fix time() function in binary comparisons Aug 16, 2019
}

func isTime(expr promql.Expr) bool {
return expr.String() == "time()"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Hm, surely there's a better way to work out of it's a time expr? Isn't there a type safe enum like value you can use?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not before it gets parsed unfortunately; alternatively could do some weird stuff where it attempts to edit the parent's params if you receive a time() function, but I think that breaks the model in a worse way than this. Figured since parsing is going to be messy and special-casey anyway it won't be a huge difference

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ok actually going to refactor it to make it a little less awkward; will rely on block types rather than on prom's param types and remove that janky dependency

// NB: Prometheus handles `time()` in a way that's not entirely compatible
// with the query engine; special handling is required here.
lTime, rTime := isTime(expr.LHS), isTime(expr.RHS)
if matching == nil {
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: Could we make promMatchingToM3 return *thing, bool instead of using nil to specify it didn't convert the expr? Just tends to be the pattern we use rather than checking whether thing is nil or not (which can lead to some people forgetting to nil check, and then nil ptr dereference).


// Iff one of left or right is a time() function, match match one to many
// against it, and match everything.
func timeMatcher(left, right bool) *binary.VectorMatching {
Copy link
Collaborator

@robskillington robskillington Aug 16, 2019

Choose a reason for hiding this comment

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

Similar, maybe here we make it return (*binary.VectorMatching, bool)?

Even if we don't always use the return of the bool side, still makes the top level code look better:

matching, ok := promMatchingToM3(expr.VectorMatching)
if !ok {
  matching, _ = timeMatcher(isTime(expr.LHS), isTime(expr.RHS))
}

"github.com/m3db/m3/src/query/models"
"github.com/stretchr/testify/assert"

"github.com/uber-go/tally"
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: Combine the external imports here? (don't know why linter is clearly not working...)

i.e. this should be:

	"context"
	"testing"

 	"github.com/m3db/m3/src/query/cost"
	"github.com/m3db/m3/src/query/models"

	"github.com/stretchr/testify/assert"
 	"github.com/uber-go/tally"

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Haha can't say I miss the linter no longer breaking builds, but will fix it up

func (t BlockType) String() string {
switch t {
case BlockM3TSZCompressed:
return "M3TSZ_compressed"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Any reason this should be upper case and rest lower? Maybe we should make it just "compressedM3TSZ" for lower camel casing or "compressed_m3tsz" if we want to do lowercase underscore separated.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

SGTM; don't really see this used as anything other than as human-readable debug info since it's all runtime stuff so makes sense to pretty it up 👍

@@ -0,0 +1,86 @@
// Copyright (c) 2019 Uber Technologies, Inc.
Copy link
Collaborator

Choose a reason for hiding this comment

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

super nit: Rename this file info.go for more "Go-ish" name?

return "unknown"
}

type BlockInformation struct {
Copy link
Collaborator

@robskillington robskillington Aug 22, 2019

Choose a reason for hiding this comment

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

Should we call this just BlockInfo? Sounds more "Go-ish" (I know that's so subjective obviously though...).

Also needs comment yeah? (think the exported types in this file are all missing comments)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ah fair enough; thought the general idea was functions and types have full names but variables have Go-ish names, will change it

BlockTime
BlockContainer
BlockWrapper
BlockConsolidated
Copy link
Collaborator

Choose a reason for hiding this comment

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

These all needs comments yeah?

@@ -107,6 +76,34 @@ func tagMap(t models.Tags) map[string]models.Tag {
return m
}

// Iff one of left or right is a time block, match match one to many
// against it, and match everything.
func defaultVectorMatcherBuilder(lhs, rhs block.Block) *VectorMatching {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we just make VectorMatching be a non-ptr type? Then it shouldn't panic if accidentally used without being set.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sure, was mostly using it for the unset case, will add a bool indicating that it's been updated


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

"github.com/m3db/m3/src/query/executor/transform"
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: missing endline here?

@@ -22,7 +22,8 @@ package promql

import (
"fmt"
"time"

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

"github.com/m3db/m3/src/query/functions"
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: extra new line here?

@@ -167,6 +182,7 @@ func (m Metadata) String() string {
type Builder interface {
AppendValue(idx int, value float64) error
AppendValues(idx int, values []float64) error
SetBlockType(blockType BlockType)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Instead of using SetBlockType can we just force it to be supplied in the constructor to the builder?

Seems like people could forget otherwise rather than forcing them to supply in the constructor.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Discussed offline re: adding a BuildAsType method to Builder instead to make this more explicit as most usages of Build want default typing

Copy link
Collaborator

@robskillington robskillington left a comment

Choose a reason for hiding this comment

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

LGTM

@arnikola arnikola merged commit f04a2e1 into master Aug 22, 2019
@arnikola arnikola deleted the arnikola/time-fix branch August 22, 2019 22:19
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.

m3-query: scalar operator on timestamp yielding wrong result
2 participants