@khulnasoft/cdk
Version:
Define your observability as code using the AWS CDK
99 lines (81 loc) • 2.8 kB
text/typescript
import { CfnResource, Stack } from "aws-cdk-lib";
import { Kengine as Config } from "../config";
import { QueryProps, Filter, DeploymentQueryParameters } from "../types/query";
import { AlertProps } from "../types/alert";
import { Alert } from './alert';
function hasDuplicates<T>(array: T[]) {
return (new Set(array)).size !== array.length;
}
function buildShortCalculation(cal: { alias?: string; operation: string; key?: string }) {
if (cal.operation === "COUNT") {
return cal.operation;
}
return `${cal.operation}(${cal.key})`;
}
function getCalculationAlias(cal: { alias?: string; operation: string; key?: string }) {
return cal.alias ? cal.alias : buildShortCalculation(cal);
}
/**
*
*/
export class Query<TKey extends string> extends CfnResource {
id: string;
props: QueryProps<TKey>
constructor(id: string, props: QueryProps<TKey>) {
const stack = Stack.of(Config.getConstruct());
const calcs = props.parameters.calculations;
const orderByOptions = calcs?.map(cal => getCalculationAlias(cal));
if (calcs?.length && hasDuplicates(calcs.filter(c => c.alias).map(c => c.alias))) {
throw Error("Aliases must me unique across all calculations / visualisations.")
}
if (props.parameters.orderBy && !orderByOptions?.includes(props.parameters.orderBy.value)) {
throw Error("The orderBy must be present in the calculations / visualisations.")
}
const disableStackFilter = props.disableStackFilter || Config.getDisableStackFilter();
if (!disableStackFilter) {
props.parameters.filters?.push({ operation: "=", key: "$kengine.stackId", value: stack.stackName })
}
const Parameters: DeploymentQueryParameters = {
...props.parameters,
datasets: props.parameters.datasets || [],
calculations: props.parameters.calculations || [],
filters: props.parameters.filters,
groupBys: props.parameters.groupBys?.map(groupBy => {
return {
...groupBy,
type: groupBy?.type || "string"
}
}),
filterCombination: props.parameters.filterCombination || "AND",
};
super(Config.getConstruct(), id, {
type: "Custom::KengineQuery",
properties: {
id,
ServiceToken: Config.getServiceToken(),
KengineApiKey: Config.getApiKey(),
Description: props.description,
Parameters,
Origin: "cdk"
},
});
this.id = id;
this.props = props;
}
addAlert(alert: ChangeFields<AlertProps<TKey>, {
parameters: Omit<AlertProps<TKey>['parameters'], "query">
}>) {
const alertProps = {
...alert,
parameters: {
...alert.parameters,
query: this
}
}
new Alert(`${this.id}-alert`, alertProps);
}
addFilters(filters: QueryProps<string>["parameters"]["filters"]) {
this.addPropertyOverride('Parameters.filters', [...filters || []])
}
};
type ChangeFields<T, R> = Omit<T, keyof R> & R;