or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

compatibility-management.mddatastore-operations.mdgarbage-collection.mdhandle-management.mdindex.mdruntime-factories.mdstorage-utilities.mdsummary-management.mdtelemetry-utilities.md
tile.json

telemetry-utilities.mddocs/

Telemetry and Utilities ❌ Internal API

Telemetry context management and general utilities for runtime operations including ID encoding, sequence number extraction, and request header management. These utilities support monitoring, debugging, and efficient data handling in Fluid Framework applications.

Internal API Warning: All APIs in this document are internal to the Fluid Framework and are not exported for public use. These utilities are implementation details that may change without notice. They are documented here for framework contributors and advanced users who need to understand the internal workings.

Internal APIs ❌

The following APIs are not available for public use and are internal implementation details:

Telemetry Context Management ❌ Internal

Implementation for collecting, organizing, and serializing telemetry data with hierarchical property management.

Status: Internal implementation detail - not exported

/**
 * Implementation of telemetry context for collecting and serializing telemetry data
 */
class TelemetryContext implements ITelemetryContext, ITelemetryContextExt {
  /**
   * Set a telemetry property with a given prefix and property name
   * @param prefix - The prefix to organize related properties
   * @param property - The property name
   * @param value - The value to set (various telemetry-compatible types)
   */
  set(prefix: string, property: string, value: TelemetryEventPropertyTypeExt): void;
  
  /**
   * Set multiple telemetry properties at once with a given prefix
   * @param prefix - The prefix to organize related properties
   * @param property - The base property name
   * @param values - Record of property names to values
   */
  setMultiple(
    prefix: string,
    property: string,
    values: Record<string, TelemetryEventPropertyTypeExt>
  ): void;
  
  /**
   * Get a telemetry property value
   * @param prefix - The prefix of the property
   * @param property - The property name
   * @returns The stored value or undefined if not found
   */
  get(prefix: string, property: string): TelemetryEventPropertyTypeExt;
  
  /**
   * Serialize all telemetry data to a string format
   * @returns Serialized representation of all telemetry data
   */
  serialize(): string;
}

Runtime Request Headers ❌ Internal

Enumeration of standard header keys used in runtime requests for controlling behavior and passing metadata.

Status: Internal implementation detail - not exported

/**
 * Accepted header keys for requests coming to the runtime
 */
enum RuntimeHeaders {
  /** True to wait for a data store to be created and loaded before returning it */
  wait = "wait",
  
  /** True if the request is coming from an IFluidHandle */
  viaHandle = "viaHandle",
  
  /** True if the request is coming from a handle with a pending payload */
  payloadPending = "payloadPending"
}

ID Encoding Utilities ❌ Internal

Functions for encoding IDs into compact string representations, optimizing storage and network efficiency.

Status: Internal implementation detail - not exported

/**
 * Encode compact ID to a compact string representation. Strings are returned as is, numbers are encoded
 * @param idArg - Input - either a non-negative integer or a string
 * @param prefix - Optional string prefix to add to the encoded result
 * @returns String representation of the input
 */
function encodeCompactIdToString(idArg: number | string, prefix?: string): string;

/**
 * Character set for encoding IDs. Must never be changed to avoid collisions with existing ids.
 */
const charSetForEncodingIds: "ABCDEFGHIJKLMNOPQRSTUVWXYZ(abcdefghijklmnopqrstuvwxyz)0123456789";

Snapshot Utilities ❌ Internal

Functions for extracting information from snapshot trees, including sequence numbers and metadata.

Status: Internal implementation detail - not exported

/**
 * Function to read blob contents from storage and parse the result from JSON
 */
type ReadAndParseBlob = <T>(id: string) => Promise<T>;

/**
 * Fetches the sequence number of the snapshot tree by examining the protocol
 * @param tree - Snapshot tree to examine
 * @param readAndParseBlob - Function to read blob contents from storage and parse the result from JSON
 * @returns Promise resolving to the sequence number
 */
function seqFromTree(
  tree: ISnapshotTree,
  readAndParseBlob: ReadAndParseBlob
): Promise<number>;

Delta Manager Utilities ❌ Internal

Type casting utilities for accessing internal delta manager APIs while maintaining type safety.

Status: Internal implementation detail - not exported

/**
 * Casts the public API for delta manager into the internal one, exposing access to APIs needed by the implementation
 * @param deltaManager - The public delta manager interface
 * @returns Internal delta manager interface with additional methods
 */
