Fixes telemetry for the IdCompressor and also adds telemetry for summary size
This commit is contained in:
justus-camp 2022-12-08 11:35:11 -08:00 коммит произвёл GitHub
Родитель 8db0601af7
Коммит 05000808d1
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 248 добавлений и 13 удалений

Просмотреть файл

@ -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;
}