Skip to content

Commit addfc67

Browse files
committed
json_mode option is added, tests are passing. ready for review
revert changes made to JQ transformation update code as per ticket discussion; update tests fix config tests address comments clecar up SpModeV2 tests; disable interState for SpModeV2 remove config update cleanup the test update test case improve tests fix test revert back to json_mode only
1 parent 1690c37 commit addfc67

5 files changed

Lines changed: 667 additions & 226 deletions

File tree

assets/docs/configuration/transformations/custom-scripts/examples/js-snowplow-config-example.hcl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ transform {
77
# For this example, we use an environment variable, to facilitate unit tests. A hardcoded value may also be provided (eg. "/tmp/myscript.js")
88
script_path = env.JS_SNOWPLOW_SCRIPT_PATH
99

10-
snowplow_mode = true # Snowplow mode enabled - this transforms the tsv to an object on input
10+
# If the data is in JSON format, then it would be converted into an object to use in JS script
11+
# If the data is not in JSON format, transformation would fail
12+
json_mode = true # If true, then overrides snowplow_mode
1113
}
1214
}

assets/docs/configuration/transformations/custom-scripts/js-configuration-full-example.hcl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ transform {
2121
# This will transform the data so that the `Data` field contains an object representation of the event - with keys as returned by the Snowplow Analytics SDK.
2222
snowplow_mode = true
2323

24+
# optional, if used overrides snowplow_mode value
25+
# If the data is in JSON format, then it would be converted into an object to use in JS script
26+
# If the data is not in JSON format, transformation would fail
27+
# Otherwise, the transformation will fail
28+
json_mode = true
29+
2430
# optional, removes null or empty keys from JSON object output of transformation. Only applicable when the script returns an object. Does not remove null or empty elements of arrays.
2531
remove_nulls = true
2632

docs/configuration_transformations_docs_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ func TestScriptTransformationCustomScripts(t *testing.T) {
106106
testJSScriptCompiles(t, file)
107107
case ".hcl":
108108
isFull := strings.Contains(file, "full-example")
109-
110109
testTransformationConfig(t, file, isFull)
111110
case "":
112111
// If there's no extension, fail the test.
@@ -116,7 +115,6 @@ func TestScriptTransformationCustomScripts(t *testing.T) {
116115
// Otherwise it's likely a typo or error.
117116
assert.Fail("unexpected file extension found: %v", file)
118117
}
119-
120118
}
121119
}
122120

pkg/transform/engine/engine_javascript.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ type JSEngineConfig struct {
3333
Script string `hcl:"script,optional"`
3434
RunTimeout int `hcl:"timeout_sec,optional"`
3535
SpMode bool `hcl:"snowplow_mode,optional"`
36+
JsonMode bool `hcl:"json_mode,optional"`
3637
RemoveNulls bool `hcl:"remove_nulls,optional"`
3738
HashSaltSecret string `hcl:"hash_salt_secret,optional"`
3839
}
@@ -42,6 +43,7 @@ type JSEngine struct {
4243
Code *goja.Program
4344
RunTimeout time.Duration
4445
SpMode bool
46+
JsonMode bool
4547
RemoveNulls bool
4648
HashSaltSecret string
4749
}
@@ -134,6 +136,7 @@ func NewJSEngine(c *JSEngineConfig, script string) (*JSEngine, error) {
134136
Code: compiledCode,
135137
RunTimeout: time.Duration(c.RunTimeout) * time.Second,
136138
SpMode: c.SpMode,
139+
JsonMode: c.JsonMode,
137140
RemoveNulls: c.RemoveNulls,
138141
HashSaltSecret: c.HashSaltSecret,
139142
}
@@ -331,10 +334,31 @@ func mkJSEngineInput(e *JSEngine, message *models.Message, interState any) (*eng
331334
HTTPHeaders: message.HTTPHeaders,
332335
}
333336

337+
if e.JsonMode {
338+
var cInput map[string]any
339+
jErr := json.Unmarshal(message.Data, &cInput)
340+
if jErr != nil {
341+
return nil, fmt.Errorf("failed to transform input into JSON: %w", jErr)
342+
}
343+
344+
candidate.Data = cInput
345+
return candidate, nil
346+
}
347+
334348
if !e.SpMode {
335349
return candidate, nil
336350
}
337351

352+
spMap, err := parseAsTSV(interState, message)
353+
if err != nil {
354+
return nil, err
355+
}
356+
357+
candidate.Data = spMap
358+
return candidate, nil
359+
}
360+
361+
func parseAsTSV(interState any, message *models.Message) (map[string]any, error) {
338362
parsedEvent, err := transform.IntermediateAsSpEnrichedParsed(interState, message)
339363
if err != nil {
340364
// if spMode, error for non Snowplow enriched event data
@@ -346,8 +370,7 @@ func mkJSEngineInput(e *JSEngine, message *models.Message, interState any) (*eng
346370
return nil, err
347371
}
348372

349-
candidate.Data = spMap
350-
return candidate, nil
373+
return spMap, nil
351374
}
352375

353376
// validateJSEngineOut validates the value returned by the js engine.

0 commit comments

Comments
 (0)