more metadata in reports
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -748,7 +749,20 @@ func CreateTableReport(logger *slog.Logger, Database db.Database, ctx context.Co
|
|||||||
}
|
}
|
||||||
|
|
||||||
if isDailySummary || isMonthlySummary {
|
if isDailySummary || isMonthlySummary {
|
||||||
addReportMetadataSheet(logger, xlsx)
|
meta := reportMetadata{
|
||||||
|
TableName: tableName,
|
||||||
|
ReportType: reportTypeFromTable(tableName),
|
||||||
|
GeneratedAt: time.Now(),
|
||||||
|
Duration: time.Since(start),
|
||||||
|
RowCount: rowCount,
|
||||||
|
ColumnCount: len(columns),
|
||||||
|
DBDriver: Database.DB().DriverName(),
|
||||||
|
}
|
||||||
|
if windowStart, windowEnd, ok := reportWindowFromTable(tableName); ok {
|
||||||
|
meta.WindowStart = &windowStart
|
||||||
|
meta.WindowEnd = &windowEnd
|
||||||
|
}
|
||||||
|
addReportMetadataSheet(logger, xlsx, meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
addTotalsChartSheet(logger, Database, ctx, xlsx, tableName)
|
addTotalsChartSheet(logger, Database, ctx, xlsx, tableName)
|
||||||
@@ -1057,14 +1071,102 @@ func summaryReportOrder() []string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func addReportMetadataSheet(logger *slog.Logger, xlsx *excelize.File) {
|
type reportMetadata struct {
|
||||||
|
TableName string
|
||||||
|
ReportType string
|
||||||
|
GeneratedAt time.Time
|
||||||
|
Duration time.Duration
|
||||||
|
RowCount int
|
||||||
|
ColumnCount int
|
||||||
|
WindowStart *time.Time
|
||||||
|
WindowEnd *time.Time
|
||||||
|
DBDriver string
|
||||||
|
}
|
||||||
|
|
||||||
|
func reportTypeFromTable(tableName string) string {
|
||||||
|
switch {
|
||||||
|
case strings.HasPrefix(tableName, "inventory_daily_summary_"):
|
||||||
|
return "daily"
|
||||||
|
case strings.HasPrefix(tableName, "inventory_monthly_summary_"):
|
||||||
|
return "monthly"
|
||||||
|
default:
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func reportWindowFromTable(tableName string) (time.Time, time.Time, bool) {
|
||||||
|
if strings.HasPrefix(tableName, "inventory_daily_summary_") {
|
||||||
|
suffix := strings.TrimPrefix(tableName, "inventory_daily_summary_")
|
||||||
|
dayStart, err := time.ParseInLocation("20060102", suffix, time.Local)
|
||||||
|
if err != nil {
|
||||||
|
return time.Time{}, time.Time{}, false
|
||||||
|
}
|
||||||
|
return dayStart, dayStart.AddDate(0, 0, 1), true
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(tableName, "inventory_monthly_summary_") {
|
||||||
|
suffix := strings.TrimPrefix(tableName, "inventory_monthly_summary_")
|
||||||
|
monthStart, err := time.ParseInLocation("200601", suffix, time.Local)
|
||||||
|
if err != nil {
|
||||||
|
return time.Time{}, time.Time{}, false
|
||||||
|
}
|
||||||
|
return monthStart, monthStart.AddDate(0, 1, 0), true
|
||||||
|
}
|
||||||
|
return time.Time{}, time.Time{}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func addReportMetadataSheet(logger *slog.Logger, xlsx *excelize.File, meta reportMetadata) {
|
||||||
sheetName := "Metadata"
|
sheetName := "Metadata"
|
||||||
if _, err := xlsx.NewSheet(sheetName); err != nil {
|
if _, err := xlsx.NewSheet(sheetName); err != nil {
|
||||||
logger.Error("Error creating metadata sheet", "error", err)
|
logger.Error("Error creating metadata sheet", "error", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
xlsx.SetCellValue(sheetName, "A1", "ReportGeneratedAt")
|
rows := []struct {
|
||||||
xlsx.SetCellValue(sheetName, "B1", time.Now().Format(time.RFC3339))
|
key string
|
||||||
|
value interface{}
|
||||||
|
}{
|
||||||
|
{"ReportTable", meta.TableName},
|
||||||
|
{"ReportType", meta.ReportType},
|
||||||
|
{"ReportGeneratedAt", meta.GeneratedAt.Format(time.RFC3339)},
|
||||||
|
{"ReportGeneratedAtUTC", meta.GeneratedAt.UTC().Format(time.RFC3339)},
|
||||||
|
{"ReportDuration", meta.Duration.String()},
|
||||||
|
{"ReportDurationSeconds", math.Round(meta.Duration.Seconds()*1000) / 1000},
|
||||||
|
{"RowCount", meta.RowCount},
|
||||||
|
{"ColumnCount", meta.ColumnCount},
|
||||||
|
}
|
||||||
|
if meta.WindowStart != nil && meta.WindowEnd != nil {
|
||||||
|
rows = append(rows,
|
||||||
|
struct {
|
||||||
|
key string
|
||||||
|
value interface{}
|
||||||
|
}{"DataWindowStart", meta.WindowStart.Format(time.RFC3339)},
|
||||||
|
struct {
|
||||||
|
key string
|
||||||
|
value interface{}
|
||||||
|
}{"DataWindowEnd", meta.WindowEnd.Format(time.RFC3339)},
|
||||||
|
struct {
|
||||||
|
key string
|
||||||
|
value interface{}
|
||||||
|
}{"DataWindowTimezone", time.Local.String()},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if meta.DBDriver != "" {
|
||||||
|
rows = append(rows, struct {
|
||||||
|
key string
|
||||||
|
value interface{}
|
||||||
|
}{"DatabaseDriver", meta.DBDriver})
|
||||||
|
}
|
||||||
|
if meta.Duration > 0 && meta.RowCount > 0 {
|
||||||
|
rows = append(rows, struct {
|
||||||
|
key string
|
||||||
|
value interface{}
|
||||||
|
}{"RowsPerSecond", math.Round((float64(meta.RowCount)/meta.Duration.Seconds())*1000) / 1000})
|
||||||
|
}
|
||||||
|
for i, row := range rows {
|
||||||
|
cellKey := fmt.Sprintf("A%d", i+1)
|
||||||
|
cellVal := fmt.Sprintf("B%d", i+1)
|
||||||
|
xlsx.SetCellValue(sheetName, cellKey, row.key)
|
||||||
|
xlsx.SetCellValue(sheetName, cellVal, row.value)
|
||||||
|
}
|
||||||
if err := SetColAutoWidth(xlsx, sheetName); err != nil {
|
if err := SetColAutoWidth(xlsx, sheetName); err != nil {
|
||||||
logger.Error("Error setting metadata auto width", "error", err)
|
logger.Error("Error setting metadata auto width", "error", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user