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

re(api): Initial attempt at api access logging #28741

Merged
merged 4 commits into from
Sep 22, 2021
Merged

Conversation

AniketDas-Tekky
Copy link
Contributor

@AniketDas-Tekky AniketDas-Tekky commented Sep 21, 2021

From discussions last week. We are going to log api access information and leverage logging services to create metrics. This commit has some initial metrics to be logged with more that can be added later

Log messages will look like:

00:13:37 [INFO] sentry.access.api: {'method': 'POST', 'view': "<class 'sentry.api.endpoints.relay_projectconfigs.RelayProjectConfigsEndpoint'>", 'response': 200, 'user': 'AnonymousUser', 'token_type': <class 'NoneType'>}

From discussions last week. We are going to log api access information and leverage logging services to create metrics. This commit has some initial metrics to be logged with more that can be added later
Comment on lines -237 to -242
if (
getattr(self.request.successful_authenticator, "token_name", None)
== TokenAuthentication.token_name
):
request._metric_tags["backend_request"] = True

Copy link
Member

Choose a reason for hiding this comment

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

I see that you added this earlier, are we just no longer using it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

From looking at datadog the last week, it more looks like this didn't work. We're now doing the same thing with logging, so I don't see a point of keeping this around.

token_type = getattr(self.request.auth, "__class__", None)
log_metrics = dict(
method=self.request.method,
view=str(self.request.parser_context["view"].__class__),
Copy link
Member

Choose a reason for hiding this comment

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

Is there ever a case where "view" isn't present?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure. If I add a try/catch we can find out :)

@@ -160,6 +161,20 @@ def load_json_body(self, request):
except json.JSONDecodeError:
return

def _create_api_access_log(self):
Copy link
Member

Choose a reason for hiding this comment

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

Maybe being a bit paranoid, but it might be worth just wrapping this in a try/catch to make sure this logging never breaks a request

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 actually really like this. I'll log an error in the api access log so we can see what went wrong.

Copy link
Member

@leeandher leeandher left a comment

Choose a reason for hiding this comment

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

Looks good, just a few questions 🙂

method=self.request.method,
view=str(self.request.parser_context["view"].__class__),
response=self.response.status_code,
user=str(self.request.user),
Copy link
Member

Choose a reason for hiding this comment

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

What will the user be if something like an integration or sentry app calls the API? Also, is there anyway to identify where the request came from if the user is AnonymousUser like how you showed in your example?

Just making sure we can use this to identify when users hammer our API.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For the first question, I don't know what the user will be, but we will after we start logging it :)

There might be a way to track the IP address of the caller, but generally if we're getting an AnonymousUser call then that means it's an unauthenticated user. The objective here is to add more detail in subsequent iterations.

)
api_access_logger.info(log_metrics)
except Exception as exc:
api_access_logger.error(
Copy link
Member

Choose a reason for hiding this comment

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

Let's use .exception here so that we capture the actual exception too. Then you don't need to include exc in your string format.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants