Skip to content

Commit

Permalink
implement connection to the perf monitoring service
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcoMruz committed May 17, 2024
1 parent 89456e1 commit 1a74153
Show file tree
Hide file tree
Showing 11 changed files with 358 additions and 62 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ TOPOLOGY_ENABLED=true
# either define all of them or do not define them at all
TOPOLOGY_DISCOVERY_API_URL=http://10.19.0.5:8080/api/topology/data
TOPOLOGY_DISCOVERY_GRAPHQL_API_URL=http://localhost:5000/api/graphql
PERFORMANCE_MONITORING_GRAPHQL_API_URL=http://localhost:8082/api/graphql

KAFKA_BROKER="10.19.0.25:9094"
KAFKA_TOPIC=frinx
Expand Down
15 changes: 15 additions & 0 deletions codegen-perf-monitoring.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
schema:
- 'http://localhost:8082'
documents:
- './src/external-api/performance-monitoring-graphql.ts'
generates:
src/__generated__/perf-monitoring.graphql.ts:
plugins:
- 'typescript'
- 'typescript-operations'
config:
enumsAsTypes: true
avoidOptionals:
field: true
object: false
inputValue: false
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
"test:generate": "cross-env NODE_ENV=testing ts-node --transpile-only -r dotenv/config src/schema/index.ts",
"jest": "cross-env NODE_ENV=testing jest --verbose",
"test": "run-s test:generate jest",
"codegen": "graphql-codegen --config codegen-topology-discovery.yml"
"codegen": "run-s codegen:discovery codegen:monitoring",
"codegen:discovery": "graphql-codegen --config codegen-topology-discovery.yml",
"codegen:monitoring": "graphql-codegen --config codegen-perf-monitoring.yml"
},
"devDependencies": {
"@frinx/eslint-config-typescript-base": "15.0.0-build.1",
Expand Down
159 changes: 159 additions & 0 deletions src/__generated__/perf-monitoring.graphql.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type TopologyConfigEnabled = {
topologyEnabled: true;
topologyDiscoveryURL: string;
topologyDiscoveryGraphqlURL: string;
performanceMonitoringGraphqlURL: string;
};

type TopologyConfigDisabled = {
Expand All @@ -46,22 +47,25 @@ function getTopologyConfig(): TopologyConfig {
const topologyEnabled = stringToBoolean(envString('TOPOLOGY_ENABLED'));
const topologyDiscoveryURL = optionalEnvString('TOPOLOGY_DISCOVERY_API_URL');
const topologyDiscoveryGraphqlURL = optionalEnvString('TOPOLOGY_DISCOVERY_GRAPHQL_API_URL');
const performanceMonitoringGraphqlURL = optionalEnvString('PERFORMANCE_MONITORING_GRAPHQL_API_URL');

if (!topologyEnabled) {
return {
topologyEnabled: false,
};
}

if (!topologyDiscoveryURL || !topologyDiscoveryGraphqlURL) {
if (!topologyDiscoveryURL || !topologyDiscoveryGraphqlURL || !performanceMonitoringGraphqlURL) {
throw new Error(
'Not all mandatory topology discovery url (TOPOLOGY_DISCOVERY_API_URL, TOPOLOGY_DISCOVERY_GRAPHQL_API_URL) were found.',
'Not all mandatory topology discovery url (TOPOLOGY_DISCOVERY_API_URL, TOPOLOGY_DISCOVERY_GRAPHQL_API_URL, PERFORMANCE_MONITORING_GRAPHQL_API_URL) were found.',
);
}

return {
topologyEnabled: true,
topologyDiscoveryURL,
topologyDiscoveryGraphqlURL,
performanceMonitoringGraphqlURL,
};
}

Expand Down
3 changes: 2 additions & 1 deletion src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import uniconfigAPI, { UniConfigAPI } from './external-api/uniconfig';
import prismaClient from './prisma-client';
import config from './config';
import kafkaProducers, { KafkaService } from './external-api/kafka';
import getPerformanceMonitoringAPI, { PerformanceMonitoringAPI } from './external-api/performance-monitoring';
import getPerformanceMonitoringAPI, { PerformanceMonitoringAPI } from './external-api/performance-monitoring-graphql';

export type Context = {
kafka: KafkaService | null;
Expand Down Expand Up @@ -54,5 +54,6 @@ export default async function createContext(context: ExpressContextFunctionArgum
export function createSubscriptionContext() {
return {
prisma: prismaClient,
performanceMonitoringAPI: getPerformanceMonitoringAPI(),
};
}
133 changes: 133 additions & 0 deletions src/external-api/performance-monitoring-graphql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { gql, GraphQLClient } from 'graphql-request';
import config from '../config';
import {
CurrentCpuUsageQuery,
CurrentCpuUsageQueryVariables,
CurrentCpuUsagesQuery,
CurrentCpuUsagesQueryVariables,
CurrentMemoryUsageQuery,
CurrentMemoryUsageQueryVariables,
CurrentMemoryUsagesQuery,
CurrentMemoryUsagesQueryVariables,
} from '../__generated__/perf-monitoring.graphql';

export type DeviceLoadUsage = {
cpuUsage: number | null;
memoryUsage: number | null;
};

const DEVICE_MEMORY_USAGES = gql`
query CurrentMemoryUsages($names: [String!]!) {
currentMemoryUsages(devices: $names) {
device
usage
}
}
`;

const DEVICE_CPU_USAGES = gql`
query CurrentCpuUsages($names: [String!]!) {
currentCpuUsages(devices: $names) {
device
usage
}
}
`;

const DEVICE_MEMORY_USAGE = gql`
query CurrentMemoryUsage($name: String!) {
currentMemoryUsage(device: $name) {
device
usage
}
}
`;

const DEVICE_CPU_USAGE = gql`
query CurrentCpuUsage($name: String!) {
currentCpuUsage(device: $name) {
device
usage
}
}
`;

function getPerformanceMonitoringAPI() {
if (config.topologyEnabled === false) {
return undefined;
}

const client = new GraphQLClient(config.performanceMonitoringGraphqlURL);

async function getDeviceCpuUsage(deviceName: string): Promise<CurrentCpuUsageQuery> {
const result = await client.request<CurrentCpuUsageQuery, CurrentCpuUsageQueryVariables>(DEVICE_CPU_USAGE, {
name: deviceName,
});

return result;
}

async function getDeviceMemoryUsage(deviceName: string): Promise<CurrentMemoryUsageQuery> {
const result = await client.request<CurrentMemoryUsageQuery, CurrentMemoryUsageQueryVariables>(
DEVICE_MEMORY_USAGE,
{ name: deviceName },
);

return result;
}

async function getDeviceCpuUsages(deviceNames: string[]): Promise<CurrentCpuUsagesQuery> {
const result = await client.request<CurrentCpuUsagesQuery, CurrentCpuUsagesQueryVariables>(DEVICE_CPU_USAGES, {
names: deviceNames,
});

return result;
}

async function getDeviceMemoryUsages(deviceNames: string[]): Promise<CurrentMemoryUsagesQuery> {
const result = await client.request<CurrentMemoryUsagesQuery, CurrentMemoryUsagesQueryVariables>(
DEVICE_MEMORY_USAGES,
{ names: deviceNames },
);

return result;
}

async function getDeviceLoadUsage(deviceName: string): Promise<DeviceLoadUsage> {
const [cpuUsage, memoryUsage] = await Promise.all([
getDeviceCpuUsage(deviceName),
getDeviceMemoryUsage(deviceName),
]);

return { cpuUsage: cpuUsage.currentCpuUsage.usage, memoryUsage: memoryUsage.currentMemoryUsage.usage };
}

async function getDeviceLoadUsages(deviceNames: string[]): Promise<(DeviceLoadUsage & { deviceName: string })[]> {
const [cpuUsages, memoryUsages] = await Promise.all([
getDeviceCpuUsages(deviceNames),
getDeviceMemoryUsages(deviceNames),
]);

const map = new Map<string, DeviceLoadUsage & { deviceName: string }>();

cpuUsages.currentCpuUsages?.forEach((cpuUsage) => {
map.set(cpuUsage.device, { deviceName: cpuUsage.device, cpuUsage: cpuUsage.usage, memoryUsage: null });
});

memoryUsages.currentMemoryUsages?.forEach((memoryUsage) => {
const deviceLoadUsage = map.get(memoryUsage.device);
if (deviceLoadUsage) {
deviceLoadUsage.memoryUsage = memoryUsage.usage;
} else {
map.set(memoryUsage.device, { deviceName: memoryUsage.device, cpuUsage: null, memoryUsage: memoryUsage.usage });
}
});

return Array.from(map.values());
}

return { getDeviceLoadUsage, getDeviceLoadUsages };
}

export type PerformanceMonitoringAPI = ReturnType<typeof getPerformanceMonitoringAPI>;
export default getPerformanceMonitoringAPI;
Loading

0 comments on commit 1a74153

Please sign in to comment.