Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/workers-observability/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
"dependencies": {
"@cloudflare/workers-oauth-provider": "0.0.5",
"@fast-csv/format": "^5.0.2",
"@hono/zod-validator": "0.4.3",
"@modelcontextprotocol/sdk": "1.10.2",
"@repo/mcp-common": "workspace:*",
Expand Down
112 changes: 110 additions & 2 deletions apps/workers-observability/src/tools/observability.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { writeToString } from '@fast-csv/format'

import {
handleWorkerLogsKeys,
handleWorkerLogsValues,
Expand Down Expand Up @@ -60,6 +62,103 @@ This tool provides three primary views of your Worker data:
}
try {
const response = await queryWorkersObservability(agent.props.accessToken, accountId, query)

if (query.view === 'calculations') {
let data = 'DISPLAY THE CALCULATIONS IN A GRAPHICAL WAY'
for (const calculation of response?.calculations || []) {
const alias = calculation.alias || calculation.calculation
const aggregates = calculation.aggregates.map((agg) => {
const keys = agg.groups?.reduce(
(acc, group) => {
acc[`${group.key}`] = `${group.value}`
return acc
},
{} as Record<string, string>
)
return {
...keys,
[alias]: agg.value,
}
})

const aggregatesString = await writeToString(aggregates, {
headers: true,
delimiter: '\t',
})

const series = calculation.series.map(({ time, data }) => {
return {
time,
...data.reduce(
(acc, point) => {
const key = point.groups?.reduce((acc, group) => {
return `${acc} * ${group.value}`
}, '')
if (!key) {
return {
...acc,
[alias]: point.value,
}
}
return {
...acc,
key,
[alias]: point.value,
}
},
{} as Record<string, string | number | undefined>
),
}
})
const seriesString = await writeToString(series, { headers: true, delimiter: '\t' })
data = data + '\n' + `## ${alias}`
data = data + '\n' + `### Aggregation`
data = data + '\n' + aggregatesString
data = data + '\n' + `### Series`
data = data + '\n' + seriesString
}

return {
content: [
{
type: 'text',
text: data,
},
],
}
}

if(query.view === 'events') {
const events = response?.events?.events
return {
content: [
{
type: 'text',
text: JSON.stringify(events),
},
],
}
}

if(query.view === 'invocations') {
const invocations = Object.entries(response?.invocations || {}).map(([_, logs]) => {
const invocationLog = logs.find((log) => log.$metadata.type === 'cf-worker-event')
return invocationLog?.$metadata ?? logs[0]?.$metadata
});

const tsv = await writeToString(
invocations,
{ headers: true, delimiter: '\t' }
)
return {
content: [
{
type: 'text',
text: tsv,
},
],
}
}
return {
content: [
{
Expand Down Expand Up @@ -110,11 +209,16 @@ This tool provides three primary views of your Worker data:
}
try {
const result = await handleWorkerLogsKeys(agent.props.accessToken, accountId, keysQuery)

const tsv = await writeToString(
result.map((key) => ({ type: key.type, key: key.key })),
{ headers: true, delimiter: '\t' }
)
return {
content: [
{
type: 'text',
text: JSON.stringify(result),
text: tsv,
},
],
}
Expand Down Expand Up @@ -155,11 +259,15 @@ This tool provides three primary views of your Worker data:
}
try {
const result = await handleWorkerLogsValues(agent.props.accessToken, accountId, valuesQuery)
const tsv = await writeToString(
result?.map((value) => ({ type: value.type, value: value.value })) || [],
{ headers: true, delimiter: '\t' }
)
return {
content: [
{
type: 'text',
text: JSON.stringify(result),
text: tsv,
},
],
}
Expand Down
40 changes: 40 additions & 0 deletions pnpm-lock.yaml

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

Loading