Skip to content

Commit cbb1e28

Browse files
feat(api): v3 meter (#3692)
Co-authored-by: Gergely Tamas Kurucz <[email protected]>
1 parent 268104c commit cbb1e28

File tree

16 files changed

+1335
-87
lines changed

16 files changed

+1335
-87
lines changed

api/spec/src/v3/konnect.tsp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import "@typespec/openapi";
44
import "@typespec/openapi3";
55
import "./shared/index.tsp";
66
import "./events/index.tsp";
7+
import "./meters/index.tsp";
78
import "./customers/index.tsp";
89

910
using TypeSpec.Http;
@@ -25,6 +26,7 @@ using TypeSpec.OpenAPI;
2526
// TODO: Uncomment this when the Singapore production region is available
2627
// @server("https://sg.api.konghq.com/v3", "Singapore Production region")
2728
@server("https://global.api.konghq.com/v3", "Global Production region")
29+
@tagMetadata(Shared.MetersTag, #{ description: Shared.MetersDescription })
2830
@tagMetadata(Shared.EventsTag, #{ description: Shared.EventsDescription })
2931
@tagMetadata(Shared.CustomersTag, #{ description: Shared.CustomersDescription })
3032
@useAuth(systemAccountAccessToken | personalAccessToken | konnectAccessToken)
@@ -35,6 +37,11 @@ namespace MeteringAndBilling;
3537
@friendlyName("${Shared.MeteringAndBillingTitle}: ${Shared.EventsTag}")
3638
interface EventsEndpoints extends Events.EventsOperations {}
3739

40+
@route("/openmeter/meters")
41+
@tag(Shared.MetersTag)
42+
@friendlyName("${Shared.MeteringAndBillingTitle}: ${Shared.MetersTag}")
43+
interface MetersEndpoints extends Meters.MetersOperations {}
44+
3845
@route("/openmeter/customers")
3946
@tag(Shared.CustomersTag)
4047
@friendlyName("${Shared.MeteringAndBillingTitle}: ${Shared.CustomersTag}")

api/spec/src/v3/meters/index.tsp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import "./meter.tsp";
2+
import "./operations.tsp";

api/spec/src/v3/meters/meter.tsp

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import "../shared/index.tsp";
2+
3+
namespace Meters;
4+
5+
/**
6+
* A meter is a configuration that defines how to match and aggregate events.
7+
*/
8+
@friendlyName("Meter")
9+
@example(#{
10+
id: "01G65Z755AFWAKHE12NY0CQ9FH",
11+
key: "tokens_total",
12+
name: "Tokens Total",
13+
description: "AI Token Usage",
14+
aggregation: "sum",
15+
event_type: "prompt",
16+
value_property: "$.tokens",
17+
dimensions: #{ `model`: "$.model", type: "$.type" },
18+
created_at: Shared.DateTime.fromISO("2024-01-01T01:01:01.001Z"),
19+
updated_at: Shared.DateTime.fromISO("2024-01-01T01:01:01.001Z"),
20+
})
21+
model Meter {
22+
...Shared.ResourceWithKey;
23+
24+
/**
25+
* The aggregation type to use for the meter.
26+
*/
27+
@visibility(Lifecycle.Read, Lifecycle.Create)
28+
aggregation: MeterAggregation;
29+
30+
/**
31+
* The event type to include in the aggregation.
32+
*/
33+
@visibility(Lifecycle.Read, Lifecycle.Create)
34+
@minLength(1)
35+
@example("prompt")
36+
event_type: string;
37+
38+
/**
39+
* The date since the meter should include events.
40+
* Useful to skip old events.
41+
* If not specified, all historical events are included.
42+
*/
43+
@visibility(Lifecycle.Read, Lifecycle.Create)
44+
event_from?: Shared.DateTime;
45+
46+
/**
47+
* JSONPath expression to extract the value from the ingested event's data property.
48+
*
49+
* The ingested value for sum, avg, min, and max aggregations is a number or a string that can be parsed to a number.
50+
*
51+
* For unique_count aggregation, the ingested value must be a string. For count aggregation the value_property is ignored.
52+
*/
53+
@visibility(Lifecycle.Read, Lifecycle.Create)
54+
@minLength(1)
55+
@example("$.tokens")
56+
value_property?: string;
57+
58+
/**
59+
* Named JSONPath expressions to extract the group by values from the event data.
60+
*
61+
* Keys must be unique and consist only alphanumeric and underscore characters.
62+
*
63+
*/
64+
// TODO: add key format enforcement
65+
@visibility(Lifecycle.Read, Lifecycle.Create, Lifecycle.Update)
66+
@example(#{ type: "$.type" })
67+
dimensions?: Record<string>;
68+
}
69+
70+
/**
71+
* The aggregation type to use for the meter.
72+
*/
73+
@friendlyName("MeterAggregation")
74+
union MeterAggregation {
75+
sum: "sum",
76+
count: "count",
77+
unique_count: "unique_count",
78+
avg: "avg",
79+
min: "min",
80+
max: "max",
81+
latest: "latest",
82+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import "@typespec/http";
2+
import "@typespec/rest";
3+
import "@typespec/openapi";
4+
import "@typespec/openapi3";
5+
import "../common/error.tsp";
6+
import "../common/pagination.tsp";
7+
import "../common/parameters.tsp";
8+
import "../shared/index.tsp";
9+
import "./meter.tsp";
10+
11+
using TypeSpec.Http;
12+
using TypeSpec.OpenAPI;
13+
14+
namespace Meters;
15+
16+
interface MetersOperations {
17+
/**
18+
* Create a meter.
19+
*/
20+
@post
21+
@operationId("create-meter")
22+
@summary("Create meter")
23+
create(
24+
@body meter: Shared.CreateRequest<Meter>,
25+
): Shared.CreateResponse<Meter> | Common.ErrorResponses;
26+
27+
/**
28+
* Get a meter by ID.
29+
*/
30+
@get
31+
@operationId("get-meter")
32+
@summary("Get meter")
33+
get(
34+
@path meterId: Shared.ULID,
35+
): Shared.GetResponse<Meter> | Common.NotFound | Common.ErrorResponses;
36+
37+
/**
38+
* List meters.
39+
*/
40+
@get
41+
@operationId("list-meters")
42+
@summary("List meters")
43+
list(
44+
...Common.PagePaginationQuery,
45+
): Shared.PagePaginatedResponse<Meter> | Common.ErrorResponses;
46+
47+
/**
48+
* Delete a meter.
49+
*/
50+
@delete
51+
@operationId("delete-meter")
52+
@summary("Delete meter")
53+
delete(
54+
@path meterId: Shared.ULID,
55+
): Shared.DeleteResponse | Common.NotFound | Common.ErrorResponses;
56+
}

api/spec/src/v3/openmeter.tsp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import "@typespec/http";
22
import "@typespec/rest";
33
import "@typespec/openapi";
44
import "@typespec/openapi3";
5-
import "./events/index.tsp";
65
import "./shared/index.tsp";
6+
import "./events/index.tsp";
7+
import "./meters/index.tsp";
78
import "./customers/index.tsp";
89

910
using TypeSpec.Http;
@@ -23,6 +24,7 @@ using TypeSpec.OpenAPI;
2324
termsOfService: "https://openmeter.cloud/terms-of-service",
2425
})
2526
@server("https://openmeter.cloud/api/v3", "Cloud")
27+
@tagMetadata(Shared.MetersTag, #{ description: Shared.MetersDescription })
2628
@tagMetadata(Shared.EventsTag, #{ description: Shared.EventsDescription })
2729
@tagMetadata(Shared.CustomersTag, #{ description: Shared.CustomersDescription })
2830
namespace OpenMeter;
@@ -32,6 +34,11 @@ namespace OpenMeter;
3234
@friendlyName("${Shared.OpenMeterTitle}: ${Shared.EventsTag}")
3335
interface EventsEndpoints extends Events.EventsOperations {}
3436

37+
@route("/openmeter/meters")
38+
@tag(Shared.MetersTag)
39+
@friendlyName("${Shared.OpenMeterTitle}: ${Shared.MetersTag}")
40+
interface MetersEndpoints extends Meters.MetersOperations {}
41+
3542
@route("/openmeter/customers")
3643
@tag(Shared.CustomersTag)
3744
@friendlyName("${Shared.OpenMeterTitle}: ${Shared.CustomersTag}")

0 commit comments

Comments
 (0)