Skip to content

Commit a48b68b

Browse files
refactor(observability): simplify SelectBest config matching and update default configs
- Rewrite SelectBest to use two-phase direct matching instead of bit-score approach - Reduce default column extract configs from 3 to 2: (0,*,llm_span) and (0,prompt,root_span) - Change span_list_type SQL query from wildcard IN to exact match - Update tests with 20 cases for 100% SelectBest coverage
1 parent aa26547 commit a48b68b

6 files changed

Lines changed: 153 additions & 139 deletions

File tree

backend/modules/observability/domain/trace/entity/column_extract_config.go

Lines changed: 16 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -50,85 +50,27 @@ func (c *ColumnExtractConfig) Extract(content string, column string) string {
5050
// ColumnExtractConfigs is a list of ColumnExtractConfig with selection logic.
5151
type ColumnExtractConfigs []*ColumnExtractConfig
5252

53-
// SelectBest selects the best matching config using a scoring strategy.
54-
//
55-
// Priority dimensions (highest to lowest weight):
56-
// 1. Workspace: target workspace > default (wsID=0). Cross-workspace configs are excluded.
57-
// 2. Agent: exact agent match > empty agent (wildcard).
58-
// 3. SpanListType: exact match > wildcard '*'.
59-
// 4. PlatformType: exact match > wildcard '*'.
60-
//
61-
// Returns nil if no config matches.
6253
func (configs ColumnExtractConfigs) SelectBest(workspaceId int64, agentName, platformType, spanListType string) *ColumnExtractConfig {
63-
var (
64-
best *ColumnExtractConfig
65-
bestScore int
66-
)
67-
54+
var bestConfig *ColumnExtractConfig
6855
for _, cfg := range configs {
69-
score := configScore(cfg, workspaceId, agentName, platformType, spanListType)
70-
if score < 0 {
71-
continue // not a valid match
72-
}
73-
if best == nil || score > bestScore {
74-
best = cfg
75-
bestScore = score
56+
if cfg.WorkspaceID == workspaceId && cfg.PlatformType == platformType && cfg.SpanListType == spanListType && cfg.AgentName == agentName {
57+
bestConfig = cfg
58+
break
59+
} else if cfg.WorkspaceID == workspaceId && cfg.PlatformType == platformType && cfg.SpanListType == spanListType && cfg.AgentName == "" {
60+
bestConfig = cfg
7661
}
7762
}
78-
79-
return best
80-
}
81-
82-
// configScore computes a match score for a config. Returns -1 if the config doesn't match.
83-
// Higher score = better match. Score layout (4 bits):
84-
//
85-
// bit 3 (8): workspace match (target ws=1, default ws=0)
86-
// bit 2 (4): agent match (exact=1, empty=0)
87-
// bit 1 (2): spanListType match (exact=1, wildcard=0)
88-
// bit 0 (1): platformType match (exact=1, wildcard=0)
89-
func configScore(cfg *ColumnExtractConfig, workspaceId int64, agentName, platformType, spanListType string) int {
90-
// workspace: must be target or default(0), reject cross-workspace
91-
isTarget := cfg.WorkspaceID == workspaceId
92-
isDefault := cfg.WorkspaceID == 0
93-
if !isTarget && !isDefault {
94-
return -1
95-
}
96-
97-
// agent: must be exact match or empty wildcard
98-
agentMatch := agentName != "" && cfg.AgentName == agentName
99-
agentEmpty := cfg.AgentName == ""
100-
if !agentMatch && !agentEmpty {
101-
return -1
102-
}
103-
104-
// platformType: must be exact or wildcard '*'
105-
platformExact := cfg.PlatformType == platformType
106-
platformWild := cfg.PlatformType == "*"
107-
if !platformExact && !platformWild {
108-
return -1
109-
}
110-
111-
// spanListType: must be exact or wildcard '*'
112-
spanExact := cfg.SpanListType == spanListType
113-
spanWild := cfg.SpanListType == "*"
114-
if !spanExact && !spanWild {
115-
return -1
116-
}
117-
118-
score := 0
119-
if isTarget {
120-
score |= 8
121-
}
122-
if agentMatch {
123-
score |= 4
124-
}
125-
if platformExact {
126-
score |= 1
127-
}
128-
if spanExact {
129-
score |= 2
63+
// Fallback to default
64+
if bestConfig == nil {
65+
for _, cfg := range configs {
66+
if cfg.WorkspaceID == 0 && cfg.AgentName == "" && cfg.SpanListType == spanListType &&
67+
(cfg.PlatformType == platformType || cfg.PlatformType == "*") {
68+
bestConfig = cfg
69+
break
70+
}
71+
}
13072
}
131-
return score
73+
return bestConfig
13274
}
13375

13476
func extractByJSONPath(content, jsonPath string) string {

backend/modules/observability/domain/trace/entity/column_extract_config_test.go

Lines changed: 131 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,9 @@ func TestColumnExtractConfigs_SelectBest(t *testing.T) {
2727
// workspace-specific configs
2828
makeConfig(42, "my_bot", "coze_loop", "llm_span"),
2929
makeConfig(42, "", "coze_loop", "llm_span"),
30-
// default configs (wsID=0, with wildcards)
31-
makeConfig(0, "", "*", "llm_span"), // all platform llm_span default
32-
makeConfig(0, "", "prompt", "*"), // prompt platform default
33-
makeConfig(0, "", "*", "*"), // universal fallback
30+
// default configs (wsID=0)
31+
makeConfig(0, "", "*", "llm_span"), // all platform llm_span default
32+
makeConfig(0, "", "prompt", "root_span"), // prompt root_span default
3433
}
3534

3635
tests := []struct {
@@ -83,19 +82,19 @@ func TestColumnExtractConfigs_SelectBest(t *testing.T) {
8382
wantSpan: "llm_span",
8483
},
8584
{
86-
name: "no ws match, prompt platform -> default prompt, *",
85+
name: "no ws match, prompt + root_span -> default prompt, root_span",
8786
configs: allConfigs,
8887
workspaceId: 999,
8988
agentName: "",
9089
platformType: "prompt",
91-
spanListType: "all_span",
90+
spanListType: "root_span",
9291
wantWsID: 0,
9392
wantAgent: "",
9493
wantPlatform: "prompt",
95-
wantSpan: "*",
94+
wantSpan: "root_span",
9695
},
9796
{
98-
name: "prompt + llm_span: spanList exact (*,llm_span) wins over platform exact (prompt,*)",
97+
name: "prompt + llm_span: spanList exact (*,llm_span) wins",
9998
configs: allConfigs,
10099
workspaceId: 999,
101100
agentName: "",
@@ -105,19 +104,17 @@ func TestColumnExtractConfigs_SelectBest(t *testing.T) {
105104
wantAgent: "",
106105
wantPlatform: "*",
107106
wantSpan: "llm_span",
108-
// score: (*,llm_span) = 0+0+2+0 = 2; (prompt,*) = 0+0+0+1 = 1 -> llm_span wins
109107
},
110108
{
111-
name: "unknown platform + unknown spanList -> universal fallback",
112-
configs: allConfigs,
109+
name: "unknown platform + unknown spanList -> no match",
110+
// DB query with platform_type IN ('custom','*') AND span_list_type IN ('custom_span','*')
111+
// returns nothing since no universal fallback exists
112+
configs: ColumnExtractConfigs{},
113113
workspaceId: 999,
114114
agentName: "",
115115
platformType: "custom",
116116
spanListType: "custom_span",
117-
wantWsID: 0,
118-
wantAgent: "",
119-
wantPlatform: "*",
120-
wantSpan: "*",
117+
wantNil: true,
121118
},
122119
{
123120
name: "empty configs returns nil",
@@ -177,10 +174,10 @@ func TestColumnExtractConfigs_SelectBest(t *testing.T) {
177174
wantNil: true,
178175
},
179176
{
180-
name: "ws match + spanList match but agent and platform mismatch -> fallback to universal",
177+
name: "ws match + agent and platform mismatch -> fallback to default spanList match",
181178
configs: ColumnExtractConfigs{
182-
makeConfig(42, "bot_a", "prompt", "llm_span"), // agent mismatch, platform mismatch
183-
makeConfig(0, "", "*", "*"), // universal fallback
179+
makeConfig(42, "bot_a", "prompt", "llm_span"), // agent mismatch
180+
makeConfig(0, "", "*", "llm_span"), // default with spanList match
184181
},
185182
workspaceId: 42,
186183
agentName: "bot_x",
@@ -189,7 +186,122 @@ func TestColumnExtractConfigs_SelectBest(t *testing.T) {
189186
wantWsID: 0,
190187
wantAgent: "",
191188
wantPlatform: "*",
192-
wantSpan: "*",
189+
wantSpan: "llm_span",
190+
},
191+
{
192+
name: "exact agent wins over empty agent even when empty agent appears first",
193+
configs: ColumnExtractConfigs{
194+
makeConfig(42, "", "coze_loop", "llm_span"),
195+
makeConfig(42, "my_bot", "coze_loop", "llm_span"),
196+
},
197+
workspaceId: 42,
198+
agentName: "my_bot",
199+
platformType: "coze_loop",
200+
spanListType: "llm_span",
201+
wantWsID: 42,
202+
wantAgent: "my_bot",
203+
wantPlatform: "coze_loop",
204+
wantSpan: "llm_span",
205+
},
206+
{
207+
name: "ws match but spanList mismatch -> fallback to default",
208+
configs: ColumnExtractConfigs{
209+
makeConfig(42, "", "coze_loop", "llm_span"),
210+
makeConfig(0, "", "*", "root_span"),
211+
},
212+
workspaceId: 42,
213+
agentName: "",
214+
platformType: "coze_loop",
215+
spanListType: "root_span",
216+
wantWsID: 0,
217+
wantAgent: "",
218+
wantPlatform: "*",
219+
wantSpan: "root_span",
220+
},
221+
{
222+
name: "ws match but platform mismatch -> fallback to default wildcard platform",
223+
configs: ColumnExtractConfigs{
224+
makeConfig(42, "", "prompt", "llm_span"),
225+
makeConfig(0, "", "*", "llm_span"),
226+
},
227+
workspaceId: 42,
228+
agentName: "",
229+
platformType: "coze_loop",
230+
spanListType: "llm_span",
231+
wantWsID: 0,
232+
wantAgent: "",
233+
wantPlatform: "*",
234+
wantSpan: "llm_span",
235+
},
236+
{
237+
name: "fallback: first matching config wins (order dependent)",
238+
configs: ColumnExtractConfigs{
239+
makeConfig(0, "", "*", "root_span"),
240+
makeConfig(0, "", "prompt", "root_span"),
241+
},
242+
workspaceId: 999,
243+
agentName: "",
244+
platformType: "prompt",
245+
spanListType: "root_span",
246+
wantWsID: 0,
247+
wantAgent: "",
248+
wantPlatform: "*",
249+
wantSpan: "root_span",
250+
},
251+
{
252+
name: "fallback: exact platform wins when it appears first",
253+
configs: ColumnExtractConfigs{
254+
makeConfig(0, "", "prompt", "root_span"),
255+
makeConfig(0, "", "*", "root_span"),
256+
},
257+
workspaceId: 999,
258+
agentName: "",
259+
platformType: "prompt",
260+
spanListType: "root_span",
261+
wantWsID: 0,
262+
wantAgent: "",
263+
wantPlatform: "prompt",
264+
wantSpan: "root_span",
265+
},
266+
{
267+
name: "workspaceId=0 matches default configs directly",
268+
configs: ColumnExtractConfigs{
269+
makeConfig(0, "", "*", "llm_span"),
270+
makeConfig(0, "", "prompt", "root_span"),
271+
},
272+
workspaceId: 0,
273+
agentName: "",
274+
platformType: "coze_loop",
275+
spanListType: "llm_span",
276+
wantWsID: 0,
277+
wantAgent: "",
278+
wantPlatform: "*",
279+
wantSpan: "llm_span",
280+
},
281+
{
282+
name: "single config exact match",
283+
configs: ColumnExtractConfigs{
284+
makeConfig(42, "bot", "coze_loop", "llm_span"),
285+
},
286+
workspaceId: 42,
287+
agentName: "bot",
288+
platformType: "coze_loop",
289+
spanListType: "llm_span",
290+
wantWsID: 42,
291+
wantAgent: "bot",
292+
wantPlatform: "coze_loop",
293+
wantSpan: "llm_span",
294+
},
295+
{
296+
name: "single config no match -> nil",
297+
configs: ColumnExtractConfigs{
298+
makeConfig(42, "", "coze_loop", "llm_span"),
299+
},
300+
workspaceId: 42,
301+
agentName: "",
302+
platformType: "coze_loop",
303+
spanListType: "root_span",
304+
wantNil: true,
193305
},
194306
}
195307

@@ -209,44 +321,6 @@ func TestColumnExtractConfigs_SelectBest(t *testing.T) {
209321
}
210322
}
211323

212-
func TestConfigScore(t *testing.T) {
213-
cfg := &ColumnExtractConfig{
214-
WorkspaceID: 42, AgentName: "bot", PlatformType: "coze_loop", SpanListType: "llm_span",
215-
}
216-
// Full exact match = 8+4+2+1 = 15
217-
require.Equal(t, 15, configScore(cfg, 42, "bot", "coze_loop", "llm_span"))
218-
219-
// Cross-workspace = -1
220-
require.Equal(t, -1, configScore(cfg, 999, "bot", "coze_loop", "llm_span"))
221-
222-
// Agent mismatch (non-empty agent in config, different query agent) = -1
223-
require.Equal(t, -1, configScore(cfg, 42, "other", "coze_loop", "llm_span"))
224-
225-
// Default ws=0, wildcard platform/span
226-
defaultCfg := &ColumnExtractConfig{
227-
WorkspaceID: 0, AgentName: "", PlatformType: "*", SpanListType: "*",
228-
}
229-
// score = 0 (default ws) + 0 (empty agent) + 0 (wildcard platform) + 0 (wildcard span) = 0
230-
require.Equal(t, 0, configScore(defaultCfg, 42, "bot", "coze_loop", "llm_span"))
231-
232-
// Default ws=0, exact span
233-
llmDefault := &ColumnExtractConfig{
234-
WorkspaceID: 0, AgentName: "", PlatformType: "*", SpanListType: "llm_span",
235-
}
236-
// score = 0 + 0 + 2 + 0 = 2
237-
require.Equal(t, 2, configScore(llmDefault, 42, "bot", "coze_loop", "llm_span"))
238-
239-
// Default ws=0, exact platform
240-
promptDefault := &ColumnExtractConfig{
241-
WorkspaceID: 0, AgentName: "", PlatformType: "prompt", SpanListType: "*",
242-
}
243-
// score = 0 + 0 + 0 + 1 = 1
244-
require.Equal(t, 1, configScore(promptDefault, 42, "", "prompt", "all_span"))
245-
246-
// Platform mismatch, not wildcard = -1
247-
require.Equal(t, -1, configScore(promptDefault, 42, "", "coze_loop", "llm_span"))
248-
}
249-
250324
func TestColumnExtractConfig_Extract(t *testing.T) {
251325
cfg := &ColumnExtractConfig{
252326
Columns: []ColumnExtractRule{

backend/modules/observability/domain/trace/service/trace/span_processor/clip_processor_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ func TestClipProcessor_WithDBConfig(t *testing.T) {
313313
{
314314
WorkspaceID: 0,
315315
PlatformType: "*",
316-
SpanListType: "*",
316+
SpanListType: string(loop_span.SpanListTypeLLMSpan),
317317
Columns: []entity.ColumnExtractRule{
318318
{Column: "input", JSONPath: "$..content"},
319319
{Column: "output", JSONPath: "$..content"},
@@ -388,7 +388,7 @@ func TestClipProcessor_WithDBConfigLongContent(t *testing.T) {
388388
{
389389
WorkspaceID: 0,
390390
PlatformType: "*",
391-
SpanListType: "*",
391+
SpanListType: string(loop_span.SpanListTypeLLMSpan),
392392
Columns: []entity.ColumnExtractRule{
393393
{Column: "input", JSONPath: "$.messages[0].content"},
394394
},
@@ -420,7 +420,7 @@ func TestClipProcessor_DefaultConfigSelection(t *testing.T) {
420420
WorkspaceID: 0,
421421
AgentName: "",
422422
PlatformType: "*",
423-
SpanListType: "*",
423+
SpanListType: string(loop_span.SpanListTypeLLMSpan),
424424
Columns: []entity.ColumnExtractRule{
425425
{Column: "input", JSONPath: "$..content"},
426426
{Column: "output", JSONPath: "$..content"},

backend/modules/observability/infra/repo/mysql/column_extract_config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func (t ColumnExtractConfigDaoImpl) ListColumnExtractConfigs(ctx context.Context
7777
err := t.dbMgr.NewSession(ctx).WithContext(ctx).
7878
Where("workspace_id IN (?)", []int64{0, workspaceID}).
7979
Where("platform_type IN (?, '*')", platformType).
80-
Where("span_list_type IN (?, '*')", spanListType).
80+
Where("span_list_type = ?", spanListType).
8181
Where("is_deleted = ?", false).
8282
Find(&pos).Error
8383
if err != nil {

release/deployment/docker-compose/bootstrap/mysql-init/init-sql/observability_column_extract_config.sql

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,5 @@ CREATE TABLE IF NOT EXISTS `observability_column_extract_config`
2323
INSERT INTO `observability_column_extract_config` (`id`, `workspace_id`, `platform_type`, `span_list_type`, `agent_name`, `config`, `created_by`, `updated_by`)
2424
VALUES
2525
(1, 0, '*', 'llm_span', '', '[{"Column":"input","JSONPath":"$.messages[-1:].content"},{"Column":"output","JSONPath":"$.choices[0].message.content"}]', 'system', 'system'),
26-
(2, 0, 'prompt', '*', '', '[{"Column":"input","JSONPath":"$.query.Content"},{"Column":"output","JSONPath":"$.choices[0].message.content"}]', 'system', 'system'),
27-
(3, 0, '*', '*', '', '[{"Column":"input","JSONPath":"$..content"},{"Column":"output","JSONPath":"$..content"}]', 'system', 'system')
26+
(2, 0, 'prompt', 'root_span', '', '[{"Column":"input","JSONPath":"$.query.Content"},{"Column":"output","JSONPath":"$.choices[0].message.content"}]', 'system', 'system')
2827
ON DUPLICATE KEY UPDATE `id` = `id`;

release/deployment/helm-chart/charts/app/bootstrap/init/mysql/init-sql/observability_column_extract_config.sql

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,5 @@ CREATE TABLE IF NOT EXISTS `observability_column_extract_config`
2323
INSERT INTO `observability_column_extract_config` (`id`, `workspace_id`, `platform_type`, `span_list_type`, `agent_name`, `config`, `created_by`, `updated_by`)
2424
VALUES
2525
(1, 0, '*', 'llm_span', '', '[{"Column":"input","JSONPath":"$.messages[-1:].content"},{"Column":"output","JSONPath":"$.choices[0].message.content"}]', 'system', 'system'),
26-
(2, 0, 'prompt', '*', '', '[{"Column":"input","JSONPath":"$.query.Content"},{"Column":"output","JSONPath":"$.choices[0].message.content"}]', 'system', 'system'),
27-
(3, 0, '*', '*', '', '[{"Column":"input","JSONPath":"$..content"},{"Column":"output","JSONPath":"$..content"}]', 'system', 'system')
26+
(2, 0, 'prompt', 'root_span', '', '[{"Column":"input","JSONPath":"$.query.Content"},{"Column":"output","JSONPath":"$.choices[0].message.content"}]', 'system', 'system')
2827
ON DUPLICATE KEY UPDATE `id` = `id`;

0 commit comments

Comments
 (0)