storagenode: fix hour_interval for first day defaulted to 24h
Previously because of the use of a LAG to calculate the hour_interval the first record, which is usually the first day of the month usually, doesn’t have a previous record and always assumes the at_rest_total is for 24 hours. Resolves https://github.com/storj/storj/issues/5390 Change-Id: Id532f8b38fe9df61432e62655318ff119a733d13
This commit is contained in:
parent
93fad70e4b
commit
951d5db7f7
@ -54,21 +54,28 @@ func (db *storageUsageDB) GetDaily(ctx context.Context, satelliteID storj.NodeID
|
|||||||
|
|
||||||
// hour_interval = current row interval_end_time - previous row interval_end_time
|
// hour_interval = current row interval_end_time - previous row interval_end_time
|
||||||
// Rows with 0-hour difference are assumed to be 24 hours.
|
// Rows with 0-hour difference are assumed to be 24 hours.
|
||||||
query := `SELECT satellite_id,
|
query := `SELECT su1.satellite_id,
|
||||||
at_rest_total,
|
su1.at_rest_total,
|
||||||
COALESCE(
|
COALESCE(
|
||||||
(
|
(
|
||||||
CAST(strftime('%s', interval_end_time) AS NUMERIC)
|
CAST(strftime('%s', su1.interval_end_time) AS NUMERIC)
|
||||||
-
|
-
|
||||||
CAST(strftime('%s', LAG(interval_end_time) OVER (PARTITION BY satellite_id ORDER BY interval_end_time)) AS NUMERIC)
|
CAST(strftime('%s', (
|
||||||
|
SELECT interval_end_time
|
||||||
|
FROM storage_usage
|
||||||
|
WHERE satellite_id = su1.satellite_id
|
||||||
|
AND timestamp < su1.timestamp
|
||||||
|
ORDER BY timestamp DESC
|
||||||
|
LIMIT 1
|
||||||
|
)) AS NUMERIC)
|
||||||
) / 3600,
|
) / 3600,
|
||||||
24
|
24
|
||||||
) AS hour_interval,
|
) AS hour_interval,
|
||||||
timestamp
|
su1.timestamp
|
||||||
FROM storage_usage
|
FROM storage_usage su1
|
||||||
WHERE satellite_id = ?
|
WHERE su1.satellite_id = ?
|
||||||
AND ? <= timestamp AND timestamp <= ?
|
AND ? <= su1.timestamp AND su1.timestamp <= ?
|
||||||
ORDER BY timestamp`
|
ORDER BY su1.timestamp ASC`
|
||||||
|
|
||||||
rows, err := db.QueryContext(ctx, query, satelliteID, from.UTC(), to.UTC())
|
rows, err := db.QueryContext(ctx, query, satelliteID, from.UTC(), to.UTC())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -106,22 +113,30 @@ func (db *storageUsageDB) GetDailyTotal(ctx context.Context, from, to time.Time)
|
|||||||
|
|
||||||
// hour_interval = current row interval_end_time - previous row interval_end_time
|
// hour_interval = current row interval_end_time - previous row interval_end_time
|
||||||
// Rows with 0-hour difference are assumed to be 24 hours.
|
// Rows with 0-hour difference are assumed to be 24 hours.
|
||||||
query := `SELECT SUM(usages.at_rest_total), SUM(usages.hour_interval), usages.timestamp
|
query := `SELECT SUM(su3.at_rest_total), SUM(su3.hour_interval), su3.timestamp
|
||||||
FROM (
|
FROM (
|
||||||
SELECT at_rest_total, timestamp,
|
SELECT su1.at_rest_total,
|
||||||
COALESCE(
|
COALESCE(
|
||||||
(
|
(
|
||||||
CAST(strftime('%s', interval_end_time) AS NUMERIC)
|
CAST(strftime('%s', su1.interval_end_time) AS NUMERIC)
|
||||||
-
|
-
|
||||||
CAST(strftime('%s', LAG(interval_end_time) OVER (PARTITION BY satellite_id ORDER BY interval_end_time)) AS NUMERIC)
|
CAST(strftime('%s', (
|
||||||
|
SELECT interval_end_time
|
||||||
|
FROM storage_usage su2
|
||||||
|
WHERE su2.satellite_id = su1.satellite_id
|
||||||
|
AND su2.timestamp < su1.timestamp
|
||||||
|
ORDER BY su2.timestamp DESC
|
||||||
|
LIMIT 1
|
||||||
|
)) AS NUMERIC)
|
||||||
) / 3600,
|
) / 3600,
|
||||||
24
|
24
|
||||||
) AS hour_interval
|
) AS hour_interval,
|
||||||
FROM storage_usage
|
su1.timestamp
|
||||||
WHERE ? <= timestamp AND timestamp <= ?
|
FROM storage_usage su1
|
||||||
) as usages
|
WHERE ? <= su1.timestamp AND su1.timestamp <= ?
|
||||||
GROUP BY usages.timestamp
|
) as su3
|
||||||
ORDER BY usages.timestamp`
|
GROUP BY su3.timestamp
|
||||||
|
ORDER BY su3.timestamp ASC`
|
||||||
|
|
||||||
rows, err := db.QueryContext(ctx, query, from.UTC(), to.UTC())
|
rows, err := db.QueryContext(ctx, query, from.UTC(), to.UTC())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -157,23 +172,30 @@ func (db *storageUsageDB) Summary(ctx context.Context, from, to time.Time) (_, _
|
|||||||
defer mon.Task()(&ctx, from, to)(&err)
|
defer mon.Task()(&ctx, from, to)(&err)
|
||||||
var summary, averageUsageInBytes sql.NullFloat64
|
var summary, averageUsageInBytes sql.NullFloat64
|
||||||
|
|
||||||
query := `SELECT SUM(usages.at_rest_total), AVG(usages.at_rest_total_bytes)
|
query := `SELECT SUM(su3.at_rest_total), AVG(su3.at_rest_total_bytes)
|
||||||
FROM (
|
FROM (
|
||||||
SELECT
|
SELECT
|
||||||
at_rest_total,
|
at_rest_total,
|
||||||
at_rest_total / (
|
at_rest_total / (
|
||||||
COALESCE(
|
COALESCE(
|
||||||
(
|
(
|
||||||
CAST(strftime('%s', interval_end_time) AS NUMERIC)
|
CAST(strftime('%s', su1.interval_end_time) AS NUMERIC)
|
||||||
-
|
-
|
||||||
CAST(strftime('%s', LAG(interval_end_time) OVER (PARTITION BY satellite_id ORDER BY interval_end_time)) AS NUMERIC)
|
CAST(strftime('%s', (
|
||||||
|
SELECT interval_end_time
|
||||||
|
FROM storage_usage su2
|
||||||
|
WHERE su2.satellite_id = su1.satellite_id
|
||||||
|
AND su2.timestamp < su1.timestamp
|
||||||
|
ORDER BY su2.timestamp DESC
|
||||||
|
LIMIT 1
|
||||||
|
)) AS NUMERIC)
|
||||||
) / 3600,
|
) / 3600,
|
||||||
24
|
24
|
||||||
)
|
)
|
||||||
) AS at_rest_total_bytes
|
) AS at_rest_total_bytes
|
||||||
FROM storage_usage
|
FROM storage_usage su1
|
||||||
WHERE ? <= timestamp AND timestamp <= ?
|
WHERE ? <= timestamp AND timestamp <= ?
|
||||||
) as usages`
|
) as su3`
|
||||||
|
|
||||||
err = db.QueryRowContext(ctx, query, from.UTC(), to.UTC()).Scan(&summary, &averageUsageInBytes)
|
err = db.QueryRowContext(ctx, query, from.UTC(), to.UTC()).Scan(&summary, &averageUsageInBytes)
|
||||||
return summary.Float64, averageUsageInBytes.Float64, err
|
return summary.Float64, averageUsageInBytes.Float64, err
|
||||||
@ -184,24 +206,31 @@ func (db *storageUsageDB) SatelliteSummary(ctx context.Context, satelliteID stor
|
|||||||
defer mon.Task()(&ctx, satelliteID, from, to)(&err)
|
defer mon.Task()(&ctx, satelliteID, from, to)(&err)
|
||||||
var summary, averageUsageInBytes sql.NullFloat64
|
var summary, averageUsageInBytes sql.NullFloat64
|
||||||
|
|
||||||
query := `SELECT SUM(usages.at_rest_total), AVG(usages.at_rest_total_bytes)
|
query := `SELECT SUM(su3.at_rest_total), AVG(su3.at_rest_total_bytes)
|
||||||
FROM (
|
FROM (
|
||||||
SELECT
|
SELECT
|
||||||
at_rest_total,
|
at_rest_total,
|
||||||
at_rest_total / (
|
at_rest_total / (
|
||||||
COALESCE(
|
COALESCE(
|
||||||
(
|
(
|
||||||
CAST(strftime('%s', interval_end_time) AS NUMERIC)
|
CAST(strftime('%s', su1.interval_end_time) AS NUMERIC)
|
||||||
-
|
-
|
||||||
CAST(strftime('%s', LAG(interval_end_time) OVER (PARTITION BY satellite_id ORDER BY interval_end_time)) AS NUMERIC)
|
CAST(strftime('%s', (
|
||||||
|
SELECT interval_end_time
|
||||||
|
FROM storage_usage su2
|
||||||
|
WHERE su2.satellite_id = su1.satellite_id
|
||||||
|
AND su2.timestamp < su1.timestamp
|
||||||
|
ORDER BY su2.timestamp DESC
|
||||||
|
LIMIT 1
|
||||||
|
)) AS NUMERIC)
|
||||||
) / 3600,
|
) / 3600,
|
||||||
24
|
24
|
||||||
)
|
)
|
||||||
) AS at_rest_total_bytes
|
) AS at_rest_total_bytes
|
||||||
FROM storage_usage
|
FROM storage_usage su1
|
||||||
WHERE satellite_id = ?
|
WHERE satellite_id = ?
|
||||||
AND ? <= timestamp AND timestamp <= ?
|
AND ? <= timestamp AND timestamp <= ?
|
||||||
) as usages`
|
) as su3`
|
||||||
|
|
||||||
err = db.QueryRowContext(ctx, query, satelliteID, from.UTC(), to.UTC()).Scan(&summary, &averageUsageInBytes)
|
err = db.QueryRowContext(ctx, query, satelliteID, from.UTC(), to.UTC()).Scan(&summary, &averageUsageInBytes)
|
||||||
return summary.Float64, averageUsageInBytes.Float64, err
|
return summary.Float64, averageUsageInBytes.Float64, err
|
||||||
|
@ -81,7 +81,8 @@ func TestStorageUsage(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("get daily", func(t *testing.T) {
|
t.Run("get daily", func(t *testing.T) {
|
||||||
res, err := storageUsageDB.GetDaily(ctx, satelliteID, time.Time{}, now)
|
from := now.AddDate(0, 0, -20)
|
||||||
|
res, err := storageUsageDB.GetDaily(ctx, satelliteID, from, now)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, res)
|
assert.NotNil(t, res)
|
||||||
|
|
||||||
@ -143,17 +144,17 @@ func TestEmptyStorageUsage(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("summary satellite", func(t *testing.T) {
|
t.Run("summary satellite", func(t *testing.T) {
|
||||||
summ, hourInterval, err := storageUsageDB.SatelliteSummary(ctx, storj.NodeID{}, time.Time{}, now)
|
summ, averageUsageInBytes, err := storageUsageDB.SatelliteSummary(ctx, storj.NodeID{}, time.Time{}, now)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, emptySummary, summ)
|
assert.Equal(t, emptySummary, summ)
|
||||||
assert.Equal(t, zeroHourInterval, hourInterval)
|
assert.Equal(t, zeroHourInterval, averageUsageInBytes)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("summary", func(t *testing.T) {
|
t.Run("summary", func(t *testing.T) {
|
||||||
summ, hourInterval, err := storageUsageDB.Summary(ctx, time.Time{}, now)
|
summ, averageUsageInBytes, err := storageUsageDB.Summary(ctx, time.Time{}, now)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, emptySummary, summ)
|
assert.Equal(t, emptySummary, summ)
|
||||||
assert.Equal(t, zeroHourInterval, hourInterval)
|
assert.Equal(t, zeroHourInterval, averageUsageInBytes)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user