|
| 1 | +--- |
| 2 | +description: |
| 3 | +globs: *.tsx,*.test.tsx,*.ts,*.test.ts |
| 4 | +alwaysApply: false |
| 5 | +--- |
| 6 | +# Prefer using `tsqtsq` to craft PromQL expressions |
| 7 | + |
| 8 | +When building PromQL expressions, we should use `tsqtsq` instead of building expressions via string interpolation. |
| 9 | + |
| 10 | +## `tsqtsq` Overview |
| 11 | + |
| 12 | +`tsqtsq` is a TypeScript library designed to make working with PromQL (Prometheus Query Language) more maintainable and type-safe. It provides a structured way to build PromQL queries programmatically, avoiding string interpolation and making queries more readable and maintainable. |
| 13 | + |
| 14 | +## Core Concepts |
| 15 | + |
| 16 | +### 1. Expression Class |
| 17 | + |
| 18 | +The `Expression` class is the foundation for building metric queries. It allows you to: |
| 19 | + |
| 20 | +- Define metric names |
| 21 | +- Add label selectors with specific operators |
| 22 | +- Set default operators and selectors |
| 23 | +- Compose complex metric expressions |
| 24 | + |
| 25 | +```typescript |
| 26 | +new Expression({ |
| 27 | + metric: 'test_metric', |
| 28 | + values: { |
| 29 | + arg1: 'foo', |
| 30 | + arg2: 'bar', |
| 31 | + }, |
| 32 | + defaultOperator: MatchingOperator.regexMatch, |
| 33 | + defaultSelectors: [{ label: 'baz', operator: MatchingOperator.notEqual, value: '' }], |
| 34 | +}); |
| 35 | +``` |
| 36 | + |
| 37 | +### 2. Label Selectors |
| 38 | + |
| 39 | +The library supports four types of label matching operators: |
| 40 | + |
| 41 | +- `=` (equal) |
| 42 | +- `!=` (not equal) |
| 43 | +- `=~` (regex match) |
| 44 | +- `!~` (not regex match) |
| 45 | + |
| 46 | +### 3. PromQL Functions |
| 47 | + |
| 48 | +The library provides a comprehensive set of PromQL functions through the `promql` object: |
| 49 | + |
| 50 | +#### Aggregation Functions |
| 51 | + |
| 52 | +- `sum`, `min`, `max`, `avg`, `group`, `count`, `stddev`, `stdvar` |
| 53 | +- `count_values`, `bottomk`, `topk`, `quantile` |
| 54 | + |
| 55 | +#### Time-based Functions |
| 56 | + |
| 57 | +- `rate`, `increase` |
| 58 | +- `*_over_time` functions (avg, count, last, max, min, present, stddev, stdvar, sum) |
| 59 | + |
| 60 | +#### Label Manipulation |
| 61 | + |
| 62 | +- `label_replace` |
| 63 | +- `label_join` |
| 64 | + |
| 65 | +#### Logical Operations |
| 66 | + |
| 67 | +- `and`, `or`, `unless` |
| 68 | + |
| 69 | +#### Time Offsets |
| 70 | + |
| 71 | +- Complex time offset support with units (years, weeks, days, hours, minutes, seconds, milliseconds) |
| 72 | + |
| 73 | +## Usage Examples |
| 74 | + |
| 75 | +### Basic Metric Query |
| 76 | + |
| 77 | +```typescript |
| 78 | +import { promql, Expression, MatchingOperator } from 'tsqtsq'; |
| 79 | + |
| 80 | +// Create a metric expression |
| 81 | +const expr = new Expression({ |
| 82 | + metric: 'http_requests_total', |
| 83 | + values: { |
| 84 | + status: '200', |
| 85 | + method: 'GET', |
| 86 | + }, |
| 87 | + defaultOperator: MatchingOperator.equal, |
| 88 | +}).toString(); |
| 89 | + |
| 90 | +// Use with aggregation |
| 91 | +const query = promql.sum({ |
| 92 | + expr, |
| 93 | + by: ['method', 'status'], |
| 94 | +}); |
| 95 | +``` |
| 96 | + |
| 97 | +### Time-based Queries |
| 98 | + |
| 99 | +```typescript |
| 100 | +// Rate calculation |
| 101 | +const rateQuery = promql.rate({ |
| 102 | + expr: 'http_requests_total{status="200"}', |
| 103 | + interval: '5m', |
| 104 | +}); |
| 105 | + |
| 106 | +// Aggregation over time |
| 107 | +const sumOverTime = promql.sum_over_time({ |
| 108 | + expr: 'http_requests_total', |
| 109 | + range: '1h', |
| 110 | +}); |
| 111 | +``` |
| 112 | + |
| 113 | +### Label Manipulation |
| 114 | + |
| 115 | +```typescript |
| 116 | +// Label replacement |
| 117 | +const replaced = promql.label_replace({ |
| 118 | + expr: 'http_requests_total', |
| 119 | + newLabel: 'service', |
| 120 | + existingLabel: 'instance', |
| 121 | + replacement: '$1', |
| 122 | + regex: '(.*)', |
| 123 | +}); |
| 124 | + |
| 125 | +// Label joining |
| 126 | +const joined = promql.label_join({ |
| 127 | + expr: 'http_requests_total', |
| 128 | + newLabel: 'full_path', |
| 129 | + labels: ['path', 'method'], |
| 130 | + separator: '_', |
| 131 | +}); |
| 132 | +``` |
| 133 | + |
| 134 | +## Best Practices |
| 135 | + |
| 136 | +1. **Use Expression Class for Metric Selection** |
| 137 | + |
| 138 | + - Prefer using the `Expression` class over string literals for metric selection |
| 139 | + - This provides type safety and better IDE support |
| 140 | + |
| 141 | +2. **Leverage Default Operators** |
| 142 | + |
| 143 | + - Set appropriate default operators for your use case |
| 144 | + - This reduces repetition and makes queries more consistent |
| 145 | + |
| 146 | +3. **Compose Queries** |
| 147 | + |
| 148 | + - Build complex queries by combining multiple `promql` functions |
| 149 | + - Use the result of one operation as input to another |
| 150 | + |
| 151 | +4. **Use Named Parameters** |
| 152 | + - Always use named parameters for clarity |
| 153 | + - This makes the code more maintainable and self-documenting |
| 154 | + |
| 155 | +## Type Safety |
| 156 | + |
| 157 | +The library provides strong TypeScript support with: |
| 158 | + |
| 159 | +- Enums for operators |
| 160 | +- Interfaces for all function parameters |
| 161 | +- Type checking for label selectors |
| 162 | +- Validation for time units |
| 163 | + |
| 164 | +## Common Use Cases |
| 165 | + |
| 166 | +1. **Building Dashboard Queries** |
| 167 | + |
| 168 | + - Compose complex queries for Grafana dashboards |
| 169 | + - Ensure consistency across multiple panels |
| 170 | + |
| 171 | +2. **Alert Rule Creation** |
| 172 | + |
| 173 | + - Build type-safe alert conditions |
| 174 | + - Maintain consistent query patterns |
| 175 | + |
| 176 | +3. **Query Refactoring** |
| 177 | + - Easily update query patterns across multiple places |
| 178 | + - Maintain consistency when changing metric names or labels |
| 179 | + |
| 180 | +## Limitations |
| 181 | + |
| 182 | +1. **Dynamic Query Building** |
| 183 | + |
| 184 | + - While the library supports complex queries, extremely dynamic queries might still require some string manipulation |
| 185 | + |
| 186 | +2. **PromQL Version Support** |
| 187 | + |
| 188 | + - The library supports standard PromQL features |
| 189 | + - Some newer or experimental PromQL features might not be directly supported |
| 190 | + |
| 191 | +3. **Performance** |
| 192 | + - The library adds a small overhead compared to direct string manipulation |
| 193 | + - This is generally negligible for most use cases |
| 194 | + |
| 195 | +## Integration Tips |
| 196 | + |
| 197 | +1. **With Grafana** |
| 198 | + |
| 199 | + - Use the library to generate queries for Grafana dashboards |
| 200 | + - Ensure consistent query patterns across panels |
| 201 | + |
| 202 | +2. **With Alerting Systems** |
| 203 | + |
| 204 | + - Generate alert conditions programmatically |
| 205 | + - Maintain type safety in alert definitions |
| 206 | + |
| 207 | +3. **With Custom Applications** |
| 208 | + - Use the library to build queries for custom monitoring applications |
| 209 | + - Ensure consistent query patterns across the application |
| 210 | + |
0 commit comments