mirror of
https://github.com/ddworken/hishtory.git
synced 2025-06-20 11:57:50 +02:00
Track queries in usage data + better formatting in the internal usage page
This commit is contained in:
parent
98a4f002fa
commit
18ddbf2ca9
@ -17,6 +17,7 @@ import (
|
|||||||
|
|
||||||
"github.com/ddworken/hishtory/shared"
|
"github.com/ddworken/hishtory/shared"
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
|
"github.com/rodaine/table"
|
||||||
"gorm.io/driver/postgres"
|
"gorm.io/driver/postgres"
|
||||||
|
|
||||||
"gorm.io/driver/sqlite"
|
"gorm.io/driver/sqlite"
|
||||||
@ -40,8 +41,12 @@ type UsageData struct {
|
|||||||
LastUsed time.Time `json:"last_used"`
|
LastUsed time.Time `json:"last_used"`
|
||||||
LastIp string `json:"last_ip"`
|
LastIp string `json:"last_ip"`
|
||||||
NumEntriesHandled int `json:"num_entries_handled"`
|
NumEntriesHandled int `json:"num_entries_handled"`
|
||||||
|
LastQueried time.Time `json:"last_queried"`
|
||||||
|
NumQueries int `json:"num_queries"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Audit this file for queries that don't check result.Error
|
||||||
|
|
||||||
func getRequiredQueryParam(r *http.Request, queryParam string) string {
|
func getRequiredQueryParam(r *http.Request, queryParam string) string {
|
||||||
val := r.URL.Query().Get(queryParam)
|
val := r.URL.Query().Get(queryParam)
|
||||||
if val == "" {
|
if val == "" {
|
||||||
@ -50,18 +55,20 @@ func getRequiredQueryParam(r *http.Request, queryParam string) string {
|
|||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateUsageData(r *http.Request, userId, deviceId string, numEntries int) {
|
func updateUsageData(r *http.Request, userId, deviceId string, numEntriesHandled int, isQuery bool) {
|
||||||
var usageData []UsageData
|
var usageData []UsageData
|
||||||
GLOBAL_DB.Where("user_id = ? AND device_id = ?", userId, deviceId).Find(&usageData)
|
GLOBAL_DB.Where("user_id = ? AND device_id = ?", userId, deviceId).Find(&usageData)
|
||||||
if len(usageData) == 0 {
|
if len(usageData) == 0 {
|
||||||
GLOBAL_DB.Create(&UsageData{UserId: userId, DeviceId: deviceId, LastUsed: time.Now(), NumEntriesHandled: numEntries})
|
GLOBAL_DB.Create(&UsageData{UserId: userId, DeviceId: deviceId, LastUsed: time.Now(), NumEntriesHandled: numEntriesHandled})
|
||||||
} else {
|
} else {
|
||||||
GLOBAL_DB.Model(&UsageData{}).Where("user_id = ? AND device_id = ?", userId, deviceId).Update("last_used", time.Now()).Update("last_ip", getRemoteAddr(r))
|
GLOBAL_DB.Model(&UsageData{}).Where("user_id = ? AND device_id = ?", userId, deviceId).Update("last_used", time.Now()).Update("last_ip", getRemoteAddr(r))
|
||||||
if numEntries > 0 {
|
if numEntriesHandled > 0 {
|
||||||
GLOBAL_DB.Exec("UPDATE usage_data SET num_entries_handled = COALESCE(num_entries_handled, 0) + ? WHERE user_id = ? AND device_id = ?", numEntries, userId, deviceId)
|
GLOBAL_DB.Exec("UPDATE usage_data SET num_entries_handled = COALESCE(num_entries_handled, 0) + ? WHERE user_id = ? AND device_id = ?", numEntriesHandled, userId, deviceId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if isQuery {
|
||||||
|
GLOBAL_DB.Exec("UPDATE usage_data SET num_queries = COALESCE(num_queries, 0) + 1, last_queried = ? WHERE user_id = ? AND device_id = ?", time.Now(), userId, deviceId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func usageStatsHandler(w http.ResponseWriter, r *http.Request) {
|
func usageStatsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -71,7 +78,9 @@ func usageStatsHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
COUNT(DISTINCT devices.device_id) as num_devices,
|
COUNT(DISTINCT devices.device_id) as num_devices,
|
||||||
SUM(usage_data.num_entries_handled) as num_history_entries,
|
SUM(usage_data.num_entries_handled) as num_history_entries,
|
||||||
MAX(usage_data.last_used) as last_active,
|
MAX(usage_data.last_used) as last_active,
|
||||||
COALESCE(STRING_AGG(DISTINCT usage_data.last_ip, ' ') FILTER (WHERE usage_data.last_ip != 'Unknown'), 'Unknown') as ip_addresses
|
COALESCE(STRING_AGG(DISTINCT usage_data.last_ip, ' ') FILTER (WHERE usage_data.last_ip != 'Unknown'), 'Unknown') as ip_addresses,
|
||||||
|
COALESCE(SUM(usage_data.num_queries), 0) as num_queries,
|
||||||
|
COALESCE(MAX(usage_data.last_queried), 'January 1, 1970') as last_queried
|
||||||
FROM devices
|
FROM devices
|
||||||
INNER JOIN usage_data ON devices.device_id = usage_data.device_id
|
INNER JOIN usage_data ON devices.device_id = usage_data.device_id
|
||||||
GROUP BY devices.user_id
|
GROUP BY devices.user_id
|
||||||
@ -81,18 +90,23 @@ func usageStatsHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
tbl := table.New("Registration Date", "Num Devices", "Num Entries", "Num Queries", "Last Active", "Last Query", "IPs")
|
||||||
|
tbl.WithWriter(w)
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var registrationDate time.Time
|
var registrationDate time.Time
|
||||||
var numDevices int
|
var numDevices int
|
||||||
var numEntries int
|
var numEntries int
|
||||||
var lastUsedDate time.Time
|
var lastUsedDate time.Time
|
||||||
var ipAddresses string
|
var ipAddresses string
|
||||||
err = rows.Scan(®istrationDate, &numDevices, &numEntries, &lastUsedDate, &ipAddresses)
|
var numQueries int
|
||||||
|
var lastQueried time.Time
|
||||||
|
err = rows.Scan(®istrationDate, &numDevices, &numEntries, &lastUsedDate, &ipAddresses, &numQueries, &lastQueried)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
w.Write([]byte(fmt.Sprintf("Registered: %s\tNumDevices: %d\tNumEntries: %d\tLastUsed: %s\tIP: %s\n", registrationDate.Format("2006-01-02"), numDevices, numEntries, lastUsedDate.Format("2006-01-02"), ipAddresses)))
|
tbl.AddRow(registrationDate.Format("2006-01-02"), numDevices, numEntries, numQueries, lastUsedDate.Format("2006-01-02"), lastQueried.Format("2006-01-02"), ipAddresses)
|
||||||
}
|
}
|
||||||
|
tbl.Print()
|
||||||
}
|
}
|
||||||
|
|
||||||
func apiSubmitHandler(w http.ResponseWriter, r *http.Request) {
|
func apiSubmitHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -107,7 +121,7 @@ func apiSubmitHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
fmt.Printf("apiSubmitHandler: received request containg %d EncHistoryEntry\n", len(entries))
|
fmt.Printf("apiSubmitHandler: received request containg %d EncHistoryEntry\n", len(entries))
|
||||||
for _, entry := range entries {
|
for _, entry := range entries {
|
||||||
updateUsageData(r, entry.UserId, entry.DeviceId, 1)
|
updateUsageData(r, entry.UserId, entry.DeviceId, 1, false)
|
||||||
tx := GLOBAL_DB.Where("user_id = ?", entry.UserId)
|
tx := GLOBAL_DB.Where("user_id = ?", entry.UserId)
|
||||||
var devices []*shared.Device
|
var devices []*shared.Device
|
||||||
result := tx.Find(&devices)
|
result := tx.Find(&devices)
|
||||||
@ -131,7 +145,7 @@ func apiSubmitHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
func apiBootstrapHandler(w http.ResponseWriter, r *http.Request) {
|
func apiBootstrapHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
userId := getRequiredQueryParam(r, "user_id")
|
userId := getRequiredQueryParam(r, "user_id")
|
||||||
deviceId := getRequiredQueryParam(r, "device_id")
|
deviceId := getRequiredQueryParam(r, "device_id")
|
||||||
updateUsageData(r, userId, deviceId, 0)
|
updateUsageData(r, userId, deviceId, 0, false)
|
||||||
tx := GLOBAL_DB.Where("user_id = ?", userId)
|
tx := GLOBAL_DB.Where("user_id = ?", userId)
|
||||||
var historyEntries []*shared.EncHistoryEntry
|
var historyEntries []*shared.EncHistoryEntry
|
||||||
result := tx.Find(&historyEntries)
|
result := tx.Find(&historyEntries)
|
||||||
@ -148,7 +162,7 @@ func apiBootstrapHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
func apiQueryHandler(w http.ResponseWriter, r *http.Request) {
|
func apiQueryHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
userId := getRequiredQueryParam(r, "user_id")
|
userId := getRequiredQueryParam(r, "user_id")
|
||||||
deviceId := getRequiredQueryParam(r, "device_id")
|
deviceId := getRequiredQueryParam(r, "device_id")
|
||||||
updateUsageData(r, userId, deviceId, 0)
|
updateUsageData(r, userId, deviceId, 0, true)
|
||||||
// Increment the count
|
// Increment the count
|
||||||
result := GLOBAL_DB.Exec("UPDATE enc_history_entries SET read_count = read_count + 1 WHERE device_id = ?", deviceId)
|
result := GLOBAL_DB.Exec("UPDATE enc_history_entries SET read_count = read_count + 1 WHERE device_id = ?", deviceId)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
@ -201,7 +215,7 @@ func apiRegisterHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
if existingDevicesCount > 0 {
|
if existingDevicesCount > 0 {
|
||||||
GLOBAL_DB.Create(&shared.DumpRequest{UserId: userId, RequestingDeviceId: deviceId, RequestTime: time.Now()})
|
GLOBAL_DB.Create(&shared.DumpRequest{UserId: userId, RequestingDeviceId: deviceId, RequestTime: time.Now()})
|
||||||
}
|
}
|
||||||
updateUsageData(r, userId, deviceId, 0)
|
updateUsageData(r, userId, deviceId, 0, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func apiGetPendingDumpRequestsHandler(w http.ResponseWriter, r *http.Request) {
|
func apiGetPendingDumpRequestsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -254,7 +268,7 @@ func apiSubmitDumpHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
panic(fmt.Errorf("failed to clear the dump request: %v", err))
|
panic(fmt.Errorf("failed to clear the dump request: %v", err))
|
||||||
}
|
}
|
||||||
updateUsageData(r, userId, srcDeviceId, len(entries))
|
updateUsageData(r, userId, srcDeviceId, len(entries), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func apiBannerHandler(w http.ResponseWriter, r *http.Request) {
|
func apiBannerHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user