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] In one-to-one with labels matcher only labels should be included #2417

Merged
merged 5 commits into from
Jun 23, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/query/functions/binary/binary.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@ func intersect(
if rIdx, ok := rightSigs[id]; ok {
takeLeft = append(takeLeft, lIdx)
correspondingRight = append(correspondingRight, rIdx)
if matching.On && matching.Card == CardOneToOne && len(matching.MatchingLabels) > 0 {
ls.Tags = ls.Tags.TagsWithKeys(matching.MatchingLabels)
}
leftMetas = append(leftMetas, ls)
}
}
Expand Down
91 changes: 91 additions & 0 deletions src/query/functions/binary/binary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1027,3 +1027,94 @@ func TestBinaryFunctionWithDifferentNames(t *testing.T) {
assert.Equal(t, expectedMeta, sink.Meta)
assert.Equal(t, expectedMetas, sink.Metas)
}

func TestOneToOneMatcher(t *testing.T) {
now := time.Now()

meta := func(bounds models.Bounds, name string, m block.ResultMetadata) block.Metadata {
return block.Metadata{
Bounds: bounds,
Tags: models.NewTags(1, models.NewTagOptions()).SetName([]byte(name)),
ResultMetadata: m,
}
}

var (
bounds = models.Bounds{
Start: now,
Duration: time.Minute * 3,
StepSize: time.Minute,
}

lhsResultMeta = block.ResultMetadata{
LocalOnly: true,
Exhaustive: false,
Warnings: []block.Warning{},
}

lhsMeta = meta(bounds, "left", lhsResultMeta)
lhsMetas = test.NewSeriesMeta("a", 2)
lhs = [][]float64{{1, 2, 3}, {4, 5, 6}}
left = test.NewBlockFromValuesWithMetaAndSeriesMeta(
lhsMeta, lhsMetas, lhs,
)

rhsResultMeta = block.ResultMetadata{
LocalOnly: false,
Exhaustive: true,
Warnings: []block.Warning{{Name: "foo", Message: "bar"}},
}

rhsMeta = meta(bounds, "right", rhsResultMeta)
rhsMetas = test.NewSeriesMeta("a", 3)[1:]
rhs = [][]float64{{10, 20, 30}, {40, 50, 60}}
right = test.NewBlockFromValuesWithMetaAndSeriesMeta(
rhsMeta, rhsMetas, rhs,
)

expected = [][]float64{{41, 52, 63}, {14, 25, 36}}
)

op, err := NewOp(
PlusType,
NodeParams{
LNode: parser.NodeID(0),
RNode: parser.NodeID(1),
VectorMatcherBuilder: oneToOneVectorMatchingBuilder,
},
)
require.NoError(t, err)

c, sink := executor.NewControllerWithSink(parser.NodeID(2))
node := op.(baseOp).Node(c, transform.Options{})

err = node.Process(models.NoopQueryContext(), parser.NodeID(0), left)
require.NoError(t, err)

err = node.Process(models.NoopQueryContext(), parser.NodeID(1), right)
require.NoError(t, err)

test.EqualsWithNans(t, expected, sink.Values)

expectedMetas := []block.SeriesMeta{
{
Name: []byte("a0"),
Tags: models.EmptyTags(),
},
{
Name: []byte("a1"),
Tags: models.NewTags(1, models.NewTagOptions()).AddTag(toTag("a1", "a1")),
},
}

assert.Equal(t, expectedMetas, sink.Metas)
}

func oneToOneVectorMatchingBuilder(_, _ block.Block) VectorMatching {
return VectorMatching{
Set: true,
Card: CardOneToOne,
On: true,
MatchingLabels: [][]byte{[]byte("a1")},
}
}
10 changes: 5 additions & 5 deletions src/query/test/testdata/operators.test
Original file line number Diff line number Diff line change
Expand Up @@ -198,11 +198,11 @@ eval instant at 50m (http_requests{group="canary"} + 1) and ignoring(group, job)
# http_requests{group="canary", instance="1", job="api-server"} 400
# http_requests{group="canary", instance="1", job="app-server"} 800

# FAILING issue #36. eval instant at 50m http_requests{group="canary"} / on(instance,job) http_requests{group="production"}
# {instance="0", job="api-server"} 3
# {instance="0", job="app-server"} 1.4
# {instance="1", job="api-server"} 2
# {instance="1", job="app-server"} 1.3333333333333333
eval instant at 50m http_requests{group="canary"} / on(instance,job) http_requests{group="production"}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I see there is one more case with FAILING issue #36. Did it not get fixed by this change? If so, we might need to assign it a different issue number.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Could you add a link to it? I can't find it.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I've marked one additional case with #36 in my PR:
https://github.com/m3db/m3/pull/2419/files#diff-a3fd6ac3032f77b54447c6fd5e9188bdR423
While not 100% it's the same issue, could you please check if maybe your fix addresses it as well?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Actually that issue it's not #36, but I think my fix possibly will fix it too after you will push your PR with comparator changes, as now I get "foo" metric for the test you mention. Maybe actually we should have a switch to disable random data generation?

{instance="0", job="api-server"} 3
{instance="0", job="app-server"} 1.4
{instance="1", job="api-server"} 2
{instance="1", job="app-server"} 1.3333333333333333

# FAILING issue #35. eval instant at 50m http_requests{group="canary"} unless ignoring(group, instance) http_requests{instance="0"}

Expand Down