Skip to content

Commit

Permalink
Added support for the system stats query endpoint.
Browse files Browse the repository at this point in the history
  • Loading branch information
eriq-augustine committed Jan 3, 2025
1 parent 5158cd3 commit 316fadb
Show file tree
Hide file tree
Showing 13 changed files with 334 additions and 84 deletions.
Empty file.
Empty file.
36 changes: 36 additions & 0 deletions autograder/api/stats/system/query.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import autograder.api.common
import autograder.api.config

API_ENDPOINT = 'stats/system/query'
API_PARAMS = [
autograder.api.config.PARAM_USER_EMAIL,
autograder.api.config.PARAM_USER_PASS,

autograder.api.config.APIParam('limit',
'The maximum number of records to return.',
required = False, parser_options = {'action': 'store', 'type': int}),

autograder.api.config.APIParam('after',
'If supplied, only return stat records after this timestamp.',
required = False),

autograder.api.config.APIParam('before',
'If supplied, only return stat records before this timestamp.',
required = False),

autograder.api.config.APIParam('sort',
'Sort the results. -1 for ascending, 0 for no sorting, 1 for descending.',
required = False, parser_options = {'action': 'store', 'type': int}),
]

DESCRIPTION = 'Query system stats from the autograder server.'

def send(arguments, **kwargs):
return autograder.api.common.handle_api_request(arguments, API_PARAMS, API_ENDPOINT, **kwargs)

def _get_parser():
parser = autograder.api.config.get_argument_parser(
description = DESCRIPTION,
params = API_PARAMS)

return parser
Empty file.
14 changes: 14 additions & 0 deletions autograder/cli/stats/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""
The `autograder.cli.stats` package contains tools for
managing stats from the autograder server.
"""

import sys

import autograder.util.cli

def main():
return autograder.util.cli.main()

if (__name__ == '__main__'):
sys.exit(main())
Empty file.
14 changes: 14 additions & 0 deletions autograder/cli/stats/system/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""
The `autograder.cli.stats.system` package contains tools for
managing system-level stats from the autograder server.
"""

import sys

import autograder.util.cli

def main():
return autograder.util.cli.main()

if (__name__ == '__main__'):
sys.exit(main())
20 changes: 20 additions & 0 deletions autograder/cli/stats/system/query.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import json
import sys

import autograder.api.stats.system.query

def run(arguments):
result = autograder.api.stats.system.query.send(arguments, exit_on_error = True)
print(json.dumps(result['results'], indent = 4))
return 0

def main():
return run(_get_parser().parse_args())

def _get_parser():
parser = autograder.api.stats.system.query._get_parser()

return parser

if (__name__ == '__main__'):
sys.exit(main())
32 changes: 32 additions & 0 deletions tests/api/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,35 @@ def clean_output_logs(output):
return output

_discover_api_tests()

def fake_system_stats(output):
"""
Beause of the variable and fine-grained level of system stats,
the enture output must be faked.
"""

