198 lines
6.0 KiB
Go
198 lines
6.0 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"fmt"
|
|
)
|
|
|
|
func (s *Store) InsertProxyRequestLog(ctx context.Context, l *ProxyRequestLog) error {
|
|
res, err := s.db.ExecContext(ctx, `
|
|
INSERT INTO proxy_request_logs(host,network,rule_type,rule_payload,rule_line,outbound_node,outbound_chain,upload,download,success,started_at,ended_at)
|
|
VALUES(?,?,?,?,?,?,?,?,?,?,?,?)`,
|
|
l.Host, l.Network, l.RuleType, l.RulePayload, l.RuleLine, l.OutboundNode, l.OutboundChain,
|
|
l.Upload, l.Download, intFromBool(l.Success), l.StartedAt.Format("2006-01-02 15:04:05"), l.EndedAt.Format("2006-01-02 15:04:05"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
id, _ := res.LastInsertId()
|
|
l.ID = id
|
|
return nil
|
|
}
|
|
|
|
func (s *Store) ListProxyRequestLogs(ctx context.Context, keyword string, limit, offset int) ([]ProxyRequestLog, int, error) {
|
|
query := `SELECT id,host,network,rule_type,rule_payload,rule_line,outbound_node,outbound_chain,upload,download,success,started_at,ended_at,created_at FROM proxy_request_logs WHERE 1=1`
|
|
countQuery := `SELECT COUNT(*) FROM proxy_request_logs WHERE 1=1`
|
|
args := []any{}
|
|
if keyword != "" {
|
|
query += ` AND (host LIKE ? OR rule_line LIKE ? OR outbound_node LIKE ? OR outbound_chain LIKE ?)`
|
|
countQuery += ` AND (host LIKE ? OR rule_line LIKE ? OR outbound_node LIKE ? OR outbound_chain LIKE ?)`
|
|
kw := "%" + keyword + "%"
|
|
args = append(args, kw, kw, kw, kw)
|
|
}
|
|
var total int
|
|
if err := s.db.QueryRowContext(ctx, countQuery, args...).Scan(&total); err != nil {
|
|
return nil, 0, err
|
|
}
|
|
query += ` ORDER BY id DESC LIMIT ? OFFSET ?`
|
|
args = append(args, limit, offset)
|
|
rows, err := s.db.QueryContext(ctx, query, args...)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
defer rows.Close()
|
|
var out []ProxyRequestLog
|
|
for rows.Next() {
|
|
var l ProxyRequestLog
|
|
var success int
|
|
var started, ended, created string
|
|
if err := rows.Scan(&l.ID, &l.Host, &l.Network, &l.RuleType, &l.RulePayload, &l.RuleLine, &l.OutboundNode, &l.OutboundChain,
|
|
&l.Upload, &l.Download, &success, &started, &ended, &created); err != nil {
|
|
return nil, 0, err
|
|
}
|
|
l.Success = boolFromInt(success)
|
|
l.StartedAt = parseTime(started)
|
|
l.EndedAt = parseTime(ended)
|
|
l.CreatedAt = parseTime(created)
|
|
out = append(out, l)
|
|
}
|
|
return out, total, rows.Err()
|
|
}
|
|
|
|
func (s *Store) PruneProxyRequestLogs(ctx context.Context, keep int) error {
|
|
_, err := s.db.ExecContext(ctx, `DELETE FROM proxy_request_logs WHERE id NOT IN (SELECT id FROM proxy_request_logs ORDER BY id DESC LIMIT ?)`, keep)
|
|
return err
|
|
}
|
|
|
|
type TrafficAgg struct {
|
|
Key string `json:"key"`
|
|
Upload int64 `json:"upload"`
|
|
Download int64 `json:"download"`
|
|
Connections int `json:"connections"`
|
|
}
|
|
|
|
type TrafficHostNodeAgg struct {
|
|
Host string `json:"host"`
|
|
NodeKey string `json:"node_key"`
|
|
Upload int64 `json:"upload"`
|
|
Download int64 `json:"download"`
|
|
Connections int `json:"connections"`
|
|
}
|
|
|
|
func (s *Store) AggregateTrafficByHost(ctx context.Context, hours, limit int) ([]TrafficAgg, error) {
|
|
if hours <= 0 {
|
|
hours = 24
|
|
}
|
|
if limit <= 0 {
|
|
limit = 30
|
|
}
|
|
rows, err := s.db.QueryContext(ctx, `
|
|
SELECT host, COALESCE(SUM(upload),0), COALESCE(SUM(download),0), COUNT(*)
|
|
FROM proxy_request_logs
|
|
WHERE host != '' AND created_at >= datetime('now', ?)
|
|
GROUP BY host
|
|
ORDER BY (SUM(upload)+SUM(download)) DESC
|
|
LIMIT ?`, fmt.Sprintf("-%d hours", hours), limit)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
return scanTrafficAgg(rows)
|
|
}
|
|
|
|
func (s *Store) CountAggregateTrafficByNode(ctx context.Context, hours int) (int, error) {
|
|
if hours <= 0 {
|
|
hours = 24
|
|
}
|
|
var n int
|
|
err := s.db.QueryRowContext(ctx, `
|
|
SELECT COUNT(*) FROM (
|
|
SELECT 1 FROM proxy_request_logs
|
|
WHERE outbound_node != '' AND created_at >= datetime('now', ?)
|
|
GROUP BY outbound_node
|
|
)`, fmt.Sprintf("-%d hours", hours)).Scan(&n)
|
|
return n, err
|
|
}
|
|
|
|
func (s *Store) AggregateTrafficByNode(ctx context.Context, hours, limit, offset int) ([]TrafficAgg, error) {
|
|
if hours <= 0 {
|
|
hours = 24
|
|
}
|
|
if limit <= 0 {
|
|
limit = 50
|
|
}
|
|
if offset < 0 {
|
|
offset = 0
|
|
}
|
|
rows, err := s.db.QueryContext(ctx, `
|
|
SELECT outbound_node, COALESCE(SUM(upload),0), COALESCE(SUM(download),0), COUNT(*)
|
|
FROM proxy_request_logs
|
|
WHERE outbound_node != '' AND created_at >= datetime('now', ?)
|
|
GROUP BY outbound_node
|
|
ORDER BY (SUM(upload)+SUM(download)) DESC
|
|
LIMIT ? OFFSET ?`, fmt.Sprintf("-%d hours", hours), limit, offset)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
return scanTrafficAgg(rows)
|
|
}
|
|
|
|
func (s *Store) CountAggregateTrafficByHostNode(ctx context.Context, hours int) (int, error) {
|
|
if hours <= 0 {
|
|
hours = 24
|
|
}
|
|
var n int
|
|
err := s.db.QueryRowContext(ctx, `
|
|
SELECT COUNT(*) FROM (
|
|
SELECT 1 FROM proxy_request_logs
|
|
WHERE host != '' AND outbound_node != '' AND created_at >= datetime('now', ?)
|
|
GROUP BY host, outbound_node
|
|
)`, fmt.Sprintf("-%d hours", hours)).Scan(&n)
|
|
return n, err
|
|
}
|
|
|
|
func (s *Store) AggregateTrafficByHostNode(ctx context.Context, hours, limit, offset int) ([]TrafficHostNodeAgg, error) {
|
|
if hours <= 0 {
|
|
hours = 24
|
|
}
|
|
if limit <= 0 {
|
|
limit = 50
|
|
}
|
|
if offset < 0 {
|
|
offset = 0
|
|
}
|
|
rows, err := s.db.QueryContext(ctx, `
|
|
SELECT host, outbound_node, COALESCE(SUM(upload),0), COALESCE(SUM(download),0), COUNT(*)
|
|
FROM proxy_request_logs
|
|
WHERE host != '' AND outbound_node != '' AND created_at >= datetime('now', ?)
|
|
GROUP BY host, outbound_node
|
|
ORDER BY (SUM(upload)+SUM(download)) DESC
|
|
LIMIT ? OFFSET ?`, fmt.Sprintf("-%d hours", hours), limit, offset)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var out []TrafficHostNodeAgg
|
|
for rows.Next() {
|
|
var item TrafficHostNodeAgg
|
|
if err := rows.Scan(&item.Host, &item.NodeKey, &item.Upload, &item.Download, &item.Connections); err != nil {
|
|
return nil, err
|
|
}
|
|
out = append(out, item)
|
|
}
|
|
return out, rows.Err()
|
|
}
|
|
|
|
func scanTrafficAgg(rows *sql.Rows) ([]TrafficAgg, error) {
|
|
var out []TrafficAgg
|
|
for rows.Next() {
|
|
var item TrafficAgg
|
|
if err := rows.Scan(&item.Key, &item.Upload, &item.Download, &item.Connections); err != nil {
|
|
return nil, err
|
|
}
|
|
out = append(out, item)
|
|
}
|
|
return out, rows.Err()
|
|
}
|