Skip to content

Commit

Permalink
feat: (observability) plumb and pass ObservabilityConfig into Spanner…
Browse files Browse the repository at this point in the history
…, 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
  • Loading branch information
odeke-em committed Sep 28, 2024
1 parent 37e0346 commit 5335b40
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 6 deletions.
4 changes: 3 additions & 1 deletion src/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ import Policy = google.iam.v1.Policy;
import FieldMask = google.protobuf.FieldMask;
import IDatabase = google.spanner.admin.database.v1.IDatabase;
import snakeCase = require('lodash.snakecase');
import {getActiveOrNoopSpan} from './instrument';
import {ObservabilityOptions, getActiveOrNoopSpan} from './instrument';

export type GetDatabaseRolesCallback = RequestCallback<
IDatabaseRole,
Expand Down Expand Up @@ -337,6 +337,7 @@ class Database extends common.GrpcServiceObject {
databaseDialect?: EnumKey<
typeof databaseAdmin.spanner.admin.database.v1.DatabaseDialect
> | null;
observabilityConfig: ObservabilityOptions | undefined;
constructor(
instance: Instance,
name: string,
Expand Down Expand Up @@ -459,6 +460,7 @@ class Database extends common.GrpcServiceObject {
Object.assign({}, queryOptions),
Database.getEnvironmentQueryOptions()
);
this.observabilityConfig = instance.observabilityConfig;
}
/**
* @typedef {array} SetDatabaseMetadataResponse
Expand Down
5 changes: 5 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ import {
import grpcGcpModule = require('grpc-gcp');
const grpcGcp = grpcGcpModule(grpc);
import * as v1 from './v1';
import {ObservabilityOptions} from './instrument';

// eslint-disable-next-line @typescript-eslint/no-var-requires
const gcpApiConfig = require('./spanner_grpc_config.json');
Expand Down Expand Up @@ -138,6 +139,7 @@ export interface SpannerOptions extends GrpcClientOptions {
sslCreds?: grpc.ChannelCredentials;
routeToLeaderEnabled?: boolean;
directedReadOptions?: google.spanner.v1.IDirectedReadOptions | null;
observabilityConfig?: ObservabilityOptions | undefined;
}
export interface RequestConfig {
client: string;
Expand Down Expand Up @@ -239,6 +241,7 @@ class Spanner extends GrpcService {
resourceHeader_: {[k: string]: string};
routeToLeaderEnabled = true;
directedReadOptions: google.spanner.v1.IDirectedReadOptions | null;
observabilityConfig: ObservabilityOptions | undefined;

/**
* Placeholder used to auto populate a column with the commit timestamp.
Expand Down Expand Up @@ -365,6 +368,7 @@ class Spanner extends GrpcService {
[CLOUD_RESOURCE_HEADER]: this.projectFormattedName_,
};
this.directedReadOptions = directedReadOptions;
this.observabilityConfig = options.observabilityConfig;
}

/**
Expand Down Expand Up @@ -585,6 +589,7 @@ class Spanner extends GrpcService {
return;
}
const instance = this.instance(formattedName);
instance.observabilityConfig = this.observabilityConfig;
callback!(null, instance, operation, resp);
}
);
Expand Down
11 changes: 7 additions & 4 deletions src/instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import {google as instanceAdmin} from '../protos/protos';
import {google as databaseAdmin} from '../protos/protos';
import {google as spannerClient} from '../protos/protos';
import {CreateInstanceRequest} from './index';
import {ObservabilityOptions} from './instrument';

export type IBackup = databaseAdmin.spanner.admin.database.v1.IBackup;
export type IDatabase = databaseAdmin.spanner.admin.database.v1.IDatabase;
Expand Down Expand Up @@ -164,6 +165,7 @@ class Instance extends common.GrpcServiceObject {
databases_: Map<string, Database>;
metadata?: IInstance;
resourceHeader_: {[k: string]: string};
observabilityConfig: ObservabilityOptions | undefined;
constructor(spanner: Spanner, name: string) {
const formattedName_ = Instance.formatName_(spanner.projectId, name);
const methods = {
Expand Down Expand Up @@ -239,6 +241,7 @@ class Instance extends common.GrpcServiceObject {
this.resourceHeader_ = {
[CLOUD_RESOURCE_HEADER]: this.formattedName_,
};
this.observabilityConfig = spanner.observabilityConfig;
}

/**
Expand Down Expand Up @@ -925,6 +928,7 @@ class Instance extends common.GrpcServiceObject {
return;
}
const database = this.database(name, poolOptions || poolCtor);
database.observabilityConfig = this.observabilityConfig;
callback(null, database, operation, resp);
}
);
Expand Down Expand Up @@ -973,10 +977,9 @@ class Instance extends common.GrpcServiceObject {
}
const key = name.split('/').pop() + optionsKey;
if (!this.databases_.has(key!)) {
this.databases_.set(
key!,
new Database(this, name, poolOptions, queryOptions)
);
const db = new Database(this, name, poolOptions, queryOptions);
db.observabilityConfig = this.observabilityConfig;
this.databases_.set(key!, db);
}
return this.databases_.get(key!)!;
}
Expand Down
58 changes: 57 additions & 1 deletion test/spanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const {
InMemorySpanExporter,
} = require('@opentelemetry/sdk-trace-node');
const {SimpleSpanProcessor} = require('@opentelemetry/sdk-trace-base');
const {startTrace} = require('../src/instrument');
const {ObservabilityOptions, startTrace} = require('../src/instrument');

function numberToEnglishWord(num: number): string {
switch (num) {
Expand Down Expand Up @@ -5061,6 +5061,62 @@ describe('Spanner with mock server', () => {
);
});
});

it('Plumb ObservabilityConfig into Spanner, Instance and Database', () => {
const exporter = new InMemorySpanExporter();
const provider = new NodeTracerProvider({
sampler: new AlwaysOnSampler(),
exporter: exporter,
});
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));

const observabilityConfig: typeof ObservabilityOptions = {
tracerProvider: provider,
enableExtendedTracing: true,
};
const spanner = new Spanner({
servicePath: 'localhost',
port,
sslCreds: grpc.credentials.createInsecure(),
observabilityConfig: observabilityConfig,
});

// Ensure that the same observability configuration is set on the Spanner client.
assert.deepStrictEqual(spanner.observabilityConfig, observabilityConfig);

// Acquire a handle to the Instance through spanner.instance.
const instanceByHandle = spanner.instance('instance');
assert.deepStrictEqual(
instanceByHandle.observabilityConfig,
observabilityConfig
);

// Create the Instance by means of a constructor directly.
const instanceByConstructor = new Instance(spanner, 'myInstance');
assert.deepStrictEqual(
instanceByConstructor.observabilityConfig,
observabilityConfig
);

// Acquire a handle to the Database through instance.database.
const databaseByHandle = instanceByHandle.database('database');
assert.deepStrictEqual(
databaseByHandle.observabilityConfig,
observabilityConfig
);

// Create the Database by means of a constructor directly.
const databaseByConstructor = new Database(
instanceByConstructor,
'myDatabase'
);
assert.deepStrictEqual(
databaseByConstructor.observabilityConfig,
observabilityConfig
);

spanner.close();
});
});

function executeSimpleUpdate(
Expand Down

0 comments on commit 5335b40

Please sign in to comment.