Skip to content
Open
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
9 changes: 9 additions & 0 deletions src/components/grafana/builder.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import * as pulumi from '@pulumi/pulumi';
import { GrafanaConnection } from './connections';
import { Grafana } from './grafana';
import { GrafanaDashboard } from './dashboards/types';

export class GrafanaBuilder {
private name: string;
private connections: GrafanaConnection[] = [];
private dashboardConfigs: GrafanaDashboard.DashboardConfig[] = [];

constructor(name: string) {
this.name = name;
Expand All @@ -16,6 +18,12 @@ export class GrafanaBuilder {
return this;
}

public addDashboard(config: GrafanaDashboard.DashboardConfig): this {
this.dashboardConfigs.push(config);

return this;
}

public build(opts: pulumi.ComponentResourceOptions = {}): Grafana {
if (!this.connections.length) {
throw new Error(
Expand All @@ -27,6 +35,7 @@ export class GrafanaBuilder {
this.name,
{
connections: this.connections,
dashboards: this.dashboardConfigs,
},
opts,
);
Expand Down
35 changes: 18 additions & 17 deletions src/components/grafana/dashboards/panels.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Grafana } from './types';
import * as pulumi from '@pulumi/pulumi';
import { GrafanaDashboard } from './types';

const percentageFieldConfig = {
unit: 'percent',
Expand All @@ -8,10 +9,10 @@ const percentageFieldConfig = {

export function createStatPercentagePanel(
title: string,
position: Grafana.Panel.Position,
dataSource: string,
metric: Grafana.Metric,
): Grafana.Panel {
position: GrafanaDashboard.PanelPosition,
dataSource: pulumi.Input<string>,
metric: GrafanaDashboard.Metric,
): GrafanaDashboard.Panel {
return {
title,
gridPos: position,
Expand Down Expand Up @@ -41,10 +42,10 @@ export function createStatPercentagePanel(

export function createTimeSeriesPercentagePanel(
title: string,
position: Grafana.Panel.Position,
dataSource: string,
metric: Grafana.Metric,
): Grafana.Panel {
position: GrafanaDashboard.PanelPosition,
dataSource: pulumi.Input<string>,
metric: GrafanaDashboard.Metric,
): GrafanaDashboard.Panel {
return createTimeSeriesPanel(
title,
position,
Expand All @@ -58,13 +59,13 @@ export function createTimeSeriesPercentagePanel(

export function createTimeSeriesPanel(
title: string,
position: Grafana.Panel.Position,
dataSource: string,
metric: Grafana.Metric,
position: GrafanaDashboard.PanelPosition,
dataSource: pulumi.Input<string>,
metric: GrafanaDashboard.Metric,
unit?: string,
min?: number,
max?: number,
): Grafana.Panel {
): GrafanaDashboard.Panel {
return {
title,
type: 'timeseries',
Expand Down Expand Up @@ -96,10 +97,10 @@ export function createTimeSeriesPanel(

export function createBurnRatePanel(
title: string,
position: Grafana.Panel.Position,
dataSource: string,
metric: Grafana.Metric,
): Grafana.Panel {
position: GrafanaDashboard.PanelPosition,
dataSource: pulumi.Input<string>,
metric: GrafanaDashboard.Metric,
): GrafanaDashboard.Panel {
return {
type: 'stat',
title,
Expand Down
54 changes: 29 additions & 25 deletions src/components/grafana/dashboards/types.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,27 @@
import * as pulumi from '@pulumi/pulumi';
import * as grafana from '@pulumiverse/grafana';

// TODO: Should we prefix all namespaces with `Studion`
export namespace Grafana {
// TODO: Create SLO abstraction that enables configuring:
// - panels (long-window SLI, long-window error budget)
// - alerts (long-window burn, short-window burn)
export type Threshold = {
value: number | null;
color: string;
};
export type Metric = {
label: string;
query: string;
thresholds: Threshold[];
// TODO: Create SLO abstraction that enables configuring:
// - panels (long-window SLI, long-window error budget)
// - alerts (long-window burn, short-window burn)
export namespace GrafanaDashboard {
export type DataSources = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would opt for singular since this is not an array type.

prometheus?: pulumi.Output<string>;
};

export interface DashboardConfig {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just Config or Configuration?

createResource(dataSources: DataSources): grafana.oss.Dashboard;
}

export type Args = {
title: pulumi.Input<string>;
provider: pulumi.Input<grafana.Provider>;
tags: pulumi.Input<pulumi.Input<string>[]>;
};

export type Panel = {
title: string;
gridPos: Panel.Position;
gridPos: PanelPosition;
type: string;
datasource: string;
datasource: pulumi.Input<string>;
targets: {
expr: string;
legendFormat: string;
Expand Down Expand Up @@ -62,12 +57,21 @@ export namespace Grafana {
};
};

export namespace Panel {
export type Position = {
x: number;
y: number;
w: number;
h: number;
};
}
export type PanelPosition = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why break this type out of the Panel namespace?

x: number;
y: number;
w: number;
h: number;
};

export type Threshold = {
value: number | null;
color: string;
};

export type Metric = {
label: string;
query: string;
thresholds: Threshold[];
};
}
Loading