mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-18 01:51:20 -07:00
chore(core): reassign telemetry keys to avoid server conflict (#18161)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This commit is contained in:
@@ -122,7 +122,7 @@ describe('NumericalClassifierStrategy', () => {
|
|||||||
expect(decision).toEqual({
|
expect(decision).toEqual({
|
||||||
model: DEFAULT_GEMINI_FLASH_MODEL,
|
model: DEFAULT_GEMINI_FLASH_MODEL,
|
||||||
metadata: {
|
metadata: {
|
||||||
source: 'Classifier (Control)',
|
source: 'NumericalClassifier (Control)',
|
||||||
latencyMs: expect.any(Number),
|
latencyMs: expect.any(Number),
|
||||||
reasoning: expect.stringContaining('Score: 40 / Threshold: 50'),
|
reasoning: expect.stringContaining('Score: 40 / Threshold: 50'),
|
||||||
},
|
},
|
||||||
@@ -148,7 +148,7 @@ describe('NumericalClassifierStrategy', () => {
|
|||||||
expect(decision).toEqual({
|
expect(decision).toEqual({
|
||||||
model: DEFAULT_GEMINI_MODEL,
|
model: DEFAULT_GEMINI_MODEL,
|
||||||
metadata: {
|
metadata: {
|
||||||
source: 'Classifier (Control)',
|
source: 'NumericalClassifier (Control)',
|
||||||
latencyMs: expect.any(Number),
|
latencyMs: expect.any(Number),
|
||||||
reasoning: expect.stringContaining('Score: 60 / Threshold: 50'),
|
reasoning: expect.stringContaining('Score: 60 / Threshold: 50'),
|
||||||
},
|
},
|
||||||
@@ -174,7 +174,7 @@ describe('NumericalClassifierStrategy', () => {
|
|||||||
expect(decision).toEqual({
|
expect(decision).toEqual({
|
||||||
model: DEFAULT_GEMINI_FLASH_MODEL, // Routed to Flash because 60 < 80
|
model: DEFAULT_GEMINI_FLASH_MODEL, // Routed to Flash because 60 < 80
|
||||||
metadata: {
|
metadata: {
|
||||||
source: 'Classifier (Strict)',
|
source: 'NumericalClassifier (Strict)',
|
||||||
latencyMs: expect.any(Number),
|
latencyMs: expect.any(Number),
|
||||||
reasoning: expect.stringContaining('Score: 60 / Threshold: 80'),
|
reasoning: expect.stringContaining('Score: 60 / Threshold: 80'),
|
||||||
},
|
},
|
||||||
@@ -200,7 +200,7 @@ describe('NumericalClassifierStrategy', () => {
|
|||||||
expect(decision).toEqual({
|
expect(decision).toEqual({
|
||||||
model: DEFAULT_GEMINI_MODEL,
|
model: DEFAULT_GEMINI_MODEL,
|
||||||
metadata: {
|
metadata: {
|
||||||
source: 'Classifier (Strict)',
|
source: 'NumericalClassifier (Strict)',
|
||||||
latencyMs: expect.any(Number),
|
latencyMs: expect.any(Number),
|
||||||
reasoning: expect.stringContaining('Score: 90 / Threshold: 80'),
|
reasoning: expect.stringContaining('Score: 90 / Threshold: 80'),
|
||||||
},
|
},
|
||||||
@@ -228,7 +228,7 @@ describe('NumericalClassifierStrategy', () => {
|
|||||||
expect(decision).toEqual({
|
expect(decision).toEqual({
|
||||||
model: DEFAULT_GEMINI_FLASH_MODEL, // Score 60 < Threshold 70
|
model: DEFAULT_GEMINI_FLASH_MODEL, // Score 60 < Threshold 70
|
||||||
metadata: {
|
metadata: {
|
||||||
source: 'Classifier (Remote)',
|
source: 'NumericalClassifier (Remote)',
|
||||||
latencyMs: expect.any(Number),
|
latencyMs: expect.any(Number),
|
||||||
reasoning: expect.stringContaining('Score: 60 / Threshold: 70'),
|
reasoning: expect.stringContaining('Score: 60 / Threshold: 70'),
|
||||||
},
|
},
|
||||||
@@ -254,7 +254,7 @@ describe('NumericalClassifierStrategy', () => {
|
|||||||
expect(decision).toEqual({
|
expect(decision).toEqual({
|
||||||
model: DEFAULT_GEMINI_FLASH_MODEL, // Score 40 < Threshold 45.5
|
model: DEFAULT_GEMINI_FLASH_MODEL, // Score 40 < Threshold 45.5
|
||||||
metadata: {
|
metadata: {
|
||||||
source: 'Classifier (Remote)',
|
source: 'NumericalClassifier (Remote)',
|
||||||
latencyMs: expect.any(Number),
|
latencyMs: expect.any(Number),
|
||||||
reasoning: expect.stringContaining('Score: 40 / Threshold: 45.5'),
|
reasoning: expect.stringContaining('Score: 40 / Threshold: 45.5'),
|
||||||
},
|
},
|
||||||
@@ -280,7 +280,7 @@ describe('NumericalClassifierStrategy', () => {
|
|||||||
expect(decision).toEqual({
|
expect(decision).toEqual({
|
||||||
model: DEFAULT_GEMINI_MODEL, // Score 35 >= Threshold 30
|
model: DEFAULT_GEMINI_MODEL, // Score 35 >= Threshold 30
|
||||||
metadata: {
|
metadata: {
|
||||||
source: 'Classifier (Remote)',
|
source: 'NumericalClassifier (Remote)',
|
||||||
latencyMs: expect.any(Number),
|
latencyMs: expect.any(Number),
|
||||||
reasoning: expect.stringContaining('Score: 35 / Threshold: 30'),
|
reasoning: expect.stringContaining('Score: 35 / Threshold: 30'),
|
||||||
},
|
},
|
||||||
@@ -308,7 +308,7 @@ describe('NumericalClassifierStrategy', () => {
|
|||||||
expect(decision).toEqual({
|
expect(decision).toEqual({
|
||||||
model: DEFAULT_GEMINI_FLASH_MODEL, // Score 40 < Default A/B Threshold 50
|
model: DEFAULT_GEMINI_FLASH_MODEL, // Score 40 < Default A/B Threshold 50
|
||||||
metadata: {
|
metadata: {
|
||||||
source: 'Classifier (Control)',
|
source: 'NumericalClassifier (Control)',
|
||||||
latencyMs: expect.any(Number),
|
latencyMs: expect.any(Number),
|
||||||
reasoning: expect.stringContaining('Score: 40 / Threshold: 50'),
|
reasoning: expect.stringContaining('Score: 40 / Threshold: 50'),
|
||||||
},
|
},
|
||||||
@@ -335,7 +335,7 @@ describe('NumericalClassifierStrategy', () => {
|
|||||||
expect(decision).toEqual({
|
expect(decision).toEqual({
|
||||||
model: DEFAULT_GEMINI_FLASH_MODEL,
|
model: DEFAULT_GEMINI_FLASH_MODEL,
|
||||||
metadata: {
|
metadata: {
|
||||||
source: 'Classifier (Control)',
|
source: 'NumericalClassifier (Control)',
|
||||||
latencyMs: expect.any(Number),
|
latencyMs: expect.any(Number),
|
||||||
reasoning: expect.stringContaining('Score: 40 / Threshold: 50'),
|
reasoning: expect.stringContaining('Score: 40 / Threshold: 50'),
|
||||||
},
|
},
|
||||||
@@ -362,7 +362,7 @@ describe('NumericalClassifierStrategy', () => {
|
|||||||
expect(decision).toEqual({
|
expect(decision).toEqual({
|
||||||
model: DEFAULT_GEMINI_MODEL,
|
model: DEFAULT_GEMINI_MODEL,
|
||||||
metadata: {
|
metadata: {
|
||||||
source: 'Classifier (Control)',
|
source: 'NumericalClassifier (Control)',
|
||||||
latencyMs: expect.any(Number),
|
latencyMs: expect.any(Number),
|
||||||
reasoning: expect.stringContaining('Score: 60 / Threshold: 50'),
|
reasoning: expect.stringContaining('Score: 60 / Threshold: 50'),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ export class NumericalClassifierStrategy implements RoutingStrategy {
|
|||||||
return {
|
return {
|
||||||
model: selectedModel,
|
model: selectedModel,
|
||||||
metadata: {
|
metadata: {
|
||||||
source: `Classifier (${groupLabel})`,
|
source: `NumericalClassifier (${groupLabel})`,
|
||||||
latencyMs,
|
latencyMs,
|
||||||
reasoning: `[Score: ${score} / Threshold: ${threshold}] ${routerResponse.complexity_reasoning}`,
|
reasoning: `[Score: ${score} / Threshold: ${threshold}] ${routerResponse.complexity_reasoning}`,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -941,6 +941,38 @@ describe('ClearcutLogger', () => {
|
|||||||
'Something went wrong',
|
'Something went wrong',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('logs a successful routing event with numerical routing fields', () => {
|
||||||
|
const { logger } = setup();
|
||||||
|
const event = new ModelRoutingEvent(
|
||||||
|
'gemini-pro',
|
||||||
|
'NumericalClassifier (Strict)',
|
||||||
|
123,
|
||||||
|
'[Score: 90 / Threshold: 80] reasoning',
|
||||||
|
false,
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
|
'80',
|
||||||
|
);
|
||||||
|
|
||||||
|
logger?.logModelRoutingEvent(event);
|
||||||
|
|
||||||
|
const events = getEvents(logger!);
|
||||||
|
expect(events.length).toBe(1);
|
||||||
|
expect(events[0]).toHaveEventName(EventNames.MODEL_ROUTING);
|
||||||
|
expect(events[0]).toHaveMetadataValue([
|
||||||
|
EventMetadataKey.GEMINI_CLI_ROUTING_REASONING,
|
||||||
|
'[Score: 90 / Threshold: 80] reasoning',
|
||||||
|
]);
|
||||||
|
expect(events[0]).toHaveMetadataValue([
|
||||||
|
EventMetadataKey.GEMINI_CLI_ROUTING_NUMERICAL_ENABLED,
|
||||||
|
'true',
|
||||||
|
]);
|
||||||
|
expect(events[0]).toHaveMetadataValue([
|
||||||
|
EventMetadataKey.GEMINI_CLI_ROUTING_CLASSIFIER_THRESHOLD,
|
||||||
|
'80',
|
||||||
|
]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('logAgentStartEvent', () => {
|
describe('logAgentStartEvent', () => {
|
||||||
|
|||||||
@@ -1234,6 +1234,28 @@ export class ClearcutLogger {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event.reasoning && this.config?.getTelemetryLogPromptsEnabled()) {
|
||||||
|
data.push({
|
||||||
|
gemini_cli_key: EventMetadataKey.GEMINI_CLI_ROUTING_REASONING,
|
||||||
|
value: event.reasoning,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.enable_numerical_routing !== undefined) {
|
||||||
|
data.push({
|
||||||
|
gemini_cli_key: EventMetadataKey.GEMINI_CLI_ROUTING_NUMERICAL_ENABLED,
|
||||||
|
value: event.enable_numerical_routing.toString(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.classifier_threshold) {
|
||||||
|
data.push({
|
||||||
|
gemini_cli_key:
|
||||||
|
EventMetadataKey.GEMINI_CLI_ROUTING_CLASSIFIER_THRESHOLD,
|
||||||
|
value: event.classifier_threshold,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.enqueueLogEvent(this.createLogEvent(EventNames.MODEL_ROUTING, data));
|
this.enqueueLogEvent(this.createLogEvent(EventNames.MODEL_ROUTING, data));
|
||||||
this.flushIfNeeded();
|
this.flushIfNeeded();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
// Defines valid event metadata keys for Clearcut logging.
|
// Defines valid event metadata keys for Clearcut logging.
|
||||||
export enum EventMetadataKey {
|
export enum EventMetadataKey {
|
||||||
// Deleted enums: 24
|
// Deleted enums: 24
|
||||||
// Next ID: 144
|
// Next ID: 148
|
||||||
|
|
||||||
GEMINI_CLI_KEY_UNKNOWN = 0,
|
GEMINI_CLI_KEY_UNKNOWN = 0,
|
||||||
|
|
||||||
@@ -542,4 +542,17 @@ export enum EventMetadataKey {
|
|||||||
|
|
||||||
// Logs the duration spent in an approval mode in milliseconds.
|
// Logs the duration spent in an approval mode in milliseconds.
|
||||||
GEMINI_CLI_APPROVAL_MODE_DURATION_MS = 143,
|
GEMINI_CLI_APPROVAL_MODE_DURATION_MS = 143,
|
||||||
|
|
||||||
|
// ==========================================================================
|
||||||
|
// Model Routing Event Keys (Cont.)
|
||||||
|
// ==========================================================================
|
||||||
|
|
||||||
|
// Logs the reasoning for the routing decision.
|
||||||
|
GEMINI_CLI_ROUTING_REASONING = 145,
|
||||||
|
|
||||||
|
// Logs whether numerical routing was enabled.
|
||||||
|
GEMINI_CLI_ROUTING_NUMERICAL_ENABLED = 146,
|
||||||
|
|
||||||
|
// Logs the classifier threshold used.
|
||||||
|
GEMINI_CLI_ROUTING_CLASSIFIER_THRESHOLD = 147,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1734,6 +1734,37 @@ describe('loggers', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should log the event with numerical routing fields', () => {
|
||||||
|
const event = new ModelRoutingEvent(
|
||||||
|
'gemini-pro',
|
||||||
|
'NumericalClassifier (Strict)',
|
||||||
|
150,
|
||||||
|
'[Score: 90 / Threshold: 80] reasoning',
|
||||||
|
false,
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
|
'80',
|
||||||
|
);
|
||||||
|
|
||||||
|
logModelRouting(mockConfig, event);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
ClearcutLogger.prototype.logModelRoutingEvent,
|
||||||
|
).toHaveBeenCalledWith(event);
|
||||||
|
|
||||||
|
expect(mockLogger.emit).toHaveBeenCalledWith({
|
||||||
|
body: 'Model routing decision. Model: gemini-pro, Source: NumericalClassifier (Strict)',
|
||||||
|
attributes: {
|
||||||
|
'session.id': 'test-session-id',
|
||||||
|
'user.email': 'test-user@example.com',
|
||||||
|
'installation.id': 'test-installation-id',
|
||||||
|
...event,
|
||||||
|
'event.name': EVENT_MODEL_ROUTING,
|
||||||
|
interactive: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should only log to Clearcut if OTEL SDK is not initialized', () => {
|
it('should only log to Clearcut if OTEL SDK is not initialized', () => {
|
||||||
vi.spyOn(sdk, 'isTelemetrySdkInitialized').mockReturnValue(false);
|
vi.spyOn(sdk, 'isTelemetrySdkInitialized').mockReturnValue(false);
|
||||||
vi.spyOn(sdk, 'bufferTelemetryEvent').mockImplementation(() => {});
|
vi.spyOn(sdk, 'bufferTelemetryEvent').mockImplementation(() => {});
|
||||||
|
|||||||
@@ -489,7 +489,7 @@ describe('Telemetry Metrics', () => {
|
|||||||
initializeMetricsModule(mockConfig);
|
initializeMetricsModule(mockConfig);
|
||||||
const event = new ModelRoutingEvent(
|
const event = new ModelRoutingEvent(
|
||||||
'gemini-pro',
|
'gemini-pro',
|
||||||
'classifier',
|
'Classifier',
|
||||||
200,
|
200,
|
||||||
'test-reason',
|
'test-reason',
|
||||||
true,
|
true,
|
||||||
@@ -502,7 +502,7 @@ describe('Telemetry Metrics', () => {
|
|||||||
'installation.id': 'test-installation-id',
|
'installation.id': 'test-installation-id',
|
||||||
'user.email': 'test@example.com',
|
'user.email': 'test@example.com',
|
||||||
'routing.decision_model': 'gemini-pro',
|
'routing.decision_model': 'gemini-pro',
|
||||||
'routing.decision_source': 'classifier',
|
'routing.decision_source': 'Classifier',
|
||||||
'routing.failed': true,
|
'routing.failed': true,
|
||||||
'routing.reasoning': 'test-reason',
|
'routing.reasoning': 'test-reason',
|
||||||
});
|
});
|
||||||
@@ -513,7 +513,7 @@ describe('Telemetry Metrics', () => {
|
|||||||
'installation.id': 'test-installation-id',
|
'installation.id': 'test-installation-id',
|
||||||
'user.email': 'test@example.com',
|
'user.email': 'test@example.com',
|
||||||
'routing.decision_model': 'gemini-pro',
|
'routing.decision_model': 'gemini-pro',
|
||||||
'routing.decision_source': 'classifier',
|
'routing.decision_source': 'Classifier',
|
||||||
'routing.failed': true,
|
'routing.failed': true,
|
||||||
'routing.reasoning': 'test-reason',
|
'routing.reasoning': 'test-reason',
|
||||||
'routing.error_message': 'test-error',
|
'routing.error_message': 'test-error',
|
||||||
|
|||||||
Reference in New Issue
Block a user