Skip to content

Commit

Permalink
Distribution API
Browse files Browse the repository at this point in the history
  • Loading branch information
dianaclarke committed Jul 20, 2021
1 parent 93f999b commit a23abe8
Show file tree
Hide file tree
Showing 13 changed files with 377 additions and 107 deletions.
1 change: 1 addition & 0 deletions conbench/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from .benchmarks import * # noqa
from .compare import * # noqa
from .contexts import * # noqa
from .distributions import * # noqa
from .index import * # noqa
from .machines import * # noqa
from .runs import * # noqa
Expand Down
3 changes: 3 additions & 0 deletions conbench/api/_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ def _201_created(example, schema=None):
spec.components.response("BenchmarkCreated", _201_created(ex.BENCHMARK_ENTITY))
spec.components.response("CompareEntity", _200_ok(ex.COMPARE_ENTITY))
spec.components.response("CompareList", _200_ok(ex.COMPARE_LIST))
spec.components.response("DistributionEntity", _200_ok(ex.DISTRIBUTION_ENTITY))
spec.components.response("DistributionList", _200_ok(ex.DISTRIBUTION_LIST))
spec.components.response("ContextEntity", _200_ok(ex.CONTEXT_ENTITY))
spec.components.response("MachineEntity", _200_ok(ex.MACHINE_ENTITY))
spec.components.response("RunEntity", _200_ok(ex.RUN_ENTITY))
Expand All @@ -82,6 +84,7 @@ def _201_created(example, schema=None):
{"name": "Benchmarks", "description": "Record benchmarks"},
{"name": "Compare", "description": "Compare benchmarks"},
{"name": "Contexts", "description": "Benchmark contexts"},
{"name": "Distributions", "description": "Benchmark distributions"},
{"name": "Machines", "description": "Benchmark machines"},
{"name": "Runs", "description": "Benchmark runs"},
{"name": "Ping", "description": "Monitor status"},
Expand Down
56 changes: 56 additions & 0 deletions conbench/api/_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,36 @@ def _api_context_entity(context_id, links=True):
return result


def _api_distribution_entity(
distribution_id,
sha,
case_id,
context_id,
machine_hash,
observations,
links=True,
):
result = {
"id": distribution_id,
"sha": sha,
"case_id": case_id,
"context_id": context_id,
"machine_hash": machine_hash,
"unit": "s",
"mean_mean": "0.036369",
"first_timestamp": "2021-02-25T01:02:51",
"last_timestamp": "2021-02-25T01:02:51",
"observations": observations,
"repository": "https://github.com/apache/arrow",
"links": {
"self": "http://localhost/api/distributions/%s/" % distribution_id,
},
}
if not links:
result.pop("links", None)
return result