return {
"results": [
{
"timestamp": 100,
"cpu-percent": 1,
"mem-percent": 1,
"net-bytes-sent": 1,
"net-bytes-received": 1,
},
{
"timestamp": 200,
"cpu-percent": 2,
"mem-percent": 2,
"net-bytes-sent": 2,
"net-bytes-received": 2,
},
{
"timestamp": 300,
"cpu-percent": 3,
"mem-percent": 3,
"net-bytes-sent": 3,
"net-bytes-received": 3,
},
],
}
119 changes: 77 additions & 42 deletions tests/api/testdata/metadata/metadata_describe_base.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,123 +5,158 @@
"endpoints": {
"courses/admin/update": {
"request-type": "*admin.UpdateRequest",
"response-type": "*admin.UpdateResponse"
"response-type": "*admin.UpdateResponse",
"description": "Update an existing course."
},
"courses/assignments/get": {
"request-type": "*assignments.GetRequest",
"response-type": "*assignments.GetResponse"
"response-type": "*assignments.GetResponse",
"description": "Get the information for a course assignment."
},
"courses/assignments/list": {
"request-type": "*assignments.ListRequest",
"response-type": "*assignments.ListResponse"
"response-type": "*assignments.ListResponse",
"description": "List the assignments in the course."
},
"courses/assignments/submissions/fetch/course/attempts": {
"request-type": "*submissions.FetchCourseAttemptsRequest",
"response-type": "*submissions.FetchCourseAttemptsResponse"
"request-type": "*course.FetchCourseAttemptsRequest",
"response-type": "*course.FetchCourseAttemptsResponse",
"description": "Get all recent submissions and grading information for this assignment."
},
"courses/assignments/submissions/fetch/course/scores": {
"request-type": "*submissions.FetchCourseScoresRequest",
"response-type": "*submissions.FetchCourseScoresResponse"
"request-type": "*course.FetchCourseScoresRequest",
"response-type": "*course.FetchCourseScoresResponse",
"description": "Get a summary of the most recent scores for this assignment."
},
"courses/assignments/submissions/fetch/user/attempt": {
"request-type": "*submissions.FetchUserAttemptRequest",
"response-type": "*submissions.FetchUserAttemptResponse"
"request-type": "*user.FetchUserAttemptRequest",
"response-type": "*user.FetchUserAttemptResponse",
"description": "Get a submission along with all grading information."
},
"courses/assignments/submissions/fetch/user/attempts": {
"request-type": "*submissions.FetchUserAttemptsRequest",
"response-type": "*submissions.FetchUserAttemptsResponse"
"request-type": "*user.FetchUserAttemptsRequest",
"response-type": "*user.FetchUserAttemptsResponse",
"description": "Get all submission attempts made by a user along with all grading information."
},
"courses/assignments/submissions/fetch/user/history": {
"request-type": "*submissions.FetchUserHistoryRequest",
"response-type": "*submissions.FetchUserHistoryResponse"
"request-type": "*user.FetchUserHistoryRequest",
"response-type": "*user.FetchUserHistoryResponse",
"description": "Get a summary of the submissions for this assignment."
},
"courses/assignments/submissions/fetch/user/peek": {
"request-type": "*submissions.FetchUserPeekRequest",
"response-type": "*submissions.FetchUserPeekResponse"
"request-type": "*user.FetchUserPeekRequest",
"response-type": "*user.FetchUserPeekResponse",
"description": "Get a copy of the grading report for the specified submission. Does not submit a new submission."
},
"courses/assignments/submissions/remove": {
"request-type": "*submissions.RemoveRequest",
"response-type": "*submissions.RemoveResponse"
"response-type": "*submissions.RemoveResponse",
"description": "Remove a specified submission. Defaults to the most recent submission."
},
"courses/assignments/submissions/submit": {
"request-type": "*submissions.SubmitRequest",
"response-type": "*submissions.SubmitResponse"
"response-type": "*submissions.SubmitResponse",
"description": "Submit an assignment submission to the autograder."
},
"courses/upsert/filespec": {
"request-type": "*upsert.FileSpecRequest",
"response-type": "*upsert.UpsertResponse"
"response-type": "*upsert.UpsertResponse",
"description": "Upsert a course using a filespec."
},
"courses/upsert/zip": {
"request-type": "*upsert.ZipFileRequest",
"response-type": "*upsert.UpsertResponse"
"response-type": "*upsert.UpsertResponse",
"description": "Upsert a course using a zip file."
},
"courses/users/drop": {
"request-type": "*users.DropRequest",
"response-type": "*users.DropResponse"
"response-type": "*users.DropResponse",
"description": "Drop a user from the course."
},
"courses/users/enroll": {
"request-type": "*users.EnrollRequest",
"response-type": "*users.EnrollResponse"
"response-type": "*users.EnrollResponse",
"description": "Enroll one or more users to the course."
},
"courses/users/get": {
"request-type": "*users.GetRequest",
"response-type": "*users.GetResponse"
"response-type": "*users.GetResponse",
"description": "Get the information for a course user."
},
"courses/users/list": {
"request-type": "*users.ListRequest",
"response-type": "*users.ListResponse"
"response-type": "*users.ListResponse",
"description": "List the users in the course."
},
"lms/upload/scores": {
"request-type": "*lms.UploadScoresRequest",
"response-type": "*lms.UploadScoresResponse"
"request-type": "*upload.UploadScoresRequest",
"response-type": "*upload.UploadScoresResponse",
"description": "Upload scores from a tab-separated file to the course's LMS.\nThe file should not have headers, and should have two columns: email and score."
},
"lms/user/get": {
"request-type": "*lms.UserGetRequest",
"response-type": "*lms.UserGetResponse"
"request-type": "*user.UserGetRequest",
"response-type": "*user.UserGetResponse",
"description": "Get information for an LMS user."
},
"logs/query": {
"request-type": "*logs.QueryRequest",
"response-type": "*logs.QueryResponse"
"response-type": "*logs.QueryResponse",
"description": "Query log entries from the autograder server."
},
"metadata/describe": {
"request-type": "*metadata.DescribeRequest",
"response-type": "*metadata.DescribeResponse"
"response-type": "*metadata.DescribeResponse",
"description": "Describe all endpoints on the server."
},
"stats/system/query": {
"request-type": "*system.QueryRequest",
"response-type": "*system.QueryResponse",
"description": "Query the system stats for the server."
},
"users/auth": {
"request-type": "*users.AuthRequest",
"response-type": "*users.AuthResponse"
"response-type": "*users.AuthResponse",
"description": "Authenticate as a user."
},
"users/get": {
"request-type": "*users.GetRequest",
"response-type": "*users.GetResponse"
"response-type": "*users.GetResponse",
"description": "Get the information for a server user."
},
"users/list": {
"request-type": "*users.ListRequest",
"response-type": "*users.ListResponse"
"response-type": "*users.ListResponse",
"description": "List the users on the server."
},
"users/password/change": {
"request-type": "*users.PasswordChangeRequest",
"response-type": "*users.PasswordChangeResponse"
"request-type": "*password.PasswordChangeRequest",
"response-type": "*password.PasswordChangeResponse",
"description": "Change your password to the one provided."
},
"users/password/reset": {
"request-type": "*users.PasswordResetRequest",
"response-type": "*users.PasswordResetResponse"
"request-type": "*password.PasswordResetRequest",
"response-type": "*password.PasswordResetResponse",
"description": "Reset to a random password that will be emailed to you."
},
"users/remove": {
"request-type": "*users.RemoveRequest",
"response-type": "*users.RemoveResponse"
"response-type": "*users.RemoveResponse",
"description": "Remove a user from the server."
},
"users/tokens/create": {
"request-type": "*users.TokensCreateRequest",
"response-type": "*users.TokensCreateResponse"
"request-type": "*tokens.TokensCreateRequest",
"response-type": "*tokens.TokensCreateResponse",
"description": "Create a new authentication token."
},
"users/tokens/delete": {
"request-type": "*users.TokensDeleteRequest",
"response-type": "*users.TokensDeleteResponse"
"request-type": "*tokens.TokensDeleteRequest",
"response-type": "*tokens.TokensDeleteResponse",
"description": "Delete an authentication token."
},
"users/upsert": {
"request-type": "*users.UpsertRequest",
"response-type": "*users.UpsertResponse"
"response-type": "*users.UpsertResponse",
"description": "Upsert one or more users to the server (update if exists, insert otherwise)."
}
}
}
Expand Down
33 changes: 33 additions & 0 deletions tests/api/testdata/stats/system/stats_system_query_base.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"module": "autograder.api.stats.system.query",
"arguments": {
"user": "[email protected]",
"pass": "server-admin"
},
"output-modifier": "fake_system_stats",
"output": {
"results": [
{
"timestamp": 100,
"cpu-percent": 1,
"mem-percent": 1,
"net-bytes-sent": 1,
"net-bytes-received": 1
},
{
"timestamp": 200,
"cpu-percent": 2,
"mem-percent": 2,
"net-bytes-sent": 2,
"net-bytes-received": 2
},
{
"timestamp": 300,
"cpu-percent": 3,
"mem-percent": 3,
"net-bytes-sent": 3,
"net-bytes-received": 3
}
]
}
}
Loading

0 comments on commit 316fadb

Please sign in to comment.