/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { IGarbageCollectionData } from "@fluidframework/runtime-definitions/internal";
import { ITelemetryLoggerExt, MonitoringContext, type ITelemetryPropertiesExt } from "@fluidframework/telemetry-utils/internal";
import { RuntimeHeaderData } from "../containerRuntime.js";
import { ICreateContainerMetadata } from "../summary/index.js";
import { GCNodeType, IGarbageCollectorConfigs } from "./gcDefinitions.js";
import { UnreferencedStateTracker } from "./gcUnreferencedStateTracker.js";
type NodeUsageType = "Changed" | "Loaded" | "Revived" | "Realized";
/**
 * Properties that are common to IUnreferencedEventProps and INodeUsageProps
 */
interface ICommonProps {
    usageType: NodeUsageType;
    completedGCRuns: number;
    isTombstoned: boolean;
    lastSummaryTime?: number;
    headers?: RuntimeHeaderData;
    additionalProps?: ITelemetryPropertiesExt;
}
/**
 * Properties passed to nodeUsed function when a node is used.
 */
interface INodeUsageProps extends ICommonProps {
    /**
     * The full path (in GC Path format) to the node in question
     */
    id: string;
    /**
     * Latest timestamp received from the server, as a baseline for computing GC state/age
     */
    currentReferenceTimestampMs: number;
    /**
     * The package path of the node. This may not be available if the node hasn't been loaded yet
     */
    packagePath: readonly string[] | undefined;
    /**
     * In case of Revived - what node added the reference?
     */
    fromId?: string;
    /**
     * In case of Revived - was it revived due to autorecovery?
     */
    autorecovery?: true;
    /**
     * URL (including query string) if this usage came from a request
     */
    requestUrl?: string;
    /**
     * Original request headers if this usage came from a request or handle.get
     */
    requestHeaders?: string;
}
/**
 * Encapsulates the logic that tracks the various telemetry logged by the Garbage Collector.
 *
 * These events are not logged as errors, just generic events, since there can be false positives:
 *
 * 1. inactiveObject telemetry - When an inactive node is used - A node that has been unreferenced for inactiveTimeoutMs.
 * 2. tombstoneReadyObject telemetry - When a tombstone-ready node is used - A node that has been unreferenced for tombstoneTimeoutMs.
 * 3. sweepReadyObject telemetry - When a sweep-ready node is used - A node that has been unreferenced for tombstoneTimeoutMs + sweepGracePeriodMs.
 *
 * These events are logged as errors since they are based on the core GC logic:
 *
 * 1. Tombstone telemetry - When a tombstoned node is used - A node that has been marked as tombstone.
 * 2. Unknown outbound reference telemetry - When a node is referenced but GC was not notified of it when the new reference appeared.
 *
 * Note: The telemetry for a Deleted node being used is logged elsewhere in this package.
 */
export declare class GCTelemetryTracker {
    private readonly mc;
    private readonly configs;
    private readonly isSummarizerClient;
    private readonly createContainerMetadata;
    private readonly getNodeType;
    private readonly getNodeStateTracker;
    private readonly getNodePackagePath;
    private readonly loggedUnreferencedEvents;
    private pendingEventsQueue;
    constructor(mc: MonitoringContext, configs: IGarbageCollectorConfigs, isSummarizerClient: boolean, createContainerMetadata: ICreateContainerMetadata, getNodeType: (nodeId: string) => GCNodeType, getNodeStateTracker: (nodeId: string) => UnreferencedStateTracker | undefined, getNodePackagePath: (nodePath: string) => Promise<readonly string[] | undefined>);
    /**
     * Returns whether an event should be logged for a node that isn't active anymore.
     *
     * @remarks
     * This does not apply to tombstoned nodes for which an event is always logged. Some scenarios where we won't log:
     *
     * 1. When a DDS is changed. The corresponding data store's event will be logged instead.
     *
     * 2. An event is logged only once per container instance per event per node.
     */
    private shouldLogNonActiveEvent;
    /**
     * Called when a node is used. If the node is inactive or tombstoned, log telemetry indicating object is used
     * when it should not have been.
     * @param trackedId - The id that GC uses to track the node. For SubDataStore nodes, this should be the DataStore ID.
     * @param INodeUsageProps - All kind of details about this event to be logged
     */
    nodeUsed(trackedId: string, { usageType, currentReferenceTimestampMs, packagePath, id: untaggedId, fromId: untaggedFromId, isTombstoned, ...otherNodeUsageProps }: INodeUsageProps): void;
    /**
     * Logs telemetry when a tombstoned object is changed, revived or loaded.
     */
    private logTombstoneUsageTelemetry;
    /**
     * Log all new references or outbound routes in the current graph that haven't been explicitly notified to GC.
     * The principle is that every new reference or outbound route must be notified to GC via the
     * addedOutboundReference method. It it hasn't, its a bug and we want to identify these scenarios.
     *
     * In more simple terms:
     * Missing Explicit References = Current References - Previous References - Explicitly Added References;
     *
     * @param currentGCData - The GC data (reference graph) from the current GC run.
     * @param previousGCData - The GC data (reference graph) from the previous GC run.
     * @param explicitReferences - New references added explicity between the previous and the current run.
     */
    logIfMissingExplicitReferences(currentGCData: IGarbageCollectionData, previousGCData: IGarbageCollectionData, explicitReferences: Map<string, string[]>, logger: ITelemetryLoggerExt): void;
    /**
     * Log events that are pending in pendingEventsQueue. This is called after GC runs in the summarizer client
     * so that the state of an unreferenced node is updated.
     */
    logPendingEvents(logger: ITelemetryLoggerExt): Promise<void>;
}
export {};
//# sourceMappingURL=gcTelemetry.d.ts.map