Skip to content

Commit 8ff0c57

Browse files
authored
[DX-1355] Simpler subject name derivation logic + new dashboard panel (#1970)
1 parent 5078050 commit 8ff0c57

File tree

5 files changed

+93
-57
lines changed

5 files changed

+93
-57
lines changed

framework/.changeset/v0.10.3.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Adds Container Critical level Node logs to CL Node Errors dashboard
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- Simpler algorithm for creation message subject
2+
- Support for optional subject prefix

framework/components/dockercompose/chip_ingress_set/protos.go

Lines changed: 39 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,19 @@ type protoFile struct {
2323
}
2424

2525
type ProtoSchemaSet struct {
26-
Owner string `toml:"owner"`
27-
Repository string `toml:"repository"`
28-
Ref string `toml:"ref"` // ref or tag or commit SHA
29-
Folders []string `toml:"folders"` // if not provided, all protos will be fetched, otherwise only protos in these folders will be fetched
26+
Owner string `toml:"owner"`
27+
Repository string `toml:"repository"`
28+
Ref string `toml:"ref"` // ref or tag or commit SHA
29+
Folders []string `toml:"folders"` // if not provided, all protos will be fetched, otherwise only protos in these folders will be fetched
30+
SubjectPrefix string `toml:"subject_prefix"` // optional prefix for subjects
3031
}
3132

3233
// SubjectNamingStrategyFn is a function that is used to determine the subject name for a given proto file in a given repo
33-
type SubjectNamingStrategyFn func(path, source string, repoConfig ProtoSchemaSet) (string, error)
34+
type SubjectNamingStrategyFn func(subjectPrefix string, protoFile protoFile, repoConfig ProtoSchemaSet) (string, error)
3435

3536
// RepositoryToSubjectNamingStrategyFn is a map of repository names to SubjectNamingStrategyFn functions
3637
type RepositoryToSubjectNamingStrategyFn map[string]SubjectNamingStrategyFn
3738

38-
// DefaultRepositoryToSubjectNamingStrategy is a map of repository names to SubjectNamingStrategyFn functions
39-
var DefaultRepositoryToSubjectNamingStrategy = RepositoryToSubjectNamingStrategyFn{
40-
"smartcontractkit/chainlink-protos": ChainlinkProtosSubjectNamingStrategy,
41-
}
42-
4339
func ValidateRepoConfiguration(repoConfig ProtoSchemaSet) error {
4440
if repoConfig.Owner == "" {
4541
return errors.New("owner is required")
@@ -56,7 +52,7 @@ func ValidateRepoConfiguration(repoConfig ProtoSchemaSet) error {
5652
}
5753

5854
func DefaultRegisterAndFetchProtos(ctx context.Context, client *github.Client, protoSchemaSets []ProtoSchemaSet, schemaRegistryURL string) error {
59-
return RegisterAndFetchProtos(ctx, client, protoSchemaSets, schemaRegistryURL, DefaultRepositoryToSubjectNamingStrategy)
55+
return RegisterAndFetchProtos(ctx, client, protoSchemaSets, schemaRegistryURL, map[string]SubjectNamingStrategyFn{})
6056
}
6157

6258
func RegisterAndFetchProtos(ctx context.Context, client *github.Client, protoSchemaSets []ProtoSchemaSet, schemaRegistryURL string, repoToSubjectNamingStrategy RepositoryToSubjectNamingStrategyFn) error {
@@ -69,10 +65,10 @@ func RegisterAndFetchProtos(ctx context.Context, client *github.Client, protoSch
6965
}
7066

7167
protoMap := make(map[string]string)
72-
subjectMap := make(map[string]string)
68+
subjects := make(map[string]string)
7369

74-
for _, pf := range protos {
75-
protoMap[pf.Path] = pf.Content
70+
for _, proto := range protos {
71+
protoMap[proto.Path] = proto.Content
7672

7773
var subjectStrategy SubjectNamingStrategyFn
7874
if strategy, ok := repoToSubjectNamingStrategy[protoSchemaSet.Owner+"/"+protoSchemaSet.Repository]; ok {
@@ -81,14 +77,14 @@ func RegisterAndFetchProtos(ctx context.Context, client *github.Client, protoSch
8177
subjectStrategy = DefaultSubjectNamingStrategy
8278
}
8379

84-
subject, nameErr := subjectStrategy(pf.Path, pf.Content, protoSchemaSet)
80+
subjectMessage, nameErr := subjectStrategy(protoSchemaSet.SubjectPrefix, proto, protoSchemaSet)
8581
if nameErr != nil {
86-
return errors.Wrapf(nameErr, "failed to extract message name from %s", pf.Path)
82+
return errors.Wrapf(nameErr, "failed to extract message name from %s", proto.Path)
8783
}
88-
subjectMap[pf.Path] = subject
84+
subjects[proto.Path] = subjectMessage
8985
}
9086

91-
registerErr := registerAllWithTopologicalSortingByTrial(schemaRegistryURL, protoMap, subjectMap)
87+
registerErr := registerAllWithTopologicalSortingByTrial(schemaRegistryURL, protoMap, subjects)
9288
if registerErr != nil {
9389
return errors.Wrapf(registerErr, "failed to register protos from %s/%s", protoSchemaSet.Owner, protoSchemaSet.Repository)
9490
}
@@ -97,46 +93,39 @@ func RegisterAndFetchProtos(ctx context.Context, client *github.Client, protoSch
9793
return nil
9894
}
9995

100-
func DefaultSubjectNamingStrategy(path, source string, protoSchemaSet ProtoSchemaSet) (string, error) {
101-
messageName, nameErr := extractTopLevelMessageNamesWithRegex(source)
102-
if nameErr != nil {
103-
return "", errors.Wrapf(nameErr, "failed to extract message name from %s", path)
96+
func DefaultSubjectNamingStrategy(subjectPrefix string, proto protoFile, protoSchemaSet ProtoSchemaSet) (string, error) {
97+
packageName, packageErr := extractPackageNameWithRegex(proto.Content)
98+
if packageErr != nil {
99+
return "", errors.Wrapf(packageErr, "failed to extract package name from %s", proto.Path)
104100
}
105-
return protoSchemaSet.Repository + "." + messageName, nil
106-
}
107101

108-
// TODO once we have single source of truth for the relationship between protos and subjects, we need to modify this function
109-
func ChainlinkProtosSubjectNamingStrategy(path, source string, protoSchemaSet ProtoSchemaSet) (string, error) {
110-
messageName, nameErr := extractTopLevelMessageNamesWithRegex(source)
102+
messageNames, nameErr := extractTopLevelMessageNamesWithRegex(proto.Content)
111103
if nameErr != nil {
112-
return "", errors.Wrapf(nameErr, "failed to extract message name from %s", path)
104+
return "", errors.Wrapf(nameErr, "failed to extract message name from %s", proto.Path)
113105
}
106+
messageName := messageNames[0]
114107

115-
// this only covers BaseMessage
116-
if strings.HasPrefix(path, "common") {
117-
return "cre-pb." + messageName, nil
108+
return subjectPrefix + packageName + "." + messageName, nil
109+
}
110+
111+
// extractPackageNameWithRegex extracts the package name from a proto source file using regex.
112+
// It returns an error if no package name is found.
113+
func extractPackageNameWithRegex(protoSrc string) (string, error) {
114+
matches := regexp.MustCompile(`(?m)^\s*package\s+([a-zA-Z0-9.]+)\s*;`).FindStringSubmatch(protoSrc)
115+
if len(matches) < 2 {
116+
return "", fmt.Errorf("no package name found in proto source")
118117
}
119118

120-
// this covers all other protos we currently have in the chainlink-protos repo
121-
subject := "cre-workflows."
122-
pathSplit := strings.Split(path, "/")
123-
if len(pathSplit) > 1 {
124-
for _, part := range pathSplit {
125-
matches := regexp.MustCompile(`v[0-9]+`).FindAllStringSubmatch(part, -1)
126-
if len(matches) > 0 {
127-
subject += matches[0][0]
128-
}
129-
}
130-
} else {
131-
return "", fmt.Errorf("no subject found for %s", path)
119+
if matches[1] == "" {
120+
return "", fmt.Errorf("empty package name found in proto source")
132121
}
133122

134-
return subject + "." + messageName, nil
123+
return matches[1], nil
135124
}
136125

137126
// we use simple regex to extract top-level message names from a proto file
138127
// so that we don't need to parse the proto file with a parser (which would require a lot of dependencies)
139-
func extractTopLevelMessageNamesWithRegex(protoSrc string) (string, error) {
128+
func extractTopLevelMessageNamesWithRegex(protoSrc string) ([]string, error) {
140129
matches := regexp.MustCompile(`(?m)^\s*message\s+(\w+)\s*{`).FindAllStringSubmatch(protoSrc, -1)
141130
var names []string
142131
for _, match := range matches {
@@ -146,11 +135,10 @@ func extractTopLevelMessageNamesWithRegex(protoSrc string) (string, error) {
146135
}
147136

148137
if len(names) == 0 {
149-
return "", fmt.Errorf("no message names found in %s", protoSrc)
138+
return nil, fmt.Errorf("no message names found in %s", protoSrc)
150139
}
151140

152-
// even though there could be more than 1 message in a single proto, we still need to register all of them under one subject
153-
return names[0], nil
141+
return names, nil
154142
}
155143

156144
// Fetches .proto files from a GitHub repo optionally scoped to specific folders. It is recommended to use `*github.Client` with auth token to avoid rate limiting.
@@ -280,10 +268,12 @@ func registerAllWithTopologicalSortingByTrial(
280268
continue
281269
}
282270

271+
singleProtoFailures := []error{}
283272
framework.L.Debug().Msgf("🔄 registering %s as %s", path, subject)
284273
_, registerErr := registerSingleProto(schemaRegistryURL, subject, schema.Source, refs)
285274
if registerErr != nil {
286275
failures = append(failures, fmt.Sprintf("%s: %v", path, registerErr))
276+
singleProtoFailures = append(singleProtoFailures, registerErr)
287277
continue
288278
}
289279

@@ -296,6 +286,7 @@ func registerAllWithTopologicalSortingByTrial(
296286
})
297287

298288
framework.L.Info().Msgf("✔ registered: %s as %s", path, subject)
289+
299290
progress = true
300291
}
301292

framework/examples/myproject/smoke_chip_ingress_test.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,11 @@ func TestChipIngressSmoke(t *testing.T) {
4848

4949
err := chipingressset.DefaultRegisterAndFetchProtos(ctx, client, []chipingressset.ProtoSchemaSet{
5050
{
51-
Owner: "smartcontractkit",
52-
Repository: "chainlink-protos",
53-
Ref: "626c42d55bdcb36dffe0077fff58abba40acc3e5",
54-
Folders: []string{"workflows"},
51+
Owner: "smartcontractkit",
52+
Repository: "chainlink-protos",
53+
Ref: "95decc005a91a1fd2621af9d9f00cb36d8061067",
54+
Folders: []string{"workflows"},
55+
SubjectPrefix: "cre-",
5556
},
5657
}, out.RedPanda.SchemaRegistryExternalURL)
5758
require.NoError(t, err, "failed to register protos")

framework/observability/compose/conf/provisioning/dashboards/clnode-errors/errors.json

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
"editable": true,
1919
"fiscalYearStartMonth": 0,
2020
"graphTooltip": 0,
21-
"id": 4,
2221
"links": [],
2322
"liveNow": false,
2423
"panels": [
@@ -202,9 +201,10 @@
202201
},
203202
{
204203
"datasource": {
205-
"type": "loki"
204+
"type": "loki",
205+
"uid": "P8E80F9AEF21F6940"
206206
},
207-
"description": "Node Errors",
207+
"description": "Node Criticals",
208208
"gridPos": {
209209
"h": 7,
210210
"w": 24,
@@ -223,6 +223,47 @@
223223
"wrapLogMessage": false
224224
},
225225
"pluginVersion": "10.2.6",
226+
"targets": [
227+
{
228+
"datasource": {
229+
"type": "loki"
230+
},
231+
"editorMode": "code",
232+
"expr": "{job=\"ctf\", container=~\".*node.*\"}\n | json \n | level=\"crit\" \n | logfmt \n | line_format \"{{.container }} {{.logger }} {{.msg }} {{.err}}\"",
233+
"legendFormat": "",
234+
"queryType": "range",
235+
"refId": "A"
236+
}
237+
],
238+
"title": "Node Criticals",
239+
"transformations": [],
240+
"transparent": true,
241+
"type": "logs"
242+
},
243+
{
244+
"datasource": {
245+
"type": "loki",
246+
"uid": "P8E80F9AEF21F6940"
247+
},
248+
"description": "Node Errors",
249+
"gridPos": {
250+
"h": 7,
251+
"w": 24,
252+
"x": 0,
253+
"y": 17
254+
},
255+
"id": 5,
256+
"options": {
257+
"dedupStrategy": "none",
258+
"enableLogDetails": true,
259+
"prettifyLogMessage": false,
260+
"showCommonLabels": false,
261+
"showLabels": false,
262+
"showTime": false,
263+
"sortOrder": "Descending",
264+
"wrapLogMessage": false
265+
},
266+
"pluginVersion": "10.2.6",
226267
"targets": [
227268
{
228269
"datasource": {
@@ -249,7 +290,7 @@
249290
"h": 6,
250291
"w": 24,
251292
"x": 0,
252-
"y": 17
293+
"y": 24
253294
},
254295
"id": 3,
255296
"options": {
@@ -280,7 +321,7 @@
280321
"type": "logs"
281322
}
282323
],
283-
"refresh": "",
324+
"refresh": "5s",
284325
"schemaVersion": 38,
285326
"style": "dark",
286327
"tags": [],

0 commit comments

Comments
 (0)