mirror of
https://github.com/hyperdxio/hyperdx
synced 2026-04-21 13:37:15 +00:00
fix: services endpoint bug (#219)
The bug happened when: 1. Property map has custom attributes 2. Found log lines don't have custom properties And because the query has 'group-by' column checks in where clause, it ends up no matches even 'service' should exist.
This commit is contained in:
parent
2f40c30157
commit
95ddbb87bf
3 changed files with 90 additions and 24 deletions
6
.changeset/violet-singers-melt.md
Normal file
6
.changeset/violet-singers-melt.md
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
'@hyperdx/api': patch
|
||||
'@hyperdx/app': patch
|
||||
---
|
||||
|
||||
fix: services endpoint bug (missing log lines results in no matches)
|
||||
|
|
@ -9,6 +9,7 @@ import {
|
|||
closeDB,
|
||||
getLoggedInAgent,
|
||||
getServer,
|
||||
mockLogsPropertyTypeMappingsModel,
|
||||
} from '@/fixtures';
|
||||
|
||||
describe('charts router', () => {
|
||||
|
|
@ -119,6 +120,43 @@ Object {
|
|||
"service1": Array [],
|
||||
"service2": Array [],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('GET /chart/services (missing data but custom attributes exist)', async () => {
|
||||
const now = Date.now();
|
||||
const { agent, team } = await getLoggedInAgent(server);
|
||||
|
||||
await clickhouse.bulkInsertTeamLogStream(
|
||||
team.logStreamTableVersion,
|
||||
team.id,
|
||||
[
|
||||
buildEvent({
|
||||
timestamp: now,
|
||||
service: 'service1',
|
||||
}),
|
||||
buildEvent({
|
||||
timestamp: now,
|
||||
service: 'service1',
|
||||
}),
|
||||
buildEvent({
|
||||
timestamp: now - ms('1d'),
|
||||
service: 'service2',
|
||||
}),
|
||||
],
|
||||
);
|
||||
|
||||
mockLogsPropertyTypeMappingsModel({
|
||||
service: 'string',
|
||||
'k8s.namespace.name': 'string',
|
||||
});
|
||||
|
||||
const results = await agent.get('/chart/services').expect(200);
|
||||
expect(results.body.data).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"service1": Array [],
|
||||
"service2": Array [],
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -48,37 +48,59 @@ router.get('/services', async (req, res, next) => {
|
|||
const MAX_NUM_GROUPS = 2000;
|
||||
|
||||
const simpleCache = new SimpleCache<
|
||||
Awaited<ReturnType<typeof clickhouse.getMultiSeriesChart>>
|
||||
Awaited<ReturnType<typeof clickhouse.getMultiSeriesChart>>[]
|
||||
>(`chart-services-${teamId}`, ms('10m'), () =>
|
||||
clickhouse.getMultiSeriesChart({
|
||||
series: [
|
||||
{
|
||||
aggFn: clickhouse.AggFn.Count,
|
||||
groupBy: targetGroupByFields,
|
||||
table: 'logs',
|
||||
type: 'table',
|
||||
where: '',
|
||||
},
|
||||
],
|
||||
endTime,
|
||||
granularity: undefined,
|
||||
maxNumGroups: MAX_NUM_GROUPS,
|
||||
startTime,
|
||||
tableVersion: team.logStreamTableVersion,
|
||||
teamId: teamId.toString(),
|
||||
seriesReturnType: clickhouse.SeriesReturnType.Column,
|
||||
}),
|
||||
Promise.all([
|
||||
clickhouse.getMultiSeriesChart({
|
||||
series: [
|
||||
{
|
||||
aggFn: clickhouse.AggFn.Count,
|
||||
groupBy: targetGroupByFields,
|
||||
table: 'logs',
|
||||
type: 'table',
|
||||
where: '',
|
||||
},
|
||||
],
|
||||
endTime,
|
||||
granularity: undefined,
|
||||
maxNumGroups: MAX_NUM_GROUPS,
|
||||
startTime,
|
||||
tableVersion: team.logStreamTableVersion,
|
||||
teamId: teamId.toString(),
|
||||
seriesReturnType: clickhouse.SeriesReturnType.Column,
|
||||
}),
|
||||
clickhouse.getMultiSeriesChart({
|
||||
series: [
|
||||
{
|
||||
aggFn: clickhouse.AggFn.Count,
|
||||
groupBy: ['service'],
|
||||
table: 'logs',
|
||||
type: 'table',
|
||||
where: '',
|
||||
},
|
||||
],
|
||||
endTime,
|
||||
granularity: undefined,
|
||||
maxNumGroups: MAX_NUM_GROUPS,
|
||||
startTime,
|
||||
tableVersion: team.logStreamTableVersion,
|
||||
teamId: teamId.toString(),
|
||||
seriesReturnType: clickhouse.SeriesReturnType.Column,
|
||||
}),
|
||||
]),
|
||||
);
|
||||
|
||||
const results = await simpleCache.get();
|
||||
const [customAttrsResults, servicesResults] = await simpleCache.get();
|
||||
// restructure service maps
|
||||
const serviceMap: Record<string, Record<string, string>[]> = {};
|
||||
for (const row of results.data) {
|
||||
for (const row of servicesResults.data) {
|
||||
const service = row.group[0];
|
||||
serviceMap[service] = [];
|
||||
}
|
||||
|
||||
for (const row of customAttrsResults.data) {
|
||||
const values = row.group;
|
||||
const service = values[0];
|
||||
if (!(service in serviceMap)) {
|
||||
serviceMap[service] = [];
|
||||
}
|
||||
const attrs: Record<string, string> = {};
|
||||
for (let i = 1; i < values.length; i++) {
|
||||
const field = targetGroupByFields[i];
|
||||
|
|
|
|||
Loading…
Reference in a new issue