def _api_machine_entity(machine_id, links=True):
result = {
"id": machine_id,
Expand Down Expand Up @@ -331,6 +361,32 @@ def _api_run_entity(run_id, commit_id, machine_id, now, baseline_id):
],
)
CONTEXT_ENTITY = _api_context_entity("some-context-uuid-1")
DISTRIBUTION_ENTITY = _api_distribution_entity(
"some-distribution-uuid-1",
"some-sha-1",
"some-case-uuid-1",
"some-context-uuid-1",
"some-machine-hash-1",
33,
)
DISTRIBUTION_LIST = [
_api_distribution_entity(
"some-distribution-uuid-1",
"some-sha-1",
"some-case-uuid-1",
"some-context-uuid-1",
"some-machine-hash-1",
33,
),
_api_distribution_entity(
"some-distribution-uuid-2",
"some-sha-2",
"some-case-uuid-2",
"some-context-uuid-2",
"some-machine-hash-2",
33,
),
]
MACHINE_ENTITY = _api_machine_entity("some-machine-uuid-1")
RUN_ENTITY = _api_run_entity(
"some-run-uuid-1",
Expand Down
66 changes: 66 additions & 0 deletions conbench/api/distributions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from ..api import rule
from ..api._endpoint import ApiEndpoint
from ..entities._entity import NotFound
from ..entities.distribution import Distribution, DistributionSerializer


class DistributionListAPI(ApiEndpoint):
serializer = DistributionSerializer()

def get(self):
"""
---
description: Get a list of distributions.
responses:
"200": "DistributionList"
"401": "401"
tags:
- Distributions
"""
distributions = Distribution.all()
return self.serializer.many.dump(distributions)


class DistributionEntityAPI(ApiEndpoint):
serializer = DistributionSerializer()

def _get(self, distribution_id):
try:
distribution = Distribution.one(id=distribution_id)
except NotFound:
self.abort_404_not_found()
return distribution

def get(self, distribution_id):
"""
---
description: Get a distribution.
responses:
"200": "DistributionEntity"
"401": "401"
"404": "404"
parameters:
- name: distribution_id
in: path
schema:
type: string
tags:
- Distributions
"""
distribution = self._get(distribution_id)
return self.serializer.one.dump(distribution)


distribution_entity_view = DistributionEntityAPI.as_view("distribution")
distribution_list_view = DistributionListAPI.as_view("distributions")

rule(
"/distributions/<distribution_id>/",
view_func=distribution_entity_view,
methods=["GET"],
)
rule(
"/distributions/",
view_func=distribution_list_view,
methods=["GET"],
)
32 changes: 32 additions & 0 deletions conbench/entities/distribution.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import flask as f
import sqlalchemy as s
from sqlalchemy import func
from sqlalchemy import CheckConstraint as check
Expand All @@ -7,6 +8,7 @@
from ..entities._entity import (
Base,
EntityMixin,
EntitySerializer,
generate_uuid,
NotNull,
Nullable,
Expand Down Expand Up @@ -55,6 +57,36 @@ class Distribution(Base, EntityMixin):
s.Index("distribution_machine_hash_index", Distribution.machine_hash)


class _Serializer(EntitySerializer):
decimal_fmt = "{:.6f}"

def _dump(self, distribution):
result = {
"id": distribution.id,
"sha": distribution.sha,
"repository": distribution.repository,
"case_id": distribution.case_id,
"context_id": distribution.context_id,
"machine_hash": distribution.machine_hash,
"unit": distribution.unit,
"mean_mean": self.decimal_fmt.format(distribution.mean_mean),
"first_timestamp": distribution.first_timestamp.isoformat(),
"last_timestamp": distribution.last_timestamp.isoformat(),
"observations": distribution.observations,
"links": {
"self": f.url_for(
"api.distribution", distribution_id=distribution.id, _external=True
),
},
}
return result


class DistributionSerializer:
one = _Serializer()
many = _Serializer(many=True)


def get_commit_index(repository):
ordered = (
Session.query(Commit.id, Commit.sha, Commit.timestamp)
Expand Down
94 changes: 94 additions & 0 deletions conbench/tests/api/_expected_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,70 @@
},
"description": "OK",
},
"DistributionEntity": {
"content": {
"application/json": {
"example": {
"case_id": "some-case-uuid-1",
"context_id": "some-context-uuid-1",
"first_timestamp": "2021-02-25T01:02:51",
"id": "some-distribution-uuid-1",
"last_timestamp": "2021-02-25T01:02:51",
"links": {
"self": "http://localhost/api/distributions/some-distribution-uuid-1/"
},
"machine_hash": "some-machine-hash-1",
"mean_mean": "0.036369",
"observations": 33,
"repository": "https://github.com/apache/arrow",
"sha": "some-sha-1",
"unit": "s",
}
}
},
"description": "OK",
},
"DistributionList": {
"content": {
"application/json": {
"example": [
{
"case_id": "some-case-uuid-1",
"context_id": "some-context-uuid-1",
"first_timestamp": "2021-02-25T01:02:51",
"id": "some-distribution-uuid-1",
"last_timestamp": "2021-02-25T01:02:51",
"links": {
"self": "http://localhost/api/distributions/some-distribution-uuid-1/"
},
"machine_hash": "some-machine-hash-1",
"mean_mean": "0.036369",
"observations": 33,
"repository": "https://github.com/apache/arrow",
"sha": "some-sha-1",
"unit": "s",
},
{
"case_id": "some-case-uuid-2",
"context_id": "some-context-uuid-2",
"first_timestamp": "2021-02-25T01:02:51",
"id": "some-distribution-uuid-2",
"last_timestamp": "2021-02-25T01:02:51",
"links": {
"self": "http://localhost/api/distributions/some-distribution-uuid-2/"
},
"machine_hash": "some-machine-hash-2",
"mean_mean": "0.036369",
"observations": 33,
"repository": "https://github.com/apache/arrow",
"sha": "some-sha-2",
"unit": "s",
},
]
}
},
"description": "OK",
},
"Index": {
"content": {
"application/json": {
Expand Down Expand Up @@ -1046,6 +1110,35 @@
"tags": ["Contexts"],
}
},
"/api/distributions/": {
"get": {
"description": "Get a list of distributions.",
"responses": {
"200": {"$ref": "#/components/responses/DistributionList"},
"401": {"$ref": "#/components/responses/401"},
},
"tags": ["Distributions"],
}
},
"/api/distributions/{distribution_id}/": {
"get": {
"description": "Get a distribution.",
"parameters": [
{
"in": "path",
"name": "distribution_id",
"required": True,
"schema": {"type": "string"},
}
],
"responses": {
"200": {"$ref": "#/components/responses/DistributionEntity"},
"401": {"$ref": "#/components/responses/401"},
"404": {"$ref": "#/components/responses/404"},
},
"tags": ["Distributions"],
}
},
"/api/docs.json": {},
"/api/login/": {
"post": {
Expand Down Expand Up @@ -1238,6 +1331,7 @@
{"description": "Record benchmarks", "name": "Benchmarks"},
{"description": "Compare benchmarks", "name": "Compare"},
{"description": "Benchmark contexts", "name": "Contexts"},
{"description": "Benchmark distributions", "name": "Distributions"},
{"description": "Benchmark machines", "name": "Machines"},
{"description": "Benchmark runs", "name": "Runs"},
{"description": "Monitor status", "name": "Ping"},
Expand Down
35 changes: 35 additions & 0 deletions conbench/tests/api/_fixtures.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import copy

from ...entities.summary import Summary
from ...runner import Conbench


CHILD = "02addad336ba19a654f9c857ede546331be7b631"
PARENT = "4beb514d071c9beec69b8917b5265e77ade22fb3"
GRANDPARENT = "6d703c4c7b15be630af48d5e9ef61628751674b2"
Expand Down Expand Up @@ -89,3 +95,32 @@
"name": "file-write",
},
}


def create_benchmark_summary(
name=None,
batch_id=None,
run_id=None,
results=None,
unit=None,
sha=None,
language=None,
):
data = copy.deepcopy(VALID_PAYLOAD)

if name:
data["tags"]["name"] = name
if batch_id:
data["batch_id"] = batch_id
if run_id:
data["run_id"] = run_id
if sha:
data["github"]["commit"] = sha
if language:
data["context"]["benchmark_language"] = language

if results is not None:
unit = unit if unit else "s"
data["stats"] = Conbench._stats(results, unit, [], "s")

return Summary.create(data)

0 comments on commit a23abe8

Please sign in to comment.