Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test in-memory test github actions falkiness #2237

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions dev/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -792,8 +792,7 @@ export class Firestore implements firestore.Firestore {
}

private newTraceUtilInstance(settings: firestore.Settings): TraceUtil {
// Take the tracing option from the settings.
let createEnabledInstance = settings.openTelemetryOptions?.enableTracing;
let createEnabledInstance = true;

// The environment variable can override options to enable/disable telemetry collection.
if ('FIRESTORE_ENABLE_TRACING' in process.env) {
Expand Down
7 changes: 6 additions & 1 deletion dev/src/reference/query-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ export class QueryUtil<
const tag = requestTag();
const startTime = Date.now();
const isExplain = explainOptions !== undefined;
const methodName = 'runQuery';

let numDocumentsReceived = 0;
let lastReceivedDocument: QueryDocumentSnapshot<
Expand Down Expand Up @@ -245,6 +246,11 @@ export class QueryUtil<

if (proto.done) {
logger('QueryUtil._stream', tag, 'Trigger Logical Termination.');
this._firestore._traceUtil
.currentSpan()
.addEvent(
`Firestore.${methodName}: Received RunQueryResponse.Done.`
);
backendStream.unpipe(stream);
backendStream.resume();
backendStream.end();
Expand All @@ -265,7 +271,6 @@ export class QueryUtil<
let streamActive: Deferred<boolean>;
do {
streamActive = new Deferred<boolean>();
const methodName = 'runQuery';

this._firestore._traceUtil
.currentSpan()
Expand Down
4 changes: 4 additions & 0 deletions dev/src/telemetry/disabled-trace-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
import {Attributes, TraceUtil} from './trace-util';
import {Span} from './span';

/**
* @private
* @internal
*/
export class DisabledTraceUtil implements TraceUtil {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
startSpan(name: string): Span {
Expand Down
27 changes: 23 additions & 4 deletions dev/src/telemetry/enabled-trace-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
trace,
Tracer,
Span as OpenTelemetrySpan,
TracerProvider,
} from '@opentelemetry/api';

import {Span} from './span';
Expand All @@ -33,22 +34,40 @@ import {DEFAULT_DATABASE_ID} from '../path';
import {DEFAULT_MAX_IDLE_CHANNELS} from '../index';
const serviceConfig = interfaces['google.firestore.v1.Firestore'];

/**
* @private
* @internal
*/
export class EnabledTraceUtil implements TraceUtil {
private tracer: Tracer;
private settingsAttributes: Attributes;

// Visible for testing
tracerProvider: TracerProvider;

constructor(settings: Settings) {
let tracerProvider = settings.openTelemetryOptions?.tracerProvider;
let provider: TracerProvider | undefined =
settings.openTelemetry?.tracerProvider;

// If a TracerProvider has not been given to us, we try to use the global one.
if (!tracerProvider) {
if (!provider) {
const {trace} = require('@opentelemetry/api');
tracerProvider = trace.getTracerProvider();
provider = trace.getTracerProvider();
}

// At this point provider is guaranteed to be defined because
// `trace.getTracerProvider()` does not return null or undefined.
this.tracerProvider = provider!;

const libVersion = require('../../../package.json').version;
const libName = require('../../../package.json').name;
this.tracer = tracerProvider.getTracer(libName, libVersion);
try {
this.tracer = this.tracerProvider.getTracer(libName, libVersion);
} catch (e) {
throw new Error(
"The object provided for 'tracerProvider' does not conform to the TracerProvider interface."
);
}

this.settingsAttributes = {};
this.settingsAttributes['otel.scope.name'] = libName;
Expand Down
4 changes: 4 additions & 0 deletions dev/src/telemetry/span.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
import {Span as OpenTelemetrySpan} from '@opentelemetry/api';
import {Attributes} from './trace-util';

/**
* @private
* @internal
*/
export class Span {
constructor(private span?: OpenTelemetrySpan) {}

Expand Down
13 changes: 13 additions & 0 deletions dev/src/telemetry/trace-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,18 @@

import {Span} from './span';

/**
* @private
* @internal
*/
export interface Attributes {
[attributeKey: string]: AttributeValue | undefined;
}

/**
* @private
* @internal
*/
export declare type AttributeValue =
| string
| number
Expand Down Expand Up @@ -67,6 +76,10 @@ export const ATTRIBUTE_KEY_TRANSACTION_TYPE = 'transaction_type';
export const ATTRIBUTE_KEY_ATTEMPTS_ALLOWED = 'attempts_allowed';
export const ATTRIBUTE_KEY_ATTEMPTS_REMAINING = 'attempts_remaining';

/**
* @private
* @internal
*/
export interface TraceUtil {
startActiveSpan<F extends (span: Span) => unknown>(
name: string,
Expand Down
61 changes: 49 additions & 12 deletions dev/system-test/tracing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
Context as OpenTelemetryContext,
} from '@opentelemetry/api';
import {TraceExporter} from '@google-cloud/opentelemetry-cloud-trace-exporter';
import {Settings} from '@google-cloud/firestore';
import {FirestoreOpenTelemetryOptions, Settings} from '@google-cloud/firestore';
import {
AlwaysOnSampler,
BatchSpanProcessor,
Expand Down Expand Up @@ -96,13 +96,6 @@
console.log(`LOG: ${msg}`);
});

// TODO(tracing): This should be moved to firestore.d.ts when we want to
// release the feature.
export interface FirestoreOpenTelemetryOptions {
enableTracing?: boolean;
tracerProvider?: any;
}

interface TestConfig {
// In-Memory tests check trace correctness by inspecting traces in memory by
// utilizing InMemorySpanExporter. These tests have `e2e` set to `false`.
Expand Down Expand Up @@ -160,7 +153,7 @@
}
}

describe('Tracing Tests', () => {
describe.only('Tracing Tests', () => {

Check failure on line 156 in dev/system-test/tracing.ts

View workflow job for this annotation

GitHub Actions / lint

'describe.only' is restricted from being used
let firestore: Firestore;
let tracerProvider: NodeTracerProvider;
let inMemorySpanExporter: InMemorySpanExporter;
Expand Down Expand Up @@ -192,7 +185,6 @@
tracerProvider: TracerProvider
): FirestoreOpenTelemetryOptions {
const options: FirestoreOpenTelemetryOptions = {
enableTracing: true,
tracerProvider: undefined,
};

Expand Down Expand Up @@ -285,7 +277,7 @@

const settings: Settings = {
preferRest: testConfig.preferRest,
openTelemetryOptions: getOpenTelemetryOptions(tracerProvider),
openTelemetry: getOpenTelemetryOptions(tracerProvider),
};

// Named-database tests use an environment variable to specify the database ID. Add it to the settings.
Expand Down Expand Up @@ -660,7 +652,7 @@

// Expect that the span exists first.
const span = getSpanByName(spanName);
expect(span).to.not.be.null;
expect(span, `Could not find the span named ${spanName}`).to.not.be.null;

// Assert that the expected attributes are present in the span attributes.
// Note that the span attributes may be a superset of the attributes passed
Expand All @@ -672,6 +664,29 @@
}
}

// Ensures that the given span exists and has the given attributes.
function expectSpanHasEvents(spanName: string, eventNames: string[]): void {
// The Cloud Trace API does not return span attributes and events.
if (testConfig.e2e) {
return;
}

// Expect that the span exists first.
const span = getSpanByName(spanName);
expect(span, `Could not find the span named ${spanName}`).to.not.be.null;

// Assert that the expected attributes are present in the span attributes.
// Note that the span attributes may be a superset of the attributes passed
// to this function.
if (span?.events) {
const numEvents = eventNames.length;
expect(numEvents).to.equal(span.events.length, `${span.events.map(value => value.name)} did not match ${eventNames}`);

Check failure on line 683 in dev/system-test/tracing.ts

View workflow job for this annotation

GitHub Actions / lint

Replace `span.events.length,·`${span.events.map(value·=>·value.name)}·did·not·match·${eventNames}`` with `⏎········span.events.length,⏎········`${span.events.map(value·=>·value.name)}·did·not·match·${eventNames}`⏎······`
for (let i = 0; i < numEvents; ++i) {
expect(span.events[i].name).to.equal(eventNames[i]);
}
}
}

describe(IN_MEMORY_TEST_SUITE_TITLE, () => {
describe(NON_GLOBAL_OTEL_TEST_SUITE_TITLE, () => {
describe(GRPC_TEST_SUITE_TITLE, () => {
Expand Down Expand Up @@ -753,6 +768,11 @@
SPAN_NAME_DOC_REF_GET,
SPAN_NAME_BATCH_GET_DOCUMENTS
);
expectSpanHasEvents(SPAN_NAME_BATCH_GET_DOCUMENTS, [
'Firestore.batchGetDocuments: Start',
'Firestore.batchGetDocuments: First response received',
'Firestore.batchGetDocuments: Completed',
]);
});

it('document reference create()', async () => {
Expand Down Expand Up @@ -820,6 +840,11 @@
);
await waitForCompletedSpans(2);
expectSpanHierarchy(SPAN_NAME_TEST_ROOT, SPAN_NAME_AGGREGATION_QUERY_GET);
expectSpanHasEvents(SPAN_NAME_AGGREGATION_QUERY_GET, [
'Firestore.runAggregationQuery: Start',
'Firestore.runAggregationQuery: First response received',
'Firestore.runAggregationQuery: Completed',
]);
});

it('collection reference add()', async () => {
Expand Down Expand Up @@ -852,6 +877,12 @@
);
await waitForCompletedSpans(2);
expectSpanHierarchy(SPAN_NAME_TEST_ROOT, SPAN_NAME_QUERY_GET);
expectSpanHasEvents(SPAN_NAME_QUERY_GET, [
'RunQuery',
'Firestore.runQuery: Start',
'Firestore.runQuery: First response received',
'Firestore.runQuery: Completed',
]);
});

it('firestore getAll()', async () => {
Expand All @@ -862,6 +893,11 @@
);
await waitForCompletedSpans(2);
expectSpanHierarchy(SPAN_NAME_TEST_ROOT, SPAN_NAME_BATCH_GET_DOCUMENTS);
expectSpanHasEvents(SPAN_NAME_BATCH_GET_DOCUMENTS, [
'Firestore.batchGetDocuments: Start',
'Firestore.batchGetDocuments: First response received',
'Firestore.batchGetDocuments: Completed',
]);
});

it('transaction', async () => {
Expand Down Expand Up @@ -920,6 +956,7 @@
await runFirestoreOperationInRootSpan(async () => {
const query = firestore.collectionGroup('foo');
let numPartitions = 0;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for await (const partition of query.getPartitions(3)) {
numPartitions++;
}
Expand Down
Loading
Loading