Skip to content

Commit

Permalink
feat(observability): trace Transaction
Browse files Browse the repository at this point in the history
This change adds observability tracing for
Transaction along with tests.

Updates googleapis#2079
Updates googleapis#2114
Requires PR googleapis#2145.
  • Loading branch information
odeke-em committed Oct 4, 2024
1 parent 5237e11 commit 1050d50
Show file tree
Hide file tree
Showing 3 changed files with 1,331 additions and 258 deletions.
214 changes: 214 additions & 0 deletions observability-test/spanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,220 @@ describe('ObservabilityOptions injection and propagation', async () => {
done();
});

describe('Transaction', () => {
it('run', done => {
database.getTransaction((err, tx) => {
assert.ifError(err);

tx!.run('SELECT 1', (err, rows) => {
traceExporter.forceFlush();

const spans = traceExporter.getFinishedSpans();

const actualSpanNames: string[] = [];
const actualEventNames: string[] = [];
spans.forEach(span => {
actualSpanNames.push(span.name);
span.events.forEach(event => {
actualEventNames.push(event.name);
});
});

const expectedSpanNames = [
'CloudSpanner.SessionPool.createSessions',
'CloudSpanner.Database.getTransaction',
'CloudSpanner.Snapshot.runStream',
'CloudSpanner.Snapshot.run',
];
assert.deepStrictEqual(
actualSpanNames,
expectedSpanNames,
`span names mismatch:\n\tGot: ${actualSpanNames}\n\tWant: ${expectedSpanNames}`
);

const expectedEventNames = [
'Requesting 25 sessions',
'Creating 25 sessions',
'Requested for 25 sessions returned 25',
'Acquiring session',
'Waiting for a session to become available',
'Acquired session',
'Using Session',
'Transaction Creation Done',
];
assert.strictEqual(
actualEventNames.every(value => expectedEventNames.includes(value)),
true,
`Unexpected events:\n\tGot: ${actualEventNames}\n\tWant: ${expectedEventNames}`
);

done();
});
});
});

it('Transaction.begin+Dml.runUpdate', done => {
database.getTransaction((err, tx) => {
assert.ifError(err);

// Firstly erase the prior spans so that we can have only Transaction spans.
traceExporter.reset();

tx!.begin();
tx!.runUpdate(updateSql, (err, rowCount) => {
assert.ifError(err);

traceExporter.forceFlush();

const spans = traceExporter.getFinishedSpans();
assert.strictEqual(spans.length, 4);

const actualSpanNames: string[] = [];
const actualEventNames: string[] = [];
spans.forEach(span => {
actualSpanNames.push(span.name);
span.events.forEach(event => {
actualEventNames.push(event.name);
});
});

const expectedSpanNames = [
'CloudSpanner.Snapshot.begin',
'CloudSpanner.Snapshot.runStream',
'CloudSpanner.Snapshot.run',
'CloudSpanner.Dml.runUpdate',
];
assert.deepStrictEqual(
actualSpanNames,
expectedSpanNames,
`span names mismatch:\n\tGot: ${actualSpanNames}\n\tWant: ${expectedSpanNames}`
);

const expectedEventNames = [
'Begin Transaction',
'Transaction Creation Done',
];
assert.strictEqual(
actualEventNames.every(value => expectedEventNames.includes(value)),
true,
`Unexpected events:\n\tGot: ${actualEventNames}\n\tWant: ${expectedEventNames}`
);

done();
});
});
});

it('runStream', done => {
let rowCount = 0;
database.getTransaction((err, tx) => {
assert.ifError(err);
tx!
.runStream(selectSql)
.on('data', () => rowCount++)
.on('error', assert.ifError)
.on('stats', _stats => {})
.on('end', () => {
tx!.end();

traceExporter.forceFlush();

const spans = traceExporter.getFinishedSpans();

const actualSpanNames: string[] = [];
const actualEventNames: string[] = [];
spans.forEach(span => {
actualSpanNames.push(span.name);
span.events.forEach(event => {
actualEventNames.push(event.name);
});
});

const expectedSpanNames = [
'CloudSpanner.SessionPool.createSessions',
'CloudSpanner.Database.getTransaction',
'CloudSpanner.Snapshot.runStream',
];
assert.deepStrictEqual(
actualSpanNames,
expectedSpanNames,
`span names mismatch:\n\tGot: ${actualSpanNames}\n\tWant: ${expectedSpanNames}`
);

const expectedEventNames = [
'Requesting 25 sessions',
'Creating 25 sessions',
'Requested for 25 sessions returned 25',
'Using Session',
];
assert.deepStrictEqual(
actualEventNames,
expectedEventNames,
`Unexpected events:\n\tGot: ${actualEventNames}\n\tWant: ${expectedEventNames}`
);

done();
});
});
});

it('rollback', done => {
database.getTransaction((err, tx) => {
assert.ifError(err);

// Firstly erase the prior spans so that we can have only Transaction spans.
traceExporter.reset();

tx!.begin();

tx!.runUpdate(updateSql, async (err, rowCount) => {
assert.ifError(err);
tx!.rollback(err => {
traceExporter.forceFlush();

const spans = traceExporter.getFinishedSpans();

const actualSpanNames: string[] = [];
const actualEventNames: string[] = [];
spans.forEach(span => {
actualSpanNames.push(span.name);
span.events.forEach(event => {
actualEventNames.push(event.name);
});
});

const expectedSpanNames = [
'CloudSpanner.Snapshot.begin',
'CloudSpanner.Snapshot.runStream',
'CloudSpanner.Snapshot.run',
'CloudSpanner.Dml.runUpdate',
'CloudSpanner.Transaction.rollback',
];
assert.deepStrictEqual(
actualSpanNames,
expectedSpanNames,
`span names mismatch:\n\tGot: ${actualSpanNames}\n\tWant: ${expectedSpanNames}`
);

const expectedEventNames = [
'Begin Transaction',
'Transaction Creation Done',
];
assert.strictEqual(
actualEventNames.every(value =>
expectedEventNames.includes(value)
),
true,
`Unexpected events:\n\tGot: ${actualEventNames}\n\tWant: ${expectedEventNames}`
);

done();
});
});
});
});
});

it('Propagates spans to the injected not global TracerProvider', done => {
const instance = spanner.instance('instance');
const database = instance.database('database');
Expand Down
Loading

0 comments on commit 1050d50

Please sign in to comment.