flexmetric 0.2.0__tar.gz → 0.3.1__tar.gz
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.
- {flexmetric-0.2.0/flexmetric.egg-info → flexmetric-0.3.1}/PKG-INFO +46 -11
- flexmetric-0.2.0/PKG-INFO → flexmetric-0.3.1/README.md +40 -38
- {flexmetric-0.2.0 → flexmetric-0.3.1}/flexmetric/metric_process/prometheus_agent.py +34 -19
- flexmetric-0.3.1/flexmetric/metric_process/views.py +38 -0
- flexmetric-0.2.0/README.md → flexmetric-0.3.1/flexmetric.egg-info/PKG-INFO +73 -9
- {flexmetric-0.2.0 → flexmetric-0.3.1}/setup.py +8 -3
- flexmetric-0.2.0/flexmetric/metric_process/views.py +0 -29
- {flexmetric-0.2.0 → flexmetric-0.3.1}/flexmetric/__init__.py +0 -0
- {flexmetric-0.2.0 → flexmetric-0.3.1}/flexmetric/config/__init__.py +0 -0
- {flexmetric-0.2.0 → flexmetric-0.3.1}/flexmetric/config/configuration.py +0 -0
- {flexmetric-0.2.0 → flexmetric-0.3.1}/flexmetric/file_recognition/__init__.py +0 -0
- {flexmetric-0.2.0 → flexmetric-0.3.1}/flexmetric/file_recognition/exec_file.py +0 -0
- {flexmetric-0.2.0 → flexmetric-0.3.1}/flexmetric/logging_module/__init__.py +0 -0
- {flexmetric-0.2.0 → flexmetric-0.3.1}/flexmetric/logging_module/logger.py +0 -0
- {flexmetric-0.2.0 → flexmetric-0.3.1}/flexmetric/metric_process/__init__.py +0 -0
- {flexmetric-0.2.0 → flexmetric-0.3.1}/flexmetric/metric_process/database_processing.py +0 -0
- {flexmetric-0.2.0 → flexmetric-0.3.1}/flexmetric/metric_process/expiring_queue.py +0 -0
- {flexmetric-0.2.0 → flexmetric-0.3.1}/flexmetric/metric_process/process_commands.py +0 -0
- {flexmetric-0.2.0 → flexmetric-0.3.1}/flexmetric.egg-info/SOURCES.txt +0 -0
- {flexmetric-0.2.0 → flexmetric-0.3.1}/flexmetric.egg-info/dependency_links.txt +0 -0
- {flexmetric-0.2.0 → flexmetric-0.3.1}/flexmetric.egg-info/entry_points.txt +0 -0
- {flexmetric-0.2.0 → flexmetric-0.3.1}/flexmetric.egg-info/requires.txt +0 -0
- {flexmetric-0.2.0 → flexmetric-0.3.1}/flexmetric.egg-info/top_level.txt +0 -0
- {flexmetric-0.2.0 → flexmetric-0.3.1}/setup.cfg +0 -0
@@ -1,10 +1,13 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: flexmetric
|
3
|
-
Version: 0.
|
4
|
-
Summary: A flexible Prometheus exporter for commands, databases, functions, and scripts.
|
5
|
-
Home-page: https://github.com/nikhillingadhal1999/
|
3
|
+
Version: 0.3.1
|
4
|
+
Summary: A secure flexible Prometheus exporter for commands, databases, functions, and scripts.
|
5
|
+
Home-page: https://github.com/nikhillingadhal1999/flexmetric
|
6
6
|
Author: Nikhil Lingadhal
|
7
7
|
License: MIT
|
8
|
+
Project-URL: Homepage, https://github.com/nikhillingadhal1999
|
9
|
+
Project-URL: Source, https://github.com/nikhillingadhal1999/flexmetric
|
10
|
+
Project-URL: Tracker, https://github.com/nikhillingadhal1999/flexmetric/issues
|
8
11
|
Classifier: Programming Language :: Python :: 3
|
9
12
|
Classifier: License :: OSI Approved :: MIT License
|
10
13
|
Classifier: Operating System :: OS Independent
|
@@ -23,24 +26,30 @@ Dynamic: description
|
|
23
26
|
Dynamic: description-content-type
|
24
27
|
Dynamic: home-page
|
25
28
|
Dynamic: license
|
29
|
+
Dynamic: project-url
|
26
30
|
Dynamic: requires-dist
|
27
31
|
Dynamic: requires-python
|
28
32
|
Dynamic: summary
|
29
33
|
|
30
34
|
# FlexMetric
|
31
35
|
|
32
|
-
FlexMetric is a lightweight, flexible, and extensible Prometheus exporter that allows you to expose system metrics, database query results, Python function outputs, and externally submitted metrics
|
36
|
+
FlexMetric is a lightweight, flexible, and extensible Prometheus exporter that allows you to securely expose system metrics, database query results, Python function outputs, and externally submitted metrics—via an optional Flask API with HTTPS support—as Prometheus-compatible metrics, all with minimal setup and maximum customization.
|
33
37
|
|
34
38
|
---
|
35
39
|
|
36
40
|
## Features
|
37
41
|
|
38
|
-
- Run shell commands and expose the results as Prometheus metrics.
|
39
|
-
|
42
|
+
- Run shell commands and expose the results as Prometheus metrics.
|
43
|
+
➔ **Harmful commands (e.g., file deletion, system shutdown) are blocked for safety.**
|
44
|
+
- Execute SQL queries (e.g., SQLite) and monitor database statistics.
|
45
|
+
➔ **Potentially dangerous queries (e.g., `DROP`, `DELETE`, `TRUNCATE`) are not allowed.**
|
40
46
|
- Automatically discover and expose Python function outputs as metrics.
|
41
47
|
- Expose an optional **Flask API** (`/update_metric`) to receive external metrics dynamically.
|
42
48
|
- Modular and easy to extend—add your own custom integrations.
|
43
49
|
- Built-in Prometheus HTTP server (`/metrics`) with configurable port.
|
50
|
+
- **Supports HTTPS** to securely expose both metrics and API endpoints.
|
51
|
+
- **Input sanitization** is performed to ensure only safe commands and queries are executed.
|
52
|
+
|
44
53
|
|
45
54
|
---
|
46
55
|
|
@@ -86,7 +95,7 @@ To use the Flask API for submitting external metrics, you need to start the agen
|
|
86
95
|
### Start FlexMetric with Flask API
|
87
96
|
|
88
97
|
```bash
|
89
|
-
flexmetric --expose-api --
|
98
|
+
flexmetric --expose-api --port <port> --host <host>
|
90
99
|
```
|
91
100
|
|
92
101
|
## Example: Running FlexMetric with Flask API
|
@@ -94,11 +103,11 @@ flexmetric --expose-api --flask-port <port> --flask-host <host> --metrics-port <
|
|
94
103
|
To run FlexMetric with both Prometheus metrics and the Flask API enabled:
|
95
104
|
|
96
105
|
```bash
|
97
|
-
flexmetric --expose-api --
|
106
|
+
flexmetric --expose-api --port 5000 --host 0.0.0.0
|
98
107
|
```
|
99
108
|
|
100
109
|
Prometheus metrics exposed at:
|
101
|
-
http://localhost:
|
110
|
+
http://localhost:5000/metrics
|
102
111
|
|
103
112
|
Flask API exposed at:
|
104
113
|
http://localhost:5000/update_metric
|
@@ -116,6 +125,30 @@ curl -X POST http://localhost:5000/update_metric \
|
|
116
125
|
|
117
126
|
```
|
118
127
|
|
128
|
+
### Using flex metrics in secure mode
|
129
|
+
|
130
|
+
```bash
|
131
|
+
flexmetric --port 5000 --host 0.0.0.0 --enable-https --ssl-cert=cert.pem --ssl-key=key.pem
|
132
|
+
```
|
133
|
+
Prometheus metrics exposed at:
|
134
|
+
https://localhost:5000/metrics
|
135
|
+
|
136
|
+
Flask API exposed at:
|
137
|
+
https://localhost:5000/update_metric
|
138
|
+
|
139
|
+
### Submitting a Metric to the Flask API
|
140
|
+
```bash
|
141
|
+
curl -k -X POST https://localhost:5000/update_metric \
|
142
|
+
-H "Content-Type: application/json" \
|
143
|
+
-d '{
|
144
|
+
"result": [
|
145
|
+
{ "label": "cpu_usage", "value": 42.5 }
|
146
|
+
],
|
147
|
+
"labels": ["cpu"]
|
148
|
+
}'
|
149
|
+
|
150
|
+
```
|
151
|
+
|
119
152
|
### commands.yaml
|
120
153
|
|
121
154
|
```yaml
|
@@ -181,11 +214,13 @@ The following command-line options are available when running FlexMetric:
|
|
181
214
|
| `--queries-config` | Path to queries YAML file | `queries.yaml` |
|
182
215
|
| `--functions` | Enable Python functions mode | |
|
183
216
|
| `--functions-file` | Path to functions file | `executable_functions.txt` |
|
184
|
-
| `--scripts` | Enable shell scripts mode | |
|
185
|
-
| `--scripts-config` | Path to scripts YAML file | `scripts.yaml` |
|
186
217
|
| `--expose-api` | Enable Flask API mode to receive external metrics | |
|
187
218
|
| `--flask-port` | Port for the Flask API (`/update_metric`) | `5000` |
|
188
219
|
| `--flask-host` | Hostname for the Flask API | `0.0.0.0` |
|
220
|
+
| `--enable-https` | Enable HTTPS for the Flask API | |
|
221
|
+
| `--ssl-cert` | Path to SSL certificate file (`cert.pem`) | |
|
222
|
+
| `--ssl-key` | Path to SSL private key file (`key.pem`) | |
|
223
|
+
|
189
224
|
### Example Command:
|
190
225
|
|
191
226
|
```bash
|
@@ -1,46 +1,22 @@
|
|
1
|
-
Metadata-Version: 2.4
|
2
|
-
Name: flexmetric
|
3
|
-
Version: 0.2.0
|
4
|
-
Summary: A flexible Prometheus exporter for commands, databases, functions, and scripts.
|
5
|
-
Home-page: https://github.com/nikhillingadhal1999/custom_prometheus_agent
|
6
|
-
Author: Nikhil Lingadhal
|
7
|
-
License: MIT
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
9
|
-
Classifier: License :: OSI Approved :: MIT License
|
10
|
-
Classifier: Operating System :: OS Independent
|
11
|
-
Requires-Python: >=3.7
|
12
|
-
Description-Content-Type: text/markdown
|
13
|
-
Requires-Dist: prometheus_client
|
14
|
-
Requires-Dist: PyYAML
|
15
|
-
Requires-Dist: psutil
|
16
|
-
Requires-Dist: setuptools
|
17
|
-
Requires-Dist: wheel
|
18
|
-
Requires-Dist: twine
|
19
|
-
Requires-Dist: flask
|
20
|
-
Dynamic: author
|
21
|
-
Dynamic: classifier
|
22
|
-
Dynamic: description
|
23
|
-
Dynamic: description-content-type
|
24
|
-
Dynamic: home-page
|
25
|
-
Dynamic: license
|
26
|
-
Dynamic: requires-dist
|
27
|
-
Dynamic: requires-python
|
28
|
-
Dynamic: summary
|
29
|
-
|
30
1
|
# FlexMetric
|
31
2
|
|
32
|
-
FlexMetric is a lightweight, flexible, and extensible Prometheus exporter that allows you to expose system metrics, database query results, Python function outputs, and externally submitted metrics
|
3
|
+
FlexMetric is a lightweight, flexible, and extensible Prometheus exporter that allows you to securely expose system metrics, database query results, Python function outputs, and externally submitted metrics—via an optional Flask API with HTTPS support—as Prometheus-compatible metrics, all with minimal setup and maximum customization.
|
33
4
|
|
34
5
|
---
|
35
6
|
|
36
7
|
## Features
|
37
8
|
|
38
|
-
- Run shell commands and expose the results as Prometheus metrics.
|
39
|
-
|
9
|
+
- Run shell commands and expose the results as Prometheus metrics.
|
10
|
+
➔ **Harmful commands (e.g., file deletion, system shutdown) are blocked for safety.**
|
11
|
+
- Execute SQL queries (e.g., SQLite) and monitor database statistics.
|
12
|
+
➔ **Potentially dangerous queries (e.g., `DROP`, `DELETE`, `TRUNCATE`) are not allowed.**
|
40
13
|
- Automatically discover and expose Python function outputs as metrics.
|
41
14
|
- Expose an optional **Flask API** (`/update_metric`) to receive external metrics dynamically.
|
42
15
|
- Modular and easy to extend—add your own custom integrations.
|
43
16
|
- Built-in Prometheus HTTP server (`/metrics`) with configurable port.
|
17
|
+
- **Supports HTTPS** to securely expose both metrics and API endpoints.
|
18
|
+
- **Input sanitization** is performed to ensure only safe commands and queries are executed.
|
19
|
+
|
44
20
|
|
45
21
|
---
|
46
22
|
|
@@ -86,7 +62,7 @@ To use the Flask API for submitting external metrics, you need to start the agen
|
|
86
62
|
### Start FlexMetric with Flask API
|
87
63
|
|
88
64
|
```bash
|
89
|
-
flexmetric --expose-api --
|
65
|
+
flexmetric --expose-api --port <port> --host <host>
|
90
66
|
```
|
91
67
|
|
92
68
|
## Example: Running FlexMetric with Flask API
|
@@ -94,11 +70,11 @@ flexmetric --expose-api --flask-port <port> --flask-host <host> --metrics-port <
|
|
94
70
|
To run FlexMetric with both Prometheus metrics and the Flask API enabled:
|
95
71
|
|
96
72
|
```bash
|
97
|
-
flexmetric --expose-api --
|
73
|
+
flexmetric --expose-api --port 5000 --host 0.0.0.0
|
98
74
|
```
|
99
75
|
|
100
76
|
Prometheus metrics exposed at:
|
101
|
-
http://localhost:
|
77
|
+
http://localhost:5000/metrics
|
102
78
|
|
103
79
|
Flask API exposed at:
|
104
80
|
http://localhost:5000/update_metric
|
@@ -116,6 +92,30 @@ curl -X POST http://localhost:5000/update_metric \
|
|
116
92
|
|
117
93
|
```
|
118
94
|
|
95
|
+
### Using flex metrics in secure mode
|
96
|
+
|
97
|
+
```bash
|
98
|
+
flexmetric --port 5000 --host 0.0.0.0 --enable-https --ssl-cert=cert.pem --ssl-key=key.pem
|
99
|
+
```
|
100
|
+
Prometheus metrics exposed at:
|
101
|
+
https://localhost:5000/metrics
|
102
|
+
|
103
|
+
Flask API exposed at:
|
104
|
+
https://localhost:5000/update_metric
|
105
|
+
|
106
|
+
### Submitting a Metric to the Flask API
|
107
|
+
```bash
|
108
|
+
curl -k -X POST https://localhost:5000/update_metric \
|
109
|
+
-H "Content-Type: application/json" \
|
110
|
+
-d '{
|
111
|
+
"result": [
|
112
|
+
{ "label": "cpu_usage", "value": 42.5 }
|
113
|
+
],
|
114
|
+
"labels": ["cpu"]
|
115
|
+
}'
|
116
|
+
|
117
|
+
```
|
118
|
+
|
119
119
|
### commands.yaml
|
120
120
|
|
121
121
|
```yaml
|
@@ -181,11 +181,13 @@ The following command-line options are available when running FlexMetric:
|
|
181
181
|
| `--queries-config` | Path to queries YAML file | `queries.yaml` |
|
182
182
|
| `--functions` | Enable Python functions mode | |
|
183
183
|
| `--functions-file` | Path to functions file | `executable_functions.txt` |
|
184
|
-
| `--scripts` | Enable shell scripts mode | |
|
185
|
-
| `--scripts-config` | Path to scripts YAML file | `scripts.yaml` |
|
186
184
|
| `--expose-api` | Enable Flask API mode to receive external metrics | |
|
187
185
|
| `--flask-port` | Port for the Flask API (`/update_metric`) | `5000` |
|
188
186
|
| `--flask-host` | Hostname for the Flask API | `0.0.0.0` |
|
187
|
+
| `--enable-https` | Enable HTTPS for the Flask API | |
|
188
|
+
| `--ssl-cert` | Path to SSL certificate file (`cert.pem`) | |
|
189
|
+
| `--ssl-key` | Path to SSL private key file (`key.pem`) | |
|
190
|
+
|
189
191
|
### Example Command:
|
190
192
|
|
191
193
|
```bash
|
@@ -209,4 +211,4 @@ Each metric includes labels and numeric values that Prometheus can scrape and vi
|
|
209
211
|
The following features are planned or under consideration to improve FlexMetric:
|
210
212
|
|
211
213
|
- Support for additional databases such as PostgreSQL and MySQL.
|
212
|
-
- Enhanced support for more complex scripts and richer label extraction.
|
214
|
+
- Enhanced support for more complex scripts and richer label extraction.
|
@@ -11,7 +11,11 @@ from flexmetric.metric_process.database_processing import process_database_queri
|
|
11
11
|
from flexmetric.metric_process.expiring_queue import metric_queue
|
12
12
|
import argparse
|
13
13
|
import os
|
14
|
-
from flexmetric.metric_process.views import
|
14
|
+
from flexmetric.metric_process.views import (
|
15
|
+
run_flask,
|
16
|
+
add_update_metric_route,
|
17
|
+
secure_flask_run,
|
18
|
+
)
|
15
19
|
import sched
|
16
20
|
import threading
|
17
21
|
|
@@ -77,16 +81,25 @@ def arguments():
|
|
77
81
|
"--port", type=int, default=8000, help="port on which exportor runs"
|
78
82
|
)
|
79
83
|
parser.add_argument(
|
80
|
-
"--
|
84
|
+
"--host",
|
81
85
|
type=str,
|
82
86
|
default="0.0.0.0",
|
83
87
|
help="The hostname or IP address on which to run the Flask server (default: 0.0.0.0)",
|
84
88
|
)
|
85
89
|
parser.add_argument(
|
86
|
-
"--
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
+
"--enable-https",
|
91
|
+
action="store_true",
|
92
|
+
help="Enable HTTPS for Flask API using SSL certificates.",
|
93
|
+
)
|
94
|
+
parser.add_argument(
|
95
|
+
"--ssl-cert",
|
96
|
+
type=str,
|
97
|
+
help="Path to the SSL certificate file (cert.pem) for HTTPS.",
|
98
|
+
)
|
99
|
+
parser.add_argument(
|
100
|
+
"--ssl-key",
|
101
|
+
type=str,
|
102
|
+
help="Path to the SSL private key file (key.pem) for HTTPS.",
|
90
103
|
)
|
91
104
|
|
92
105
|
return parser.parse_args()
|
@@ -111,7 +124,9 @@ gauges = {}
|
|
111
124
|
def validate_required_files(mode_name, required_files):
|
112
125
|
missing = [desc for desc, path in required_files.items() if path == None]
|
113
126
|
if missing:
|
114
|
-
|
127
|
+
logger.error(
|
128
|
+
f"Missing {', '.join(missing)} for '{mode_name}' mode. Skipping..."
|
129
|
+
)
|
115
130
|
return False
|
116
131
|
|
117
132
|
return True
|
@@ -147,7 +162,8 @@ def validate_all_modes(args):
|
|
147
162
|
"functions-file": args.functions_file,
|
148
163
|
},
|
149
164
|
),
|
150
|
-
(args.expose_api, "expose-api", {})
|
165
|
+
(args.expose_api, "expose-api", {}),
|
166
|
+
(args.enable_https,"enable-https",{"ssl-cert":args.ssl_cert,"ssl-key" :args.ssl_key})
|
151
167
|
]
|
152
168
|
|
153
169
|
for is_enabled, mode_name, files in mode_validations:
|
@@ -161,7 +177,6 @@ def validate_all_modes(args):
|
|
161
177
|
def measure(args):
|
162
178
|
exec_result = []
|
163
179
|
queue_items = metric_queue.pop_all()
|
164
|
-
print("QUEUE_ITEMS : ", queue_items)
|
165
180
|
if len(queue_items) != 0:
|
166
181
|
exec_result.extend(queue_items)
|
167
182
|
if args.database:
|
@@ -186,7 +201,6 @@ def measure(args):
|
|
186
201
|
else:
|
187
202
|
gauge = gauges[gauge_name]
|
188
203
|
for result in results:
|
189
|
-
print(result, isinstance(result["label"], list))
|
190
204
|
if isinstance(result["label"], str):
|
191
205
|
try:
|
192
206
|
gauge.labels(result["label"]).set(
|
@@ -211,23 +225,24 @@ def start_scheduler(args):
|
|
211
225
|
|
212
226
|
def main():
|
213
227
|
args = arguments()
|
214
|
-
|
228
|
+
logger.info("Validating configuration...")
|
215
229
|
if not validate_all_modes(args):
|
216
|
-
|
230
|
+
logger.error("No valid modes with proper configuration found. Exiting.")
|
217
231
|
exit(1)
|
218
232
|
|
219
|
-
|
220
|
-
|
221
|
-
start_http_server(args.port)
|
233
|
+
logger.info(f"Starting Prometheus metrics server on port {args.port}...")
|
234
|
+
logger.info("Starting server")
|
235
|
+
# start_http_server(args.port)
|
236
|
+
|
222
237
|
scheduler_thread = threading.Thread(
|
223
238
|
target=start_scheduler, args=(args,), daemon=True
|
224
239
|
)
|
225
240
|
scheduler_thread.start()
|
226
241
|
if args.expose_api:
|
227
|
-
|
242
|
+
add_update_metric_route()
|
243
|
+
if args.enable_https:
|
244
|
+
secure_flask_run(args)
|
228
245
|
else:
|
229
|
-
|
230
|
-
time.sleep(2)
|
231
|
-
|
246
|
+
run_flask(args.host, args.port)
|
232
247
|
|
233
248
|
main()
|
@@ -0,0 +1,38 @@
|
|
1
|
+
from flask import Flask, request, jsonify, Response
|
2
|
+
from flexmetric.metric_process.expiring_queue import metric_queue
|
3
|
+
import argparse
|
4
|
+
from prometheus_client import generate_latest, REGISTRY, CONTENT_TYPE_LATEST
|
5
|
+
|
6
|
+
app = Flask(__name__)
|
7
|
+
|
8
|
+
|
9
|
+
@app.route('/metrics')
|
10
|
+
def metrics():
|
11
|
+
return Response(generate_latest(REGISTRY), mimetype=CONTENT_TYPE_LATEST)
|
12
|
+
|
13
|
+
|
14
|
+
def add_update_metric_route():
|
15
|
+
@app.route("/update_metric", methods=["POST"])
|
16
|
+
def update_metric():
|
17
|
+
try:
|
18
|
+
data = request.get_json()
|
19
|
+
|
20
|
+
if not data or "result" not in data or not isinstance(data["result"], list):
|
21
|
+
return jsonify({"status": "no"}), 400
|
22
|
+
|
23
|
+
for item in data["result"]:
|
24
|
+
if "label" not in item or "value" not in item:
|
25
|
+
return jsonify({"status": "no"}), 400
|
26
|
+
|
27
|
+
metric_queue.put(data)
|
28
|
+
print(metric_queue)
|
29
|
+
return jsonify({"status": "success"}), 200
|
30
|
+
|
31
|
+
except Exception:
|
32
|
+
return jsonify({"status": "no"}), 500
|
33
|
+
|
34
|
+
|
35
|
+
def run_flask(host, port):
|
36
|
+
app.run(host=host, port=port)
|
37
|
+
def secure_flask_run(args):
|
38
|
+
app.run(host=args.host, port=args.port, ssl_context=(args.ssl_cert, args.ssl_key))
|
@@ -1,17 +1,55 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: flexmetric
|
3
|
+
Version: 0.3.1
|
4
|
+
Summary: A secure flexible Prometheus exporter for commands, databases, functions, and scripts.
|
5
|
+
Home-page: https://github.com/nikhillingadhal1999/flexmetric
|
6
|
+
Author: Nikhil Lingadhal
|
7
|
+
License: MIT
|
8
|
+
Project-URL: Homepage, https://github.com/nikhillingadhal1999
|
9
|
+
Project-URL: Source, https://github.com/nikhillingadhal1999/flexmetric
|
10
|
+
Project-URL: Tracker, https://github.com/nikhillingadhal1999/flexmetric/issues
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
13
|
+
Classifier: Operating System :: OS Independent
|
14
|
+
Requires-Python: >=3.7
|
15
|
+
Description-Content-Type: text/markdown
|
16
|
+
Requires-Dist: prometheus_client
|
17
|
+
Requires-Dist: PyYAML
|
18
|
+
Requires-Dist: psutil
|
19
|
+
Requires-Dist: setuptools
|
20
|
+
Requires-Dist: wheel
|
21
|
+
Requires-Dist: twine
|
22
|
+
Requires-Dist: flask
|
23
|
+
Dynamic: author
|
24
|
+
Dynamic: classifier
|
25
|
+
Dynamic: description
|
26
|
+
Dynamic: description-content-type
|
27
|
+
Dynamic: home-page
|
28
|
+
Dynamic: license
|
29
|
+
Dynamic: project-url
|
30
|
+
Dynamic: requires-dist
|
31
|
+
Dynamic: requires-python
|
32
|
+
Dynamic: summary
|
33
|
+
|
1
34
|
# FlexMetric
|
2
35
|
|
3
|
-
FlexMetric is a lightweight, flexible, and extensible Prometheus exporter that allows you to expose system metrics, database query results, Python function outputs, and externally submitted metrics
|
36
|
+
FlexMetric is a lightweight, flexible, and extensible Prometheus exporter that allows you to securely expose system metrics, database query results, Python function outputs, and externally submitted metrics—via an optional Flask API with HTTPS support—as Prometheus-compatible metrics, all with minimal setup and maximum customization.
|
4
37
|
|
5
38
|
---
|
6
39
|
|
7
40
|
## Features
|
8
41
|
|
9
|
-
- Run shell commands and expose the results as Prometheus metrics.
|
10
|
-
|
42
|
+
- Run shell commands and expose the results as Prometheus metrics.
|
43
|
+
➔ **Harmful commands (e.g., file deletion, system shutdown) are blocked for safety.**
|
44
|
+
- Execute SQL queries (e.g., SQLite) and monitor database statistics.
|
45
|
+
➔ **Potentially dangerous queries (e.g., `DROP`, `DELETE`, `TRUNCATE`) are not allowed.**
|
11
46
|
- Automatically discover and expose Python function outputs as metrics.
|
12
47
|
- Expose an optional **Flask API** (`/update_metric`) to receive external metrics dynamically.
|
13
48
|
- Modular and easy to extend—add your own custom integrations.
|
14
49
|
- Built-in Prometheus HTTP server (`/metrics`) with configurable port.
|
50
|
+
- **Supports HTTPS** to securely expose both metrics and API endpoints.
|
51
|
+
- **Input sanitization** is performed to ensure only safe commands and queries are executed.
|
52
|
+
|
15
53
|
|
16
54
|
---
|
17
55
|
|
@@ -57,7 +95,7 @@ To use the Flask API for submitting external metrics, you need to start the agen
|
|
57
95
|
### Start FlexMetric with Flask API
|
58
96
|
|
59
97
|
```bash
|
60
|
-
flexmetric --expose-api --
|
98
|
+
flexmetric --expose-api --port <port> --host <host>
|
61
99
|
```
|
62
100
|
|
63
101
|
## Example: Running FlexMetric with Flask API
|
@@ -65,11 +103,11 @@ flexmetric --expose-api --flask-port <port> --flask-host <host> --metrics-port <
|
|
65
103
|
To run FlexMetric with both Prometheus metrics and the Flask API enabled:
|
66
104
|
|
67
105
|
```bash
|
68
|
-
flexmetric --expose-api --
|
106
|
+
flexmetric --expose-api --port 5000 --host 0.0.0.0
|
69
107
|
```
|
70
108
|
|
71
109
|
Prometheus metrics exposed at:
|
72
|
-
http://localhost:
|
110
|
+
http://localhost:5000/metrics
|
73
111
|
|
74
112
|
Flask API exposed at:
|
75
113
|
http://localhost:5000/update_metric
|
@@ -87,6 +125,30 @@ curl -X POST http://localhost:5000/update_metric \
|
|
87
125
|
|
88
126
|
```
|
89
127
|
|
128
|
+
### Using flex metrics in secure mode
|
129
|
+
|
130
|
+
```bash
|
131
|
+
flexmetric --port 5000 --host 0.0.0.0 --enable-https --ssl-cert=cert.pem --ssl-key=key.pem
|
132
|
+
```
|
133
|
+
Prometheus metrics exposed at:
|
134
|
+
https://localhost:5000/metrics
|
135
|
+
|
136
|
+
Flask API exposed at:
|
137
|
+
https://localhost:5000/update_metric
|
138
|
+
|
139
|
+
### Submitting a Metric to the Flask API
|
140
|
+
```bash
|
141
|
+
curl -k -X POST https://localhost:5000/update_metric \
|
142
|
+
-H "Content-Type: application/json" \
|
143
|
+
-d '{
|
144
|
+
"result": [
|
145
|
+
{ "label": "cpu_usage", "value": 42.5 }
|
146
|
+
],
|
147
|
+
"labels": ["cpu"]
|
148
|
+
}'
|
149
|
+
|
150
|
+
```
|
151
|
+
|
90
152
|
### commands.yaml
|
91
153
|
|
92
154
|
```yaml
|
@@ -152,11 +214,13 @@ The following command-line options are available when running FlexMetric:
|
|
152
214
|
| `--queries-config` | Path to queries YAML file | `queries.yaml` |
|
153
215
|
| `--functions` | Enable Python functions mode | |
|
154
216
|
| `--functions-file` | Path to functions file | `executable_functions.txt` |
|
155
|
-
| `--scripts` | Enable shell scripts mode | |
|
156
|
-
| `--scripts-config` | Path to scripts YAML file | `scripts.yaml` |
|
157
217
|
| `--expose-api` | Enable Flask API mode to receive external metrics | |
|
158
218
|
| `--flask-port` | Port for the Flask API (`/update_metric`) | `5000` |
|
159
219
|
| `--flask-host` | Hostname for the Flask API | `0.0.0.0` |
|
220
|
+
| `--enable-https` | Enable HTTPS for the Flask API | |
|
221
|
+
| `--ssl-cert` | Path to SSL certificate file (`cert.pem`) | |
|
222
|
+
| `--ssl-key` | Path to SSL private key file (`key.pem`) | |
|
223
|
+
|
160
224
|
### Example Command:
|
161
225
|
|
162
226
|
```bash
|
@@ -180,4 +244,4 @@ Each metric includes labels and numeric values that Prometheus can scrape and vi
|
|
180
244
|
The following features are planned or under consideration to improve FlexMetric:
|
181
245
|
|
182
246
|
- Support for additional databases such as PostgreSQL and MySQL.
|
183
|
-
- Enhanced support for more complex scripts and richer label extraction.
|
247
|
+
- Enhanced support for more complex scripts and richer label extraction.
|
@@ -2,12 +2,17 @@ from setuptools import setup, find_packages
|
|
2
2
|
|
3
3
|
setup(
|
4
4
|
name="flexmetric",
|
5
|
-
version="0.
|
5
|
+
version="0.3.1",
|
6
6
|
author="Nikhil Lingadhal",
|
7
|
-
description="A flexible Prometheus exporter for commands, databases, functions, and scripts.",
|
7
|
+
description="A secure flexible Prometheus exporter for commands, databases, functions, and scripts.",
|
8
8
|
long_description=open("README.md").read(),
|
9
9
|
long_description_content_type="text/markdown",
|
10
|
-
url="https://github.com/nikhillingadhal1999/
|
10
|
+
url="https://github.com/nikhillingadhal1999/flexmetric",
|
11
|
+
project_urls={
|
12
|
+
"Homepage": "https://github.com/nikhillingadhal1999",
|
13
|
+
"Source": "https://github.com/nikhillingadhal1999/flexmetric",
|
14
|
+
"Tracker": "https://github.com/nikhillingadhal1999/flexmetric/issues",
|
15
|
+
},
|
11
16
|
license="MIT",
|
12
17
|
packages=find_packages(),
|
13
18
|
install_requires=[
|
@@ -1,29 +0,0 @@
|
|
1
|
-
from flask import Flask, request, jsonify
|
2
|
-
from flexmetric.metric_process.expiring_queue import metric_queue
|
3
|
-
import argparse
|
4
|
-
|
5
|
-
app = Flask(__name__)
|
6
|
-
|
7
|
-
|
8
|
-
@app.route("/update_metric", methods=["POST"])
|
9
|
-
def update_metric():
|
10
|
-
try:
|
11
|
-
data = request.get_json()
|
12
|
-
|
13
|
-
if not data or "result" not in data or not isinstance(data["result"], list):
|
14
|
-
return jsonify({"status": "no"}), 400
|
15
|
-
|
16
|
-
for item in data["result"]:
|
17
|
-
if "label" not in item or "value" not in item:
|
18
|
-
return jsonify({"status": "no"}), 400
|
19
|
-
|
20
|
-
metric_queue.put(data)
|
21
|
-
print(metric_queue)
|
22
|
-
return jsonify({"status": "success"}), 200
|
23
|
-
|
24
|
-
except Exception:
|
25
|
-
return jsonify({"status": "no"}), 500
|
26
|
-
|
27
|
-
|
28
|
-
def run_flask(host, port):
|
29
|
-
app.run(host=host, port=port)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|