function toDeltaManagerInternal(
  deltaManager: IDeltaManagerErased
): IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>;

/**
 * Casts the internal API for delta manager into the public type erased API for returning from public APIs
 * @param deltaManager - The internal delta manager interface
 * @returns Public type-erased delta manager interface
 */
function toDeltaManagerErased(
  deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>
): IDeltaManagerErased;

Migration Guidance

Since all APIs in this module are internal and not exported, there are no direct replacements available in the public API. If you need similar functionality:

  1. Telemetry: Use the public telemetry APIs from @fluidframework/core-interfaces or your own telemetry system
  2. Request Headers: Use standard HTTP header patterns or the public container/data store request APIs
  3. ID Encoding: Implement your own ID encoding utilities or use standard libraries
  4. Snapshot Operations: Use the public container and snapshot APIs
  5. Delta Manager: Use the public container runtime and delta connection APIs

Example Usage (Internal Only - Not Available Publicly):

// ❌ These imports will NOT work - APIs are internal
// import { 
//   TelemetryContext,
//   RuntimeHeaders,
//   encodeCompactIdToString,
//   seqFromTree,
//   toDeltaManagerInternal,
//   toDeltaManagerErased
// } from "@fluidframework/runtime-utils";

// Telemetry context usage
const telemetryContext = new TelemetryContext();

// Set individual properties
telemetryContext.set("performance", "loadTime", 1250);
telemetryContext.set("performance", "renderTime", 340);
telemetryContext.set("user", "id", "user123");

// Set multiple properties at once
telemetryContext.setMultiple("errors", "count", {
  "validation": 2,
  "network": 1,
  "timeout": 0
});

// Retrieve properties
const loadTime = telemetryContext.get("performance", "loadTime");
console.log("Load time:", loadTime);

// Serialize for logging/transmission
const serializedData = telemetryContext.serialize();
console.log("Telemetry data:", serializedData);

// Runtime headers usage
const request: IRequest = {
  url: "/datastore/component",
  headers: {
    [RuntimeHeaders.wait]: true,
    [RuntimeHeaders.viaHandle]: false,
    [RuntimeHeaders.payloadPending]: false
  }
};

// Check for specific headers
if (request.headers?.[RuntimeHeaders.wait]) {
  console.log("Client wants to wait for data store creation");
}

// ID encoding for compact storage
const numericId = 12345;
const encodedId = encodeCompactIdToString(numericId, "msg");
console.log("Encoded ID:", encodedId); // e.g., "msgABC123"

const stringId = "my-component";
const encodedStringId = encodeCompactIdToString(stringId, "comp");
console.log("String ID:", encodedStringId); // "compmy-component"

// Snapshot sequence number extraction
async function getSnapshotSequenceNumber(
  snapshotTree: ISnapshotTree,
  storage: IChannelStorageService
): Promise<number> {
  const readAndParseBlob = async <T>(id: string): Promise<T> => {
    const blob = await storage.readBlob(id);
    const text = new TextDecoder().decode(blob);
    return JSON.parse(text) as T;
  };
  
  return seqFromTree(snapshotTree, readAndParseBlob);
}

// Delta manager type casting
function setupDeltaManagerAccess(publicDeltaManager: IDeltaManagerErased) {
  // Cast to internal interface to access additional methods
  const internalDeltaManager = toDeltaManagerInternal(publicDeltaManager);
  
  // Use internal methods for framework operations
  internalDeltaManager.submitMessage(/* ... */);
  internalDeltaManager.flush();
  
  // Cast back to public interface when returning from APIs
  const publicInterface = toDeltaManagerErased(internalDeltaManager);
  return publicInterface;
}

Advanced Telemetry and Utility Patterns

// Hierarchical telemetry management
class ComponentTelemetryManager {
  private context = new TelemetryContext();
  private componentId: string;
  
  constructor(componentId: string) {
    this.componentId = componentId;
    this.context.set("component", "id", componentId);
    this.context.set("component", "startTime", Date.now());
  }
  
  // Track performance metrics
  trackPerformance(operation: string, duration: number): void {
    this.context.set("performance", operation, duration);
  }
  
  // Track errors with categorization
  trackError(category: string, error: Error): void {
    this.context.set("errors", `${category}_count`, 
      (this.context.get("errors", `${category}_count`) as number || 0) + 1
    );
    this.context.set("errors", `${category}_latest`, error.message);
  }
  
