flexmetric 0.4.2__tar.gz → 0.4.4__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.4.2 → flexmetric-0.4.4}/PKG-INFO +45 -13
- {flexmetric-0.4.2 → flexmetric-0.4.4}/README.md +42 -11
- flexmetric-0.4.4/flexmetric/metric_process/database_connections.py +55 -0
- flexmetric-0.4.4/flexmetric/metric_process/database_processing.py +140 -0
- {flexmetric-0.4.2 → flexmetric-0.4.4}/flexmetric/metric_process/prometheus_agent.py +1 -1
- flexmetric-0.4.4/flexmetric/metric_process/queries_execution.py +24 -0
- {flexmetric-0.4.2 → flexmetric-0.4.4}/flexmetric.egg-info/PKG-INFO +45 -13
- {flexmetric-0.4.2 → flexmetric-0.4.4}/flexmetric.egg-info/SOURCES.txt +2 -0
- {flexmetric-0.4.2 → flexmetric-0.4.4}/flexmetric.egg-info/requires.txt +1 -0
- {flexmetric-0.4.2 → flexmetric-0.4.4}/setup.py +4 -3
- flexmetric-0.4.2/flexmetric/metric_process/database_processing.py +0 -90
- {flexmetric-0.4.2 → flexmetric-0.4.4}/flexmetric/__init__.py +0 -0
- {flexmetric-0.4.2 → flexmetric-0.4.4}/flexmetric/config/__init__.py +0 -0
- {flexmetric-0.4.2 → flexmetric-0.4.4}/flexmetric/config/configuration.py +0 -0
- {flexmetric-0.4.2 → flexmetric-0.4.4}/flexmetric/file_recognition/__init__.py +0 -0
- {flexmetric-0.4.2 → flexmetric-0.4.4}/flexmetric/file_recognition/exec_file.py +0 -0
- {flexmetric-0.4.2 → flexmetric-0.4.4}/flexmetric/logging_module/__init__.py +0 -0
- {flexmetric-0.4.2 → flexmetric-0.4.4}/flexmetric/logging_module/logger.py +0 -0
- {flexmetric-0.4.2 → flexmetric-0.4.4}/flexmetric/metric_process/__init__.py +0 -0
- {flexmetric-0.4.2 → flexmetric-0.4.4}/flexmetric/metric_process/expiring_queue.py +0 -0
- {flexmetric-0.4.2 → flexmetric-0.4.4}/flexmetric/metric_process/process_commands.py +0 -0
- {flexmetric-0.4.2 → flexmetric-0.4.4}/flexmetric/metric_process/views.py +0 -0
- {flexmetric-0.4.2 → flexmetric-0.4.4}/flexmetric.egg-info/dependency_links.txt +0 -0
- {flexmetric-0.4.2 → flexmetric-0.4.4}/flexmetric.egg-info/entry_points.txt +0 -0
- {flexmetric-0.4.2 → flexmetric-0.4.4}/flexmetric.egg-info/top_level.txt +0 -0
- {flexmetric-0.4.2 → flexmetric-0.4.4}/setup.cfg +0 -0
@@ -1,7 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: flexmetric
|
3
|
-
Version: 0.4.
|
4
|
-
Summary: A secure flexible Prometheus exporter for commands, databases, functions
|
3
|
+
Version: 0.4.4
|
4
|
+
Summary: A secure flexible Prometheus exporter for commands, databases, functions.
|
5
5
|
Home-page: https://github.com/nikhillingadhal1999/flexmetric
|
6
6
|
Author: Nikhil Lingadhal
|
7
7
|
License: MIT
|
@@ -20,6 +20,7 @@ Requires-Dist: setuptools
|
|
20
20
|
Requires-Dist: wheel
|
21
21
|
Requires-Dist: twine
|
22
22
|
Requires-Dist: flask
|
23
|
+
Requires-Dist: clickhouse-connect
|
23
24
|
Dynamic: author
|
24
25
|
Dynamic: classifier
|
25
26
|
Dynamic: description
|
@@ -188,21 +189,52 @@ Filesystem Size Used Avail Use% Mounted on
|
|
188
189
|
| `timeout_seconds` | Maximum time (in seconds) to wait for the command to complete. If it exceeds this time, the command is aborted. |
|
189
190
|
|
190
191
|
## Database mode
|
191
|
-
|
192
|
+
file - database.yaml
|
192
193
|
```yaml
|
193
194
|
databases:
|
194
|
-
-
|
195
|
-
|
196
|
-
|
197
|
-
|
195
|
+
- id: "active_user_count"
|
196
|
+
type: "clickhouse"
|
197
|
+
host: "localhost"
|
198
|
+
port: 8123
|
199
|
+
username: "default"
|
200
|
+
password: ""
|
201
|
+
client_cert: ""
|
202
|
+
client_key: ""
|
203
|
+
ca_cert: ""
|
204
|
+
|
205
|
+
- id: "userdb"
|
206
|
+
type: "sqlite"
|
207
|
+
db_connection: "/path/to/my.db"
|
208
|
+
```
|
209
|
+
file - queries.yaml
|
198
210
|
```yaml
|
199
211
|
commands:
|
200
|
-
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
212
|
+
- id: "active_user_count"
|
213
|
+
type: "clickhouse"
|
214
|
+
database_id: "active_user_count"
|
215
|
+
query: |
|
216
|
+
SELECT
|
217
|
+
country AS country_name,
|
218
|
+
COUNT() AS active_user_count
|
219
|
+
FROM users
|
220
|
+
WHERE is_active = 1
|
221
|
+
GROUP BY country
|
222
|
+
main_label: "active_user_count"
|
223
|
+
labels: ["country_name"]
|
224
|
+
value_column: "active_user_count"
|
225
|
+
|
226
|
+
- id: "list_all_users_sqlite"
|
227
|
+
type: "sqlite"
|
228
|
+
database_id: "userdb"
|
229
|
+
query: |
|
230
|
+
SELECT
|
231
|
+
id,
|
232
|
+
name
|
233
|
+
FROM users
|
234
|
+
main_label: "user_list"
|
235
|
+
labels: ["id", "name"]
|
236
|
+
value_column: "id"
|
237
|
+
|
206
238
|
```
|
207
239
|
## Functions mode
|
208
240
|
|
@@ -155,21 +155,52 @@ Filesystem Size Used Avail Use% Mounted on
|
|
155
155
|
| `timeout_seconds` | Maximum time (in seconds) to wait for the command to complete. If it exceeds this time, the command is aborted. |
|
156
156
|
|
157
157
|
## Database mode
|
158
|
-
|
158
|
+
file - database.yaml
|
159
159
|
```yaml
|
160
160
|
databases:
|
161
|
-
-
|
162
|
-
|
163
|
-
|
164
|
-
|
161
|
+
- id: "active_user_count"
|
162
|
+
type: "clickhouse"
|
163
|
+
host: "localhost"
|
164
|
+
port: 8123
|
165
|
+
username: "default"
|
166
|
+
password: ""
|
167
|
+
client_cert: ""
|
168
|
+
client_key: ""
|
169
|
+
ca_cert: ""
|
170
|
+
|
171
|
+
- id: "userdb"
|
172
|
+
type: "sqlite"
|
173
|
+
db_connection: "/path/to/my.db"
|
174
|
+
```
|
175
|
+
file - queries.yaml
|
165
176
|
```yaml
|
166
177
|
commands:
|
167
|
-
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
178
|
+
- id: "active_user_count"
|
179
|
+
type: "clickhouse"
|
180
|
+
database_id: "active_user_count"
|
181
|
+
query: |
|
182
|
+
SELECT
|
183
|
+
country AS country_name,
|
184
|
+
COUNT() AS active_user_count
|
185
|
+
FROM users
|
186
|
+
WHERE is_active = 1
|
187
|
+
GROUP BY country
|
188
|
+
main_label: "active_user_count"
|
189
|
+
labels: ["country_name"]
|
190
|
+
value_column: "active_user_count"
|
191
|
+
|
192
|
+
- id: "list_all_users_sqlite"
|
193
|
+
type: "sqlite"
|
194
|
+
database_id: "userdb"
|
195
|
+
query: |
|
196
|
+
SELECT
|
197
|
+
id,
|
198
|
+
name
|
199
|
+
FROM users
|
200
|
+
main_label: "user_list"
|
201
|
+
labels: ["id", "name"]
|
202
|
+
value_column: "id"
|
203
|
+
|
173
204
|
```
|
174
205
|
## Functions mode
|
175
206
|
|
@@ -0,0 +1,55 @@
|
|
1
|
+
import clickhouse_connect
|
2
|
+
import sqlite3
|
3
|
+
from flexmetric.logging_module.logger import get_logger
|
4
|
+
import os
|
5
|
+
|
6
|
+
logger = get_logger(__name__)
|
7
|
+
|
8
|
+
logger.info("database logs")
|
9
|
+
|
10
|
+
def create_clickhouse_client(db_conf):
|
11
|
+
id = db_conf.get('id')
|
12
|
+
host = db_conf.get('host', 'localhost')
|
13
|
+
port = db_conf.get('port', 9440)
|
14
|
+
username = db_conf.get('username', 'default')
|
15
|
+
password = db_conf.get('password', '')
|
16
|
+
|
17
|
+
client_cert = db_conf.get('client_cert')
|
18
|
+
client_cert_key = db_conf.get('client_cert_key')
|
19
|
+
ca_cert = db_conf.get('ca_cert')
|
20
|
+
|
21
|
+
secure = bool(client_cert and client_cert_key and ca_cert)
|
22
|
+
|
23
|
+
settings = {
|
24
|
+
'host': host,
|
25
|
+
'port': port,
|
26
|
+
'username': username,
|
27
|
+
'password': password,
|
28
|
+
'secure': secure,
|
29
|
+
}
|
30
|
+
|
31
|
+
if secure:
|
32
|
+
settings.update({
|
33
|
+
'client_cert': client_cert,
|
34
|
+
'client_cert_key': client_cert_key,
|
35
|
+
'secure_ca': ca_cert,
|
36
|
+
})
|
37
|
+
|
38
|
+
client = clickhouse_connect.get_client(**settings)
|
39
|
+
logger.info(f"Clickhouse connection '{id}' created")
|
40
|
+
return client
|
41
|
+
|
42
|
+
|
43
|
+
def create_sqlite_client(db_conf: dict):
|
44
|
+
db_path = db_conf.get('db_connection')
|
45
|
+
db_name = db_conf.get('db_name', 'default_sqlite_db')
|
46
|
+
|
47
|
+
if not db_path or not os.path.isfile(db_path):
|
48
|
+
raise FileNotFoundError(f"SQLite database file not found at {db_path}")
|
49
|
+
|
50
|
+
try:
|
51
|
+
conn = sqlite3.connect(db_path)
|
52
|
+
logger.info(f"SQLite connection '{db_name}' created")
|
53
|
+
return conn
|
54
|
+
except Exception as e:
|
55
|
+
raise ConnectionError(f"Failed to create SQLite client: {e}")
|
@@ -0,0 +1,140 @@
|
|
1
|
+
import yaml
|
2
|
+
import re
|
3
|
+
from flexmetric.metric_process.database_connections import create_clickhouse_client,create_sqlite_client
|
4
|
+
from flexmetric.metric_process.queries_execution import execute_clickhouse_command,execute_sqlite_query
|
5
|
+
from flexmetric.logging_module.logger import get_logger
|
6
|
+
logger = get_logger(__name__)
|
7
|
+
|
8
|
+
logger.info("query execution")
|
9
|
+
|
10
|
+
|
11
|
+
def read_yaml_file(file_path):
|
12
|
+
with open(file_path, "r") as f:
|
13
|
+
return yaml.safe_load(f)
|
14
|
+
|
15
|
+
|
16
|
+
def get_database_config(databases, db_name):
|
17
|
+
for db in databases:
|
18
|
+
if db["name"] == db_name:
|
19
|
+
return db
|
20
|
+
raise ValueError(
|
21
|
+
f"[ERROR] Database config for '{db_name}' not found in database.yaml."
|
22
|
+
)
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
def is_safe_query(query):
|
27
|
+
cleaned_query = query.strip().lower()
|
28
|
+
return re.match(r"^\(*\s*select", cleaned_query) is not None
|
29
|
+
|
30
|
+
|
31
|
+
def read_yaml_file(filepath: str) -> dict:
|
32
|
+
try:
|
33
|
+
with open(filepath, 'r') as f:
|
34
|
+
return yaml.safe_load(f)
|
35
|
+
except Exception as e:
|
36
|
+
raise Exception(f"Error reading {filepath}: {e}")
|
37
|
+
|
38
|
+
|
39
|
+
def create_clients_from_config(config_file: str):
|
40
|
+
db_configs = read_yaml_file(config_file).get('databases', [])
|
41
|
+
clients = {}
|
42
|
+
|
43
|
+
for db_conf in db_configs:
|
44
|
+
db_id = db_conf.get('id')
|
45
|
+
logger.info(db_id)
|
46
|
+
db_type = db_conf.get('type')
|
47
|
+
|
48
|
+
if not db_id:
|
49
|
+
logger.info(f"Skipping unnamed database block: {db_conf}")
|
50
|
+
continue
|
51
|
+
|
52
|
+
try:
|
53
|
+
if db_type == 'clickhouse':
|
54
|
+
client = create_clickhouse_client(db_conf)
|
55
|
+
clients[db_id] = client
|
56
|
+
logger.info(clients)
|
57
|
+
|
58
|
+
elif db_type == 'sqlite':
|
59
|
+
client = create_sqlite_client(db_conf)
|
60
|
+
clients[db_id] = client
|
61
|
+
logger.info(clients)
|
62
|
+
|
63
|
+
else:
|
64
|
+
logger.info(f"Unsupported database type: {db_type}")
|
65
|
+
|
66
|
+
except Exception as e:
|
67
|
+
logger.error(f"Failed to create client '{db_id}': {e}")
|
68
|
+
return clients
|
69
|
+
|
70
|
+
def process_and_get_value(cmd,rows_data,column_names):
|
71
|
+
labels = cmd.get('labels', [])
|
72
|
+
value_column = cmd.get('value_column', [])
|
73
|
+
label_values = cmd.get('label_values', [])
|
74
|
+
main_label = cmd.get('main_label', 'default_db_metric')
|
75
|
+
missing_columns = [col for col in labels + [value_column] if col not in column_names]
|
76
|
+
if missing_columns:
|
77
|
+
raise ValueError(f"Missing columns in result: {missing_columns}")
|
78
|
+
rows = []
|
79
|
+
for row in rows_data:
|
80
|
+
label_values = [str(row[column_names.index(col)]) for col in labels]
|
81
|
+
value = row[column_names.index(value_column)]
|
82
|
+
|
83
|
+
rows.append({
|
84
|
+
'label': label_values,
|
85
|
+
'value': value
|
86
|
+
})
|
87
|
+
|
88
|
+
return {
|
89
|
+
'result': rows,
|
90
|
+
'labels': labels,
|
91
|
+
'main_label': main_label
|
92
|
+
}
|
93
|
+
|
94
|
+
def execute_commands(clients: dict, commands_file: str):
|
95
|
+
commands = read_yaml_file(commands_file).get('commands', [])
|
96
|
+
results = []
|
97
|
+
for cmd in commands:
|
98
|
+
print("CMD : ",cmd)
|
99
|
+
if cmd == None:
|
100
|
+
continue
|
101
|
+
cmd_id = cmd.get('id')
|
102
|
+
db_id = cmd.get('database_id')
|
103
|
+
db_type = cmd.get('type')
|
104
|
+
query = cmd.get('query')
|
105
|
+
if not cmd_id or not db_id or not db_type or not query:
|
106
|
+
logger.info(f"Missing required fields in command '{cmd_id}'")
|
107
|
+
continue
|
108
|
+
|
109
|
+
client = clients.get(db_id)
|
110
|
+
logger.info(clients)
|
111
|
+
logger.info(db_id)
|
112
|
+
logger.info(client)
|
113
|
+
if not client:
|
114
|
+
logger.info(f"No client for database_id '{db_id}' in command '{cmd_id}'")
|
115
|
+
continue
|
116
|
+
try:
|
117
|
+
if db_type == 'clickhouse':
|
118
|
+
logger.info("In clickhouse")
|
119
|
+
response,column_names = execute_clickhouse_command(client,query)
|
120
|
+
result = process_and_get_value(cmd,response,column_names)
|
121
|
+
results.append(result)
|
122
|
+
elif db_type == 'sqlite':
|
123
|
+
response ,column_names = execute_sqlite_query(client,query)
|
124
|
+
result = process_and_get_value(cmd,response,column_names)
|
125
|
+
results.append(result)
|
126
|
+
else:
|
127
|
+
logger.info(f"Unknown type '{db_type}' in command '{cmd_id}'")
|
128
|
+
continue
|
129
|
+
|
130
|
+
except Exception as e:
|
131
|
+
logger.error(f"Command '{cmd_id}' failed: {e}")
|
132
|
+
return results
|
133
|
+
|
134
|
+
|
135
|
+
def process_database_queries(queries_file, databases_file):
|
136
|
+
try:
|
137
|
+
client_configs = create_clients_from_config(databases_file)
|
138
|
+
return execute_commands(clients=client_configs,commands_file=queries_file)
|
139
|
+
except Exception as ex:
|
140
|
+
logger.error(f"Exception : {ex}")
|
@@ -0,0 +1,24 @@
|
|
1
|
+
from flexmetric.logging_module.logger import get_logger
|
2
|
+
logger = get_logger(__name__)
|
3
|
+
|
4
|
+
logger.info("query execution")
|
5
|
+
|
6
|
+
def execute_clickhouse_command(client, command: str):
|
7
|
+
try:
|
8
|
+
result = client.query(command)
|
9
|
+
row_list = result.result_rows
|
10
|
+
column_names = result.column_names
|
11
|
+
return row_list,column_names
|
12
|
+
except Exception as e:
|
13
|
+
logger.error(f"Error executing command: {e}")
|
14
|
+
return None
|
15
|
+
def execute_sqlite_query(conn, query):
|
16
|
+
try:
|
17
|
+
cursor = conn.cursor()
|
18
|
+
cursor.execute(query)
|
19
|
+
rows = cursor.fetchall()
|
20
|
+
column_names = [desc[0] for desc in cursor.description]
|
21
|
+
return rows, column_names
|
22
|
+
except Exception as ex:
|
23
|
+
logger.error(f"Exception during SQLite query: {ex}")
|
24
|
+
return [], []
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: flexmetric
|
3
|
-
Version: 0.4.
|
4
|
-
Summary: A secure flexible Prometheus exporter for commands, databases, functions
|
3
|
+
Version: 0.4.4
|
4
|
+
Summary: A secure flexible Prometheus exporter for commands, databases, functions.
|
5
5
|
Home-page: https://github.com/nikhillingadhal1999/flexmetric
|
6
6
|
Author: Nikhil Lingadhal
|
7
7
|
License: MIT
|
@@ -20,6 +20,7 @@ Requires-Dist: setuptools
|
|
20
20
|
Requires-Dist: wheel
|
21
21
|
Requires-Dist: twine
|
22
22
|
Requires-Dist: flask
|
23
|
+
Requires-Dist: clickhouse-connect
|
23
24
|
Dynamic: author
|
24
25
|
Dynamic: classifier
|
25
26
|
Dynamic: description
|
@@ -188,21 +189,52 @@ Filesystem Size Used Avail Use% Mounted on
|
|
188
189
|
| `timeout_seconds` | Maximum time (in seconds) to wait for the command to complete. If it exceeds this time, the command is aborted. |
|
189
190
|
|
190
191
|
## Database mode
|
191
|
-
|
192
|
+
file - database.yaml
|
192
193
|
```yaml
|
193
194
|
databases:
|
194
|
-
-
|
195
|
-
|
196
|
-
|
197
|
-
|
195
|
+
- id: "active_user_count"
|
196
|
+
type: "clickhouse"
|
197
|
+
host: "localhost"
|
198
|
+
port: 8123
|
199
|
+
username: "default"
|
200
|
+
password: ""
|
201
|
+
client_cert: ""
|
202
|
+
client_key: ""
|
203
|
+
ca_cert: ""
|
204
|
+
|
205
|
+
- id: "userdb"
|
206
|
+
type: "sqlite"
|
207
|
+
db_connection: "/path/to/my.db"
|
208
|
+
```
|
209
|
+
file - queries.yaml
|
198
210
|
```yaml
|
199
211
|
commands:
|
200
|
-
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
212
|
+
- id: "active_user_count"
|
213
|
+
type: "clickhouse"
|
214
|
+
database_id: "active_user_count"
|
215
|
+
query: |
|
216
|
+
SELECT
|
217
|
+
country AS country_name,
|
218
|
+
COUNT() AS active_user_count
|
219
|
+
FROM users
|
220
|
+
WHERE is_active = 1
|
221
|
+
GROUP BY country
|
222
|
+
main_label: "active_user_count"
|
223
|
+
labels: ["country_name"]
|
224
|
+
value_column: "active_user_count"
|
225
|
+
|
226
|
+
- id: "list_all_users_sqlite"
|
227
|
+
type: "sqlite"
|
228
|
+
database_id: "userdb"
|
229
|
+
query: |
|
230
|
+
SELECT
|
231
|
+
id,
|
232
|
+
name
|
233
|
+
FROM users
|
234
|
+
main_label: "user_list"
|
235
|
+
labels: ["id", "name"]
|
236
|
+
value_column: "id"
|
237
|
+
|
206
238
|
```
|
207
239
|
## Functions mode
|
208
240
|
|
@@ -14,8 +14,10 @@ flexmetric/file_recognition/exec_file.py
|
|
14
14
|
flexmetric/logging_module/__init__.py
|
15
15
|
flexmetric/logging_module/logger.py
|
16
16
|
flexmetric/metric_process/__init__.py
|
17
|
+
flexmetric/metric_process/database_connections.py
|
17
18
|
flexmetric/metric_process/database_processing.py
|
18
19
|
flexmetric/metric_process/expiring_queue.py
|
19
20
|
flexmetric/metric_process/process_commands.py
|
20
21
|
flexmetric/metric_process/prometheus_agent.py
|
22
|
+
flexmetric/metric_process/queries_execution.py
|
21
23
|
flexmetric/metric_process/views.py
|
@@ -2,9 +2,9 @@ from setuptools import setup, find_packages
|
|
2
2
|
|
3
3
|
setup(
|
4
4
|
name="flexmetric",
|
5
|
-
version="0.4.
|
5
|
+
version="0.4.4",
|
6
6
|
author="Nikhil Lingadhal",
|
7
|
-
description="A secure flexible Prometheus exporter for commands, databases, functions
|
7
|
+
description="A secure flexible Prometheus exporter for commands, databases, functions.",
|
8
8
|
long_description=open("README.md").read(),
|
9
9
|
long_description_content_type="text/markdown",
|
10
10
|
url="https://github.com/nikhillingadhal1999/flexmetric",
|
@@ -22,7 +22,8 @@ setup(
|
|
22
22
|
"setuptools",
|
23
23
|
"wheel",
|
24
24
|
"twine",
|
25
|
-
"flask"
|
25
|
+
"flask",
|
26
|
+
"clickhouse-connect"
|
26
27
|
],
|
27
28
|
entry_points={
|
28
29
|
"console_scripts": [
|
@@ -1,90 +0,0 @@
|
|
1
|
-
import yaml
|
2
|
-
import sqlite3
|
3
|
-
import re
|
4
|
-
|
5
|
-
|
6
|
-
def read_yaml_file(file_path):
|
7
|
-
with open(file_path, "r") as f:
|
8
|
-
return yaml.safe_load(f)
|
9
|
-
|
10
|
-
|
11
|
-
def get_database_config(databases, db_name):
|
12
|
-
for db in databases:
|
13
|
-
if db["name"] == db_name:
|
14
|
-
return db
|
15
|
-
raise ValueError(
|
16
|
-
f"[ERROR] Database config for '{db_name}' not found in database.yaml."
|
17
|
-
)
|
18
|
-
|
19
|
-
|
20
|
-
def execute_sqlite_query(db_path, query):
|
21
|
-
try:
|
22
|
-
conn = sqlite3.connect(db_path)
|
23
|
-
cursor = conn.cursor()
|
24
|
-
cursor.execute(query)
|
25
|
-
result = cursor.fetchone()
|
26
|
-
conn.close()
|
27
|
-
return float(result[0]) if result and result[0] is not None else None
|
28
|
-
except Exception as e:
|
29
|
-
print(f"[ERROR] SQLite query failed on {db_path}: {e}")
|
30
|
-
return None
|
31
|
-
|
32
|
-
|
33
|
-
def is_safe_query(query):
|
34
|
-
# Remove leading spaces and brackets
|
35
|
-
cleaned_query = query.strip().lower()
|
36
|
-
# Match only queries that start with "select"
|
37
|
-
return re.match(r"^\(*\s*select", cleaned_query) is not None
|
38
|
-
|
39
|
-
|
40
|
-
def process_database_queries(queries_file, databases_file):
|
41
|
-
# Get queries from queries file
|
42
|
-
queries_config = read_yaml_file(queries_file)
|
43
|
-
# Get database from database file
|
44
|
-
databases_config = read_yaml_file(databases_file)
|
45
|
-
|
46
|
-
commands = queries_config.get("commands", [])
|
47
|
-
databases = databases_config.get("databases", [])
|
48
|
-
|
49
|
-
all_results = []
|
50
|
-
|
51
|
-
for cmd in commands:
|
52
|
-
try:
|
53
|
-
db_conf = get_database_config(databases, cmd["database"])
|
54
|
-
|
55
|
-
if db_conf["db_type"] != "sqlite":
|
56
|
-
print(
|
57
|
-
f"[WARN] Unsupported database type: {db_conf['db_type']} in command {cmd['name']}"
|
58
|
-
)
|
59
|
-
continue
|
60
|
-
|
61
|
-
db_path = db_conf["db_connection"]
|
62
|
-
query = cmd["query"]
|
63
|
-
labels = cmd.get('labels', [])
|
64
|
-
label_values = cmd.get('label_values', [])
|
65
|
-
main_label = cmd.get('main_label', 'default_db_metric')
|
66
|
-
|
67
|
-
# check if query is safe
|
68
|
-
if is_safe_query(query):
|
69
|
-
value = execute_sqlite_query(db_path, query)
|
70
|
-
else:
|
71
|
-
print(f"[WARN] Unsupported query type: {query}")
|
72
|
-
return None
|
73
|
-
|
74
|
-
if not isinstance(label_values, list):
|
75
|
-
label_values = [label_values]
|
76
|
-
|
77
|
-
result = {
|
78
|
-
'result': [{
|
79
|
-
'label': label_values,
|
80
|
-
'value': value
|
81
|
-
}],
|
82
|
-
'labels': labels,
|
83
|
-
'main_label': main_label
|
84
|
-
}
|
85
|
-
all_results.append(result)
|
86
|
-
except Exception as e:
|
87
|
-
print(
|
88
|
-
f"[ERROR] Processing command '{cmd.get('name', 'unknown')}' failed: {e}"
|
89
|
-
)
|
90
|
-
return all_results
|
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
|