Skip to content
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

feat: experimental - Studio Overview and Performance Widgets #8292

Merged
merged 12 commits into from
May 11, 2023
13 changes: 13 additions & 0 deletions packages/studio/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Contribute to Studio

## Build

### Front End

* `cd packages/studio/frontend`
* be sure to `yarn install`
* `yarn build --emptyOutDir` or `yarn build --emptyOutDir --watch`

### Back End

The backend will build and sync if you're using the project sync from `yarn rwfw`
36 changes: 35 additions & 1 deletion packages/studio/backend/graphql/yoga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@ import { JSONDefinition, JSONResolver } from 'graphql-scalars'
import { createYoga, createSchema } from 'graphql-yoga'

import { authProvider, generateAuthHeaders } from '../services/auth'
import { spanTypeTimeline, spanTreeMapData } from '../services/charts'
import {
spanTypeTimeline,
spanTreeMapData,
spanTypeTimeSeriesData,
} from '../services/charts'
import { studioConfig, webConfig } from '../services/config'
import { span, spans } from '../services/explore/span'
import { traces, trace, traceCount } from '../services/explore/trace'
import { seriesTypeBarList } from '../services/lists'
import { prismaQuerySpans } from '../services/prismaSpans'
import { retypeSpans, truncateSpans } from '../services/span'
import { getAncestorSpans, getDescendantSpans } from '../services/util'
Expand Down Expand Up @@ -70,6 +75,25 @@ export const setupYoga = (fastify: FastifyInstance) => {
axisBottom: JSON
}

# Charts - Line Time Series
type TimeSeriesType {
ts: String!
generic: Float
graphql: Float
http: Float
prisma: Float
redwoodfunction: Float
redwoodservice: Float
sql: Float
}

# Lists - Series Type Lists
type SeriesTypeList {
series_type: String!
series_name: String
quantity: Int!
}

type PrismaQuerySpan {
id: String
trace: String
Expand Down Expand Up @@ -147,7 +171,12 @@ export const setupYoga = (fastify: FastifyInstance) => {
timeLimit: Int!
timeBucket: Int!
): SpanTypeTimelineData
spanTypeTimeSeriesData(timeLimit: Int!): [TimeSeriesType]

# Lists
seriesTypeBarList(timeLimit: Int!): [SeriesTypeList]

# Maps
spanTreeMapData(spanId: String): JSON
}

Expand Down Expand Up @@ -177,6 +206,10 @@ export const setupYoga = (fastify: FastifyInstance) => {
spans,
// Charts
spanTypeTimeline,
spanTypeTimeSeriesData,
// Lists
seriesTypeBarList,
// Maps
spanTreeMapData,
},
Span: {
Expand All @@ -201,6 +234,7 @@ export const setupYoga = (fastify: FastifyInstance) => {
warn: (...args) => args.forEach((arg) => fastify.log.warn(arg)),
error: (...args) => args.forEach((arg) => fastify.log.error(arg)),
},
graphiql: true,
})

return yoga
Expand Down
45 changes: 45 additions & 0 deletions packages/studio/backend/services/charts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,51 @@ import { getDatabase } from '../database'

import { getDescendantSpans, getSpan } from './util'

export async function spanTypeTimeSeriesData(
_parent: unknown,
{
timeLimit,
}: {
timeLimit: number
}
) {
const db = await getDatabase()
const stmt = await db.prepare(`
SELECT
ts,
json_patch (json_object('ts', ts),
json_group_object (series_type,
duration_msec)) AS chartdata
FROM (
SELECT
datetime (start_nano / 1000000000,
'unixepoch',
'utc') AS ts,
replace(coalesce(TYPE, 'generic'), '-', '') AS series_type,
sum(duration_nano / 1000000.0) AS duration_msec
FROM
span
GROUP BY
ts,
series_type
ORDER BY
start_nano ASC,
series_type)
WHERE
ts >= datetime ('now', ?, 'utc')
GROUP BY
ts
ORDER BY
ts ASC;
`)

const result = await stmt.all(`-${timeLimit} seconds`)
await stmt.finalize()
const chartData = result.map((row) => JSON.parse(row['chartdata']))

return chartData
}

export async function spanTypeTimeline(
_parent: unknown,
{
Expand Down
38 changes: 38 additions & 0 deletions packages/studio/backend/services/lists.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { getDatabase } from '../database'

export async function seriesTypeBarList(
_parent: unknown,
{
timeLimit,
}: {
timeLimit: number
}
) {
const db = await getDatabase()
const stmt = await db.prepare(`
SELECT
TYPE AS series_type,
CASE
WHEN instr(brief, '/*') > 0 THEN
substr(substr(brief, 1, instr(brief, '/*') - 1), 0, 255)
ELSE
brief
END AS series_name,
count(brief) AS quantity
FROM
span
WHERE
datetime (start_nano / 1000000000, 'unixepoch', 'utc') >= datetime ('now', ?, 'utc')
AND brief IS NOT NULL
GROUP BY
series_type,
series_name
ORDER BY
quantity DESC;
`)

const result = await stmt.all(`-${timeLimit} seconds`)
await stmt.finalize()

return result
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading