@fluid-tools/fetch-tool 1.2.7 → 2.0.0-dev.1.3.0.96595

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -24,6 +24,20 @@ In order to connect to ODSP, the clientID and clientSecret must be set as enviro
24
24
  --snapshotVersionIndex <number> : Index of the version to dump
25
25
  --saveDir <outdir> : Save data of the snapshots and messages
26
26
 
27
+ ### Tips
28
+
29
+ - If not done already run `npm run build`
30
+ - Example command - run `node bin/fluid-fetch --saveDir example 'URL'` in the `fetch-tool` directory
31
+ - An example URL is something from office.com that looks like `https://www.office.com/launch/fluid/...`
32
+ - This command creates an `example` directory (if it doesn't exist) in the `fetch-tool` folder.
33
+ - If run multiple times without clearing the `example` directory, the snapshot will overwrite any old folders or files.
34
+ - Looking at the `example` directory:
35
+ - Go to `1-XYZ/decoded/tree.json` to see the snapshot tree.
36
+ - Each `'#-XYZ'` string in the `tree.json` correlates to a file in the decoded folder. These files are essentially blobs.
37
+ - `0-XYZ/decoded/tree.json` is an older snapshot tree.
38
+ - The `messages.json` is a list of ops/messages that are stored.
39
+ - For 401 authentication errors, as stated above, check that [getkeys](../../../tools/getkeys) has been run.
40
+
27
41
  ## Example Output
28
42
 
29
43
  ### Messages Stats
@@ -1 +1 @@
1
- {"version":3,"file":"fluidAnalyzeMessages.d.ts","sourceRoot":"","sources":["../src/fluidAnalyzeMessages.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAyEH,eAAO,MAAM,YAAY,QAAS,MAAM,KAAG,MAA8D,CAAC;AAgW1G,wBAAsB,iBAAiB,CACnC,SAAS,KAAA,EAAE,+CAA+C;AAC1D,gBAAgB,EAAE,OAAO,EACzB,YAAY,EAAE,OAAO,EACrB,iBAAiB,GAAE,GAAG,CAAC,MAAM,CAAqB,iBAwCrD"}
1
+ {"version":3,"file":"fluidAnalyzeMessages.d.ts","sourceRoot":"","sources":["../src/fluidAnalyzeMessages.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAwEH,eAAO,MAAM,YAAY,QAAS,MAAM,KAAG,MAA8D,CAAC;AAgW1G,wBAAsB,iBAAiB,CACnC,SAAS,KAAA,EAAE,+CAA+C;AAC1D,gBAAgB,EAAE,OAAO,EACzB,YAAY,EAAE,OAAO,EACrB,iBAAiB,GAAE,GAAG,CAAC,MAAM,CAAqB,iBAwCrD"}
@@ -414,25 +414,24 @@ dumpMessageStats, dumpMessages, messageTypeFilter = new Set()) {
414
414
  console.log("");
415
415
  }
416
416
  exports.printMessageStats = printMessageStats;
417
- function processOp(message, dataType, objectStats, msgSize, dataTypeStats, messageTypeStats, chunkMap) {
418
- let type = message.type;
417
+ function processOp(runtimeMessage, dataType, objectStats, msgSize, dataTypeStats, messageTypeStats, chunkMap) {
418
+ let type = runtimeMessage.type;
419
419
  let recorded = false;
420
420
  let totalMsgSize = msgSize;
421
421
  let opCount = 1;
422
- if ((0, container_runtime_1.isRuntimeMessage)(message)) {
423
- let runtimeMessage = (0, container_runtime_1.unpackRuntimeMessage)(message);
422
+ if ((0, container_runtime_1.unpackRuntimeMessage)(runtimeMessage)) {
424
423
  const messageType = runtimeMessage.type;
425
424
  switch (messageType) {
426
- case container_runtime_1.RuntimeMessage.Attach: {
425
+ case container_runtime_1.ContainerMessageType.Attach: {
427
426
  const attachMessage = runtimeMessage.contents;
428
427
  processDataStoreAttachOp(attachMessage, dataType);
429
428
  break;
430
429
  }
431
430
  // skip for now because these ops do not have contents
432
- case container_runtime_1.RuntimeMessage.BlobAttach: {
431
+ case container_runtime_1.ContainerMessageType.BlobAttach: {
433
432
  break;
434
433
  }
435
- case container_runtime_1.RuntimeMessage.ChunkedOp: {
434
+ case container_runtime_1.ContainerMessageType.ChunkedOp: {
436
435
  const chunk = runtimeMessage.contents;
437
436
  if (!chunkMap.has(runtimeMessage.clientId)) {
438
437
  chunkMap.set(runtimeMessage.clientId, {
@@ -451,22 +450,21 @@ function processOp(message, dataType, objectStats, msgSize, dataTypeStats, messa
451
450
  value.totalSize += msgSize;
452
451
  if (chunk.chunkId === chunk.totalChunks) {
453
452
  opCount = chunk.totalChunks; // 1 op for each chunk.
454
- runtimeMessage = Object.create(runtimeMessage);
455
- runtimeMessage.contents = chunks.join("");
456
- runtimeMessage.type = chunk.originalType;
453
+ const patchedMessage = Object.create(runtimeMessage);
454
+ patchedMessage.contents = chunks.join("");
455
+ patchedMessage.type = chunk.originalType;
457
456
  type = chunk.originalType;
458
457
  totalMsgSize = value.totalSize;
459
- chunkMap.delete(runtimeMessage.clientId);
458
+ chunkMap.delete(patchedMessage.clientId);
460
459
  }
461
460
  else {
462
461
  return;
463
462
  }
464
463
  // eslint-disable-next-line no-fallthrough
465
464
  }
466
- case container_runtime_1.RuntimeMessage.FluidDataStoreOp:
467
- case container_runtime_1.RuntimeMessage.Alias:
468
- case container_runtime_1.RuntimeMessage.Rejoin:
469
- case container_runtime_1.RuntimeMessage.Operation:
465
+ case container_runtime_1.ContainerMessageType.FluidDataStoreOp:
466
+ case container_runtime_1.ContainerMessageType.Alias:
467
+ case container_runtime_1.ContainerMessageType.Rejoin:
470
468
  {
471
469
  let envelope = runtimeMessage.contents;
472
470
  // TODO: Legacy?
@@ -541,13 +539,7 @@ function processDataStoreAttachOp(attachMessage, dataType) {
541
539
  // dataType.set(getObjectId(attachMessage.id), attachMessage.type);
542
540
  // That's data store, and it brings a bunch of data structures.
543
541
  // Let's try to crack it.
544
- let parsedAttachMessage;
545
- if (typeof attachMessage === "string") {
546
- parsedAttachMessage = JSON.parse(attachMessage);
547
- }
548
- else {
549
- parsedAttachMessage = attachMessage;
550
- }
542
+ const parsedAttachMessage = typeof attachMessage === "string" ? JSON.parse(attachMessage) : attachMessage;
551
543
  for (const entry of parsedAttachMessage.snapshot.entries) {
552
544
  if (entry.type === protocol_definitions_1.TreeEntry.Tree) {
553
545
  for (const entry2 of entry.value.entries) {
@@ -1 +1 @@
1
- {"version":3,"file":"fluidAnalyzeMessages.js","sourceRoot":"","sources":["../src/fluidAnalyzeMessages.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert, unreachableCase } from \"@fluidframework/common-utils\";\nimport {\n ISequencedDocumentMessage,\n ISummaryProposal,\n MessageType,\n TreeEntry,\n} from \"@fluidframework/protocol-definitions\";\nimport { IAttachMessage, IEnvelope } from \"@fluidframework/runtime-definitions\";\nimport {\n IChunkedOp,\n isRuntimeMessage,\n RuntimeMessage,\n unpackRuntimeMessage,\n} from \"@fluidframework/container-runtime\";\nimport { DataStoreMessageType } from \"@fluidframework/datastore\";\n\nconst noClientName = \"No Client\";\nconst objectTypePrefix = \"https://graph.microsoft.com/types/\";\n\nfunction incr(map: Map<string, [number, number]>, key: string, size: number, count = 1) {\n const value = map.get(key);\n if (value === undefined) {\n map.set(key, [count, size]);\n } else {\n value[0] += count;\n value[1] += size;\n map.set(key, value);\n }\n}\n\ninterface ISessionInfo {\n startSeq: number;\n opCount: number;\n email: string;\n duration: number;\n}\n\ninterface IMessageAnalyzer {\n processOp(op: ISequencedDocumentMessage, msgSize: number, filteredOutOp: boolean): void;\n reportAnalyzes(lastOp: ISequencedDocumentMessage): void;\n}\n\n/**\n * Helper class to track session statistics\n */\nclass ActiveSession {\n public static create(email: string, message: ISequencedDocumentMessage) {\n return new ActiveSession(email, message);\n }\n\n private opCount = 0;\n\n constructor(private readonly email: string, private readonly startMessage: ISequencedDocumentMessage) {\n }\n\n public reportOp(timestamp: number) {\n this.opCount++;\n }\n\n public leave(timestamp: number): ISessionInfo {\n return {\n opCount: this.opCount,\n email: this.email,\n startSeq: this.startMessage.sequenceNumber,\n duration: timestamp - this.startMessage.timestamp,\n };\n }\n}\n\n// Format a number separating 3 digits by comma\n// eslint-disable-next-line unicorn/no-unsafe-regex\nexport const formatNumber = (num: number): string => num.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\n\nfunction dumpStats(\n map: Map<string, [number, number]>,\n props: {\n title: string;\n headers: [string, string];\n lines?: number;\n orderByFirstColumn?: boolean;\n reverseColumnsInUI?: boolean;\n removeTotals?: boolean;\n reverseSort?: boolean;\n }) {\n const fieldSizes = [10, 14];\n const nameLength = 72;\n const fieldsLength = fieldSizes[0] + fieldSizes[1] + 1;\n let headers = props.headers;\n\n let recordsToShow = props.lines ?? 10;\n if (map.size !== recordsToShow && props.removeTotals === undefined && recordsToShow > 1) {\n recordsToShow--;\n }\n\n let sorted: [string, [number, number]][];\n const sortIndex = props.orderByFirstColumn === true ? 0 : 1;\n let add: string;\n if (props.reverseSort !== undefined) {\n sorted = [...map.entries()].sort((a, b) => a[1][sortIndex] - b[1][sortIndex]);\n add = \"↑\";\n } else {\n sorted = [...map.entries()].sort((a, b) => b[1][sortIndex] - a[1][sortIndex]);\n add = \"↓\";\n }\n headers[sortIndex] = `${headers[sortIndex]} ${add}`;\n\n if (props.reverseColumnsInUI !== undefined) {\n headers = [headers[1], headers[0]];\n const sorted2: [string, [number, number]][] = [];\n for (const [name, [count, size]] of sorted) {\n sorted2.push([name, [size, count]]);\n }\n sorted = sorted2;\n }\n\n let totalCount = 0;\n let sizeTotal = 0;\n\n props.title = `${props.title} (${sorted.length})`;\n const header0 = headers[0].padStart(fieldSizes[0]);\n let overflow = header0.length - fieldSizes[0];\n console.log(`\\n\\n${props.title.padEnd(nameLength)} │ ${header0} ${headers[1].padStart(fieldSizes[1] - overflow)}`);\n\n console.log(`${\"─\".repeat(nameLength + 1)}┼${\"─\".repeat(fieldsLength + 1)}`);\n let index = 0;\n let allOtherCount = 0;\n let allOtherSize = 0;\n for (const [name, [count, size]] of sorted) {\n index++;\n totalCount += count;\n sizeTotal += size;\n if (index <= recordsToShow) {\n const item = name.padEnd(nameLength);\n overflow = item.length - nameLength;\n const col1 = formatNumber(count).padStart(fieldSizes[0] - overflow);\n overflow += col1.length - fieldSizes[0];\n const col2 = formatNumber(size).padStart(fieldSizes[1] - overflow);\n console.log(`${item} │ ${col1} ${col2}`);\n } else {\n allOtherCount += count;\n allOtherSize += size;\n }\n }\n\n if (props.removeTotals === undefined) {\n if (allOtherCount || allOtherSize) {\n // eslint-disable-next-line max-len\n console.log(`${`All Others (${sorted.length - recordsToShow})`.padEnd(nameLength)} │ ${formatNumber(allOtherCount).padStart(fieldSizes[0])} ${formatNumber(allOtherSize).padStart(fieldSizes[1])}`);\n }\n console.log(`${\"─\".repeat(nameLength + 1)}┼${\"─\".repeat(fieldsLength + 1)}`);\n // eslint-disable-next-line max-len\n console.log(`${\"Total\".padEnd(nameLength)} │ ${formatNumber(totalCount).padStart(fieldSizes[0])} ${formatNumber(sizeTotal).padStart(fieldSizes[1])}`);\n }\n}\n\nconst getObjectId = (dataStoreId: string, id: string) => `[${dataStoreId}]/${id}`;\n\n/**\n * Analyzer for sessions\n */\nclass SessionAnalyzer implements IMessageAnalyzer {\n private readonly sessionsInProgress = new Map<string, ActiveSession>();\n private readonly sessions = new Map<string, [number, number]>();\n private readonly users = new Map<string, [number, number]>();\n\n private first = true;\n\n public processOp(message: ISequencedDocumentMessage, msgSize: number, skipMessage: boolean): void {\n if (this.first) {\n this.first = false;\n // Start of the road.\n const noNameSession = ActiveSession.create(noClientName, message);\n this.sessionsInProgress.set(noClientName, noNameSession);\n }\n const session = processQuorumMessages(\n message,\n skipMessage,\n this.sessionsInProgress,\n this.sessions,\n this.users);\n if (!skipMessage && session) {\n session.reportOp(message.timestamp);\n }\n }\n\n public reportAnalyzes(lastOp: ISequencedDocumentMessage): void {\n // Close any open sessions\n reportOpenSessions(\n lastOp.timestamp,\n this.sessionsInProgress,\n this.sessions,\n this.users);\n dumpStats(this.users, {\n title: \"Users\",\n headers: [\"Sessions\", \"Op count\"],\n reverseColumnsInUI: true,\n lines: 6,\n });\n dumpStats(this.sessions, {\n title: \"Sessions\",\n headers: [\"Duration(s)\", \"Op count\"],\n reverseColumnsInUI: true,\n lines: 6,\n });\n dumpStats(this.sessions, {\n title: \"Sessions\",\n headers: [\"Duration(s)\", \"Op count\"],\n orderByFirstColumn: true,\n reverseColumnsInUI: true,\n removeTotals: true,\n lines: 5,\n });\n }\n}\n\n/**\n * Analyzer for data structures\n */\nclass DataStructureAnalyzer implements IMessageAnalyzer {\n private readonly messageTypeStats = new Map<string, [number, number]>();\n private readonly dataType = new Map<string, string>();\n private readonly dataTypeStats = new Map<string, [number, number]>();\n private readonly objectStats = new Map<string, [number, number]>();\n private readonly chunkMap = new Map<string, { chunks: string[]; totalSize: number; }>();\n\n public processOp(message: ISequencedDocumentMessage, msgSize: number, skipMessage: boolean): void {\n if (!skipMessage) {\n processOp(\n message,\n this.dataType,\n this.objectStats,\n msgSize,\n this.dataTypeStats,\n this.messageTypeStats,\n this.chunkMap);\n }\n }\n\n public reportAnalyzes(lastOp: ISequencedDocumentMessage): void {\n dumpStats(this.messageTypeStats, {\n title: \"Message Type\",\n headers: [\"Op count\", \"Bytes\"],\n lines: 20,\n });\n dumpStats(calcChannelStats(this.dataType, this.objectStats), {\n title: \"Channel name\",\n headers: [\"Op count\", \"Bytes\"],\n lines: 7,\n });\n /*\n dumpStats(this.dataTypeStats, {\n title: \"Channel type\",\n headers: [\"Op count\", \"Bytes\"],\n });\n */\n }\n}\n\n/**\n * Helper class to report if we filtered out any messages.\n */\nclass FilteredMessageAnalyzer implements IMessageAnalyzer {\n private sizeTotal = 0;\n private opsTotal = 0;\n private sizeFiltered = 0;\n private opsFiltered = 0;\n private filtered = false;\n\n public processOp(message: ISequencedDocumentMessage, msgSize: number, skipMessage: boolean): void {\n this.sizeTotal += msgSize;\n this.opsTotal++;\n if (!skipMessage) {\n this.sizeFiltered += msgSize;\n this.opsFiltered++;\n } else {\n this.filtered = true;\n }\n }\n\n public reportAnalyzes(lastOp: ISequencedDocumentMessage): void {\n if (this.filtered) {\n // eslint-disable-next-line max-len\n console.log(`\\nData is filtered according to --filter:messageType argument(s):\\nOp size: ${this.sizeFiltered} / ${this.sizeTotal}\\nOp count ${this.opsFiltered} / ${this.opsTotal}`);\n }\n if (this.opsTotal === 0) {\n console.error(\"No ops were found\");\n }\n }\n}\n\n/**\n * Helper class to find places where we generated too many ops\n */\nclass MessageDensityAnalyzer implements IMessageAnalyzer {\n private readonly opChunk = 1000;\n private opLimit = 1;\n private size = 0;\n private timeStart = 0;\n private doctimerStart = 0;\n private readonly ranges = new Map<string, [number, number]>();\n\n public processOp(message: ISequencedDocumentMessage, msgSize: number, skipMessage: boolean): void {\n if (message.sequenceNumber >= this.opLimit) {\n if (message.sequenceNumber !== 1) {\n const timeDiff = durationFromTime(message.timestamp - this.timeStart);\n const opsString = `ops = [${this.opLimit - this.opChunk}, ${this.opLimit - 1}]`.padEnd(26);\n // eslint-disable-next-line max-len\n const timeString = `time = [${durationFromTime(this.timeStart - this.doctimerStart)}, ${durationFromTime(message.timestamp - this.doctimerStart)}]`;\n this.ranges.set(\n `${opsString} ${timeString}`,\n [timeDiff, this.size]);\n } else {\n this.doctimerStart = message.timestamp;\n }\n this.opLimit += this.opChunk;\n this.size = 0;\n this.timeStart = message.timestamp;\n }\n if (!skipMessage) {\n this.size += msgSize;\n }\n }\n\n public reportAnalyzes(lastOp: ISequencedDocumentMessage): void {\n dumpStats(this.ranges, {\n title: \"Fastest 1000 op ranges\",\n headers: [\"Duration(s)\", \"Bytes\"],\n orderByFirstColumn: true,\n reverseSort: true,\n removeTotals: true,\n lines: 3,\n });\n }\n}\n\n/**\n * Helper class to analyze collab window size\n */\nclass CollabWindowSizeAnalyzer implements IMessageAnalyzer {\n private maxCollabWindow = 0;\n private opSeq = 0;\n\n public processOp(message: ISequencedDocumentMessage, msgSize: number, skipMessage: boolean): void {\n const value = message.sequenceNumber - message.minimumSequenceNumber;\n if (value > this.maxCollabWindow) {\n this.maxCollabWindow = value;\n this.opSeq = message.sequenceNumber;\n }\n }\n\n public reportAnalyzes(lastOp: ISequencedDocumentMessage): void {\n console.log(`\\nMaximum collab window size: ${this.maxCollabWindow}, seq# ${this.opSeq}`);\n }\n}\n\n/**\n * Helper class to analyze frequency of summaries\n */\nclass SummaryAnalyzer implements IMessageAnalyzer {\n private lastSummaryOp = 0;\n private maxDistance = 0;\n private maxSeq = 0;\n private minDistance = Number.MAX_SAFE_INTEGER;\n private minSeq = 0;\n private maxResponse = 0;\n private maxResponseSeq = 0;\n\n public processOp(message: ISequencedDocumentMessage, msgSize: number, skipMessage: boolean): void {\n if (message.type === MessageType.SummaryAck) {\n const distance = message.sequenceNumber - this.lastSummaryOp - 1;\n if (this.maxDistance < distance) {\n this.maxDistance = distance;\n this.maxSeq = message.sequenceNumber;\n }\n if (this.minDistance > distance) {\n this.minDistance = distance;\n this.minSeq = message.sequenceNumber;\n }\n\n this.lastSummaryOp = message.sequenceNumber;\n }\n if (message.type === MessageType.SummaryAck || message.type === MessageType.SummaryNack) {\n const contents: ISummaryProposal = message.contents.summaryProposal;\n const distance = message.sequenceNumber - contents.summarySequenceNumber;\n if (distance > this.maxResponse) {\n this.maxResponse = distance;\n this.maxResponseSeq = message.sequenceNumber;\n }\n }\n }\n\n public reportAnalyzes(lastOp: ISequencedDocumentMessage): void {\n const distance = lastOp.sequenceNumber - this.lastSummaryOp;\n if (this.maxDistance < distance) {\n this.maxDistance = distance;\n this.maxSeq = lastOp.sequenceNumber + 1;\n }\n\n console.log(\"\");\n if (this.minDistance === Number.MAX_SAFE_INTEGER) {\n console.log(\"No summaries found in this document\");\n } else {\n console.log(`Maximum distance between summaries: ${this.maxDistance}, seq# ${this.maxSeq}`);\n console.log(`Maximum server response for summary: ${this.maxResponse}, seq# ${this.maxResponseSeq}`);\n console.log(`Minimum distance between summaries: ${this.minDistance}, seq# ${this.minSeq}`);\n }\n }\n}\n\n/**\n * Helper class to dump messages to console\n */\nclass MessageDumper implements IMessageAnalyzer {\n public processOp(message: ISequencedDocumentMessage, msgSize: number, skipMessage: boolean): void {\n if (!skipMessage) {\n console.log(JSON.stringify(message, undefined, 2));\n }\n }\n\n public reportAnalyzes(lastOp: ISequencedDocumentMessage): void {\n }\n}\n\nexport async function printMessageStats(\n generator, // AsyncGenerator<ISequencedDocumentMessage[]>,\n dumpMessageStats: boolean,\n dumpMessages: boolean,\n messageTypeFilter: Set<string> = new Set<string>()) {\n let lastMessage: ISequencedDocumentMessage | undefined;\n\n const analyzers: IMessageAnalyzer[] = [\n new FilteredMessageAnalyzer(), // Should come first\n new SessionAnalyzer(),\n new DataStructureAnalyzer(),\n new MessageDensityAnalyzer(),\n new CollabWindowSizeAnalyzer(),\n new SummaryAnalyzer(),\n ];\n\n if (dumpMessages) {\n analyzers.push(new MessageDumper());\n }\n\n for await (const messages of generator) {\n for (const message of (messages as ISequencedDocumentMessage[])) {\n const msgSize = JSON.stringify(message).length;\n lastMessage = message;\n\n const skipMessage = messageTypeFilter.size !== 0 && !messageTypeFilter.has(message.type);\n\n for (const analyzer of analyzers) {\n analyzer.processOp(message, msgSize, skipMessage);\n }\n }\n }\n\n if (lastMessage !== undefined) {\n if (dumpMessageStats) {\n for (const analyzer of analyzers) {\n analyzer.reportAnalyzes(lastMessage);\n }\n } else {\n // Warn about filtered messages\n analyzers[0].reportAnalyzes(lastMessage);\n }\n }\n console.log(\"\");\n}\n\nfunction processOp(\n message: ISequencedDocumentMessage,\n dataType: Map<string, string>,\n objectStats: Map<string, [number, number]>,\n msgSize: number,\n dataTypeStats: Map<string, [number, number]>,\n messageTypeStats: Map<string, [number, number]>,\n chunkMap: Map<string, { chunks: string[]; totalSize: number; }>) {\n let type = message.type;\n let recorded = false;\n let totalMsgSize = msgSize;\n let opCount = 1;\n if (isRuntimeMessage(message)) {\n let runtimeMessage = unpackRuntimeMessage(message);\n const messageType = runtimeMessage.type as RuntimeMessage;\n switch (messageType) {\n case RuntimeMessage.Attach: {\n const attachMessage = runtimeMessage.contents as IAttachMessage;\n processDataStoreAttachOp(attachMessage, dataType);\n break;\n }\n // skip for now because these ops do not have contents\n case RuntimeMessage.BlobAttach: {\n break;\n }\n case RuntimeMessage.ChunkedOp: {\n const chunk = runtimeMessage.contents as IChunkedOp;\n if (!chunkMap.has(runtimeMessage.clientId)) {\n chunkMap.set(\n runtimeMessage.clientId, {\n chunks: new Array<string>(chunk.totalChunks),\n totalSize: 0,\n });\n }\n const value = chunkMap.get(runtimeMessage.clientId);\n assert(value !== undefined, 0x2b8 /* \"Chunk should be set in map\" */);\n const chunks = value.chunks;\n const chunkIndex = chunk.chunkId - 1;\n if (chunks[chunkIndex] !== undefined) {\n throw new Error(\"Chunk already assigned\");\n }\n chunks[chunkIndex] = chunk.contents;\n value.totalSize += msgSize;\n if (chunk.chunkId === chunk.totalChunks) {\n opCount = chunk.totalChunks; // 1 op for each chunk.\n runtimeMessage = Object.create(runtimeMessage);\n runtimeMessage.contents = chunks.join(\"\");\n runtimeMessage.type = chunk.originalType;\n type = chunk.originalType;\n totalMsgSize = value.totalSize;\n chunkMap.delete(runtimeMessage.clientId);\n } else {\n return;\n }\n // eslint-disable-next-line no-fallthrough\n }\n case RuntimeMessage.FluidDataStoreOp:\n case RuntimeMessage.Alias:\n case RuntimeMessage.Rejoin:\n case RuntimeMessage.Operation:\n {\n let envelope = runtimeMessage.contents as IEnvelope;\n // TODO: Legacy?\n if (envelope !== undefined && typeof envelope === \"string\") {\n envelope = JSON.parse(envelope);\n }\n const innerContent = envelope.contents as {\n content: any;\n type: string;\n };\n const address = envelope.address;\n type = `${type}/${innerContent.type}`;\n switch (innerContent.type) {\n case DataStoreMessageType.Attach: {\n const attachMessage = innerContent.content as IAttachMessage;\n let objectType = attachMessage.type;\n if (objectType.startsWith(objectTypePrefix)) {\n objectType = objectType.substring(objectTypePrefix.length);\n }\n dataType.set(getObjectId(address, attachMessage.id), objectType);\n break;\n }\n case DataStoreMessageType.ChannelOp:\n default: {\n const innerEnvelope = innerContent.content as IEnvelope;\n const innerContent2 = innerEnvelope.contents as {\n type?: string;\n value?: any;\n };\n\n const objectId = getObjectId(address, innerEnvelope.address);\n incr(objectStats, objectId, totalMsgSize, opCount);\n let objectType = dataType.get(objectId);\n if (objectType === undefined) {\n // Somehow we do not have data...\n dataType.set(objectId, objectId);\n objectType = objectId;\n }\n incr(dataTypeStats, objectType, totalMsgSize, opCount);\n recorded = true;\n\n let subType = innerContent2.type;\n if (innerContent2.type === \"set\" &&\n typeof innerContent2.value === \"object\" &&\n innerContent2.value !== null) {\n type = `${type}/${subType}`;\n subType = innerContent2.value.type;\n } else if (objectType === \"mergeTree\" && subType !== undefined) {\n const types = [\"insert\", \"remove\", \"annotate\", \"group\"];\n if (types[subType] !== undefined) {\n subType = types[subType];\n }\n }\n if (subType !== undefined) {\n type = `${type}/${subType}`;\n }\n\n type = `${type} (${objectType})`;\n }\n }\n break;\n }\n default:\n unreachableCase(messageType, \"Message type not recognized!\");\n }\n }\n\n incr(messageTypeStats, type, totalMsgSize, opCount);\n if (!recorded) {\n // const objectId = `${type} (system)`;\n const objectId = `(system messages)`;\n const objectType = objectId;\n if (dataType.get(objectId) === undefined) {\n dataType.set(objectId, objectId);\n }\n incr(objectStats, objectId, totalMsgSize, opCount);\n incr(dataTypeStats, objectType, totalMsgSize, opCount);\n }\n}\n\nfunction processDataStoreAttachOp(\n attachMessage: IAttachMessage | string,\n dataType: Map<string, string>) {\n // dataType.set(getObjectId(attachMessage.id), attachMessage.type);\n\n // That's data store, and it brings a bunch of data structures.\n // Let's try to crack it.\n let parsedAttachMessage: IAttachMessage;\n if (typeof attachMessage === \"string\") {\n parsedAttachMessage = JSON.parse(attachMessage);\n } else {\n parsedAttachMessage = attachMessage;\n }\n for (const entry of parsedAttachMessage.snapshot.entries) {\n if (entry.type === TreeEntry.Tree) {\n for (const entry2 of entry.value.entries) {\n if (entry2.path === \".attributes\" && entry2.type === TreeEntry.Blob) {\n const attrib = JSON.parse(entry2.value.contents);\n let objectType: string = attrib.type;\n if (objectType.startsWith(objectTypePrefix)) {\n objectType = objectType.substring(objectTypePrefix.length);\n }\n dataType.set(getObjectId(parsedAttachMessage.id, entry.path), objectType);\n }\n }\n }\n }\n}\n\nfunction reportOpenSessions(\n lastOpTimestamp: number,\n sessionsInProgress: Map<string, ActiveSession>,\n sessions: Map<string, [number, number]>,\n users: Map<string, [number, number]>) {\n const activeSessions = new Map<string, [number, number]>();\n\n for (const [clientId, ses] of sessionsInProgress) {\n const sessionInfo = ses.leave(lastOpTimestamp);\n if (clientId !== noClientName) {\n const sessionName = `${clientId} (${sessionInfo.email})`;\n const sessionPayload: [number, number] = [durationFromTime(sessionInfo.duration), sessionInfo.opCount];\n sessions.set(sessionName, sessionPayload);\n activeSessions.set(sessionName, sessionPayload);\n } else {\n sessions.set(\n `Full file lifespan (noClient messages)`,\n [durationFromTime(sessionInfo.duration), sessionInfo.opCount]);\n }\n incr(users, sessionInfo.email, sessionInfo.opCount);\n }\n\n if (activeSessions.size > 0) {\n dumpStats(activeSessions, {\n title: \"Active sessions\",\n headers: [\"Duration\", \"Op count\"],\n lines: 6,\n orderByFirstColumn: true,\n removeTotals: true,\n });\n }\n}\n\nfunction calcChannelStats(dataType: Map<string, string>, objectStats: Map<string, [number, number]>) {\n const channelStats = new Map<string, [number, number]>();\n for (const [objectId, type] of dataType) {\n let value = objectStats.get(objectId);\n if (value === undefined) {\n value = [0, 0];\n }\n if (type === objectId) {\n channelStats.set(`${objectId}`, value);\n } else {\n channelStats.set(`${objectId} (${type})`, value);\n }\n }\n return channelStats;\n}\n\nfunction processQuorumMessages(\n message: ISequencedDocumentMessage,\n skipMessage: boolean,\n sessionsInProgress: Map<string, ActiveSession>,\n sessions: Map<string, [number, number]>,\n users: Map<string, [number, number]>) {\n let session: ActiveSession | undefined;\n const dataString = (message as any).data;\n if (message.type === \"join\") {\n const data = JSON.parse(dataString);\n session = ActiveSession.create(data.detail.user.id, message);\n sessionsInProgress.set(data.clientId, session);\n } else if (message.type === \"leave\") {\n const clientId = JSON.parse(dataString);\n session = sessionsInProgress.get(clientId);\n sessionsInProgress.delete(clientId);\n assert(!!session, 0x1b7 /* \"Bad session state for processing quorum messages\" */);\n if (session !== undefined) {\n if (!skipMessage) {\n session.reportOp(message.timestamp);\n }\n const sessionInfo: ISessionInfo = session.leave(message.timestamp);\n sessions.set(\n `${clientId} (${sessionInfo.email})`,\n [durationFromTime(sessionInfo.duration), sessionInfo.opCount]);\n incr(users, sessionInfo.email, sessionInfo.opCount);\n session = undefined; // Do not record it second time\n }\n } else {\n // message.clientId can be null\n session = sessionsInProgress.get(message.clientId);\n if (session === undefined) {\n session = sessionsInProgress.get(noClientName);\n assert(!!session, 0x1b8 /* \"Bad session state for processing quorum messages\" */);\n }\n }\n return session;\n}\n\nconst durationFromTime = (time: number): number => Math.floor(time / 1000);\n"]}
1
+ {"version":3,"file":"fluidAnalyzeMessages.js","sourceRoot":"","sources":["../src/fluidAnalyzeMessages.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert, unreachableCase } from \"@fluidframework/common-utils\";\nimport {\n ISequencedDocumentMessage,\n ISummaryProposal,\n MessageType,\n TreeEntry,\n} from \"@fluidframework/protocol-definitions\";\nimport { IAttachMessage, IEnvelope } from \"@fluidframework/runtime-definitions\";\nimport {\n IChunkedOp,\n ContainerMessageType,\n unpackRuntimeMessage,\n} from \"@fluidframework/container-runtime\";\nimport { DataStoreMessageType } from \"@fluidframework/datastore\";\n\nconst noClientName = \"No Client\";\nconst objectTypePrefix = \"https://graph.microsoft.com/types/\";\n\nfunction incr(map: Map<string, [number, number]>, key: string, size: number, count = 1) {\n const value = map.get(key);\n if (value === undefined) {\n map.set(key, [count, size]);\n } else {\n value[0] += count;\n value[1] += size;\n map.set(key, value);\n }\n}\n\ninterface ISessionInfo {\n startSeq: number;\n opCount: number;\n email: string;\n duration: number;\n}\n\ninterface IMessageAnalyzer {\n processOp(op: ISequencedDocumentMessage, msgSize: number, filteredOutOp: boolean): void;\n reportAnalyzes(lastOp: ISequencedDocumentMessage): void;\n}\n\n/**\n * Helper class to track session statistics\n */\nclass ActiveSession {\n public static create(email: string, message: ISequencedDocumentMessage) {\n return new ActiveSession(email, message);\n }\n\n private opCount = 0;\n\n constructor(private readonly email: string, private readonly startMessage: ISequencedDocumentMessage) {\n }\n\n public reportOp(timestamp: number) {\n this.opCount++;\n }\n\n public leave(timestamp: number): ISessionInfo {\n return {\n opCount: this.opCount,\n email: this.email,\n startSeq: this.startMessage.sequenceNumber,\n duration: timestamp - this.startMessage.timestamp,\n };\n }\n}\n\n// Format a number separating 3 digits by comma\n// eslint-disable-next-line unicorn/no-unsafe-regex\nexport const formatNumber = (num: number): string => num.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\n\nfunction dumpStats(\n map: Map<string, [number, number]>,\n props: {\n title: string;\n headers: [string, string];\n lines?: number;\n orderByFirstColumn?: boolean;\n reverseColumnsInUI?: boolean;\n removeTotals?: boolean;\n reverseSort?: boolean;\n }) {\n const fieldSizes = [10, 14];\n const nameLength = 72;\n const fieldsLength = fieldSizes[0] + fieldSizes[1] + 1;\n let headers = props.headers;\n\n let recordsToShow = props.lines ?? 10;\n if (map.size !== recordsToShow && props.removeTotals === undefined && recordsToShow > 1) {\n recordsToShow--;\n }\n\n let sorted: [string, [number, number]][];\n const sortIndex = props.orderByFirstColumn === true ? 0 : 1;\n let add: string;\n if (props.reverseSort !== undefined) {\n sorted = [...map.entries()].sort((a, b) => a[1][sortIndex] - b[1][sortIndex]);\n add = \"↑\";\n } else {\n sorted = [...map.entries()].sort((a, b) => b[1][sortIndex] - a[1][sortIndex]);\n add = \"↓\";\n }\n headers[sortIndex] = `${headers[sortIndex]} ${add}`;\n\n if (props.reverseColumnsInUI !== undefined) {\n headers = [headers[1], headers[0]];\n const sorted2: [string, [number, number]][] = [];\n for (const [name, [count, size]] of sorted) {\n sorted2.push([name, [size, count]]);\n }\n sorted = sorted2;\n }\n\n let totalCount = 0;\n let sizeTotal = 0;\n\n props.title = `${props.title} (${sorted.length})`;\n const header0 = headers[0].padStart(fieldSizes[0]);\n let overflow = header0.length - fieldSizes[0];\n console.log(`\\n\\n${props.title.padEnd(nameLength)} │ ${header0} ${headers[1].padStart(fieldSizes[1] - overflow)}`);\n\n console.log(`${\"─\".repeat(nameLength + 1)}┼${\"─\".repeat(fieldsLength + 1)}`);\n let index = 0;\n let allOtherCount = 0;\n let allOtherSize = 0;\n for (const [name, [count, size]] of sorted) {\n index++;\n totalCount += count;\n sizeTotal += size;\n if (index <= recordsToShow) {\n const item = name.padEnd(nameLength);\n overflow = item.length - nameLength;\n const col1 = formatNumber(count).padStart(fieldSizes[0] - overflow);\n overflow += col1.length - fieldSizes[0];\n const col2 = formatNumber(size).padStart(fieldSizes[1] - overflow);\n console.log(`${item} │ ${col1} ${col2}`);\n } else {\n allOtherCount += count;\n allOtherSize += size;\n }\n }\n\n if (props.removeTotals === undefined) {\n if (allOtherCount || allOtherSize) {\n // eslint-disable-next-line max-len\n console.log(`${`All Others (${sorted.length - recordsToShow})`.padEnd(nameLength)} │ ${formatNumber(allOtherCount).padStart(fieldSizes[0])} ${formatNumber(allOtherSize).padStart(fieldSizes[1])}`);\n }\n console.log(`${\"─\".repeat(nameLength + 1)}┼${\"─\".repeat(fieldsLength + 1)}`);\n // eslint-disable-next-line max-len\n console.log(`${\"Total\".padEnd(nameLength)} │ ${formatNumber(totalCount).padStart(fieldSizes[0])} ${formatNumber(sizeTotal).padStart(fieldSizes[1])}`);\n }\n}\n\nconst getObjectId = (dataStoreId: string, id: string) => `[${dataStoreId}]/${id}`;\n\n/**\n * Analyzer for sessions\n */\nclass SessionAnalyzer implements IMessageAnalyzer {\n private readonly sessionsInProgress = new Map<string, ActiveSession>();\n private readonly sessions = new Map<string, [number, number]>();\n private readonly users = new Map<string, [number, number]>();\n\n private first = true;\n\n public processOp(message: ISequencedDocumentMessage, msgSize: number, skipMessage: boolean): void {\n if (this.first) {\n this.first = false;\n // Start of the road.\n const noNameSession = ActiveSession.create(noClientName, message);\n this.sessionsInProgress.set(noClientName, noNameSession);\n }\n const session = processQuorumMessages(\n message,\n skipMessage,\n this.sessionsInProgress,\n this.sessions,\n this.users);\n if (!skipMessage && session) {\n session.reportOp(message.timestamp);\n }\n }\n\n public reportAnalyzes(lastOp: ISequencedDocumentMessage): void {\n // Close any open sessions\n reportOpenSessions(\n lastOp.timestamp,\n this.sessionsInProgress,\n this.sessions,\n this.users);\n dumpStats(this.users, {\n title: \"Users\",\n headers: [\"Sessions\", \"Op count\"],\n reverseColumnsInUI: true,\n lines: 6,\n });\n dumpStats(this.sessions, {\n title: \"Sessions\",\n headers: [\"Duration(s)\", \"Op count\"],\n reverseColumnsInUI: true,\n lines: 6,\n });\n dumpStats(this.sessions, {\n title: \"Sessions\",\n headers: [\"Duration(s)\", \"Op count\"],\n orderByFirstColumn: true,\n reverseColumnsInUI: true,\n removeTotals: true,\n lines: 5,\n });\n }\n}\n\n/**\n * Analyzer for data structures\n */\nclass DataStructureAnalyzer implements IMessageAnalyzer {\n private readonly messageTypeStats = new Map<string, [number, number]>();\n private readonly dataType = new Map<string, string>();\n private readonly dataTypeStats = new Map<string, [number, number]>();\n private readonly objectStats = new Map<string, [number, number]>();\n private readonly chunkMap = new Map<string, { chunks: string[]; totalSize: number; }>();\n\n public processOp(message: ISequencedDocumentMessage, msgSize: number, skipMessage: boolean): void {\n if (!skipMessage) {\n processOp(\n message,\n this.dataType,\n this.objectStats,\n msgSize,\n this.dataTypeStats,\n this.messageTypeStats,\n this.chunkMap);\n }\n }\n\n public reportAnalyzes(lastOp: ISequencedDocumentMessage): void {\n dumpStats(this.messageTypeStats, {\n title: \"Message Type\",\n headers: [\"Op count\", \"Bytes\"],\n lines: 20,\n });\n dumpStats(calcChannelStats(this.dataType, this.objectStats), {\n title: \"Channel name\",\n headers: [\"Op count\", \"Bytes\"],\n lines: 7,\n });\n /*\n dumpStats(this.dataTypeStats, {\n title: \"Channel type\",\n headers: [\"Op count\", \"Bytes\"],\n });\n */\n }\n}\n\n/**\n * Helper class to report if we filtered out any messages.\n */\nclass FilteredMessageAnalyzer implements IMessageAnalyzer {\n private sizeTotal = 0;\n private opsTotal = 0;\n private sizeFiltered = 0;\n private opsFiltered = 0;\n private filtered = false;\n\n public processOp(message: ISequencedDocumentMessage, msgSize: number, skipMessage: boolean): void {\n this.sizeTotal += msgSize;\n this.opsTotal++;\n if (!skipMessage) {\n this.sizeFiltered += msgSize;\n this.opsFiltered++;\n } else {\n this.filtered = true;\n }\n }\n\n public reportAnalyzes(lastOp: ISequencedDocumentMessage): void {\n if (this.filtered) {\n // eslint-disable-next-line max-len\n console.log(`\\nData is filtered according to --filter:messageType argument(s):\\nOp size: ${this.sizeFiltered} / ${this.sizeTotal}\\nOp count ${this.opsFiltered} / ${this.opsTotal}`);\n }\n if (this.opsTotal === 0) {\n console.error(\"No ops were found\");\n }\n }\n}\n\n/**\n * Helper class to find places where we generated too many ops\n */\nclass MessageDensityAnalyzer implements IMessageAnalyzer {\n private readonly opChunk = 1000;\n private opLimit = 1;\n private size = 0;\n private timeStart = 0;\n private doctimerStart = 0;\n private readonly ranges = new Map<string, [number, number]>();\n\n public processOp(message: ISequencedDocumentMessage, msgSize: number, skipMessage: boolean): void {\n if (message.sequenceNumber >= this.opLimit) {\n if (message.sequenceNumber !== 1) {\n const timeDiff = durationFromTime(message.timestamp - this.timeStart);\n const opsString = `ops = [${this.opLimit - this.opChunk}, ${this.opLimit - 1}]`.padEnd(26);\n // eslint-disable-next-line max-len\n const timeString = `time = [${durationFromTime(this.timeStart - this.doctimerStart)}, ${durationFromTime(message.timestamp - this.doctimerStart)}]`;\n this.ranges.set(\n `${opsString} ${timeString}`,\n [timeDiff, this.size]);\n } else {\n this.doctimerStart = message.timestamp;\n }\n this.opLimit += this.opChunk;\n this.size = 0;\n this.timeStart = message.timestamp;\n }\n if (!skipMessage) {\n this.size += msgSize;\n }\n }\n\n public reportAnalyzes(lastOp: ISequencedDocumentMessage): void {\n dumpStats(this.ranges, {\n title: \"Fastest 1000 op ranges\",\n headers: [\"Duration(s)\", \"Bytes\"],\n orderByFirstColumn: true,\n reverseSort: true,\n removeTotals: true,\n lines: 3,\n });\n }\n}\n\n/**\n * Helper class to analyze collab window size\n */\nclass CollabWindowSizeAnalyzer implements IMessageAnalyzer {\n private maxCollabWindow = 0;\n private opSeq = 0;\n\n public processOp(message: ISequencedDocumentMessage, msgSize: number, skipMessage: boolean): void {\n const value = message.sequenceNumber - message.minimumSequenceNumber;\n if (value > this.maxCollabWindow) {\n this.maxCollabWindow = value;\n this.opSeq = message.sequenceNumber;\n }\n }\n\n public reportAnalyzes(lastOp: ISequencedDocumentMessage): void {\n console.log(`\\nMaximum collab window size: ${this.maxCollabWindow}, seq# ${this.opSeq}`);\n }\n}\n\n/**\n * Helper class to analyze frequency of summaries\n */\nclass SummaryAnalyzer implements IMessageAnalyzer {\n private lastSummaryOp = 0;\n private maxDistance = 0;\n private maxSeq = 0;\n private minDistance = Number.MAX_SAFE_INTEGER;\n private minSeq = 0;\n private maxResponse = 0;\n private maxResponseSeq = 0;\n\n public processOp(message: ISequencedDocumentMessage, msgSize: number, skipMessage: boolean): void {\n if (message.type === MessageType.SummaryAck) {\n const distance = message.sequenceNumber - this.lastSummaryOp - 1;\n if (this.maxDistance < distance) {\n this.maxDistance = distance;\n this.maxSeq = message.sequenceNumber;\n }\n if (this.minDistance > distance) {\n this.minDistance = distance;\n this.minSeq = message.sequenceNumber;\n }\n\n this.lastSummaryOp = message.sequenceNumber;\n }\n if (message.type === MessageType.SummaryAck || message.type === MessageType.SummaryNack) {\n const contents: ISummaryProposal = message.contents.summaryProposal;\n const distance = message.sequenceNumber - contents.summarySequenceNumber;\n if (distance > this.maxResponse) {\n this.maxResponse = distance;\n this.maxResponseSeq = message.sequenceNumber;\n }\n }\n }\n\n public reportAnalyzes(lastOp: ISequencedDocumentMessage): void {\n const distance = lastOp.sequenceNumber - this.lastSummaryOp;\n if (this.maxDistance < distance) {\n this.maxDistance = distance;\n this.maxSeq = lastOp.sequenceNumber + 1;\n }\n\n console.log(\"\");\n if (this.minDistance === Number.MAX_SAFE_INTEGER) {\n console.log(\"No summaries found in this document\");\n } else {\n console.log(`Maximum distance between summaries: ${this.maxDistance}, seq# ${this.maxSeq}`);\n console.log(`Maximum server response for summary: ${this.maxResponse}, seq# ${this.maxResponseSeq}`);\n console.log(`Minimum distance between summaries: ${this.minDistance}, seq# ${this.minSeq}`);\n }\n }\n}\n\n/**\n * Helper class to dump messages to console\n */\nclass MessageDumper implements IMessageAnalyzer {\n public processOp(message: ISequencedDocumentMessage, msgSize: number, skipMessage: boolean): void {\n if (!skipMessage) {\n console.log(JSON.stringify(message, undefined, 2));\n }\n }\n\n public reportAnalyzes(lastOp: ISequencedDocumentMessage): void {\n }\n}\n\nexport async function printMessageStats(\n generator, // AsyncGenerator<ISequencedDocumentMessage[]>,\n dumpMessageStats: boolean,\n dumpMessages: boolean,\n messageTypeFilter: Set<string> = new Set<string>()) {\n let lastMessage: ISequencedDocumentMessage | undefined;\n\n const analyzers: IMessageAnalyzer[] = [\n new FilteredMessageAnalyzer(), // Should come first\n new SessionAnalyzer(),\n new DataStructureAnalyzer(),\n new MessageDensityAnalyzer(),\n new CollabWindowSizeAnalyzer(),\n new SummaryAnalyzer(),\n ];\n\n if (dumpMessages) {\n analyzers.push(new MessageDumper());\n }\n\n for await (const messages of generator) {\n for (const message of (messages as ISequencedDocumentMessage[])) {\n const msgSize = JSON.stringify(message).length;\n lastMessage = message;\n\n const skipMessage = messageTypeFilter.size !== 0 && !messageTypeFilter.has(message.type);\n\n for (const analyzer of analyzers) {\n analyzer.processOp(message, msgSize, skipMessage);\n }\n }\n }\n\n if (lastMessage !== undefined) {\n if (dumpMessageStats) {\n for (const analyzer of analyzers) {\n analyzer.reportAnalyzes(lastMessage);\n }\n } else {\n // Warn about filtered messages\n analyzers[0].reportAnalyzes(lastMessage);\n }\n }\n console.log(\"\");\n}\n\nfunction processOp(\n runtimeMessage: ISequencedDocumentMessage,\n dataType: Map<string, string>,\n objectStats: Map<string, [number, number]>,\n msgSize: number,\n dataTypeStats: Map<string, [number, number]>,\n messageTypeStats: Map<string, [number, number]>,\n chunkMap: Map<string, { chunks: string[]; totalSize: number; }>) {\n let type = runtimeMessage.type;\n let recorded = false;\n let totalMsgSize = msgSize;\n let opCount = 1;\n if (unpackRuntimeMessage(runtimeMessage)) {\n const messageType = runtimeMessage.type as ContainerMessageType;\n switch (messageType) {\n case ContainerMessageType.Attach: {\n const attachMessage = runtimeMessage.contents as IAttachMessage;\n processDataStoreAttachOp(attachMessage, dataType);\n break;\n }\n // skip for now because these ops do not have contents\n case ContainerMessageType.BlobAttach: {\n break;\n }\n case ContainerMessageType.ChunkedOp: {\n const chunk = runtimeMessage.contents as IChunkedOp;\n if (!chunkMap.has(runtimeMessage.clientId)) {\n chunkMap.set(\n runtimeMessage.clientId, {\n chunks: new Array<string>(chunk.totalChunks),\n totalSize: 0,\n });\n }\n const value = chunkMap.get(runtimeMessage.clientId);\n assert(value !== undefined, 0x2b8 /* \"Chunk should be set in map\" */);\n const chunks = value.chunks;\n const chunkIndex = chunk.chunkId - 1;\n if (chunks[chunkIndex] !== undefined) {\n throw new Error(\"Chunk already assigned\");\n }\n chunks[chunkIndex] = chunk.contents;\n value.totalSize += msgSize;\n if (chunk.chunkId === chunk.totalChunks) {\n opCount = chunk.totalChunks; // 1 op for each chunk.\n const patchedMessage = Object.create(runtimeMessage);\n patchedMessage.contents = chunks.join(\"\");\n patchedMessage.type = chunk.originalType;\n type = chunk.originalType;\n totalMsgSize = value.totalSize;\n chunkMap.delete(patchedMessage.clientId);\n } else {\n return;\n }\n // eslint-disable-next-line no-fallthrough\n }\n case ContainerMessageType.FluidDataStoreOp:\n case ContainerMessageType.Alias:\n case ContainerMessageType.Rejoin:\n {\n let envelope = runtimeMessage.contents as IEnvelope;\n // TODO: Legacy?\n if (envelope !== undefined && typeof envelope === \"string\") {\n envelope = JSON.parse(envelope);\n }\n const innerContent = envelope.contents as {\n content: any;\n type: string;\n };\n const address = envelope.address;\n type = `${type}/${innerContent.type}`;\n switch (innerContent.type) {\n case DataStoreMessageType.Attach: {\n const attachMessage = innerContent.content as IAttachMessage;\n let objectType = attachMessage.type;\n if (objectType.startsWith(objectTypePrefix)) {\n objectType = objectType.substring(objectTypePrefix.length);\n }\n dataType.set(getObjectId(address, attachMessage.id), objectType);\n break;\n }\n case DataStoreMessageType.ChannelOp:\n default: {\n const innerEnvelope = innerContent.content as IEnvelope;\n const innerContent2 = innerEnvelope.contents as {\n type?: string;\n value?: any;\n };\n\n const objectId = getObjectId(address, innerEnvelope.address);\n incr(objectStats, objectId, totalMsgSize, opCount);\n let objectType = dataType.get(objectId);\n if (objectType === undefined) {\n // Somehow we do not have data...\n dataType.set(objectId, objectId);\n objectType = objectId;\n }\n incr(dataTypeStats, objectType, totalMsgSize, opCount);\n recorded = true;\n\n let subType = innerContent2.type;\n if (innerContent2.type === \"set\" &&\n typeof innerContent2.value === \"object\" &&\n innerContent2.value !== null) {\n type = `${type}/${subType}`;\n subType = innerContent2.value.type;\n } else if (objectType === \"mergeTree\" && subType !== undefined) {\n const types = [\"insert\", \"remove\", \"annotate\", \"group\"];\n if (types[subType] !== undefined) {\n subType = types[subType];\n }\n }\n if (subType !== undefined) {\n type = `${type}/${subType}`;\n }\n\n type = `${type} (${objectType})`;\n }\n }\n break;\n }\n default:\n unreachableCase(messageType, \"Message type not recognized!\");\n }\n }\n\n incr(messageTypeStats, type, totalMsgSize, opCount);\n if (!recorded) {\n // const objectId = `${type} (system)`;\n const objectId = `(system messages)`;\n const objectType = objectId;\n if (dataType.get(objectId) === undefined) {\n dataType.set(objectId, objectId);\n }\n incr(objectStats, objectId, totalMsgSize, opCount);\n incr(dataTypeStats, objectType, totalMsgSize, opCount);\n }\n}\n\nfunction processDataStoreAttachOp(\n attachMessage: IAttachMessage | string,\n dataType: Map<string, string>) {\n // dataType.set(getObjectId(attachMessage.id), attachMessage.type);\n\n // That's data store, and it brings a bunch of data structures.\n // Let's try to crack it.\n const parsedAttachMessage = typeof attachMessage === \"string\" ? JSON.parse(attachMessage) : attachMessage;\n for (const entry of parsedAttachMessage.snapshot.entries) {\n if (entry.type === TreeEntry.Tree) {\n for (const entry2 of entry.value.entries) {\n if (entry2.path === \".attributes\" && entry2.type === TreeEntry.Blob) {\n const attrib = JSON.parse(entry2.value.contents);\n let objectType: string = attrib.type;\n if (objectType.startsWith(objectTypePrefix)) {\n objectType = objectType.substring(objectTypePrefix.length);\n }\n dataType.set(getObjectId(parsedAttachMessage.id, entry.path), objectType);\n }\n }\n }\n }\n}\n\nfunction reportOpenSessions(\n lastOpTimestamp: number,\n sessionsInProgress: Map<string, ActiveSession>,\n sessions: Map<string, [number, number]>,\n users: Map<string, [number, number]>) {\n const activeSessions = new Map<string, [number, number]>();\n\n for (const [clientId, ses] of sessionsInProgress) {\n const sessionInfo = ses.leave(lastOpTimestamp);\n if (clientId !== noClientName) {\n const sessionName = `${clientId} (${sessionInfo.email})`;\n const sessionPayload: [number, number] = [durationFromTime(sessionInfo.duration), sessionInfo.opCount];\n sessions.set(sessionName, sessionPayload);\n activeSessions.set(sessionName, sessionPayload);\n } else {\n sessions.set(\n `Full file lifespan (noClient messages)`,\n [durationFromTime(sessionInfo.duration), sessionInfo.opCount]);\n }\n incr(users, sessionInfo.email, sessionInfo.opCount);\n }\n\n if (activeSessions.size > 0) {\n dumpStats(activeSessions, {\n title: \"Active sessions\",\n headers: [\"Duration\", \"Op count\"],\n lines: 6,\n orderByFirstColumn: true,\n removeTotals: true,\n });\n }\n}\n\nfunction calcChannelStats(dataType: Map<string, string>, objectStats: Map<string, [number, number]>) {\n const channelStats = new Map<string, [number, number]>();\n for (const [objectId, type] of dataType) {\n let value = objectStats.get(objectId);\n if (value === undefined) {\n value = [0, 0];\n }\n if (type === objectId) {\n channelStats.set(`${objectId}`, value);\n } else {\n channelStats.set(`${objectId} (${type})`, value);\n }\n }\n return channelStats;\n}\n\nfunction processQuorumMessages(\n message: ISequencedDocumentMessage,\n skipMessage: boolean,\n sessionsInProgress: Map<string, ActiveSession>,\n sessions: Map<string, [number, number]>,\n users: Map<string, [number, number]>) {\n let session: ActiveSession | undefined;\n const dataString = (message as any).data;\n if (message.type === \"join\") {\n const data = JSON.parse(dataString);\n session = ActiveSession.create(data.detail.user.id, message);\n sessionsInProgress.set(data.clientId, session);\n } else if (message.type === \"leave\") {\n const clientId = JSON.parse(dataString);\n session = sessionsInProgress.get(clientId);\n sessionsInProgress.delete(clientId);\n assert(!!session, 0x1b7 /* \"Bad session state for processing quorum messages\" */);\n if (session !== undefined) {\n if (!skipMessage) {\n session.reportOp(message.timestamp);\n }\n const sessionInfo: ISessionInfo = session.leave(message.timestamp);\n sessions.set(\n `${clientId} (${sessionInfo.email})`,\n [durationFromTime(sessionInfo.duration), sessionInfo.opCount]);\n incr(users, sessionInfo.email, sessionInfo.opCount);\n session = undefined; // Do not record it second time\n }\n } else {\n // message.clientId can be null\n session = sessionsInProgress.get(message.clientId);\n if (session === undefined) {\n session = sessionsInProgress.get(noClientName);\n assert(!!session, 0x1b8 /* \"Bad session state for processing quorum messages\" */);\n }\n }\n return session;\n}\n\nconst durationFromTime = (time: number): number => Math.floor(time / 1000);\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluid-tools/fetch-tool",
3
- "version": "1.2.7",
3
+ "version": "2.0.0-dev.1.3.0.96595",
4
4
  "description": "Console tool to fetch Fluid data from relay service",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -29,27 +29,27 @@
29
29
  "tsfmt:fix": "tsfmt --replace"
30
30
  },
31
31
  "dependencies": {
32
- "@fluid-tools/fluidapp-odsp-urlresolver": "^1.2.7",
33
- "@fluidframework/common-utils": "^0.32.1",
34
- "@fluidframework/container-runtime": "^1.2.7",
35
- "@fluidframework/datastore": "^1.2.7",
36
- "@fluidframework/driver-definitions": "^1.2.7",
37
- "@fluidframework/driver-utils": "^1.2.7",
38
- "@fluidframework/odsp-doclib-utils": "^1.2.7",
39
- "@fluidframework/odsp-driver": "^1.2.7",
40
- "@fluidframework/odsp-driver-definitions": "^1.2.7",
41
- "@fluidframework/odsp-urlresolver": "^1.2.7",
42
- "@fluidframework/protocol-definitions": "^0.1028.2000",
43
- "@fluidframework/routerlicious-driver": "^1.2.7",
44
- "@fluidframework/routerlicious-urlresolver": "^1.2.7",
45
- "@fluidframework/runtime-definitions": "^1.2.7",
46
- "@fluidframework/telemetry-utils": "^1.2.7",
47
- "@fluidframework/test-client-utils": "^1.2.7",
48
- "@fluidframework/tool-utils": "^1.2.7"
32
+ "@fluid-tools/fluidapp-odsp-urlresolver": "2.0.0-dev.1.3.0.96595",
33
+ "@fluidframework/common-utils": "^1.0.0",
34
+ "@fluidframework/container-runtime": "2.0.0-dev.1.3.0.96595",
35
+ "@fluidframework/datastore": "2.0.0-dev.1.3.0.96595",
36
+ "@fluidframework/driver-definitions": "2.0.0-dev.1.3.0.96595",
37
+ "@fluidframework/driver-utils": "2.0.0-dev.1.3.0.96595",
38
+ "@fluidframework/odsp-doclib-utils": "2.0.0-dev.1.3.0.96595",
39
+ "@fluidframework/odsp-driver": "2.0.0-dev.1.3.0.96595",
40
+ "@fluidframework/odsp-driver-definitions": "2.0.0-dev.1.3.0.96595",
41
+ "@fluidframework/odsp-urlresolver": "2.0.0-dev.1.3.0.96595",
42
+ "@fluidframework/protocol-definitions": "^1.0.0",
43
+ "@fluidframework/routerlicious-driver": "2.0.0-dev.1.3.0.96595",
44
+ "@fluidframework/routerlicious-urlresolver": "2.0.0-dev.1.3.0.96595",
45
+ "@fluidframework/runtime-definitions": "2.0.0-dev.1.3.0.96595",
46
+ "@fluidframework/telemetry-utils": "2.0.0-dev.1.3.0.96595",
47
+ "@fluidframework/test-client-utils": "2.0.0-dev.1.3.0.96595",
48
+ "@fluidframework/tool-utils": "2.0.0-dev.1.3.0.96595"
49
49
  },
50
50
  "devDependencies": {
51
- "@fluidframework/build-common": "^0.24.0",
52
- "@fluidframework/eslint-config-fluid": "^0.28.2000",
51
+ "@fluidframework/build-common": "^1.0.0",
52
+ "@fluidframework/eslint-config-fluid": "^1.0.0",
53
53
  "@rushstack/eslint-config": "^2.5.1",
54
54
  "@types/node": "^14.18.0",
55
55
  "concurrently": "^6.2.0",
@@ -13,8 +13,7 @@ import {
13
13
  import { IAttachMessage, IEnvelope } from "@fluidframework/runtime-definitions";
14
14
  import {
15
15
  IChunkedOp,
16
- isRuntimeMessage,
17
- RuntimeMessage,
16
+ ContainerMessageType,
18
17
  unpackRuntimeMessage,
19
18
  } from "@fluidframework/container-runtime";
20
19
  import { DataStoreMessageType } from "@fluidframework/datastore";
@@ -473,31 +472,30 @@ export async function printMessageStats(
473
472
  }
474
473
 
475
474
  function processOp(
476
- message: ISequencedDocumentMessage,
475
+ runtimeMessage: ISequencedDocumentMessage,
477
476
  dataType: Map<string, string>,
478
477
  objectStats: Map<string, [number, number]>,
479
478
  msgSize: number,
480
479
  dataTypeStats: Map<string, [number, number]>,
481
480
  messageTypeStats: Map<string, [number, number]>,
482
481
  chunkMap: Map<string, { chunks: string[]; totalSize: number; }>) {
483
- let type = message.type;
482
+ let type = runtimeMessage.type;
484
483
  let recorded = false;
485
484
  let totalMsgSize = msgSize;
486
485
  let opCount = 1;
487
- if (isRuntimeMessage(message)) {
488
- let runtimeMessage = unpackRuntimeMessage(message);
489
- const messageType = runtimeMessage.type as RuntimeMessage;
486
+ if (unpackRuntimeMessage(runtimeMessage)) {
487
+ const messageType = runtimeMessage.type as ContainerMessageType;
490
488
  switch (messageType) {
491
- case RuntimeMessage.Attach: {
489
+ case ContainerMessageType.Attach: {
492
490
  const attachMessage = runtimeMessage.contents as IAttachMessage;
493
491
  processDataStoreAttachOp(attachMessage, dataType);
494
492
  break;
495
493
  }
496
494
  // skip for now because these ops do not have contents
497
- case RuntimeMessage.BlobAttach: {
495
+ case ContainerMessageType.BlobAttach: {
498
496
  break;
499
497
  }
500
- case RuntimeMessage.ChunkedOp: {
498
+ case ContainerMessageType.ChunkedOp: {
501
499
  const chunk = runtimeMessage.contents as IChunkedOp;
502
500
  if (!chunkMap.has(runtimeMessage.clientId)) {
503
501
  chunkMap.set(
@@ -517,21 +515,20 @@ function processOp(
517
515
  value.totalSize += msgSize;
518
516
  if (chunk.chunkId === chunk.totalChunks) {
519
517
  opCount = chunk.totalChunks; // 1 op for each chunk.
520
- runtimeMessage = Object.create(runtimeMessage);
521
- runtimeMessage.contents = chunks.join("");
522
- runtimeMessage.type = chunk.originalType;
518
+ const patchedMessage = Object.create(runtimeMessage);
519
+ patchedMessage.contents = chunks.join("");
520
+ patchedMessage.type = chunk.originalType;
523
521
  type = chunk.originalType;
524
522
  totalMsgSize = value.totalSize;
525
- chunkMap.delete(runtimeMessage.clientId);
523
+ chunkMap.delete(patchedMessage.clientId);
526
524
  } else {
527
525
  return;
528
526
  }
529
527
  // eslint-disable-next-line no-fallthrough
530
528
  }
531
- case RuntimeMessage.FluidDataStoreOp:
532
- case RuntimeMessage.Alias:
533
- case RuntimeMessage.Rejoin:
534
- case RuntimeMessage.Operation:
529
+ case ContainerMessageType.FluidDataStoreOp:
530
+ case ContainerMessageType.Alias:
531
+ case ContainerMessageType.Rejoin:
535
532
  {
536
533
  let envelope = runtimeMessage.contents as IEnvelope;
537
534
  // TODO: Legacy?
@@ -619,12 +616,7 @@ function processDataStoreAttachOp(
619
616
 
620
617
  // That's data store, and it brings a bunch of data structures.
621
618
  // Let's try to crack it.
622
- let parsedAttachMessage: IAttachMessage;
623
- if (typeof attachMessage === "string") {
624
- parsedAttachMessage = JSON.parse(attachMessage);
625
- } else {
626
- parsedAttachMessage = attachMessage;
627
- }
619
+ const parsedAttachMessage = typeof attachMessage === "string" ? JSON.parse(attachMessage) : attachMessage;
628
620
  for (const entry of parsedAttachMessage.snapshot.entries) {
629
621
  if (entry.type === TreeEntry.Tree) {
630
622
  for (const entry2 of entry.value.entries) {