Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Log referrer header at a configurable rate #182

Merged
merged 10 commits into from
Jan 9, 2025
Merged

Conversation

guscarreon
Copy link
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.

config.yaml Outdated Show resolved Hide resolved
config/config_test.go Outdated Show resolved Hide resolved
config/config_test.go Outdated Show resolved Hide resolved
config/config_test.go Outdated Show resolved Hide resolved
config/config_test.go Outdated Show resolved Hide resolved
config/config_test.go Outdated Show resolved Hide resolved
endpoints/get.go Outdated
@@ -38,9 +46,16 @@ func NewGetHandler(storage backends.Backend, metrics *metrics.Metrics, allowCust

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
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
Contributor Author

Choose a reason for hiding this comment

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

Removed

Copy link
Contributor

@SyntaxNode SyntaxNode Dec 12, 2024

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
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

endpoints/get.go Outdated Show resolved Hide resolved
endpoints/get.go Outdated Show resolved Hide resolved
utils/constants.go Outdated Show resolved Hide resolved
expectedLogInfo []logComponents
}{
{
name: "invalid_nagative", // must be greater or equal to zero. Expect fatal log
Copy link
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
Contributor Author

Choose a reason for hiding this comment

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

😅 . Corrected

{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
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
Contributor Author

Choose a reason for hiding this comment

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

Thanks

endpoints/get.go Outdated
@@ -38,9 +46,16 @@ func NewGetHandler(storage backends.Backend, metrics *metrics.Metrics, allowCust

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
Contributor

@SyntaxNode SyntaxNode Dec 12, 2024

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?

},
}
for _, tc := range testCases {
assert.Equal(t, tc.expected, RandomPick(tc.inPickProbability), tc.desc)
Copy link
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
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
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
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

@@ -38,9 +46,16 @@ func NewGetHandler(storage backends.Backend, metrics *metrics.Metrics, allowCust

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
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?

uuid: "",
allowKeys: false,
uuid: "",
cfg: testConfig{allowKeys: false},
Copy link
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
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.

}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, RandomPick(tc.inPickProbability), tc.name)
Copy link
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
Contributor Author

Choose a reason for hiding this comment

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

Removed

@@ -9,3 +11,13 @@ func GenerateRandomID() (string, error) {
u2, err := uuid.NewV4()
return u2.String(), err
}

func RandomPick(pickProbability float64) bool {
Copy link
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?

Copy link
Collaborator

@bsardo bsardo Dec 18, 2024

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.

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
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
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

@bsardo bsardo merged commit 75dfa4e into master Jan 9, 2025
3 checks passed
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