first commit
This commit is contained in:
173
app.py
Normal file
173
app.py
Normal file
@ -0,0 +1,173 @@
|
||||
from flask import Flask, request, jsonify, render_template
|
||||
from influxdb import InfluxDBClient
|
||||
from flask_cors import CORS
|
||||
from config import get_influx_client
|
||||
|
||||
app = Flask(__name__)
|
||||
CORS(app)
|
||||
|
||||
client = get_influx_client()
|
||||
|
||||
def escape_identifier(identifier):
|
||||
"""Escapuje identyfikatory dla InfluxDB."""
|
||||
return f'"{identifier.replace("\\", "\\\\").replace("\"", "\\\"")}"'
|
||||
|
||||
def escape_value(value):
|
||||
"""Escapuje wartości dla zapytań InfluxDB."""
|
||||
if isinstance(value, str):
|
||||
escaped = value.replace("'", "''")
|
||||
return f"'{escaped}'"
|
||||
return str(value)
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
return render_template("index.html")
|
||||
|
||||
@app.route('/databases', methods=['GET'])
|
||||
def get_databases():
|
||||
databases = client.get_list_database()
|
||||
return jsonify([db['name'] for db in databases])
|
||||
|
||||
@app.route('/series', methods=['GET'])
|
||||
def get_series():
|
||||
db = request.args.get('db')
|
||||
if not db:
|
||||
return jsonify({'error': 'Baza danych nie została wybrana'}), 400
|
||||
|
||||
client.switch_database(db)
|
||||
series_info = []
|
||||
|
||||
#print("DEBUG: Pobieram listę measurementów...")
|
||||
measurements = client.query("SHOW MEASUREMENTS")
|
||||
measurement_names = [m['name'] for m in measurements.get_points()]
|
||||
#print("DEBUG: Measurementy:", measurement_names)
|
||||
|
||||
for measurement in measurement_names:
|
||||
if measurement == "results":
|
||||
print("DEBUG: Pomijam 'results'")
|
||||
continue
|
||||
|
||||
#print(f"DEBUG: SHOW SERIES FROM \"{measurement}\"")
|
||||
try:
|
||||
result = client.query(f'SHOW SERIES FROM "{measurement}"')
|
||||
for s in result.get_points():
|
||||
tags = {k: v for k, v in s.items() if k != 'time'}
|
||||
if not tags:
|
||||
continue
|
||||
series_id = f"{measurement},{','.join([f'{k}={v}' for k, v in tags.items()])}"
|
||||
#print(f"DEBUG: Series = {series_id}")
|
||||
series_info.append({
|
||||
'series': series_id,
|
||||
'measurement': measurement,
|
||||
'tags': tags
|
||||
})
|
||||
except Exception as e:
|
||||
print(f"DEBUG: Błąd w {measurement}: {str(e)}")
|
||||
|
||||
print(f"DEBUG: Zwracam do frontu {len(series_info)} serii")
|
||||
return jsonify(series_info)
|
||||
|
||||
|
||||
@app.route('/delete', methods=['POST'])
|
||||
def delete_series():
|
||||
data = request.json
|
||||
db = data.get('db')
|
||||
if not db:
|
||||
return jsonify({'error': 'Baza danych nie została wybrana'}), 400
|
||||
|
||||
client.switch_database(db)
|
||||
deleted_count = 0
|
||||
|
||||
for series in data['series']:
|
||||
try:
|
||||
parts = series.split(',', 1)
|
||||
measurement = parts[0].strip()
|
||||
tags_part = parts[1] if len(parts) > 1 else ''
|
||||
|
||||
# Raw tag parsing
|
||||
tags = {}
|
||||
for tag in tags_part.split(','):
|
||||
if '=' in tag:
|
||||
k, v = tag.split('=', 1)
|
||||
tags[k.strip()] = v.strip()
|
||||
|
||||
# Pobierz tylko tagi dostępne w measurement
|
||||
tag_keys_query = client.query(f'SHOW TAG KEYS FROM "{measurement}"')
|
||||
tag_keys = {row['tagKey'] for row in tag_keys_query.get_points()}
|
||||
|
||||
# Build WHERE clause tylko z tagów
|
||||
where_parts = []
|
||||
for k, v in tags.items():
|
||||
if k not in tag_keys:
|
||||
print(f"Pomijam '{k}', bo nie jest tagiem w '{measurement}'")
|
||||
continue
|
||||
v_escaped = v.replace("'", "\\'")
|
||||
where_parts.append(f'"{k}" = \'{v_escaped}\'')
|
||||
|
||||
# Escape measurement for InfluxQL
|
||||
measurement_escaped = measurement.replace('"', '\\"')
|
||||
|
||||
query = f'DROP SERIES FROM "{measurement_escaped}" WHERE {" AND ".join(where_parts)}'
|
||||
print(f"DEBUG: Final query to run: {query}")
|
||||
|
||||
client.query(query)
|
||||
deleted_count += 1
|
||||
|
||||
except Exception as e:
|
||||
print(f"Błąd usuwania serii {series}: {str(e)}")
|
||||
continue
|
||||
|
||||
return jsonify({'status': 'success', 'deleted': deleted_count})
|
||||
|
||||
|
||||
@app.route('/delete_range', methods=['POST'])
|
||||
def delete_range():
|
||||
data = request.json
|
||||
db = data.get('db')
|
||||
series = data.get('series')
|
||||
time_from = data.get('from')
|
||||
time_to = data.get('to')
|
||||
|
||||
if not all([db, series, time_from, time_to]):
|
||||
return jsonify({'error': 'Brakuje wymaganych parametrów'}), 400
|
||||
|
||||
client.switch_database(db)
|
||||
|
||||
try:
|
||||
# Parsowanie measurementu i tagów z serii
|
||||
parts = series.split(',', 1)
|
||||
measurement = parts[0].strip()
|
||||
tags_part = parts[1] if len(parts) > 1 else ''
|
||||
|
||||
tags = {}
|
||||
for tag in tags_part.split(','):
|
||||
if '=' in tag:
|
||||
k, v = tag.split('=', 1)
|
||||
tags[k.strip()] = v.strip()
|
||||
|
||||
# Pobierz dozwolone tagi z InfluxDB
|
||||
tag_keys_query = client.query(f'SHOW TAG KEYS FROM "{measurement}"')
|
||||
tag_keys = {row['tagKey'] for row in tag_keys_query.get_points()}
|
||||
|
||||
# Buduj WHERE tylko z tagów i czasu
|
||||
where_parts = [f"time >= '{time_from}'", f"time <= '{time_to}'"]
|
||||
for k, v in tags.items():
|
||||
if k not in tag_keys:
|
||||
print(f"Pomijam '{k}', bo nie jest tagiem w '{measurement}'")
|
||||
continue
|
||||
v_escaped = v.replace("'", "\\'")
|
||||
where_parts.append(f'"{k}" = \'{v_escaped}\'')
|
||||
|
||||
measurement_escaped = measurement.replace('"', '\\"')
|
||||
query = f'DELETE FROM "{measurement_escaped}" WHERE {" AND ".join(where_parts)}'
|
||||
|
||||
print(f"DEBUG: DELETE query: {query}")
|
||||
client.query(query)
|
||||
return jsonify({'status': 'success'})
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(host='0.0.0.0', port=9999, debug=True)
|
Reference in New Issue
Block a user