Skip to content

Commit ea08e2b

Browse files
committed
replace specific timing fields with generic label/duration pairs & add feature flag
1 parent b5fe673 commit ea08e2b

File tree

10 files changed

+59
-65
lines changed

10 files changed

+59
-65
lines changed

integration-tests/tests/api/app-deployments.spec.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,9 @@ const AddDocumentsToAppDeployment = graphql(`
9393
version
9494
status
9595
}
96-
timing {
97-
totalMs
98-
s3Ms
99-
clickhouseMs
96+
timings {
97+
label
98+
duration
10099
}
101100
}
102101
}
@@ -306,7 +305,7 @@ test('create app deployment, add operations, publish, access via CDN (happy path
306305
version: '1.0.0',
307306
status: 'pending',
308307
},
309-
timing: expect.any(Object),
308+
timings: null,
310309
},
311310
});
312311

packages/libraries/cli/src/commands/app/create.ts

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ export default class AppCreate extends Command<typeof AppCreate> {
223223
documents: buffer,
224224
format:
225225
format === 'v1' ? AppDeploymentFormatType.V1 : AppDeploymentFormatType.V2,
226+
showTimings: flags.showTiming || undefined,
226227
},
227228
},
228229
});
@@ -251,11 +252,11 @@ export default class AppCreate extends Command<typeof AppCreate> {
251252
throw new APIError(result.addDocumentsToAppDeployment.error.message);
252253
}
253254

254-
if (flags.showTiming && result.addDocumentsToAppDeployment.ok?.timing) {
255-
const t = result.addDocumentsToAppDeployment.ok.timing;
256-
this.log(
257-
` Batch timing: ${t.totalMs}ms total (${t.documentsProcessed} docs, parse: ${t.parsingMs}ms, validate: ${t.validationMs}ms, coords: ${t.coordinateExtractionMs}ms, ch: ${t.clickhouseMs}ms, s3: ${t.s3Ms}ms)`,
258-
);
255+
if (flags.showTiming && result.addDocumentsToAppDeployment.ok?.timings?.length) {
256+
const parts = result.addDocumentsToAppDeployment.ok.timings
257+
.map(t => `${t.label}: ${t.duration}ms`)
258+
.join(', ');
259+
this.log(` Batch timing: ${parts}`);
259260
}
260261

261262
buffer = [];
@@ -319,14 +320,9 @@ const AddDocumentsToAppDeploymentMutation = graphql(/* GraphQL */ `
319320
version
320321
status
321322
}
322-
timing {
323-
totalMs
324-
parsingMs
325-
validationMs
326-
coordinateExtractionMs
327-
clickhouseMs
328-
s3Ms
329-
documentsProcessed
323+
timings {
324+
label
325+
duration
330326
}
331327
}
332328
error {

packages/services/api/src/create.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import { TaskScheduler } from '@hive/workflows/kit';
44
import { adminModule } from './modules/admin';
55
import { alertsModule } from './modules/alerts';
66
import { appDeploymentsModule } from './modules/app-deployments';
7-
import { APP_DEPLOYMENTS_ENABLED } from './modules/app-deployments/providers/app-deployments-enabled-token';
7+
import {
8+
APP_DEPLOYMENT_TIMINGS_ENABLED,
9+
APP_DEPLOYMENTS_ENABLED,
10+
} from './modules/app-deployments/providers/app-deployments-enabled-token';
811
import { auditLogsModule } from './modules/audit-logs';
912
import { AuditLogRecorder } from './modules/audit-logs/providers/audit-log-recorder';
1013
import { AuditLogS3Config } from './modules/audit-logs/providers/audit-logs-manager';
@@ -115,6 +118,7 @@ export function createRegistry({
115118
organizationOIDC,
116119
pubSub,
117120
appDeploymentsEnabled,
121+
appDeploymentTimingsEnabled,
118122
schemaProposalsEnabled,
119123
otelTracingEnabled,
120124
prometheus,
@@ -160,6 +164,7 @@ export function createRegistry({
160164
organizationOIDC: boolean;
161165
pubSub: HivePubSub;
162166
appDeploymentsEnabled: boolean;
167+
appDeploymentTimingsEnabled: boolean;
163168
schemaProposalsEnabled: boolean;
164169
otelTracingEnabled: boolean;
165170
prometheus: null | Record<string, unknown>;
@@ -283,6 +288,11 @@ export function createRegistry({
283288
useValue: appDeploymentsEnabled,
284289
scope: Scope.Singleton,
285290
},
291+
{
292+
provide: APP_DEPLOYMENT_TIMINGS_ENABLED,
293+
useValue: appDeploymentTimingsEnabled,
294+
scope: Scope.Singleton,
295+
},
286296
{
287297
provide: SCHEMA_PROPOSALS_ENABLED,
288298
useValue: schemaProposalsEnabled,

packages/services/api/src/modules/app-deployments/module.graphql.ts

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,11 @@ export default gql`
290290
V2 enables cross-version deduplication and delta uploads (requires SHA256 hashes).
291291
"""
292292
format: AppDeploymentFormatType
293+
"""
294+
When true, the response will include timing measurements for document processing.
295+
Intended for benchmarking; requires server-side timing to be enabled.
296+
"""
297+
showTimings: Boolean
293298
}
294299
295300
type AddDocumentsToAppDeploymentErrorDetails {
@@ -312,42 +317,22 @@ export default gql`
312317
}
313318
314319
"""
315-
Timing breakdown for document upload operations. All time values are in milliseconds.
320+
A labeled timing measurement from document upload processing.
316321
"""
317322
type DocumentUploadTiming {
318323
"""
319-
Total elapsed time for the entire batch processing.
320-
"""
321-
totalMs: Int!
322-
"""
323-
Time spent parsing GraphQL documents.
324-
"""
325-
parsingMs: Int!
326-
"""
327-
Time spent validating documents against the schema.
328-
"""
329-
validationMs: Int!
330-
"""
331-
Time spent extracting schema coordinates from documents.
332-
"""
333-
coordinateExtractionMs: Int!
334-
"""
335-
Time spent inserting records into ClickHouse.
336-
"""
337-
clickhouseMs: Int!
338-
"""
339-
Time spent uploading documents to S3.
324+
Identifies the processing phase (e.g., "total", "parsing", "validation", "s3", "clickhouse").
340325
"""
341-
s3Ms: Int!
326+
label: String!
342327
"""
343-
Number of documents successfully processed.
328+
Duration in milliseconds.
344329
"""
345-
documentsProcessed: Int!
330+
duration: Int!
346331
}
347332
348333
type AddDocumentsToAppDeploymentOk {
349334
appDeployment: AppDeployment!
350-
timing: DocumentUploadTiming
335+
timings: [DocumentUploadTiming!]
351336
}
352337
353338
type AddDocumentsToAppDeploymentResult {
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
import { InjectionToken } from 'graphql-modules';
22

33
export const APP_DEPLOYMENTS_ENABLED = new InjectionToken<boolean>('APP_DEPLOYMENTS_ENABLED');
4+
export const APP_DEPLOYMENT_TIMINGS_ENABLED = new InjectionToken<boolean>(
5+
'APP_DEPLOYMENT_TIMINGS_ENABLED',
6+
);

packages/services/api/src/modules/app-deployments/providers/persisted-document-ingester.ts

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,7 @@ type DocumentRecord = {
2424
schemaCoordinates: Array<string>;
2525
};
2626

27-
export type ProcessingTiming = {
28-
totalMs: number;
29-
parsingMs: number;
30-
validationMs: number;
31-
coordinateExtractionMs: number;
32-
clickhouseMs: number;
33-
s3Ms: number;
34-
documentsProcessed: number;
35-
};
27+
export type ProcessingTiming = Array<{ label: string; duration: number }>;
3628

3729
const AppDeploymentOperationHashModel = z
3830
.string()
@@ -328,15 +320,14 @@ export class PersistedDocumentIngester {
328320

329321
return {
330322
type: 'success' as const,
331-
timing: {
332-
totalMs: Math.round(totalMs),
333-
parsingMs: Math.round(parsingMs),
334-
validationMs: Math.round(validationMs),
335-
coordinateExtractionMs: Math.round(coordinateExtractionMs),
336-
clickhouseMs: Math.round(clickhouseMs),
337-
s3Ms: Math.round(s3Ms),
338-
documentsProcessed: documents.length,
339-
},
323+
timing: [
324+
{ label: 'total', duration: Math.round(totalMs) },
325+
{ label: 'parsing', duration: Math.round(parsingMs) },
326+
{ label: 'validation', duration: Math.round(validationMs) },
327+
{ label: 'coordinate-extraction', duration: Math.round(coordinateExtractionMs) },
328+
{ label: 'clickhouse', duration: Math.round(clickhouseMs) },
329+
{ label: 's3', duration: Math.round(s3Ms) },
330+
],
340331
};
341332
}
342333

@@ -521,7 +512,7 @@ export class PersistedDocumentIngester {
521512
})(),
522513
(async () => {
523514
const start = performance.now();
524-
await this.insertS3Documents({ ...args, isV1Format: args.isV1Format });
515+
await this.insertS3Documents(args);
525516
return performance.now() - start;
526517
})(),
527518
]);

packages/services/api/src/modules/app-deployments/resolvers/Mutation/addDocumentsToAppDeployment.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { APP_DEPLOYMENT_TIMINGS_ENABLED } from '../../providers/app-deployments-enabled-token';
12
import { AppDeploymentsManager } from '../../providers/app-deployments-manager';
23
import type { MutationResolvers } from './../../../../__generated__/types';
34

@@ -24,11 +25,13 @@ export const addDocumentsToAppDeployment: NonNullable<
2425
};
2526
}
2627

28+
const timingsEnabled = injector.get<boolean>(APP_DEPLOYMENT_TIMINGS_ENABLED);
29+
2730
return {
2831
error: null,
2932
ok: {
3033
appDeployment: result.appDeployment,
31-
timing: result.timing,
34+
timings: timingsEnabled && input.showTimings ? result.timing : null,
3235
},
3336
};
3437
};

packages/services/server/.env.template

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ INTEGRATION_GITHUB="<sync>"
2323
INTEGRATION_GITHUB_APP_ID="<sync>"
2424
INTEGRATION_GITHUB_APP_PRIVATE_KEY="<sync>"
2525
FEATURE_FLAGS_APP_DEPLOYMENTS_ENABLED="0"
26+
FEATURE_FLAGS_APP_DEPLOYMENT_TIMINGS_ENABLED="0"
2627
FEATURE_FLAGS_SCHEMA_PROPOSALS_ENABLED="0"
2728
FEATURE_FLAGS_OTEL_TRACING_ENABLED="0"
2829

packages/services/server/src/environment.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ const EnvironmentModel = zod.object({
4040
FEATURE_FLAGS_APP_DEPLOYMENTS_ENABLED: emptyString(
4141
zod.union([zod.literal('1'), zod.literal('0')]).optional(),
4242
),
43+
FEATURE_FLAGS_APP_DEPLOYMENT_TIMINGS_ENABLED: emptyString(
44+
zod.union([zod.literal('1'), zod.literal('0')]).optional(),
45+
),
4346
FEATURE_FLAGS_SCHEMA_PROPOSALS_ENABLED: emptyString(
4447
zod.union([zod.literal('1'), zod.literal('0')]).optional(),
4548
),
@@ -555,6 +558,8 @@ export const env = {
555558
featureFlags: {
556559
/** Whether app deployments should be enabled by default for everyone. */
557560
appDeploymentsEnabled: base.FEATURE_FLAGS_APP_DEPLOYMENTS_ENABLED === '1',
561+
/** Whether app deployment upload timings should be exposed via the GraphQL API. */
562+
appDeploymentTimingsEnabled: base.FEATURE_FLAGS_APP_DEPLOYMENT_TIMINGS_ENABLED === '1',
558563
/** Whether schema proposals should be enabled for all organizations. */
559564
schemaProposalsEnabled: base.FEATURE_FLAGS_SCHEMA_PROPOSALS_ENABLED === '1',
560565
/** Whether OTEL tracing should be enabled for all organizations. */

packages/services/server/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ export async function main() {
373373
supportConfig: env.zendeskSupport,
374374
pubSub,
375375
appDeploymentsEnabled: env.featureFlags.appDeploymentsEnabled,
376+
appDeploymentTimingsEnabled: env.featureFlags.appDeploymentTimingsEnabled,
376377
schemaProposalsEnabled: env.featureFlags.schemaProposalsEnabled,
377378
otelTracingEnabled: env.featureFlags.otelTracingEnabled,
378379
prometheus: env.prometheus,

0 commit comments

Comments
 (0)