Skip to content

Commit

Permalink
feature/psa-metrics (#969)
Browse files Browse the repository at this point in the history
Adds metrics:
- upload by type (car, blob, multipart, upload)
- pin requests count
- refactors pins statuses listing
  • Loading branch information
Alexandra Stoica authored Feb 23, 2022
1 parent 352b06d commit d647ecb
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 43 deletions.
2 changes: 2 additions & 0 deletions packages/api/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ export const LOCAL_ADD_THRESHOLD = 1024 * 1024 * 2.5
export const DAG_SIZE_CALC_LIMIT = 1024 * 1024 * 9
// Maximum permitted block size in bytes.
export const MAX_BLOCK_SIZE = 1 << 20 // 1MiB
export const UPLOAD_TYPES = ['Car', 'Blob', 'Multipart', 'Upload']
export const PIN_STATUSES = ['PinQueued', 'Pinning', 'Pinned', 'PinError']
52 changes: 28 additions & 24 deletions packages/api/src/metrics.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* global Response caches */

import { METRICS_CACHE_MAX_AGE } from './constants.js'
import { METRICS_CACHE_MAX_AGE, PIN_STATUSES, UPLOAD_TYPES } from './constants.js'

/**
* Retrieve metrics in prometheus exposition format.
Expand All @@ -21,21 +21,29 @@ export async function metricsGet (request, env, ctx) {
const [
usersTotal,
uploadsTotal,
uploadMetrics,
contentTotalBytes,
pinsTotal,
pinsQueuedTotal,
pinsPinningTotal,
pinsPinnedTotal,
pinsFailedTotal
pinsMetrics,
pinsRequestsTotal
] = await Promise.all([
env.db.getMetricsValue('users_total'),
env.db.getMetricsValue('uploads_total'),
Promise.all(
UPLOAD_TYPES.map(async (t) => ({
type: t,
total: await env.db.getMetricsValue(t)
}))
),
env.db.getMetricsValue('content_bytes_total'),
env.db.getMetricsValue('pins_total'),
env.db.getMetricsValue('pins_status_queued_total'),
env.db.getMetricsValue('pins_status_pinning_total'),
env.db.getMetricsValue('pins_status_pinned_total'),
env.db.getMetricsValue('pins_status_failed_total')
Promise.all(
PIN_STATUSES.map(async (s) => ({
status: s,
total: await env.db.getMetricsValue(s)
}))
),
env.db.getMetricsValue('pin_requests_total')
])

const metrics = [
Expand All @@ -46,6 +54,10 @@ export async function metricsGet (request, env, ctx) {
'# HELP web3storage_uploads_total Total number of user uploads.',
'# TYPE web3storage_uploads_total counter',
`web3storage_uploads_total ${uploadsTotal}`,
...uploadMetrics.map(
({ type, total }) =>
`web3storage_uploads_total{type="${type}"} ${total || 0}`
),

'# HELP web3storage_content_bytes_total Total bytes of all unique DAGs stored.',
'# TYPE web3storage_content_bytes_total counter',
Expand All @@ -54,22 +66,14 @@ export async function metricsGet (request, env, ctx) {
'# HELP web3storage_pins_total Total number of pins on the IPFS Cluster',
'# TYPE web3storage_pins_total counter',
`web3storage_pins_total ${pinsTotal}`,
...pinsMetrics.map(
({ status, total }) =>
`web3storage_pins_total{status="${status}"} ${total || 0}`
),

'# HELP web3storage_pins_status_queued_total Total number of pins that are queued.',
'# TYPE web3storage_pins_status_queued_total counter',
`web3storage_pins_status_queued_total ${pinsQueuedTotal}`,

'# HELP web3storage_pins_status_pinning_total Total number of pins that are pinning.',
'# TYPE web3storage_pins_status_pinning_total counter',
`web3storage_pins_status_pinning_total ${pinsPinningTotal}`,

'# HELP web3storage_pins_status_pinned_total Total number of pins that are pinned.',
'# TYPE web3storage_pins_status_pinned_total counter',
`web3storage_pins_status_pinned_total ${pinsPinnedTotal}`,

'# HELP web3storage_pins_status_failed_total Total number of pins that are failed.',
'# TYPE web3storage_pins_status_failed_total counter',
`web3storage_pins_status_failed_total ${pinsFailedTotal}`
'# HELP web3storage_pin_requests_total Total number of pin requests via Pinning Service API.',
'# TYPE web3storage_pin_requests_total counter',
`web3storage_pin_requests_total ${pinsRequestsTotal}`
].join('\n')

res = new Response(metrics, {
Expand Down
13 changes: 9 additions & 4 deletions packages/api/test/metrics.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@ describe('GET /metrics', () => {
const text = await res.text()
assert(text.includes('web3storage_users_total'))
assert(text.includes('web3storage_uploads_total'))
assert(text.includes('web3storage_uploads_total{type="Car"}'))
assert(text.includes('web3storage_uploads_total{type="Blob"}'))
assert(text.includes('web3storage_uploads_total{type="Multipart"}'))
assert(text.includes('web3storage_uploads_total{type="Upload"}'))
assert(text.includes('web3storage_content_bytes_total'))
assert(text.includes('web3storage_pins_total'))
assert(text.includes('web3storage_pins_status_queued_total'))
assert(text.includes('web3storage_pins_status_pinning_total'))
assert(text.includes('web3storage_pins_status_pinned_total'))
assert(text.includes('web3storage_pins_status_failed_total'))
assert(text.includes('web3storage_pins_total{status="PinQueued"}'))
assert(text.includes('web3storage_pins_total{status="Pinning"}'))
assert(text.includes('web3storage_pins_total{status="Pinned"}'))
assert(text.includes('web3storage_pins_total{status="PinError"}'))
assert(text.includes('web3storage_pin_requests_total'))
})
})
8 changes: 8 additions & 0 deletions packages/api/wrangler.toml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,14 @@ vars = { CLUSTER_API_URL = "https://leslieoa-cluster-api-web3-storage.loca.lt",
[env.leslieoa.durable_objects]
bindings = [{ name = "NAME_ROOM", class_name = "NameRoom0" }]

[env.alexandra]
workers_dev = true
account_id = "a454b0d1615f83ee5d00a63ae152f36f"
vars = { CLUSTER_API_URL = "https://alexandra-cluster-api-web3-storage.loca.lt", PG_REST_URL = "https://alexandra-postgres-api-web3-storage.loca.lt", ENV = "dev" }

[env.alexandra.durable_objects]
bindings = [{ name = "NAME_ROOM", class_name = "NameRoom0" }]

# Add your env here. Override the the values you need to change.

# Create your env name as the value of `whoami` on your system, so you can run `npm start` to run in dev mode.
Expand Down
1 change: 1 addition & 0 deletions packages/db/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export { gql }
export class DBClient {
constructor(config: { endpoint?: string; token: string, postgres?: boolean })
client: PostgrestClient
getMetricsValue (key: string): Promise<{ total: number }>
upsertUser (user: UpsertUserInput): Promise<UpsertUserOutput>
getUser (issuer: string): Promise<UserOutput>
getUsedStorage (userId: number): Promise<number>
Expand Down
23 changes: 17 additions & 6 deletions packages/db/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import {
getPinMetrics,
getPinStatusMetrics,
getContentMetrics,
getPinBytesMetrics
getPinBytesMetrics,
getPinRequestsMetrics,
getUploadTypeMetrics
} from './metrics.js'

const uploadQuery = `
Expand Down Expand Up @@ -806,6 +808,12 @@ export class DBClient {
case 'uploads_total':
res = await getUploadMetrics(this._client)
return res.total
case 'Car':
case 'Blob':
case 'Multipart':
case 'Upload':
res = await getUploadTypeMetrics(this._client, key)
return res.total
case 'content_bytes_total':
res = await getContentMetrics(this._client)
return res.totalBytes
Expand All @@ -815,14 +823,17 @@ export class DBClient {
case 'pins_bytes_total':
res = await getPinBytesMetrics(this._client)
return res.totalBytes
case 'pins_status_queued_total':
case 'pins_status_pinning_total':
case 'pins_status_pinned_total':
case 'pins_status_failed_total':
case 'PinQueued':
case 'Pinning':
case 'Pinned':
case 'PinError':
res = await getPinStatusMetrics(this._client, key)
return res.total
case 'pin_requests_total':
res = await getPinRequestsMetrics(this._client)
return res.total
default:
throw new Error('unknown metric requested')
throw new Error(`unknown metric requested: ${key}`)
}
}

Expand Down
41 changes: 32 additions & 9 deletions packages/db/metrics.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,22 @@ export async function getUploadMetrics (client) {
}
}

export async function getUploadTypeMetrics (client, type) {
const { count, error } = await client
.from('upload')
.select('*', { head: true, count: 'exact' })
.match({ type })
.range(0, 1)

if (error) {
throw new DBError(error)
}

return {
total: count
}
}

export async function getContentMetrics (client) {
const { data, error } = await client.rpc('content_dag_size_total')
if (error) {
Expand Down Expand Up @@ -67,22 +83,29 @@ export async function getPinMetrics (client) {
}
}

const pinStatusMapping = {
pins_status_queued_total: 'PinQueued',
pins_status_pinning_total: 'Pinning',
pins_status_pinned_total: 'Pinned',
pins_status_failed_total: 'PinError'
export async function getPinStatusMetrics (client, status) {
const { data, error } = await client.rpc('pin_from_status_total', { query_status: status })

if (error) {
throw new DBError(error)
}

return {
total: data
}
}

export async function getPinStatusMetrics (client, key) {
const pinStatus = pinStatusMapping[key]
const { data, error } = await client.rpc('pin_from_status_total', { query_status: pinStatus })
export async function getPinRequestsMetrics (client, key) {
const { count, error } = await client
.from('psa_pin_request')
.select('*', { head: true, count: 'exact' })
.range(0, 1)

if (error) {
throw new DBError(error)
}

return {
total: data
total: count
}
}

0 comments on commit d647ecb

Please sign in to comment.