Skip to content

Commit 5335b40

Browse files
committed
feat: (observability) plumb and pass ObservabilityConfig into Spanner, Instance, Database
This change plumbs ObservabilityConfig into Spanner, Instance and Database so that any subsequent traces will use it when beginning spans and later on for metrics. Updates #2079
1 parent 37e0346 commit 5335b40

File tree

4 files changed

+72
-6
lines changed

4 files changed

+72
-6
lines changed

src/database.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ import Policy = google.iam.v1.Policy;
102102
import FieldMask = google.protobuf.FieldMask;
103103
import IDatabase = google.spanner.admin.database.v1.IDatabase;
104104
import snakeCase = require('lodash.snakecase');
105-
import {getActiveOrNoopSpan} from './instrument';
105+
import {ObservabilityOptions, getActiveOrNoopSpan} from './instrument';
106106

107107
export type GetDatabaseRolesCallback = RequestCallback<
108108
IDatabaseRole,
@@ -337,6 +337,7 @@ class Database extends common.GrpcServiceObject {
337337
databaseDialect?: EnumKey<
338338
typeof databaseAdmin.spanner.admin.database.v1.DatabaseDialect
339339
> | null;
340+
observabilityConfig: ObservabilityOptions | undefined;
340341
constructor(
341342
instance: Instance,
342343
name: string,
@@ -459,6 +460,7 @@ class Database extends common.GrpcServiceObject {
459460
Object.assign({}, queryOptions),
460461
Database.getEnvironmentQueryOptions()
461462
);
463+
this.observabilityConfig = instance.observabilityConfig;
462464
}
463465
/**
464466
* @typedef {array} SetDatabaseMetadataResponse

src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ import {
8080
import grpcGcpModule = require('grpc-gcp');
8181
const grpcGcp = grpcGcpModule(grpc);
8282
import * as v1 from './v1';
83+
import {ObservabilityOptions} from './instrument';
8384

8485
// eslint-disable-next-line @typescript-eslint/no-var-requires
8586
const gcpApiConfig = require('./spanner_grpc_config.json');
@@ -138,6 +139,7 @@ export interface SpannerOptions extends GrpcClientOptions {
138139
sslCreds?: grpc.ChannelCredentials;
139140
routeToLeaderEnabled?: boolean;
140141
directedReadOptions?: google.spanner.v1.IDirectedReadOptions | null;
142+
observabilityConfig?: ObservabilityOptions | undefined;
141143
}
142144
export interface RequestConfig {
143145
client: string;
@@ -239,6 +241,7 @@ class Spanner extends GrpcService {
239241
resourceHeader_: {[k: string]: string};
240242
routeToLeaderEnabled = true;
241243
directedReadOptions: google.spanner.v1.IDirectedReadOptions | null;
244+
observabilityConfig: ObservabilityOptions | undefined;
242245

243246
/**
244247
* Placeholder used to auto populate a column with the commit timestamp.
@@ -365,6 +368,7 @@ class Spanner extends GrpcService {
365368
[CLOUD_RESOURCE_HEADER]: this.projectFormattedName_,
366369
};
367370
this.directedReadOptions = directedReadOptions;
371+
this.observabilityConfig = options.observabilityConfig;
368372
}
369373

370374
/**
@@ -585,6 +589,7 @@ class Spanner extends GrpcService {
585589
return;
586590
}
587591
const instance = this.instance(formattedName);
592+
instance.observabilityConfig = this.observabilityConfig;
588593
callback!(null, instance, operation, resp);
589594
}
590595
);

src/instance.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import {google as instanceAdmin} from '../protos/protos';
5151
import {google as databaseAdmin} from '../protos/protos';
5252
import {google as spannerClient} from '../protos/protos';
5353
import {CreateInstanceRequest} from './index';
54+
import {ObservabilityOptions} from './instrument';
5455

5556
export type IBackup = databaseAdmin.spanner.admin.database.v1.IBackup;
5657
export type IDatabase = databaseAdmin.spanner.admin.database.v1.IDatabase;
@@ -164,6 +165,7 @@ class Instance extends common.GrpcServiceObject {
164165
databases_: Map<string, Database>;
165166
metadata?: IInstance;
166167
resourceHeader_: {[k: string]: string};
168+
observabilityConfig: ObservabilityOptions | undefined;
167169
constructor(spanner: Spanner, name: string) {
168170
const formattedName_ = Instance.formatName_(spanner.projectId, name);
169171
const methods = {
@@ -239,6 +241,7 @@ class Instance extends common.GrpcServiceObject {
239241
this.resourceHeader_ = {
240242
[CLOUD_RESOURCE_HEADER]: this.formattedName_,
241243
};
244+
this.observabilityConfig = spanner.observabilityConfig;
242245
}
243246

244247
/**
@@ -925,6 +928,7 @@ class Instance extends common.GrpcServiceObject {
925928
return;
926929
}
927930
const database = this.database(name, poolOptions || poolCtor);
931+
database.observabilityConfig = this.observabilityConfig;
928932
callback(null, database, operation, resp);
929933
}
930934
);
@@ -973,10 +977,9 @@ class Instance extends common.GrpcServiceObject {
973977
}
974978
const key = name.split('/').pop() + optionsKey;
975979
if (!this.databases_.has(key!)) {
976-
this.databases_.set(
977-
key!,
978-
new Database(this, name, poolOptions, queryOptions)
979-
);
980+
const db = new Database(this, name, poolOptions, queryOptions);
981+
db.observabilityConfig = this.observabilityConfig;
982+
this.databases_.set(key!, db);
980983
}
981984
return this.databases_.get(key!)!;
982985
}

test/spanner.ts

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ const {
7373
InMemorySpanExporter,
7474
} = require('@opentelemetry/sdk-trace-node');
7575
const {SimpleSpanProcessor} = require('@opentelemetry/sdk-trace-base');
76-
const {startTrace} = require('../src/instrument');
76+
const {ObservabilityOptions, startTrace} = require('../src/instrument');
7777

7878
function numberToEnglishWord(num: number): string {
7979
switch (num) {
@@ -5061,6 +5061,62 @@ describe('Spanner with mock server', () => {
50615061
);
50625062
});
50635063
});
5064+
5065+
it('Plumb ObservabilityConfig into Spanner, Instance and Database', () => {
5066+
const exporter = new InMemorySpanExporter();
5067+
const provider = new NodeTracerProvider({
5068+
sampler: new AlwaysOnSampler(),
5069+
exporter: exporter,
5070+
});
5071+
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
5072+
5073+
const observabilityConfig: typeof ObservabilityOptions = {
5074+
tracerProvider: provider,
5075+
enableExtendedTracing: true,
5076+
};
5077+
const spanner = new Spanner({
5078+
servicePath: 'localhost',
5079+
port,
5080+
sslCreds: grpc.credentials.createInsecure(),
5081+
observabilityConfig: observabilityConfig,
5082+
});
5083+
5084+
// Ensure that the same observability configuration is set on the Spanner client.
5085+
assert.deepStrictEqual(spanner.observabilityConfig, observabilityConfig);
5086+
5087+
// Acquire a handle to the Instance through spanner.instance.
5088+
const instanceByHandle = spanner.instance('instance');
5089+
assert.deepStrictEqual(
5090+
instanceByHandle.observabilityConfig,
5091+
observabilityConfig
5092+
);
5093+
5094+
// Create the Instance by means of a constructor directly.
5095+
const instanceByConstructor = new Instance(spanner, 'myInstance');
5096+
assert.deepStrictEqual(
5097+
instanceByConstructor.observabilityConfig,
5098+
observabilityConfig
5099+
);
5100+
5101+
// Acquire a handle to the Database through instance.database.
5102+
const databaseByHandle = instanceByHandle.database('database');
5103+
assert.deepStrictEqual(
5104+
databaseByHandle.observabilityConfig,
5105+
observabilityConfig
5106+
);
5107+
5108+
// Create the Database by means of a constructor directly.
5109+
const databaseByConstructor = new Database(
5110+
instanceByConstructor,
5111+
'myDatabase'
5112+
);
5113+
assert.deepStrictEqual(
5114+
databaseByConstructor.observabilityConfig,
5115+
observabilityConfig
5116+
);
5117+
5118+
spanner.close();
5119+
});
50645120
});
50655121

50665122
function executeSimpleUpdate(

0 commit comments

Comments
 (0)