ilumos
ilumos

Reputation: 362

How can I expose statistics about resources through a RESTful API?

I'm building an API for my web app and have got as far as exposing all the resources my app uses, e.g. /users, /roles, /posts etc with no problem.

I'm now stuck on how to expose statistics about some of these resources in a RESTful way. It doesn't seem right to have a statistics resource, as GET /statistics/1 could be anything, and the results will likely change each request, as the stats are real-time, so it will not be cacheable.

Background:

For each of the /users in the system, the app periodically queries Steam's API for the /games they are playing, and the /servers they are playing it on, and stores this information along with a timestamp in the /states resource.

This information is aggregated to show a tally of the most popular games and servers on the /statistics/games/current-usage and statistics/servers/current-usage standard HTML pages. Illustrative screenshots: servers, games (taken at different times).

EDIT: Sample data for the basic resources

"state": {
    "id": 292002,
    "user_id": 135,
    "game_id": 24663,
    "server_id": 135,
    "created_at":"2014-06-22 21:12:03"
},
"user": {
    "id": 112,
    "username": "ilumos",
    "steam_id_64": "76561197970613738"
},
"server": {
    "id": 135,
    "application_id": 24663,
    "name": null,
    "address": "192.168.241.65",
    "port": "0"
},
"game": {
    "id": 24663,
    "name": "DEFCON",
    "steam_app_id": 1520
}

EDIT 2: Does REST permit endpoints that use a timestamp as the resource identifier? e.g:

GET /statistics/1403681498/games to get a response like this:

[
    "game": {
        "id": 123,
        "name": "DEFCON",
        "users": [
            {
                "id": 7654,
                "username": "daryl",
                "server": {
                    "id": 127,
                    "ip": "123.123.123.123",
                    "port": "27960"
                }
            },
            {
                "id": 135,
                "username": "ilumos"
            },
        ]
    }
]

Upvotes: 11

Views: 6364

Answers (2)

ilumos
ilumos

Reputation: 362

I'm going to go with creating a usage resosuce as all of these statistics will be the usage of other resources, either "right now" or at a historic point in time.

My URIs will look like this: GET /usage/{resource-name}/{resource-id}

GET /usage/games/                           collection of games in use right now (with user totals)
GET /usage/servers/                         collection of servers in use right now
GET /usage/games/?timestamp=1234567890      collection of games in use at {timestamp}

GET /usage/games/1                          usage of game with id 1 right now
GET /usage/games/1?timestamp=1234567890     usage of game with id 1 at {timestamp}
GET /usage/games/?user_id=123               usage of game with id 1 filtered to show only user with id 123

And in future I can extend the resource to for example return usage for electricity usage

GET /usage/phases/                          collection of phases in use right now (with power draw totals)
GET /usage/phases/1                         usage of phase with id 1 right now
GET /usage/phases/?timestamp=1234567890     collection of phases in use at {timestsamp} (with power draw totals)

Unless there's something inhernatly un-RESTful about this it seems to be the most fitting way of exposing this info.

Upvotes: 1

Eric Stein
Eric Stein

Reputation: 13682

You have a variety of not-wholly-unreasonable options.

You can

  1. include statistics with each response. Will all clients want statistics? Are there a lot of statistics? Maybe something like GET /games?orderBy=numPlayers-&offset=0&limit=10 would work if all you're tracking is number of players.
  2. have a /statistics/{statisticId} endpoint. This is not inherently unRESTful.
  3. have a /games/{gameId}/statistics endpoint.
  4. have a /statistics/games/{gameId} endpoint.

Really, there's no way for us to tell you what the best way is to implement this because we don't have enough information.

Upvotes: 8

Related Questions