// example matcher() based on field length // if matcher() returns true, we will process the field with replacer() let max_field_length = 30 function matcher(f_value) { return f_value.length > max_field_length } // example replacer() that truncates matched fields function replacer(f_value) { return f_value.slice(0,max_field_length) + ' REDACT' } // the main function that loops through all fields in the supplied obj function loop_fields(target_field,start_string,recurse) { let value_type for (let [key, value] of Object.entries(target_field)) { value_type = typeof value; // recurse if specified, and not a string if (recurse && value_type == 'object' && !Array.isArray(value) && value) { loop_fields(target_field[key],start_string,true) // we have a string that qualifies based on matcher() } else if (value_type == 'string' && key.startsWith(start_string) && matcher(value)) { target_field[key] = replacer(value) } } } // CALL THE MAIN LOOP // __e contains the entire event // or specify an object, example: __e._raw or __e.records // the second argument will be used to match field names (via startsWith) // the last option (t/f) determines if we drill into nested objects loop_fields(__e,'foobar',true)