Refactor data recorder#233
Conversation
3dca95f to
5d9012b
Compare
|
TODO, increase test coverage for |
| // | ||
| // payload mode - it respects the encryption settings, and it will stringify the payload to unify | ||
| // the type of the output for both plaintext and encrypted payload. | ||
| // { |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
Codecov Report
@@ Coverage Diff @@
## master #233 +/- ##
==========================================
- Coverage 83.87% 83.69% -0.19%
==========================================
Files 24 25 +1
Lines 1433 1441 +8
==========================================
+ Hits 1202 1206 +4
- Misses 174 177 +3
- Partials 57 58 +1
Continue to review full report at Codecov.
|
5d9012b to
b883882
Compare
b883882 to
3e9a288
Compare
| // DataRecordFrame represents the structure we can json.Marshal into data recorders | ||
| type DataRecordFrame struct { | ||
| Encrypted bool `json:"encrypted"` | ||
| Payload string `json:"payload"` |
There was a problem hiding this comment.
I think that at the very least we should add omitempty to both Payload and PayloadRawJSON as there is only ever going to be one or the other. The more I've though about this however I've come to think that it would be nice to achieve a couple of different goals:
- Keep the output JSON message as
payloadwhether or not options are set to use raw payload or not. In each case, the resulting data is the payload. - Forgo the "encrypted" field if we have the raw JSON setting turned on. If we are outputting raw JSON then the result will by definition not be encrypted.
With these ideas in mind, I've created an alternative version of the this file that takes these scenarios into account. I'm sure there is room for some cleanup but I'd like to see what you think of this idea:
package handler
import (
"encoding/base64"
"encoding/json"
"github.com/brandur/simplebox"
"github.com/checkr/flagr/pkg/util"
"github.com/checkr/flagr/swagger_gen/models"
)
type dataRecordEncryptor interface {
Encrypt([]byte) (string, error)
}
type simpleboxEncryptor struct{ key [simplebox.KeySize]byte }
func (se *simpleboxEncryptor) Encrypt(b []byte) (string, error) {
s := base64.StdEncoding.EncodeToString(
simplebox.NewFromSecretKey(&se.key).Encrypt(b),
)
return s, nil
}
func newSimpleboxEncryptor(k string) dataRecordEncryptor {
key := [simplebox.KeySize]byte{}
copy(key[:], k)
return &simpleboxEncryptor{key: key}
}
const (
frameOutputModePayloadRawJSON = "payload_raw_json"
)
// DataRecordFrameOptions represents the options we can set to create a DataRecordFrame
type DataRecordFrameOptions struct {
Encrypted bool
Encryptor dataRecordEncryptor
FrameOutputMode string
}
type rawPayload struct {
Payload json.RawMessage `json:"payload"`
}
type stringPayload struct {
Payload string `json:"payload"`
Encrypted bool
}
// DataRecordFrame represents the structure we can json.Marshal into data recorders
type DataRecordFrame struct {
evalResult models.EvalResult
options DataRecordFrameOptions
}
func (drf *DataRecordFrame) MarshalJSON() ([]byte, error) {
payload, err := drf.evalResult.MarshalBinary()
if err != nil {
return nil, err
}
if drf.options.FrameOutputMode == frameOutputModePayloadRawJSON {
return json.Marshal(&rawPayload{
Payload: payload,
})
}
if drf.options.Encrypted && drf.options.Encryptor != nil {
encryptedPayload, err := drf.options.Encryptor.Encrypt(payload)
if err != nil {
return nil, err
}
return json.Marshal(&stringPayload{
Payload: encryptedPayload,
Encrypted: true,
})
}
return json.Marshal(&stringPayload{
Payload: string(payload),
Encrypted: false,
})
}
// GetPartitionKey gets the partition key from entityID
func (drf *DataRecordFrame) GetPartitionKey() string {
if drf.evalResult.EvalContext == nil {
return ""
}
return util.SafeString(drf.evalResult.EvalContext.EntityID)
}
// Output sets the paylaod using its input and returns the json marshal bytes
func (drf *DataRecordFrame) Output() ([]byte, error) {
return json.Marshal(drf)
}There was a problem hiding this comment.
I like it, much better!
09cc758 to
a18539c
Compare
| // "encrypted": false | ||
| // } | ||
| // | ||
| // payload_raw_json mode - ignores the encryption settings. |
There was a problem hiding this comment.
Since we have removed the MarshalIdent I think we should either put the example JSON in a single line (as in the string version) or make a note in the comment that the resulting output will consist of a single record per line.
There was a problem hiding this comment.
good catch, I changed to show the single-line version in the comments.
a18539c to
a550473
Compare
a550473 to
c952cb8
Compare
| // DataRecorder can record and produce the evaluation result | ||
| type DataRecorder interface { | ||
| AsyncRecord(*models.EvalResult) | ||
| AsyncRecord(models.EvalResult) |
There was a problem hiding this comment.
Seems like there should be some standardization on whether EvalResult is used as a pointer or a value. It seems to be a bit of both right now. Any thoughts on this?
There was a problem hiding this comment.
When I refactored this interface, I had to make too many nil checks all over the places, and they didn't give much margin benefits especially when the struct is small enough. Instead, I will just assume that we can receive a struct from upstream. Which kind of makes sense: if there's nothing to log, it shouldn't even bother any DataRecorders.
And in the evaluation code path, the ultimate response is auto generated from https://github.com/checkr/flagr/blob/master/swagger_gen/restapi/operations/evaluation/post_evaluation_responses.go#L28, which is a pointer. Therefore the pointer reference is prepared inside eval.go
There was a problem hiding this comment.
I see, that makes sense. Well that's all I really have from my end. Looks good.
|
Overall this looks pretty solid. I think at this point my only question has to do with the way EvalResult is treated (as noted above). Thanks for the help with this! |
Description
Fix #232 #203
Motivation and Context
How Has This Been Tested?
Tested locally, note that
kttool prints the value field of kafka messages with escape.Types of changes
Checklist: