Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .changeset/external-api-min-auto-granularity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'@hyperdx/api': patch
---

docs: Document `minAutoGranularity` on metric and PromQL sources in the external
API

`GET`, `POST` and `PUT /api/v2/sources` already accepted and returned
`minAutoGranularity`, but the OpenAPI spec omitted it, so clients generated from
the spec dropped or rejected the field.
12 changes: 12 additions & 0 deletions packages/api/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -5594,6 +5594,12 @@
"description": "HyperDX Source for logs associated with metrics. Optional",
"nullable": true,
"example": "507f1f77bcf86cd799439011"
},
"minAutoGranularity": {
"type": "string",
"description": "Floor for the auto-inferred chart granularity. Set it to the scrape/report interval of the metrics so a short time range does not produce buckets smaller than that interval (sparse, steppy series). Only constrains \"Auto\" granularity; an explicit granularity picked on a tile is never overridden. Omit for no minimum. Uses the SQL interval format (a positive integer followed by second, minute, hour, or day), not the short form of the materialized view granularity fields.",
"pattern": "^\\d+ (second|minute|hour|day)$",
"example": "1 minute"
}
}
},
Expand Down Expand Up @@ -5736,6 +5742,12 @@
"type": "string",
"description": "Required by the API for all source kinds; not used by PromQL queries.",
"example": "timestamp"
},
"minAutoGranularity": {
"type": "string",
"description": "Floor for the auto-inferred chart granularity, and the scrape interval that `$__rate_interval` is computed from. Set it to the Prometheus scrape interval so a short time range does not produce buckets smaller than that interval. Only constrains \"Auto\" granularity; an explicit granularity picked on a tile is never overridden. Omit for no minimum. Uses the SQL interval format (a positive integer followed by second, minute, hour, or day), not the short form of the materialized view granularity fields.",
"pattern": "^\\d+ (second|minute|hour|day)$",
"example": "1 minute"
}
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,16 @@ describe('External API v2 Sources CRUD', () => {
connection: connection._id.toString(),
});

const metricSourceBody = () => ({
kind: SourceKind.Metric,
name: 'Created Metric Source',
from: { databaseName: DEFAULT_DATABASE, tableName: '' },
timestampValueExpression: 'TimeUnix',
resourceAttributesExpression: 'ResourceAttributes',
metricTables: { gauge: 'otel_metrics_gauge' },
connection: connection._id.toString(),
});

const createOtherTeamConnection = (otherTeamId: mongoose.Types.ObjectId) =>
Connection.create({
team: otherTeamId,
Expand Down Expand Up @@ -257,6 +267,25 @@ describe('External API v2 Sources CRUD', () => {
expect(persisted!.kind).toBe(SourceKind.Promql);
});

it('should round-trip minAutoGranularity in the SQL interval format', async () => {
const response = await authRequest('post', BASE_URL)
.send({ ...metricSourceBody(), minAutoGranularity: '1 minute' })
.expect(200);

expect(response.body.data.minAutoGranularity).toBe('1 minute');

const persisted = await Source.findById(response.body.data.id);
expect(persisted!.get('minAutoGranularity')).toBe('1 minute');
});

it('should reject a short-form minAutoGranularity', async () => {
// Unlike materializedViews[].minGranularity, this field is not mapped
// from the short form, so the documented contract is the SQL interval.
await authRequest('post', BASE_URL)
.send({ ...metricSourceBody(), minAutoGranularity: '1m' })
.expect(400);
});

it('should return 400 when connection is not a valid id', async () => {
await authRequest('post', BASE_URL)
.send({ ...logSourceBody(), connection: 'my-connection-name' })
Expand Down
10 changes: 10 additions & 0 deletions packages/api/src/routers/external-api/v2/sources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,11 @@ function formatExternalSource(source: SourceDocument) {
* description: HyperDX Source for logs associated with metrics. Optional
* nullable: true
* example: 507f1f77bcf86cd799439011
* minAutoGranularity:
* type: string
* description: Floor for the auto-inferred chart granularity. Set it to the scrape/report interval of the metrics so a short time range does not produce buckets smaller than that interval (sparse, steppy series). Only constrains "Auto" granularity; an explicit granularity picked on a tile is never overridden. Omit for no minimum. Uses the SQL interval format (a positive integer followed by second, minute, hour, or day), not the short form of the materialized view granularity fields.
* pattern: '^\d+ (second|minute|hour|day)$'
* example: 1 minute
* SessionSource:
* type: object
* required:
Expand Down Expand Up @@ -830,6 +835,11 @@ function formatExternalSource(source: SourceDocument) {
* type: string
* description: Required by the API for all source kinds; not used by PromQL queries.
* example: timestamp
* minAutoGranularity:
Comment thread
karl-power marked this conversation as resolved.
Resolved
* type: string
* description: Floor for the auto-inferred chart granularity, and the scrape interval that `$__rate_interval` is computed from. Set it to the Prometheus scrape interval so a short time range does not produce buckets smaller than that interval. Only constrains "Auto" granularity; an explicit granularity picked on a tile is never overridden. Omit for no minimum. Uses the SQL interval format (a positive integer followed by second, minute, hour, or day), not the short form of the materialized view granularity fields.
* pattern: '^\d+ (second|minute|hour|day)$'
* example: 1 minute
* Source:
* oneOf:
* - $ref: '#/components/schemas/LogSource'
Expand Down
Loading