  // Track usage statistics
  trackUsage(feature: string, count: number = 1): void {
    const currentCount = this.context.get("usage", feature) as number || 0;
    this.context.set("usage", feature, currentCount + count);
  }
  
  // Get telemetry snapshot
  getSnapshot(): string {
    this.context.set("component", "snapshotTime", Date.now());
    return this.context.serialize();
  }
}

// Request header utilities
class RequestHeaderUtil {
  static createDataStoreRequest(
    path: string,
    options: {
      waitForCreation?: boolean;
      fromHandle?: boolean;
      payloadPending?: boolean;
    } = {}
  ): IRequest {
    const headers: Record<string, any> = {};
    
    if (options.waitForCreation) {
      headers[RuntimeHeaders.wait] = true;
    }
    
    if (options.fromHandle) {
      headers[RuntimeHeaders.viaHandle] = true;
    }
    
    if (options.payloadPending) {
      headers[RuntimeHeaders.payloadPending] = true;
    }
    
    return { url: path, headers };
  }
  
  static isWaitRequest(request: IRequest): boolean {
    return request.headers?.[RuntimeHeaders.wait] === true;
  }
  
  static isViaHandle(request: IRequest): boolean {
    return request.headers?.[RuntimeHeaders.viaHandle] === true;
  }
  
  static hasPayloadPending(request: IRequest): boolean {
    return request.headers?.[RuntimeHeaders.payloadPending] === true;
  }
}

// ID management system
class CompactIdManager {
  private idCounter = 0;
  private stringToId = new Map<string, number>();
  private idToString = new Map<number, string>();
  
  // Get or create a compact ID for a string
  getCompactId(identifier: string, prefix?: string): string {
    if (!this.stringToId.has(identifier)) {
      const numericId = this.idCounter++;
      this.stringToId.set(identifier, numericId);
      this.idToString.set(numericId, identifier);
    }
    
    const numericId = this.stringToId.get(identifier)!;
    return encodeCompactIdToString(numericId, prefix);
  }
  
  // Decode a compact ID back to original string
  decodeCompactId(compactId: string, prefix?: string): string | undefined {
    if (prefix && !compactId.startsWith(prefix)) {
      return undefined;
    }
    
    const idPart = prefix ? compactId.slice(prefix.length) : compactId;
    
    // This would require a decode function (not provided in the API)
    // but shows the pattern for managing compact IDs
    const numericId = this.decodeStringToNumber(idPart);
    return this.idToString.get(numericId);
  }
  
  private decodeStringToNumber(encoded: string): number {
    // Custom decoding logic would go here
    // This is a simplified example
    return parseInt(encoded, 36);
  }
}

// Snapshot analysis utilities
class SnapshotAnalyzer {
  constructor(
    private storage: IChannelStorageService
  ) {}
  
  async analyzeSnapshot(tree: ISnapshotTree): Promise<SnapshotAnalysis> {
    const readAndParseBlob = async <T>(id: string): Promise<T> => {
      const blob = await this.storage.readBlob(id);
      const text = new TextDecoder().decode(blob);
      return JSON.parse(text) as T;
    };
    
    const sequenceNumber = await seqFromTree(tree, readAndParseBlob);
    
    // Analyze tree structure
    const blobCount = this.countBlobs(tree);
    const treeDepth = this.calculateTreeDepth(tree);
    
    return {
      sequenceNumber,
      blobCount,
      treeDepth,
      timestamp: Date.now()
    };
  }
  
  private countBlobs(tree: ISnapshotTree, count = 0): number {
    for (const [_, value] of Object.entries(tree.trees ?? {})) {
      count = this.countBlobs(value, count);
    }
    return count + Object.keys(tree.blobs ?? {}).length;
  }
  
  private calculateTreeDepth(tree: ISnapshotTree, depth = 0): number {
    if (!tree.trees || Object.keys(tree.trees).length === 0) {
      return depth;
    }
    
    let maxChildDepth = depth;
    for (const childTree of Object.values(tree.trees)) {
      const childDepth = this.calculateTreeDepth(childTree, depth + 1);
      maxChildDepth = Math.max(maxChildDepth, childDepth);
    }
    
    return maxChildDepth;
  }
}

interface SnapshotAnalysis {
  sequenceNumber: number;
  blobCount: number;
  treeDepth: number;
  timestamp: number;
}