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 log user query param #5437

Merged
merged 121 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from 109 commits
Commits
Show all changes
121 commits
Select commit Hold shift + click to select a range
f771131
Add pinot dual visibility manager and new advance visibility option
neil-xie Mar 22, 2023
9b86598
update visibility store and implemented unit test
bowenxia Mar 23, 2023
360ee20
update: go mod tidy
bowenxia Mar 23, 2023
3f074de
update go.sum
bowenxia Mar 23, 2023
218e829
Fix the start options for pinot
neil-xie Mar 23, 2023
fa587cb
update unit test
bowenxia Mar 23, 2023
bb4fa67
run make cmds to update files
bowenxia Mar 23, 2023
c056a9f
update one unit test case that had errors
bowenxia Mar 23, 2023
10b4598
fix unit test
bowenxia Mar 23, 2023
7421c35
Fix pinot config file and add ES config to make it run with workers a…
neil-xie Mar 24, 2023
931f364
add ES into docker compose file
bowenxia Mar 24, 2023
624a769
Fix kafka producer message
neil-xie Mar 28, 2023
9130637
revert kafka change, update producer message struct to match with schema
neil-xie Mar 28, 2023
909ac6f
cleanup
neil-xie Mar 28, 2023
d623f8f
change tableName and places used it accordingly, to allow pinot to re…
bowenxia Mar 28, 2023
8ac32e8
add a pinotClientInterface, refactor unit test
bowenxia Mar 30, 2023
2370332
NewPinotConnectionClient should return a genetic value
bowenxia Mar 30, 2023
94cb588
fix a failed unit test & add mock genericClient component
bowenxia Mar 30, 2023
ed103a5
rename pinotConnectionClient tobe pinotClient
bowenxia Mar 30, 2023
ab15272
change PinotClient to be public
bowenxia Mar 31, 2023
d749c1a
Update visibility manager to use the new pinot generic client
neil-xie Mar 31, 2023
6191af5
Fix the log format
neil-xie Mar 31, 2023
9f7b620
update kafka config to separate kafka topics for pinot and ES, add pi…
neil-xie Apr 4, 2023
8aade6a
Fix typo in pinot table config
neil-xie Apr 5, 2023
52e993d
change json tags to start with upper case to match pinot schema
bowenxia Apr 5, 2023
97b5763
Fix run ID json tag and remove unused kafka key from schema
neil-xie Apr 5, 2023
a3c05cc
fix a naming issue that cause pinot can't receive CloseTime
bowenxia Apr 5, 2023
3ff2029
change json tag so that closeStatus won't be ignored when it is 0
bowenxia Apr 5, 2023
ba1879d
add attr into pinot
bowenxia Apr 5, 2023
6c3dd9c
update decoded attr
bowenxia Apr 6, 2023
45ccf60
Update reading from pinot dynamic config
neil-xie Apr 6, 2023
dc93318
add single quote to query
bowenxia Apr 6, 2023
c71355d
correct order Query formations
bowenxia Apr 6, 2023
b73ad5f
Add log for debug purpose
neil-xie Apr 6, 2023
0b1d5a2
fix can't unmarshal request.Attr error
bowenxia Apr 6, 2023
9407591
fix nil pointer in isRecordValid
bowenxia Apr 6, 2023
067e71c
clean up
bowenxia Apr 7, 2023
31cbb5b
Remove unnecessary debug info and unused message fields
neil-xie Apr 7, 2023
64ff7bb
solve can't unmarshal attr issue
bowenxia Apr 7, 2023
66db061
update unit test to pass
bowenxia Apr 11, 2023
8f7dcaf
Get pinot table from config
neil-xie Apr 14, 2023
543810b
Update table name in config
neil-xie Apr 14, 2023
c95251c
use table name from config
bowenxia Apr 14, 2023
d1fbe11
clean up
bowenxia Apr 15, 2023
2fa02a3
update unit test
bowenxia Apr 15, 2023
376251d
change couple types in pinot message
bowenxia Apr 20, 2023
9fda9f3
update pinot visibility triple manager to write to pinot and ES (#5229)
neil-xie Apr 25, 2023
c0c327c
Cdnc 4574 (#5230)
bowenxia Apr 26, 2023
64748d6
Add pagination and flatten customized search attributes (#5234)
bowenxia May 8, 2023
5751cd1
Adds Dynamic-config type (#5261)
davidporter-id-au May 9, 2023
3978502
clean up: delete one unused function, and one line refactor
bowenxia May 16, 2023
7ade724
update config file for deleting Attr
bowenxia May 17, 2023
5a2c271
fix a nil pointer after removing Attr
bowenxia May 17, 2023
378597b
update a test case to cover multiple order by clause case
bowenxia May 17, 2023
6bc3f61
Fix fmt
neil-xie May 19, 2023
f5b7734
Add pinot integration test (#5316)
neil-xie Jun 7, 2023
bac8352
Cdnc 4589 (#5318)
bowenxia Jun 8, 2023
97bc5a4
Update Pinot query to order by closetime when query closed wf, order …
neil-xie Jun 22, 2023
af28635
refactor pinotClient to pass in pinotConfig
bowenxia Jun 22, 2023
0d527a9
Revert "refactor pinotClient to pass in pinotConfig"
bowenxia Jun 22, 2023
16c37ea
refactor pinotClient to pass in pinotConfig
bowenxia Jun 22, 2023
3bb3010
PinotQueryValidator (#5333)
bowenxia Jun 30, 2023
76247ac
Add limit clause to pinot queries (#5337)
bowenxia Jul 5, 2023
79c83e5
Update all queries to order by startTime
neil-xie Jul 11, 2023
b695a18
Adding a PInot/ES response comparator (#5353)
bowenxia Aug 3, 2023
763e378
Fix rebase and lint
neil-xie Aug 3, 2023
fa08342
Fix integration test and minor clean up
neil-xie Aug 9, 2023
2db04d3
more clean up
neil-xie Aug 14, 2023
9afb738
Add more comments and more clean up
neil-xie Aug 15, 2023
1adf907
Update to use constants for visibility store name instead of strings
neil-xie Aug 24, 2023
91adba5
Enable json index (#5390)
bowenxia Sep 28, 2023
3d1ac46
Rebase
neil-xie Sep 28, 2023
8d9da02
Uncomment code that caused error by idl changes
neil-xie Sep 28, 2023
fca6bba
More clean up
neil-xie Sep 28, 2023
ac9c769
turn off comparator
bowenxia Oct 2, 2023
eae9ad4
Add pinot metrics client and update pinot visibility manager to use i…
neil-xie Oct 3, 2023
c49ea32
Update read and write mode to prepare for migration
neil-xie Oct 9, 2023
775a31e
Add SecondsSinceEpoch field and update Pinot schema (#5418)
neil-xie Oct 12, 2023
b4e2c66
Address comments part 1
neil-xie Oct 12, 2023
295a989
Merge branch 'master' into CDNC_4431
shijiesheng Oct 16, 2023
7b68dd3
Address comments and fix Pinot integration test
neil-xie Oct 17, 2023
ed8dbe2
remove temporarily to rename folder
neil-xie Oct 17, 2023
02a0812
Add back with new folder name
neil-xie Oct 17, 2023
593483b
Fix
neil-xie Oct 17, 2023
2cbfa21
Minor fix for stopwatch
neil-xie Oct 18, 2023
2c84916
Merge branch 'master' into CDNC_4431
neil-xie Oct 18, 2023
cce115e
Add more comments
neil-xie Oct 19, 2023
f6917e8
Merge branch 'master' into CDNC_4431
neil-xie Oct 19, 2023
5b98b5b
add range query and unit test
bowenxia Oct 19, 2023
45031c5
Merge remote-tracking branch 'origin/CDNC_4431' into CDNC_5946_RangeQ…
bowenxia Oct 19, 2023
21d1dda
Merge branch 'master' into CDNC_5946_RangeQuery
bowenxia Oct 19, 2023
0d2f41a
support <, >, >=, <= for custom attributes
bowenxia Oct 19, 2023
49fe217
Merge branch 'CDNC_5946_RangeQuery' of github.com:uber/cadence into C…
bowenxia Oct 19, 2023
41a8345
remove dead code
bowenxia Oct 19, 2023
94c308e
add unit tests
bowenxia Oct 19, 2023
2bf6418
add comment for range query function
bowenxia Oct 20, 2023
64b467c
add log for uesr queries
bowenxia Nov 1, 2023
2f37865
add a value for override visibility manager
bowenxia Nov 1, 2023
84f9bcc
add a dash to close status tag
bowenxia Nov 1, 2023
a3bad12
delete unrelated comment
bowenxia Nov 1, 2023
e818618
Merge branch 'master' into CDNC_6066_log_user_query_param
bowenxia Nov 3, 2023
7721891
add a flipr attribute to enable log customer query parameters
bowenxia Nov 3, 2023
9e90d0e
Merge branch 'CDNC_6066_log_user_query_param' of github.com:uber/cade…
bowenxia Nov 3, 2023
5e64d83
fix an error for the dynamic config
bowenxia Nov 3, 2023
e3853ec
add a comment
bowenxia Nov 3, 2023
a5d5075
config the dynamic config files
bowenxia Nov 3, 2023
546983f
code change according to review
bowenxia Nov 6, 2023
7ac0b2b
Merge branch 'master' into CDNC_6066_log_user_query_param
bowenxia Nov 6, 2023
07c4aae
add extra logic to override variable
bowenxia Nov 6, 2023
42f986f
add a comment for queryFilter
bowenxia Nov 6, 2023
24a1c0c
change variable name
bowenxia Nov 9, 2023
13e93f7
remove queryFilter and will put it into the comparator workflow
bowenxia Nov 9, 2023
b91a3c2
Merge branch 'master' into CDNC_6066_log_user_query_param
bowenxia Nov 9, 2023
d186988
clean up
bowenxia Nov 9, 2023
1b09699
typo
bowenxia Nov 9, 2023
67e59cc
change logic for how to determine an open workflow
bowenxia Nov 10, 2023
c51fd73
delete an unused const
bowenxia Nov 14, 2023
9c32d27
Merge branch 'master' into CDNC_6066_log_user_query_param
bowenxia Nov 14, 2023
93f7c7c
Merge branch 'master' into CDNC_6066_log_user_query_param
bowenxia Nov 14, 2023
0953cfc
set general case closeStatus to be 6
bowenxia Nov 14, 2023
0555c2f
Dummy commit to trigger build pipeline
neil-xie Nov 14, 2023
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
12 changes: 12 additions & 0 deletions common/dynamicconfig/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -1444,6 +1444,11 @@ const (
// Default value: true
// Allowed filters: DomainName
EnableReadVisibilityFromPinot
// EnableLogCustomerQueryParameter is key for enable log customer query parameters
// KeyName: system.enableLogCustomerQueryParameter
// Value type: Bool
// Default value: false
EnableLogCustomerQueryParameter
// EmitShardDiffLog is whether emit the shard diff log
// KeyName: history.emitShardDiffLog
// Value type: Bool
Expand Down Expand Up @@ -3683,9 +3688,16 @@ var BoolKeys = map[BoolKey]DynamicBool{
},
EnableReadVisibilityFromPinot: DynamicBool{
KeyName: "system.enableReadVisibilityFromPinot",
Filters: []Filter{DomainName},
neil-xie marked this conversation as resolved.
Show resolved Hide resolved
Description: "EnableReadVisibilityFromPinot is key for enable read from pinot or db visibility, usually using with AdvancedVisibilityWritingMode for seamless migration from db visibility to advanced visibility",
DefaultValue: true,
},
EnableLogCustomerQueryParameter: DynamicBool{
KeyName: "system.enableLogCustomerQueryParameter",
Filters: []Filter{DomainName},
Description: "EnableLogCustomerQueryParameter is key for enable log customer query parameters",
DefaultValue: false,
},
EmitShardDiffLog: DynamicBool{
KeyName: "history.emitShardDiffLog",
Description: "EmitShardDiffLog is whether emit the shard diff log",
Expand Down
10 changes: 10 additions & 0 deletions common/log/tag/tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,16 @@ func WorkflowCronSchedule(schedule string) Tag {
return newStringTag("wf-cron-schedule", schedule)
}

// WorkflowCloseStatus returns a tag to report a workflow's close status
func WorkflowCloseStatus(status int) Tag {
return newInt("close-status", status)
}

// IsWorkflowOpen returns a tag to report a workflow is open or not
func IsWorkflowOpen(isOpen bool) Tag {
return newBoolTag("is-workflow-open", isOpen)
}

// domain related

// WorkflowDomainID returns tag for WorkflowDomainID
Expand Down
1 change: 1 addition & 0 deletions common/persistence/client/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ func (f *factoryImpl) NewVisibilityManager(
resourceConfig.EnableReadVisibilityFromPinot,
resourceConfig.EnableReadVisibilityFromES,
resourceConfig.AdvancedVisibilityWritingMode,
resourceConfig.EnableLogCustomerQueryParameter,
f.logger,
), nil
} else if params.PersistenceConfig.AdvancedVisibilityStore != "" {
Expand Down
172 changes: 172 additions & 0 deletions common/persistence/pinotUserQueryTimeFilter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
// The MIT License (MIT)

// Copyright (c) 2017-2020 Uber Technologies Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// 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.

package persistence

import (
"errors"
"fmt"
"strings"

"github.com/xwb1989/sqlparser"

"github.com/uber/cadence/common"
"github.com/uber/cadence/common/definition"
"github.com/uber/cadence/common/types"
)

// VisibilityQueryFilter for sql query validation
type VisibilityQueryFilter struct {
}

// NewVisibilityQueryFilter create VisibilityQueryValidator
func NewVisibilityQueryFilter() *VisibilityQueryFilter {
return &VisibilityQueryFilter{}
}

// FilterQuery validates that search attributes in the query and returns modified query.
func (qv *VisibilityQueryFilter) FilterQuery(whereClause string) (string, error) {
neil-xie marked this conversation as resolved.
Show resolved Hide resolved
if len(whereClause) != 0 {
// Build a placeholder query that allows us to easily parse the contents of the where clause.
// IMPORTANT: This query is never executed, it is just used to parse and validate whereClause
var placeholderQuery string
whereClause := strings.TrimSpace(whereClause)
if common.IsJustOrderByClause(whereClause) { // just order by
placeholderQuery = fmt.Sprintf("SELECT * FROM dummy %s", whereClause)
} else {
placeholderQuery = fmt.Sprintf("SELECT * FROM dummy WHERE %s", whereClause)
}

stmt, err := sqlparser.Parse(placeholderQuery)
if err != nil {
return "", &types.BadRequestError{Message: "Invalid query."}
}

sel, ok := stmt.(*sqlparser.Select)
if !ok {
return "", &types.BadRequestError{Message: "Invalid select query."}
}
buf := sqlparser.NewTrackedBuffer(nil)
res := ""
// validate where expr
if sel.Where != nil {
res, err = qv.validateWhereExpr(sel.Where.Expr)
if err != nil {
return "", &types.BadRequestError{Message: err.Error()}
}
}

sel.OrderBy.Format(buf)
res += buf.String()
return res, nil
}
return whereClause, nil
}

func (qv *VisibilityQueryFilter) validateWhereExpr(expr sqlparser.Expr) (string, error) {
if expr == nil {
return "", nil
}
switch expr := expr.(type) {
case *sqlparser.AndExpr, *sqlparser.OrExpr:
return qv.filterAndOrExpr(expr)
case *sqlparser.ComparisonExpr:
return qv.filterComparisonExpr(expr)
case *sqlparser.RangeCond:
return qv.filterRangeExpr(expr)
case *sqlparser.ParenExpr:
return qv.validateWhereExpr(expr.Expr)
default:
return "", errors.New("invalid where clause")
}
}

// for "between...and..." only
func (qv *VisibilityQueryFilter) filterRangeExpr(expr sqlparser.Expr) (string, error) {
buf := sqlparser.NewTrackedBuffer(nil)
rangeCond := expr.(*sqlparser.RangeCond)
colName, ok := rangeCond.Left.(*sqlparser.ColName)
if !ok {
return "", errors.New("invalid range expression: fail to get colname")
}
colNameStr := colName.Name.String()

if colNameStr == definition.StartTime {
bowenxia marked this conversation as resolved.
Show resolved Hide resolved
return "", nil
}
expr.Format(buf)
return buf.String(), nil
}

func (qv *VisibilityQueryFilter) filterAndOrExpr(expr sqlparser.Expr) (string, error) {
var leftExpr sqlparser.Expr
var rightExpr sqlparser.Expr
isAnd := false

switch expr := expr.(type) {
case *sqlparser.AndExpr:
leftExpr = expr.Left
rightExpr = expr.Right
isAnd = true
case *sqlparser.OrExpr:
leftExpr = expr.Left
rightExpr = expr.Right
}

leftRes, err := qv.validateWhereExpr(leftExpr)
if err != nil {
return "", err
}

rightRes, err := qv.validateWhereExpr(rightExpr)
if err != nil {
return "", err
}

if leftRes == "" || rightRes == "" {
return leftRes + rightRes, nil
}

if isAnd {
return fmt.Sprintf("%s and %s", leftRes, rightRes), nil
}

return fmt.Sprintf("%s or %s", leftRes, rightRes), nil
}

func (qv *VisibilityQueryFilter) filterComparisonExpr(expr sqlparser.Expr) (string, error) {
comparisonExpr := expr.(*sqlparser.ComparisonExpr)
buf := sqlparser.NewTrackedBuffer(nil)

colName, ok := comparisonExpr.Left.(*sqlparser.ColName)
if !ok {
return "", errors.New("invalid comparison expression, left")
}

colNameStr := colName.Name.String()

if colNameStr == definition.StartTime {
return "", nil
}
expr.Format(buf)
return buf.String(), nil
}
106 changes: 106 additions & 0 deletions common/persistence/pinotUserQueryTimeFilter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// The MIT License (MIT)

// Copyright (c) 2017-2020 Uber Technologies Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// 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.

package persistence

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestFilterQuery(t *testing.T) {
tests := map[string]struct {
query string
validated string
err string
}{
"Case1: empty query": {
query: "",
validated: "",
},
"Case2: simple query": {
query: "WorkflowID = 'wid'",
validated: "WorkflowID = 'wid'",
},
"Case3: query with custom field": {
query: "CustomStringField = 'custom'",
validated: "CustomStringField = 'custom'",
},
"Case4: startTime query": {
query: "StartTime=123456789",
validated: "",
},
"Case5-1: complex query I: with parenthesis": {
query: "(CustomStringField = 'custom and custom2 or custom3 order by') or StartTime between 1 and 10",
validated: "CustomStringField = 'custom and custom2 or custom3 order by'",
},
"Case5-2: complex query II: with startTime": {
query: "DomainID = 'd-id' and (RunID = 'run-id' or StartTime < 123456778)",
validated: "DomainID = 'd-id' and RunID = 'run-id'",
},
"Case5-3: complex query II: without startTime": {
query: "DomainID = 'd-id' or RunID = 'run-id' and WorkflowID = 'wid'",
validated: "DomainID = 'd-id' or RunID = 'run-id' and WorkflowID = 'wid'",
},
"Case5-4: complex query IV": {
query: "WorkflowID = 'wid' and (CustomStringField = 'custom and custom2 or custom3 order by' or StartTime between 1 and 10)",
validated: "WorkflowID = 'wid' and CustomStringField = 'custom and custom2 or custom3 order by'",
},
"Case6: invalid sql query": {
query: "Invalid SQL",
err: "Invalid query.",
},
"Case7: query with missing val": {
query: "CloseTime = missing",
validated: "CloseTime = missing",
},
"Case8: invalid where expression": {
query: "InvalidWhereExpr",
err: "invalid where clause",
},
"Case9: or clause": {
query: "CustomIntField = 1 or CustomIntField = 2",
validated: "CustomIntField = 1 or CustomIntField = 2",
},
"Case10: range query: custom filed": {
query: "CustomIntField BETWEEN 1 AND 2",
validated: "CustomIntField between 1 and 2",
},
"Case11: system date attribute greater than or equal to": {
query: "StartTime >= 1697754674",
validated: "",
},
}

for name, test := range tests {
t.Run(name, func(t *testing.T) {
qv := NewVisibilityQueryFilter()
validated, err := qv.FilterQuery(test.query)
if err != nil {
assert.Equal(t, test.err, err.Error())
} else {
assert.Equal(t, test.validated, validated)
}
})
}
}
Loading