Compressor telemetry (#13263)
Fixes telemetry for the IdCompressor and also adds telemetry for summary size
This commit is contained in:
Родитель
8db0601af7
Коммит
05000808d1
|
@ -590,7 +590,6 @@ export class IdCompressor {
|
|||
Math.min(currentCluster.count + finalizeCount, currentCluster.capacity) -
|
||||
1) as FinalCompressedId;
|
||||
if (lastFinalInCluster > lastKnownFinal) {
|
||||
eagerFinalIdCount = lastFinalInCluster - (lastKnownFinal + 1);
|
||||
this.sessionIdNormalizer.addFinalIds(
|
||||
(lastKnownFinal + 1) as FinalCompressedId,
|
||||
lastFinalInCluster,
|
||||
|
@ -604,6 +603,7 @@ export class IdCompressor {
|
|||
const hasRoom = overflow <= 0;
|
||||
if (hasRoom || currentBaseFinalId === this.finalIdToCluster.maxKey()) {
|
||||
currentCluster.count += remainingCount;
|
||||
eagerFinalIdCount = remainingCount;
|
||||
remainingCount = 0;
|
||||
// The common case is that there is room in the cluster, and the new final IDs can simply be added to it
|
||||
if (!hasRoom) {
|
||||
|
@ -654,7 +654,7 @@ export class IdCompressor {
|
|||
// the finalization of the ranges.
|
||||
this.sessionIdNormalizer.addFinalIds(finalPivot, newLastFinal, currentCluster);
|
||||
this.logger?.sendTelemetryEvent({
|
||||
eventName: 'IdCompressor:ClusterExpansion',
|
||||
eventName: 'SharedTreeIdCompressor:ClusterExpansion',
|
||||
sessionId: this.localSessionId,
|
||||
previousCapacity,
|
||||
newCapacity: currentCluster.capacity,
|
||||
|
@ -667,19 +667,22 @@ export class IdCompressor {
|
|||
// form a new one by incrementing the previous baseUuid
|
||||
newBaseUuid = incrementUuid(currentCluster.baseUuid, currentCluster.capacity);
|
||||
currentCluster.count += remainingCapacity;
|
||||
eagerFinalIdCount = remainingCapacity;
|
||||
remainingCount -= remainingCapacity;
|
||||
this.logger?.sendTelemetryEvent({
|
||||
eventName: 'IdCompressor:OverfilledCluster',
|
||||
eventName: 'SharedTreeIdCompressor:OverfilledCluster',
|
||||
sessionId: this.localSessionId,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Session has never made a cluster, form a new one with the session UUID as the baseUuid
|
||||
newBaseUuid = session.sessionUuid;
|
||||
this.logger?.sendTelemetryEvent({
|
||||
eventName: 'IdCompressor:FirstCluster',
|
||||
sessionId: this.localSessionId,
|
||||
});
|
||||
if (isLocal) {
|
||||
this.logger?.sendTelemetryEvent({
|
||||
eventName: 'SharedTreeIdCompressor:FirstCluster',
|
||||
sessionId: this.localSessionId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Finalizing a range results in one of three cases:
|
||||
|
@ -716,7 +719,7 @@ export class IdCompressor {
|
|||
|
||||
if (isLocal) {
|
||||
this.logger?.sendTelemetryEvent({
|
||||
eventName: 'IdCompressor:NewCluster',
|
||||
eventName: 'SharedTreeIdCompressor:NewCluster',
|
||||
sessionId: this.localSessionId,
|
||||
clusterCapacity: newCapacity,
|
||||
clusterCount: remainingCount,
|
||||
|
@ -839,9 +842,9 @@ export class IdCompressor {
|
|||
|
||||
if (isLocal) {
|
||||
this.logger?.sendTelemetryEvent({
|
||||
eventName: 'IdCompressor:IdCompressorStatus',
|
||||
eagerFinalIdCount,
|
||||
localIdCount: remainingCount,
|
||||
eventName: 'SharedTreeIdCompressor:IdCompressorStatus',
|
||||
eagerFinalIdCount: eagerFinalIdCount - (overrides?.length ?? 0),
|
||||
localIdCount: remainingCount + (overrides?.length ?? 0),
|
||||
overridesCount: overrides?.length ?? 0,
|
||||
sessionId: this.localSessionId,
|
||||
});
|
||||
|
@ -1621,6 +1624,13 @@ export class IdCompressor {
|
|||
return serializedWithSession;
|
||||
}
|
||||
|
||||
this.logger?.sendTelemetryEvent({
|
||||
eventName: 'SharedTreeIdCompressor:SerializedIdCompressorSize',
|
||||
size: JSON.stringify(serializedIdCompressor).length,
|
||||
clusterCount: serializedIdCompressor.clusters.length,
|
||||
sessionCount: serializedIdCompressor.sessions.length,
|
||||
});
|
||||
|
||||
return serializedIdCompressor as SerializedIdCompressor;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import { expect } from 'chai';
|
||||
import { v4, v5 } from 'uuid';
|
||||
import { MockLogger } from '@fluidframework/telemetry-utils';
|
||||
import { take } from '@fluid-internal/stochastic-test-utils';
|
||||
import {
|
||||
IdCompressor,
|
||||
|
@ -1155,6 +1156,224 @@ describe('IdCompressor', () => {
|
|||
);
|
||||
});
|
||||
|
||||
describe('Telemetry', () => {
|
||||
it('emits first cluster and new cluster telemetry events', () => {
|
||||
const mockLogger = new MockLogger();
|
||||
const compressor = createCompressor(Client.Client1, 5, undefined, mockLogger);
|
||||
const localId1 = compressor.generateCompressedId();
|
||||
expect(isLocalId(localId1)).to.be.true;
|
||||
compressor.finalizeCreationRange(compressor.takeNextCreationRange());
|
||||
|
||||
mockLogger.assertMatch([
|
||||
{
|
||||
eventName: 'SharedTreeIdCompressor:FirstCluster',
|
||||
sessionId: '88888888-8888-4888-b088-888888888888',
|
||||
},
|
||||
{
|
||||
eventName: 'SharedTreeIdCompressor:NewCluster',
|
||||
sessionId: '88888888-8888-4888-b088-888888888888',
|
||||
clusterCapacity: 5,
|
||||
clusterCount: 1,
|
||||
},
|
||||
{
|
||||
eventName: 'SharedTreeIdCompressor:IdCompressorStatus',
|
||||
sessionId: '88888888-8888-4888-b088-888888888888',
|
||||
eagerFinalIdCount: 0,
|
||||
overridesCount: 0,
|
||||
localIdCount: 1,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('emits new cluster event on second cluster', () => {
|
||||
// Fill the first cluster
|
||||
const mockLogger = new MockLogger();
|
||||
const compressor = createCompressor(Client.Client1, 5, undefined, mockLogger);
|
||||
for (let i = 0; i < 5; i++) {
|
||||
compressor.generateCompressedId();
|
||||
}
|
||||
const range = compressor.takeNextCreationRange();
|
||||
compressor.finalizeCreationRange(range);
|
||||
|
||||
// Create another cluster with a different client so that expansion doesn't happen
|
||||
const mockLogger2 = new MockLogger();
|
||||
const compressor2 = createCompressor(Client.Client2, 5, undefined, mockLogger2);
|
||||
compressor2.finalizeCreationRange(range);
|
||||
compressor2.generateCompressedId();
|
||||
const range2 = compressor2.takeNextCreationRange();
|
||||
compressor2.finalizeCreationRange(range2);
|
||||
compressor.finalizeCreationRange(range2);
|
||||
// Make sure we emitted the FirstCluster event
|
||||
mockLogger.assertMatchAny([
|
||||
{
|
||||
eventName: 'SharedTreeIdCompressor:FirstCluster',
|
||||
},
|
||||
]);
|
||||
mockLogger.clear();
|
||||
|
||||
// Trigger a new cluster creation and make sure FirstCluster isn't emitted
|
||||
compressor.generateCompressedId();
|
||||
compressor.finalizeCreationRange(compressor.takeNextCreationRange());
|
||||
mockLogger.assertMatchAny([
|
||||
{
|
||||
eventName: 'SharedTreeIdCompressor:NewCluster',
|
||||
},
|
||||
]);
|
||||
mockLogger.assertMatchNone([
|
||||
{
|
||||
eventName: 'SharedTreeIdCompressor:FirstCluster',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('correctly logs telemetry events for eager final id allocations', () => {
|
||||
const mockLogger = new MockLogger();
|
||||
const compressor = createCompressor(Client.Client1, 5, undefined, mockLogger);
|
||||
const localId1 = compressor.generateCompressedId();
|
||||
expect(isLocalId(localId1)).to.be.true;
|
||||
|
||||
compressor.finalizeCreationRange(compressor.takeNextCreationRange());
|
||||
mockLogger.assertMatchAny([
|
||||
{
|
||||
eventName: 'SharedTreeIdCompressor:IdCompressorStatus',
|
||||
eagerFinalIdCount: 0,
|
||||
localIdCount: 1,
|
||||
overridesCount: 0,
|
||||
sessionId: '88888888-8888-4888-b088-888888888888',
|
||||
},
|
||||
]);
|
||||
mockLogger.clear();
|
||||
const finalId1 = compressor.generateCompressedId();
|
||||
const finalId2 = compressor.generateCompressedId();
|
||||
expect(isFinalId(finalId1)).to.be.true;
|
||||
expect(isFinalId(finalId2)).to.be.true;
|
||||
|
||||
compressor.finalizeCreationRange(compressor.takeNextCreationRange());
|
||||
mockLogger.assertMatchAny([
|
||||
{
|
||||
eventName: 'SharedTreeIdCompressor:IdCompressorStatus',
|
||||
eagerFinalIdCount: 2,
|
||||
localIdCount: 0,
|
||||
overridesCount: 0,
|
||||
sessionId: '88888888-8888-4888-b088-888888888888',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('correctly logs telemetry events for expansion case', () => {
|
||||
const mockLogger = new MockLogger();
|
||||
const compressor = createCompressor(Client.Client1, 5, undefined, mockLogger);
|
||||
const localId1 = compressor.generateCompressedId();
|
||||
expect(isLocalId(localId1)).to.be.true;
|
||||
|
||||
compressor.finalizeCreationRange(compressor.takeNextCreationRange());
|
||||
mockLogger.assertMatchAny([
|
||||
{
|
||||
eventName: 'SharedTreeIdCompressor:IdCompressorStatus',
|
||||
eagerFinalIdCount: 0,
|
||||
localIdCount: 1,
|
||||
overridesCount: 0,
|
||||
sessionId: '88888888-8888-4888-b088-888888888888',
|
||||
},
|
||||
]);
|
||||
mockLogger.clear();
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
const id = compressor.generateCompressedId();
|
||||
expect(isFinalId(id)).to.be.true;
|
||||
}
|
||||
|
||||
compressor.finalizeCreationRange(compressor.takeNextCreationRange());
|
||||
mockLogger.assertMatchAny([
|
||||
{
|
||||
eventName: 'SharedTreeIdCompressor:IdCompressorStatus',
|
||||
eagerFinalIdCount: 4,
|
||||
localIdCount: 0,
|
||||
overridesCount: 0,
|
||||
sessionId: '88888888-8888-4888-b088-888888888888',
|
||||
},
|
||||
]);
|
||||
mockLogger.clear();
|
||||
|
||||
const expansionId1 = compressor.generateCompressedId();
|
||||
const expansionId2 = compressor.generateCompressedId();
|
||||
expect(isLocalId(expansionId1)).to.be.true;
|
||||
expect(isLocalId(expansionId2)).to.be.true;
|
||||
|
||||
compressor.finalizeCreationRange(compressor.takeNextCreationRange());
|
||||
mockLogger.assertMatch([
|
||||
{
|
||||
eventName: 'SharedTreeIdCompressor:ClusterExpansion',
|
||||
sessionId: '88888888-8888-4888-b088-888888888888',
|
||||
previousCapacity: 5,
|
||||
newCapacity: 12,
|
||||
overflow: 2,
|
||||
},
|
||||
{
|
||||
eventName: 'SharedTreeIdCompressor:IdCompressorStatus',
|
||||
eagerFinalIdCount: 2,
|
||||
localIdCount: 0,
|
||||
overridesCount: 0,
|
||||
sessionId: '88888888-8888-4888-b088-888888888888',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('emits correct telemetry status with overrides', () => {
|
||||
const mockLogger = new MockLogger();
|
||||
const compressor = createCompressor(Client.Client1, 5, undefined, mockLogger);
|
||||
const localId1 = compressor.generateCompressedId();
|
||||
expect(isLocalId(localId1)).to.be.true;
|
||||
|
||||
compressor.finalizeCreationRange(compressor.takeNextCreationRange());
|
||||
mockLogger.assertMatchAny([
|
||||
{
|
||||
eventName: 'SharedTreeIdCompressor:IdCompressorStatus',
|
||||
eagerFinalIdCount: 0,
|
||||
localIdCount: 1,
|
||||
overridesCount: 0,
|
||||
sessionId: '88888888-8888-4888-b088-888888888888',
|
||||
},
|
||||
]);
|
||||
mockLogger.clear();
|
||||
|
||||
const finalId2 = compressor.generateCompressedId();
|
||||
const overrideId3 = compressor.generateCompressedId('override');
|
||||
expect(isFinalId(finalId2)).to.be.true;
|
||||
expect(isLocalId(overrideId3)).to.be.true;
|
||||
|
||||
compressor.finalizeCreationRange(compressor.takeNextCreationRange());
|
||||
mockLogger.assertMatchAny([
|
||||
{
|
||||
eventName: 'SharedTreeIdCompressor:IdCompressorStatus',
|
||||
eagerFinalIdCount: 1,
|
||||
localIdCount: 1,
|
||||
overridesCount: 1,
|
||||
sessionId: '88888888-8888-4888-b088-888888888888',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('emits telemetry when serialized', () => {
|
||||
const mockLogger = new MockLogger();
|
||||
const compressor = createCompressor(Client.Client1, 5, undefined, mockLogger);
|
||||
const localId1 = compressor.generateCompressedId();
|
||||
expect(isLocalId(localId1)).to.be.true;
|
||||
|
||||
compressor.finalizeCreationRange(compressor.takeNextCreationRange());
|
||||
compressor.serialize(false);
|
||||
|
||||
mockLogger.assertMatchAny([
|
||||
{
|
||||
eventName: 'SharedTreeIdCompressor:SerializedIdCompressorSize',
|
||||
size: 137,
|
||||
clusterCount: 1,
|
||||
sessionCount: 1,
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Eager final ID allocation', () => {
|
||||
it('eagerly allocates final IDs when cluster creation has been finalized', () => {
|
||||
const compressor = createCompressor(Client.Client1, 5);
|
||||
|
|
|
@ -17,6 +17,7 @@ import {
|
|||
take,
|
||||
BaseFuzzTestState,
|
||||
} from '@fluid-internal/stochastic-test-utils';
|
||||
import { ITelemetryLogger } from '@fluidframework/common-definitions';
|
||||
import { assert, assertNotUndefined, ClosedMap, fail, getOrCreate } from '../../Common';
|
||||
import { IdCompressor, isLocalId } from '../../id-compressor/IdCompressor';
|
||||
import {
|
||||
|
@ -74,8 +75,13 @@ export const DestinationClient = { ...Client, ...MetaClient };
|
|||
/**
|
||||
* Creates a new compressor with the supplied cluster capacity.
|
||||
*/
|
||||
export function createCompressor(client: Client, clusterCapacity = 5, attributionId?: AttributionId): IdCompressor {
|
||||
const compressor = new IdCompressor(sessionIds.get(client), 1024, attributionId);
|
||||
export function createCompressor(
|
||||
client: Client,
|
||||
clusterCapacity = 5,
|
||||
attributionId?: AttributionId,
|
||||
logger?: ITelemetryLogger
|
||||
): IdCompressor {
|
||||
const compressor = new IdCompressor(sessionIds.get(client), 1024, attributionId, logger);
|
||||
compressor.clusterCapacity = clusterCapacity;
|
||||
return compressor;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче