Skip to main content
Glama

mcp-google-sheets

logging-utils.ts4.24 kB
import { isObject, StepOutput } from '@activepieces/shared' import { Queue } from '@datastructures-js/queue' import sizeof from 'object-sizeof' import PriorityQueue from 'priority-queue-typescript' const TRUNCATION_TEXT_PLACEHOLDER = '(truncated)' const ERROR_OFFSET = 256 * 1024 const DEFAULT_MAX_LOG_SIZE_FOR_TESTING = '10' const MAX_LOG_SIZE = Number(process.env.AP_MAX_FILE_SIZE_MB ?? DEFAULT_MAX_LOG_SIZE_FOR_TESTING) * 1024 * 1024 const MAX_SIZE_FOR_ALL_ENTRIES = MAX_LOG_SIZE - ERROR_OFFSET const SIZE_OF_TRUNCATION_TEXT_PLACEHOLDER = sizeof(TRUNCATION_TEXT_PLACEHOLDER) const nonTruncatableKeys: Key[] = ['status', 'duration', 'type'] export const loggingUtils = { async trimExecution(steps: Record<string, StepOutput>): Promise<Record<string, StepOutput>> { const totalJsonSize = sizeof(steps) if (!jsonExceedMaxSize(totalJsonSize)) { return steps } return removeLeavesInTopologicalOrder(JSON.parse(JSON.stringify(steps))) }, } function removeLeavesInTopologicalOrder(json: Record<string, unknown>): Record<string, StepOutput> { const nodes: Node[] = traverseJsonAndConvertToNodes(json) const leaves = new PriorityQueue<Node>( undefined, (a: Node, b: Node) => b.size - a.size, ) nodes.filter((node) => node.numberOfChildren === 0).forEach((node) => leaves.add(node)) let totalJsonSize = sizeof(json) while (!leaves.empty() && jsonExceedMaxSize(totalJsonSize)) { const curNode = leaves.poll() const isDepthGreaterThanOne = curNode && curNode.depth > 1 const isTruncatable = curNode && (!nonTruncatableKeys.includes(curNode.key)) if (isDepthGreaterThanOne && isTruncatable) { totalJsonSize += SIZE_OF_TRUNCATION_TEXT_PLACEHOLDER - curNode.size const parent = curNode.parent parent.value[curNode.key] = TRUNCATION_TEXT_PLACEHOLDER nodes[parent.index].numberOfChildren-- if (nodes[parent.index].numberOfChildren == 0) { leaves.add(nodes[parent.index]) } } } return json as Record<string, StepOutput> } function traverseJsonAndConvertToNodes(root: unknown) { const nodesQueue = new Queue<BfsNode>() nodesQueue.enqueue({ key: '', value: root, parent: { index: -1, value: {} }, depth: 0 }) const nodes: Node[] = [] while (!nodesQueue.isEmpty()) { const curNode = nodesQueue.dequeue() const children = findChildren(curNode.value, curNode.key === 'iterations') nodes.push({ index: nodes.length, size: children.length === 0 ? sizeof(curNode.value) : children.length * SIZE_OF_TRUNCATION_TEXT_PLACEHOLDER, key: curNode.key, parent: { index: curNode.parent.index, value: curNode.parent.value as Record<Key, unknown>, }, numberOfChildren: children.length, depth: curNode.depth, }) children.forEach((child) => { const key = child[0], value = child[1] nodesQueue.enqueue({ value, key, parent: { index: nodes.length - 1, value: curNode.value }, depth: curNode.depth + 1 }) }) } return nodes } function findChildren(curNode: unknown, traverseArray: boolean): [Key, unknown][] { if (isObject(curNode)) { return Object.entries(curNode) } // Array should be treated as a leaf node as If it has too many small items, It will prioritize the other steps first if (Array.isArray(curNode) && traverseArray) { const children: [Key, unknown][] = [] for (let i = 0; i < curNode.length; i++) { children.push([i, curNode[i]]) } return children } return [] } const jsonExceedMaxSize = (jsonSize: number): boolean => { return jsonSize > MAX_SIZE_FOR_ALL_ENTRIES } type Node = { index: number size: number key: Key parent: { index: number value: Record<Key, unknown> } numberOfChildren: number depth: number } type BfsNode = { value: unknown key: Key parent: { index: number value: unknown } depth: number } type Key = string | number | symbol

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/activepieces/activepieces'

If you have feedback or need assistance with the MCP directory API, please join our Discord server