Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 2
Implement total_x metrics#417
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Uh oh!
There was an error while loading. Please reload this page.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| package api | ||
| import ( | ||
| "github.com/gofiber/fiber/v2" | ||
| ) | ||
| func (app *ApiServer) v1MetricsTotalArtists(c *fiber.Ctx) error { | ||
| var total int64 | ||
| if err := app.pool.QueryRow(c.Context(), ` | ||
| SELECT COUNT(*)::bigint | ||
| FROM aggregate_user | ||
| WHERE total_track_count > 0 | ||
| `).Scan(&total); err != nil { | ||
| return err | ||
| } | ||
| return c.JSON(fiber.Map{"data": map[string]int64{"total": total}}) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| package api | ||
| import ( | ||
| "testing" | ||
| "api.audius.co/database" | ||
| ) | ||
| func TestMetricsTotalArtists_Empty(t *testing.T) { | ||
| app := emptyTestApp(t) | ||
| status, body := testGet(t, app, "/v1/metrics/total_artists") | ||
| if status != 200 { | ||
| t.Fatalf("expected 200, got %d: %s", status, string(body)) | ||
| } | ||
| jsonAssert(t, body, map[string]any{ | ||
| "data.total": 0, | ||
| }) | ||
| } | ||
| func TestMetricsTotalArtists_WithFixtures(t *testing.T) { | ||
| app := emptyTestApp(t) | ||
| fixtures := database.FixtureMap{ | ||
| "aggregate_user": { | ||
| {"user_id": 1, "total_track_count": 0}, | ||
| {"user_id": 2, "total_track_count": 3}, | ||
| {"user_id": 3, "total_track_count": 10}, | ||
| }, | ||
| "users": { | ||
| {"user_id": 1, "handle": "u1"}, | ||
| {"user_id": 2, "handle": "u2"}, | ||
| {"user_id": 3, "handle": "u3"}, | ||
| }, | ||
| } | ||
| database.Seed(app.pool.Replicas[0], fixtures) | ||
| status, body := testGet(t, app, "/v1/metrics/total_artists") | ||
| if status != 200 { | ||
| t.Fatalf("expected 200, got %d: %s", status, string(body)) | ||
| } | ||
| jsonAssert(t, body, map[string]any{ | ||
| "data.total": 2, | ||
| }) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| package api | ||
| import ( | ||
| "github.com/gofiber/fiber/v2" | ||
| ) | ||
| func (app *ApiServer) v1MetricsTotalPlays(c *fiber.Ctx) error { | ||
| var total int64 | ||
| if err := app.pool.QueryRow(c.Context(), ` | ||
| SELECT COALESCE(SUM(count), 0)::bigint | ||
| FROM aggregate_plays | ||
| `).Scan(&total); err != nil { | ||
| return err | ||
| } | ||
| return c.JSON(fiber.Map{"data": map[string]int64{"total": total}}) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| package api | ||
| import ( | ||
| "testing" | ||
| "api.audius.co/database" | ||
| ) | ||
| func TestMetricsTotalPlays_Empty(t *testing.T) { | ||
| app := emptyTestApp(t) | ||
| status, body := testGet(t, app, "/v1/metrics/total_plays") | ||
| if status != 200 { | ||
| t.Fatalf("expected 200, got %d: %s", status, string(body)) | ||
| } | ||
| jsonAssert(t, body, map[string]any{ | ||
| "data.total": 0, | ||
| }) | ||
| } | ||
| func TestMetricsTotalPlays_WithFixtures(t *testing.T) { | ||
| app := emptyTestApp(t) | ||
| fixtures := database.FixtureMap{ | ||
| "aggregate_plays": { | ||
| {"play_item_id": 1, "count": 100}, | ||
| {"play_item_id": 2, "count": 50}, | ||
| {"play_item_id": 3, "count": 30}, | ||
| }, | ||
| } | ||
| database.Seed(app.pool.Replicas[0], fixtures) | ||
| status, body := testGet(t, app, "/v1/metrics/total_plays") | ||
| if status != 200 { | ||
| t.Fatalf("expected 200, got %d: %s", status, string(body)) | ||
| } | ||
| jsonAssert(t, body, map[string]any{ | ||
| "data.total": 180, | ||
| }) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package api | ||
| import ( | ||
| "github.com/gofiber/fiber/v2" | ||
| ) | ||
| func (app *ApiServer) v1MetricsTotalWallets(c *fiber.Ctx) error { | ||
| var total int64 | ||
| if err := app.pool.QueryRow(c.Context(), ` | ||
| SELECT SUM(count)::bigint AS total | ||
| FROM ( | ||
| SELECT COUNT(*)::bigint AS count FROM users | ||
| UNION ALL | ||
| SELECT COUNT(*)::bigint AS count FROM sol_claimable_accounts | ||
| ) AS combined | ||
| `).Scan(&total); err != nil { | ||
| return err | ||
| } | ||
| return c.JSON(fiber.Map{"data": map[string]int64{"total": total}}) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| package api | ||
| import ( | ||
| "testing" | ||
| "api.audius.co/database" | ||
| ) | ||
| func TestMetricsTotalWallets_Empty(t *testing.T) { | ||
| app := emptyTestApp(t) | ||
| status, body := testGet(t, app, "/v1/metrics/total_wallets") | ||
| if status != 200 { | ||
| t.Fatalf("expected 200, got %d: %s", status, string(body)) | ||
| } | ||
| jsonAssert(t, body, map[string]any{ | ||
| "data.total": 0, | ||
| }) | ||
| } | ||
| func TestMetricsTotalWallets_WithFixtures(t *testing.T) { | ||
| app := emptyTestApp(t) | ||
| fixtures := database.FixtureMap{ | ||
| "users": { | ||
| {"user_id": 1, "handle": "u1"}, | ||
| {"user_id": 2, "handle": "u2"}, | ||
| {"user_id": 3, "handle": "u3"}, | ||
| {"user_id": 4, "handle": "u4"}, | ||
| }, | ||
| "sol_claimable_accounts": { | ||
| {"signature": "sig1", "instruction_index": 0, "slot": 1, "mint": "mint1", "ethereum_address": "0xabc", "account": "acc1"}, | ||
| {"signature": "sig2", "instruction_index": 0, "slot": 1, "mint": "mint2", "ethereum_address": "0xdef", "account": "acc2"}, | ||
| {"signature": "sig3", "instruction_index": 0, "slot": 1, "mint": "mint3", "ethereum_address": "0xghi", "account": "acc3"}, | ||
| }, | ||
| } | ||
| database.Seed(app.pool.Replicas[0], fixtures) | ||
| status, body := testGet(t, app, "/v1/metrics/total_wallets") | ||
| if status != 200 { | ||
| t.Fatalf("expected 200, got %d: %s", status, string(body)) | ||
| } | ||
| jsonAssert(t, body, map[string]any{ | ||
| "data.total": 7, | ||
| }) | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I'm on a bigint kick lately.
This feels slightly off, as JSON can't represent an int64. I wonder if it just lets it truncate if you exceed the limits.
Supposedly, it should serialize as a string if you want to represent an int64.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JSON can represent it, it's JS that can't handle it w/o precision loss. I do agree that it should be a string, but i don't think that's worth the annoyance of translating it from a number everywhere we use it. we'll ever get anywhere near 2^53 for this