@pagopa/opex-dashboard 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,232 @@
1
+ # OpEx Dashboard
2
+
3
+ **Generate standardized Operational Excellence dashboards from OpenAPI 3
4
+ specifications.**
5
+
6
+ ## Features
7
+
8
+ - **Automatic Dashboard Generation** - Parses OpenAPI 3 specs to create
9
+ standardized operational dashboards
10
+ - **Multiple Cloud Providers** - Azure (current), AWS CloudWatch, Grafana
11
+ (planned)
12
+ - **High Performance** - Parallel rendering with deterministic ordering
13
+ - **Type-Safe** - Full TypeScript with Zod runtime validation
14
+
15
+ OpEx Dashboard is distributed as an **npm package** with two components:
16
+
17
+ - **CLI tool** (`opex-dashboard`) - Command-line interface for end users
18
+ - **TypeScript library** - Programmatic API for integration
19
+
20
+ ## Usage
21
+
22
+ ```bash
23
+ npx @pagopa/opex-dashboard generate --help
24
+ ```
25
+
26
+ ### Local Development
27
+
28
+ ```bash
29
+ git clone https://github.com/pagopa/dx.git
30
+ cd dx/apps/opex-dashboard-ts
31
+ pnpm install
32
+ pnpm run build
33
+ pnpm run dev
34
+ ```
35
+
36
+ ## Quick Start
37
+
38
+ ### 1. Create Configuration File
39
+
40
+ ```yaml
41
+ # config.yaml
42
+ oa3_spec: ./openapi.yaml # or HTTP URL
43
+ name: My API Dashboard
44
+ location: West Europe
45
+ resource_type: app-gateway
46
+ data_source: /subscriptions/xxx/resourceGroups/my-rg/providers/Microsoft.Network/applicationGateways/my-gtw
47
+ action_groups:
48
+ - /subscriptions/xxx/resourceGroups/my-rg/providers/microsoft.insights/actionGroups/my-alerts
49
+ ```
50
+
51
+ ### 2. Generate Dashboard
52
+
53
+ ```bash
54
+ # Output to stdout
55
+ npx @pagopa/opex-dashboard generate -t azure-dashboard-raw -c config.yaml
56
+
57
+ # Save as Terraform package
58
+ npx @pagopa/opex-dashboard generate -t azure-dashboard -c config.yaml --package ./output
59
+ ```
60
+
61
+ ### 3. Deploy with Terraform
62
+
63
+ ```bash
64
+ cd output/azure-dashboard
65
+ terraform init -backend-config=env/dev/backend.tfvars
66
+ terraform apply -var-file=env/dev/terraform.tfvars
67
+ ```
68
+
69
+ ## Dashboard Components
70
+
71
+ For each endpoint in the OpenAPI spec, the dashboard includes:
72
+
73
+ ### Graphs
74
+
75
+ 1. **Availability**: HTTP success rate (status codes < 500)
76
+ 2. **Response Codes**: Segmentation of all HTTP status codes (1XX, 2XX, 3XX,
77
+ 4XX, 5XX)
78
+ 3. **Response Time**: 95th percentile response time
79
+
80
+ ### Alarms
81
+
82
+ 1. **Availability Alarm**: Triggers when availability drops below threshold
83
+ (default: 99%)
84
+ 2. **Response Time Alarm**: Triggers when response time exceeds threshold
85
+ (default: 1 second)
86
+
87
+ ### Configurable Parameters
88
+
89
+ For each alarm, you can configure:
90
+
91
+ - **Timespan** _(Default: 5m)_ - The aggregation window
92
+ - **Evaluation Frequency** _(Default: 10 minutes)_ - How often to evaluate the
93
+ rule
94
+ - **Time Window** _(Default: 20 minutes)_ - Data fetch window (must be ≥
95
+ evaluation frequency)
96
+ - **Event Occurrences** _(Default: 1)_ - Number of events needed to trigger
97
+ alert
98
+
99
+ **NOTE:** Maximum event occurrences = time window ÷ timespan. For example, with
100
+ a 30m window and 5m timespan, max is 6 events.
101
+
102
+ ## Usage
103
+
104
+ ### CLI Commands
105
+
106
+ ```bash
107
+ opex-dashboard generate [options]
108
+
109
+ Options:
110
+ -t, --template-type <type> Template type: azure-dashboard or azure-dashboard-raw (required)
111
+ -c, --config <path> Path to YAML config file, use - for stdin (required)
112
+ --package [path] Save as package in directory (default: current dir)
113
+ -h, --help Display help
114
+ -V, --version Display version
115
+ ```
116
+
117
+ ### Configuration
118
+
119
+ Create a YAML configuration file:
120
+
121
+ ```yaml
122
+ # yaml-language-server: $schema=./config.schema.json
123
+ # Required fields
124
+ oa3_spec: string # Path or URL to OpenAPI 3 specification
125
+ name: string # Dashboard name
126
+ location: string # Azure region (e.g., "West Europe")
127
+ data_source: string # Azure resource ID
128
+ action_groups: string[] # Array of Azure Action Group IDs
129
+
130
+ # Optional fields (with defaults)
131
+ resource_type: app-gateway | api-management # Default: app-gateway
132
+ timespan: string # Default: 5m
133
+ evaluation_frequency: integer # Default: 10 (minutes)
134
+ evaluation_time_window: integer # Default: 20 (minutes)
135
+ event_occurrences: integer # Default: 1
136
+ availability_threshold`: float # Default: 0.99 (99%)
137
+ response_time_threshold: float # Default: 1.0 second
138
+
139
+ # When generating Terraform packages (using `--package` option),
140
+ # you can optionally configure environment-specific settings
141
+ terraform:
142
+ environments:
143
+ dev:
144
+ prefix: string # Max 6 chars (required)
145
+ env_short: string # Max 1 char: 'd', 'u', 'p' (required)
146
+ backend: # Optional backend state configuration
147
+ resource_group_name: string
148
+ storage_account_name: string
149
+ container_name: string
150
+ key: string
151
+ uat: # Similar to dev
152
+ prod: # Similar to dev
153
+ ```
154
+
155
+ See [`examples/`](./examples) directory for complete configuration samples.
156
+
157
+ #### JSON Schema Validation
158
+
159
+ A JSON Schema is automatically generated from the TypeScript types and included
160
+ at [`config.schema.json`](./config.schema.json). This enables IDE autocomplete
161
+ and validation for your configuration files.
162
+
163
+ To enable schema validation in VS Code and other compatible editors, add this
164
+ comment at the top of your YAML configuration file:
165
+
166
+ ```yaml
167
+ # yaml-language-server: $schema=https://raw.githubusercontent.com/pagopa/dx/refs/heads/main/apps/opex-dashboard-ts/config.schema.json
168
+ ```
169
+
170
+ The schema is:
171
+
172
+ - **Automatically generated** during build from Zod schemas using
173
+ `pnpm run build`
174
+ - **Synchronized** with TypeScript types - any changes to configuration
175
+ structure are reflected immediately
176
+ - **Versioned** - matches the package version for compatibility tracking
177
+ - **Distributed** with the npm package for programmatic access
178
+
179
+ ## CI/CD Integration
180
+
181
+ ### Using the GitHub Workflow from Another Repository
182
+
183
+ You can use the reusable workflow to automate dashboard generation in your own
184
+ repository. Create a `.github/workflows/generate-dashboard.yml` file in your
185
+ repo:
186
+
187
+ ```yaml
188
+ name: Generate Dashboard
189
+
190
+ on:
191
+ push:
192
+ branches: [main]
193
+ pull_request:
194
+ branches: [main]
195
+
196
+ jobs:
197
+ generate:
198
+ uses: pagopa/dx/.github/workflows/generate.yml@main
199
+ with:
200
+ # mandatory inputs:
201
+ config_path: ./config/dashboard-config.yaml
202
+ output_dir: ./generated
203
+ # optional inputs with defaults:
204
+ pr_title: "Update operational dashboard"
205
+ pr_body: "Automated update of dashboard terraform from OpenAPI spec"
206
+ base_branch: main
207
+ ```
208
+
209
+ This workflow will:
210
+
211
+ 1. Generate the dashboard using your configuration
212
+ 2. Commit changes to a new branch
213
+ 3. Create a pull request for review
214
+
215
+ ### Workflow Inputs
216
+
217
+ - `config_path` (required): Path to your YAML configuration file
218
+ - `output_dir` (required): Directory to save generated files
219
+ - `template_type` (optional): Template type (`azure-dashboard` or
220
+ `azure-dashboard-raw`, default: `azure-dashboard`)
221
+ - `pr_title` (optional): Title for the generated pull request
222
+ - `pr_body` (optional): Description for the generated pull request
223
+ - `base_branch` (optional): Base branch for the pull request (default: `main`)
224
+
225
+ ## Development
226
+
227
+ ### Setup
228
+
229
+ ```bash
230
+ pnpm install
231
+ pnpm run build
232
+ ```
@@ -0,0 +1,360 @@
1
+ {
2
+ "$id": "https://github.com/pagopa/dx/blob/main/apps/opex-dashboard/config.schema.json",
3
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
4
+ "description": "Configuration schema for generating operational dashboards from OpenAPI specifications",
5
+ "title": "OpEx Dashboard Configuration",
6
+ "version": "0.0.0",
7
+ "type": "object",
8
+ "properties": {
9
+ "action_groups": {
10
+ "description": "Array of Azure Action Group resource IDs for alarm notifications",
11
+ "type": "array",
12
+ "items": {
13
+ "type": "string"
14
+ }
15
+ },
16
+ "availability_threshold": {
17
+ "description": "Default minimum availability percentage (0-1). Default: 0.99 (99%)",
18
+ "default": 0.99,
19
+ "type": "number"
20
+ },
21
+ "data_source": {
22
+ "description": "Azure resource ID for metrics data source (Application Gateway or API Management)",
23
+ "type": "string"
24
+ },
25
+ "evaluation_frequency": {
26
+ "description": "Default frequency in minutes to evaluate alarms. Default: 10",
27
+ "default": 10,
28
+ "type": "number"
29
+ },
30
+ "evaluation_time_window": {
31
+ "description": "Default time window in minutes for alarm evaluation. Default: 20",
32
+ "default": 20,
33
+ "type": "number"
34
+ },
35
+ "event_occurrences": {
36
+ "description": "Default number of event occurrences to trigger an alarm. Default: 1",
37
+ "default": 1,
38
+ "type": "number"
39
+ },
40
+ "location": {
41
+ "description": "Azure region/location for the dashboard (e.g., West Europe)",
42
+ "type": "string"
43
+ },
44
+ "name": {
45
+ "description": "Name of the dashboard",
46
+ "type": "string"
47
+ },
48
+ "oa3_spec": {
49
+ "description": "Path or HTTP URL to OpenAPI 3.x specification file (supports OA2 and OA3)",
50
+ "type": "string"
51
+ },
52
+ "overrides": {
53
+ "description": "Optional overrides for hosts, per-endpoint alarm thresholds, and query configurations",
54
+ "type": "object",
55
+ "properties": {
56
+ "endpoints": {
57
+ "description": "Override alarm thresholds and settings for specific endpoints (key: endpoint path)",
58
+ "type": "object",
59
+ "propertyNames": {
60
+ "type": "string"
61
+ },
62
+ "additionalProperties": {
63
+ "type": "object",
64
+ "properties": {
65
+ "availability_evaluation_frequency": {
66
+ "description": "Frequency in minutes to evaluate availability alarm. Default: 10",
67
+ "type": "number"
68
+ },
69
+ "availability_evaluation_time_window": {
70
+ "description": "Time window in minutes for availability alarm evaluation. Default: 20",
71
+ "type": "number"
72
+ },
73
+ "availability_event_occurrences": {
74
+ "description": "Number of event occurrences to trigger availability alarm. Default: 1",
75
+ "type": "number"
76
+ },
77
+ "availability_threshold": {
78
+ "description": "Minimum availability percentage (0-1). Default: 0.99 (99%)",
79
+ "type": "number"
80
+ },
81
+ "response_time_evaluation_frequency": {
82
+ "description": "Frequency in minutes to evaluate response time alarm. Default: 10",
83
+ "type": "number"
84
+ },
85
+ "response_time_evaluation_time_window": {
86
+ "description": "Time window in minutes for response time alarm evaluation. Default: 20",
87
+ "type": "number"
88
+ },
89
+ "response_time_event_occurrences": {
90
+ "description": "Number of event occurrences to trigger response time alarm. Default: 1",
91
+ "type": "number"
92
+ },
93
+ "response_time_threshold": {
94
+ "description": "Maximum response time in seconds. Default: 1",
95
+ "type": "number"
96
+ }
97
+ },
98
+ "additionalProperties": false
99
+ }
100
+ },
101
+ "hosts": {
102
+ "description": "Override host URLs from OpenAPI spec (e.g., https://example.com)",
103
+ "type": "array",
104
+ "items": {
105
+ "type": "string"
106
+ }
107
+ },
108
+ "queries": {
109
+ "description": "Optional query configuration overrides",
110
+ "type": "object",
111
+ "properties": {
112
+ "response_time_percentile": {
113
+ "description": "Percentile for response time queries. Default: 95",
114
+ "default": 95,
115
+ "type": "number"
116
+ },
117
+ "status_code_categories": {
118
+ "description": "HTTP status code categories for response codes queries",
119
+ "default": [
120
+ "1XX",
121
+ "2XX",
122
+ "3XX",
123
+ "4XX",
124
+ "5XX"
125
+ ],
126
+ "type": "array",
127
+ "items": {
128
+ "type": "string"
129
+ }
130
+ }
131
+ },
132
+ "required": [
133
+ "response_time_percentile",
134
+ "status_code_categories"
135
+ ],
136
+ "additionalProperties": false
137
+ }
138
+ },
139
+ "additionalProperties": false
140
+ },
141
+ "queries": {
142
+ "description": "Optional global query configuration overrides",
143
+ "type": "object",
144
+ "properties": {
145
+ "response_time_percentile": {
146
+ "description": "Percentile for response time queries. Default: 95",
147
+ "default": 95,
148
+ "type": "number"
149
+ },
150
+ "status_code_categories": {
151
+ "description": "HTTP status code categories for response codes queries",
152
+ "default": [
153
+ "1XX",
154
+ "2XX",
155
+ "3XX",
156
+ "4XX",
157
+ "5XX"
158
+ ],
159
+ "type": "array",
160
+ "items": {
161
+ "type": "string"
162
+ }
163
+ }
164
+ },
165
+ "required": [
166
+ "response_time_percentile",
167
+ "status_code_categories"
168
+ ],
169
+ "additionalProperties": false
170
+ },
171
+ "resource_type": {
172
+ "description": "Type of Azure resource to monitor: app-gateway (Application Gateway) or api-management (API Management). Default: app-gateway",
173
+ "default": "app-gateway",
174
+ "type": "string",
175
+ "enum": [
176
+ "app-gateway",
177
+ "api-management"
178
+ ]
179
+ },
180
+ "response_time_threshold": {
181
+ "description": "Default maximum response time in seconds. Default: 1.0",
182
+ "default": 1,
183
+ "type": "number"
184
+ },
185
+ "terraform": {
186
+ "description": "Optional Terraform and environment-specific configuration",
187
+ "type": "object",
188
+ "properties": {
189
+ "environments": {
190
+ "description": "Environment-specific configurations for dev/uat/prod",
191
+ "type": "object",
192
+ "properties": {
193
+ "dev": {
194
+ "type": "object",
195
+ "properties": {
196
+ "backend": {
197
+ "description": "Azure backend configuration for Terraform state",
198
+ "type": "object",
199
+ "properties": {
200
+ "container_name": {
201
+ "description": "Blob container name for Terraform state",
202
+ "type": "string"
203
+ },
204
+ "key": {
205
+ "description": "State file key/path",
206
+ "type": "string"
207
+ },
208
+ "resource_group_name": {
209
+ "description": "Azure resource group for backend state",
210
+ "type": "string"
211
+ },
212
+ "storage_account_name": {
213
+ "description": "Storage account for Terraform state",
214
+ "type": "string"
215
+ }
216
+ },
217
+ "required": [
218
+ "container_name",
219
+ "key",
220
+ "resource_group_name",
221
+ "storage_account_name"
222
+ ],
223
+ "additionalProperties": false
224
+ },
225
+ "env_short": {
226
+ "description": "Environment short name (1 char: 'd'=dev, 'u'=uat, 'p'=prod)",
227
+ "type": "string",
228
+ "maxLength": 1
229
+ },
230
+ "prefix": {
231
+ "description": "Project prefix (max 6 chars, e.g., 'io', 'pagopa')",
232
+ "type": "string",
233
+ "maxLength": 6
234
+ }
235
+ },
236
+ "required": [
237
+ "env_short",
238
+ "prefix"
239
+ ],
240
+ "additionalProperties": false
241
+ },
242
+ "prod": {
243
+ "type": "object",
244
+ "properties": {
245
+ "backend": {
246
+ "description": "Azure backend configuration for Terraform state",
247
+ "type": "object",
248
+ "properties": {
249
+ "container_name": {
250
+ "description": "Blob container name for Terraform state",
251
+ "type": "string"
252
+ },
253
+ "key": {
254
+ "description": "State file key/path",
255
+ "type": "string"
256
+ },
257
+ "resource_group_name": {
258
+ "description": "Azure resource group for backend state",
259
+ "type": "string"
260
+ },
261
+ "storage_account_name": {
262
+ "description": "Storage account for Terraform state",
263
+ "type": "string"
264
+ }
265
+ },
266
+ "required": [
267
+ "container_name",
268
+ "key",
269
+ "resource_group_name",
270
+ "storage_account_name"
271
+ ],
272
+ "additionalProperties": false
273
+ },
274
+ "env_short": {
275
+ "description": "Environment short name (1 char: 'd'=dev, 'u'=uat, 'p'=prod)",
276
+ "type": "string",
277
+ "maxLength": 1
278
+ },
279
+ "prefix": {
280
+ "description": "Project prefix (max 6 chars, e.g., 'io', 'pagopa')",
281
+ "type": "string",
282
+ "maxLength": 6
283
+ }
284
+ },
285
+ "required": [
286
+ "env_short",
287
+ "prefix"
288
+ ],
289
+ "additionalProperties": false
290
+ },
291
+ "uat": {
292
+ "type": "object",
293
+ "properties": {
294
+ "backend": {
295
+ "description": "Azure backend configuration for Terraform state",
296
+ "type": "object",
297
+ "properties": {
298
+ "container_name": {
299
+ "description": "Blob container name for Terraform state",
300
+ "type": "string"
301
+ },
302
+ "key": {
303
+ "description": "State file key/path",
304
+ "type": "string"
305
+ },
306
+ "resource_group_name": {
307
+ "description": "Azure resource group for backend state",
308
+ "type": "string"
309
+ },
310
+ "storage_account_name": {
311
+ "description": "Storage account for Terraform state",
312
+ "type": "string"
313
+ }
314
+ },
315
+ "required": [
316
+ "container_name",
317
+ "key",
318
+ "resource_group_name",
319
+ "storage_account_name"
320
+ ],
321
+ "additionalProperties": false
322
+ },
323
+ "env_short": {
324
+ "description": "Environment short name (1 char: 'd'=dev, 'u'=uat, 'p'=prod)",
325
+ "type": "string",
326
+ "maxLength": 1
327
+ },
328
+ "prefix": {
329
+ "description": "Project prefix (max 6 chars, e.g., 'io', 'pagopa')",
330
+ "type": "string",
331
+ "maxLength": 6
332
+ }
333
+ },
334
+ "required": [
335
+ "env_short",
336
+ "prefix"
337
+ ],
338
+ "additionalProperties": false
339
+ }
340
+ },
341
+ "additionalProperties": false
342
+ }
343
+ },
344
+ "additionalProperties": false
345
+ },
346
+ "timespan": {
347
+ "description": "Time range for dashboard queries (e.g., 5m, 1h, 24h). Default: 5m",
348
+ "default": "5m",
349
+ "type": "string"
350
+ }
351
+ },
352
+ "required": [
353
+ "action_groups",
354
+ "data_source",
355
+ "location",
356
+ "name",
357
+ "oa3_spec"
358
+ ],
359
+ "additionalProperties": false
360
+ }
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@pagopa/opex-dashboard",
3
+ "repository": {
4
+ "type": "git",
5
+ "url": "git+https://github.com/pagopa/dx.git",
6
+ "directory": "apps/opex-dashboard"
7
+ },
8
+ "version": "0.0.1",
9
+ "description": "Generate operational dashboards from OpenAPI specifications",
10
+ "main": "dist/index.js",
11
+ "bin": {
12
+ "opex-dashboard": "./bin/index.js"
13
+ },
14
+ "type": "module",
15
+ "files": [
16
+ "bin",
17
+ "dist",
18
+ "config.schema.json"
19
+ ],
20
+ "publishConfig": {
21
+ "registry": "https://registry.npmjs.org/",
22
+ "access": "public"
23
+ },
24
+ "scripts": {
25
+ "format": "prettier --write .",
26
+ "format:check": "prettier --check .",
27
+ "build": "tsup && tsx scripts/generate-json-schema.ts",
28
+ "dev": "tsup --watch",
29
+ "typecheck": "tsc --noEmit"
30
+ },
31
+ "keywords": [
32
+ "dashboard",
33
+ "openapi",
34
+ "azure",
35
+ "terraform",
36
+ "monitoring",
37
+ "observability"
38
+ ],
39
+ "dependencies": {
40
+ "@apidevtools/swagger-parser": "^12.1.0",
41
+ "commander": "^14.0.2",
42
+ "js-yaml": "^4.1.1",
43
+ "tmp": "^0.2.5",
44
+ "zod": "^4.1.13"
45
+ },
46
+ "devDependencies": {
47
+ "@pagopa/eslint-config": "workspace:^",
48
+ "@tsconfig/node22": "catalog:",
49
+ "@types/js-yaml": "^4.0.9",
50
+ "@types/node": "catalog:",
51
+ "@types/tmp": "^0.2.6",
52
+ "@vitest/coverage-v8": "catalog:",
53
+ "eslint": "catalog:",
54
+ "prettier": "catalog:",
55
+ "tsup": "catalog:",
56
+ "tsx": "^4.21.0",
57
+ "typescript": "catalog:",
58
+ "vitest": "catalog:"
59
+ },
60
+ "engines": {
61
+ "node": ">=22.0.0"
62
+ }
63
+ }