flexmetric 0.2.0__py3-none-any.whl → 0.3.1__py3-none-any.whl

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.
@@ -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 run_flask
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
- "--flask-host",
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
- "--flask-port",
87
- type=int,
88
- default=5000,
89
- help="The port number on which to run the Flask server (default: 5000)",
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
- print(f"Missing {', '.join(missing)} for '{mode_name}' mode. Skipping...")
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
- print("Validating configuration...")
228
+ logger.info("Validating configuration...")
215
229
  if not validate_all_modes(args):
216
- print("No valid modes with proper configuration found. Exiting.")
230
+ logger.error("No valid modes with proper configuration found. Exiting.")
217
231
  exit(1)
218
232
 
219
- print(f"Starting Prometheus metrics server on port {args.port}...")
220
- print("Starting server")
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
- run_flask(args.flask_host, args.flask_port)
242
+ add_update_metric_route()
243
+ if args.enable_https:
244
+ secure_flask_run(args)
228
245
  else:
229
- while True:
230
- time.sleep(2)
231
-
246
+ run_flask(args.host, args.port)
232
247
 
233
248
  main()
@@ -1,29 +1,38 @@
1
- from flask import Flask, request, jsonify
1
+ from flask import Flask, request, jsonify, Response
2
2
  from flexmetric.metric_process.expiring_queue import metric_queue
3
3
  import argparse
4
+ from prometheus_client import generate_latest, REGISTRY, CONTENT_TYPE_LATEST
4
5
 
5
6
  app = Flask(__name__)
6
7
 
7
8
 
8
- @app.route("/update_metric", methods=["POST"])
9
- def update_metric():
10
- try:
11
- data = request.get_json()
9
+ @app.route('/metrics')
10
+ def metrics():
11
+ return Response(generate_latest(REGISTRY), mimetype=CONTENT_TYPE_LATEST)
12
12
 
13
- if not data or "result" not in data or not isinstance(data["result"], list):
14
- return jsonify({"status": "no"}), 400
15
13
 
16
- for item in data["result"]:
17
- if "label" not in item or "value" not in item:
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):
18
21
  return jsonify({"status": "no"}), 400
19
22
 
20
- metric_queue.put(data)
21
- print(metric_queue)
22
- return jsonify({"status": "success"}), 200
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
23
30
 
24
- except Exception:
25
- return jsonify({"status": "no"}), 500
31
+ except Exception:
32
+ return jsonify({"status": "no"}), 500
26
33
 
27
34
 
28
35
  def run_flask(host, port):
29
- app.run(host=host, port=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,10 +1,13 @@
1
1
  Metadata-Version: 2.4
2
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
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 via an optional Flask API as Prometheus-compatible metricswith minimal setup and maximum customization.
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 metricsvia 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
- - Execute SQL queries (e.g., SQLite) and monitor database statistics.
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 --flask-port <port> --flask-host <host> --metrics-port <metrics-port>
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 --flask-port 5000 --flask-host 0.0.0.0 --port 8000
106
+ flexmetric --expose-api --port 5000 --host 0.0.0.0
98
107
  ```
99
108
 
100
109
  Prometheus metrics exposed at:
101
- http://localhost:8000/metrics
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
@@ -9,10 +9,10 @@ flexmetric/metric_process/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
9
9
  flexmetric/metric_process/database_processing.py,sha256=W06P7ybno_9gFtndUtEY6vI2gMQvtYn1Z14w8h4FYwU,2668
10
10
  flexmetric/metric_process/expiring_queue.py,sha256=1oC0MjloitPiRo7yDgVarz81ETEQavKI_W-GFUvp5_Y,1920
11
11
  flexmetric/metric_process/process_commands.py,sha256=QAsR5uXt6rku_lTrBCfslerpqW0hMLSffzUFmxPC-fw,3556
12
- flexmetric/metric_process/prometheus_agent.py,sha256=kUUrsUyW-G_be5ohDGH37Izr16bfHV2i1sZFDWzJGes,7027
13
- flexmetric/metric_process/views.py,sha256=qIQ7twEwpir3aMV4GEZhIj7YWKx5Wix2fGiEjtk6KOs,788
14
- flexmetric-0.2.0.dist-info/METADATA,sha256=DIZ7ZxmdN4BfP7qeNOmyxlewqgb_DzkHGsDUj9bNQbY,7480
15
- flexmetric-0.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
16
- flexmetric-0.2.0.dist-info/entry_points.txt,sha256=urVePn5EWr3JqNvkYP7OsB_h2_Bqvv-Wq1MJRBexm8A,79
17
- flexmetric-0.2.0.dist-info/top_level.txt,sha256=zBlrNwKhXUNhgu9RRZnXxYwYnmE-eocRe6wKSmQROA4,11
18
- flexmetric-0.2.0.dist-info/RECORD,,
12
+ flexmetric/metric_process/prometheus_agent.py,sha256=hjPmNhJiB-844CgIcaw5A-VLmJqyMwQ_j1e_GI-UPSo,7422
13
+ flexmetric/metric_process/views.py,sha256=05UbGBrAkEn_aJq7qBb_1yphCfnXiTqmXFLznMMpkN8,1194
14
+ flexmetric-0.3.1.dist-info/METADATA,sha256=EdYDXO-Vkojc0PZ2AKXabRmr2M5QLxgaDBoh-c3pWpA,8650
15
+ flexmetric-0.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
16
+ flexmetric-0.3.1.dist-info/entry_points.txt,sha256=urVePn5EWr3JqNvkYP7OsB_h2_Bqvv-Wq1MJRBexm8A,79
17
+ flexmetric-0.3.1.dist-info/top_level.txt,sha256=zBlrNwKhXUNhgu9RRZnXxYwYnmE-eocRe6wKSmQROA4,11
18
+ flexmetric-0.3.1.dist-info/RECORD,,