1- import type {
1+ import { z } from "zod/v4" ;
2+ import {
23 CloudchamberMetricsResponse ,
34 Container ,
4- MetricsGroup ,
5+ type MetricsGroup ,
56} from "../types" ;
67
78export interface CloudflareApiConfig {
89 accountId : string ;
910 apiToken : string ;
1011}
1112
12- export interface ContainersListResponse {
13- success : boolean ;
14- result : Container [ ] ;
15- errors : unknown [ ] ;
16- messages : unknown [ ] ;
17- }
13+ const ContainersListResponseSchema = z . object ( {
14+ success : z . boolean ( ) ,
15+ result : z . array ( Container ) ,
16+ errors : z . array ( z . unknown ( ) ) . optional ( ) ,
17+ messages : z . array ( z . unknown ( ) ) . optional ( ) ,
18+ } ) ;
1819
1920export interface GraphQLResponse < T > {
2021 data : T | null ;
2122 errors : { message : string ; path : string [ ] | null } [ ] | null ;
2223}
2324
2425const CONTAINERS_METRICS_QUERY = `
25- query GetCloudchamberMetrics($accountTag: string!, $datetimeStart: Time, $datetimeEnd: Time, $applicationId: string) {
26+ query GetCloudchamberMetrics($accountTag: string!, $datetimeStart: Time, $datetimeEnd: Time, $applicationIds: [ string!] ) {
2627 viewer {
2728 accounts(filter: {accountTag: $accountTag}) {
28- cloudchamberMetricsAdaptiveGroups(limit: 10000, filter: {applicationId : $applicationId , datetimeMinute_geq: $datetimeStart, datetimeMinute_leq: $datetimeEnd}) {
29+ cloudchamberMetricsAdaptiveGroups(limit: 10000, filter: {applicationId_in : $applicationIds , datetimeMinute_geq: $datetimeStart, datetimeMinute_leq: $datetimeEnd}) {
2930 avg {
3031 memory
3132 cpuLoad
@@ -91,7 +92,7 @@ export class CloudflareApi {
9192 ) ;
9293 }
9394
94- const data = ( await response . json ( ) ) as ContainersListResponse ;
95+ const data = ContainersListResponseSchema . parse ( await response . json ( ) ) ;
9596
9697 if ( ! data . success ) {
9798 throw new Error ( `API error: ${ JSON . stringify ( data . errors ) } ` ) ;
@@ -101,13 +102,13 @@ export class CloudflareApi {
101102 }
102103
103104 /**
104- * Get metrics for a specific container application
105- * @param applicationId - The container application ID
105+ * Get metrics for multiple container applications
106+ * @param applicationIds - Array of container application IDs
106107 * @param startTime - Start of the time range (defaults to 5 minutes ago)
107108 * @param endTime - End of the time range (defaults to now)
108109 */
109110 async getContainerMetrics (
110- applicationId : string ,
111+ applicationIds : string [ ] ,
111112 startTime ?: Date ,
112113 endTime ?: Date ,
113114 ) : Promise < MetricsGroup [ ] > {
@@ -118,7 +119,7 @@ export class CloudflareApi {
118119 accountTag : this . config . accountId ,
119120 datetimeStart : start . toISOString ( ) ,
120121 datetimeEnd : now . toISOString ( ) ,
121- applicationId ,
122+ applicationIds ,
122123 } ;
123124
124125 const response = await fetch ( this . graphqlUrl , {
@@ -136,16 +137,17 @@ export class CloudflareApi {
136137 ) ;
137138 }
138139
139- const data = ( await response . json ( ) ) as CloudchamberMetricsResponse ;
140+ const data = CloudchamberMetricsResponse . parse ( await response . json ( ) ) ;
140141
141142 if ( data . errors && data . errors . length > 0 ) {
142143 throw new Error ( `GraphQL errors: ${ JSON . stringify ( data . errors ) } ` ) ;
143144 }
144145
145146 const groups =
146147 data . data ?. viewer ?. accounts ?. [ 0 ] ?. cloudchamberMetricsAdaptiveGroups ?? [ ] ;
148+
147149 console . log ( "Fetched container metrics" , {
148- applicationId ,
150+ applicationCount : applicationIds . length ,
149151 groupCount : groups . length ,
150152 } ) ;
151153
0 commit comments