Skip to content

Log referrer header at a configurable rate#182

Merged
bsardo merged 10 commits into
masterfrom
logReferrerHeader
Jan 9, 2025
Merged

Log referrer header at a configurable rate#182
bsardo merged 10 commits into
masterfrom
logReferrerHeader

Conversation

@guscarreon

Copy link
Copy Markdown
Contributor

This pull request modifies PRebid Cache core so, when configure, it is able to output the value of incoming requests Referer header at a rate that can be configured in config.yaml or config.json or the environment variable PBC_REQUEST_LOGGING_REFERER_SAMPLING_RATE. The config value represents the probability of logging the Referer header of a given request.

The sampling method uses a golang-generated random number and, if set to say, 0.1, it will log approximately 10% of all incoming request Referer headers.

Comment thread config.yaml Outdated
Comment thread config/config_test.go Outdated
Comment thread config/config_test.go Outdated
Comment thread config/config_test.go Outdated
Comment thread config/config_test.go Outdated
Comment thread config/config_test.go Outdated
Comment thread endpoints/get.go Outdated
func (e *GetHandler) handle(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
e.metrics.RecordGetTotal()

if utils.RandomPick(e.cfg.refererLogRate) == true {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The == true check isn't required.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

@SyntaxNode SyntaxNode Dec 12, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still looks like it's there. Did you forget to save or commit?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know 😅 . Corrected

Comment thread endpoints/get.go Outdated
Comment thread endpoints/get.go Outdated
Comment thread utils/constants.go Outdated
Comment thread config/config_test.go Outdated
expectedLogInfo []logComponents
}{
{
name: "invalid_nagative", // must be greater or equal to zero. Expect fatal log

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Typo invalid_nagative -> invalid_negative

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😅 . Corrected

Comment thread config/config_test.go
{msg: "config.request_logging.referer_sampling_rate: 0", lvl: logrus.InfoLevel},
{msg: "config.backend.type: memory", lvl: logrus.InfoLevel},
{msg: "config.compression.type: snappy", lvl: logrus.InfoLevel},
{msg: "Prebid Cache will run without metrics", lvl: logrus.InfoLevel},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice simplification here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

Comment thread endpoints/get.go Outdated
func (e *GetHandler) handle(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
e.metrics.RecordGetTotal()

if utils.RandomPick(e.cfg.refererLogRate) == true {

@SyntaxNode SyntaxNode Dec 12, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still looks like it's there. Did you forget to save or commit?

Comment thread utils/utils_test.go Outdated
},
}
for _, tc := range testCases {
assert.Equal(t, tc.expected, RandomPick(tc.inPickProbability), tc.desc)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you use t.Run here too? .. and also change desc to name. Test names can be simplified to "zero" and "one". Thank you for not trying to test the random number generator part. :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. Modified

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you agree with naming this function RandomPick? I'm not so sure about the name but, I can't think of anything better of the top of my head.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't bother me. Other options to consider:

  • ShouldSample
  • ShouldLog
  • RandomChance

Comment thread endpoints/get.go
func (e *GetHandler) handle(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
e.metrics.RecordGetTotal()

// If incoming request comes with a referer header, there's a e.cfg.refererLogRate percent chance

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO: You don't need these comments. You added them in this commit, is that related to the RandomPick name?

Comment thread endpoints/get_test.go Outdated
uuid: "",
allowKeys: false,
uuid: "",
cfg: testConfig{allowKeys: false},

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add two test cases where the referer log rate is 1.0 and the referer is specified in one test case and not specified in the other test case? It seems like that would be easy to do since this test already has logEntries as an expectation right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Added those two unit tests.

Comment thread utils/utils_test.go Outdated
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, RandomPick(tc.inPickProbability), tc.name)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't need tc.name at the end of this assert statement since it is already passed in as the first parameter to t.Run.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

Comment thread utils/utils.go
return u2.String(), err
}

func RandomPick(pickProbability float64) bool {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any value in injecting rand as a dependency as a second parameter of type interface to this function or by creating a RandomPicker struct with the dependency being a field and this function is a receiver method so that we can mock it for testing purposes? Is that overkill @SyntaxNode @guscarreon?

@bsardo bsardo Dec 18, 2024

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed offline. The extra work required to make this fully testable via unit test is not worth it due to the simplicity of the logic.

Comment thread endpoints/put.go Outdated
// If incoming request comes with a referer header, there's a e.cfg.refererLogRate percent chance
// getting it logged
if referer := r.Referer(); referer != "" && utils.RandomPick(e.cfg.refererLogRate) {
logrus.Info("PUT request Referer header: " + referer)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this line being tested in put_test.go? I don't see coverage. Is it worth adding a test similar to my recommendation in get_test.go?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Added JSON tests on both endpoints

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants