Skip to content

Commit

Permalink
add transcation root attribute (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
NimrodAvni78 authored Dec 4, 2023
1 parent 194c725 commit 8b973ea
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 7 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
- "**"

jobs:
build:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@coralogix/opentelemetry",
"version": "0.1.1",
"version": "0.1.2",
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
Expand Down
1 change: 1 addition & 0 deletions src/trace/common/coralogix-attributes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export const CoralogixAttributes = {
TRANSACTION_IDENTIFIER: 'cgx.transaction',
DISTRIBUTED_TRANSACTION_IDENTIFIER: 'cgx.transaction.distributed',
TRANSACTION_ROOT: 'cgx.transaction.root',
}
10 changes: 7 additions & 3 deletions src/trace/samplers/coralogix-transaction-sampler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@ export class CoralogixTransactionSampler implements Sampler {
// if distributed transaction exists, use it, if not this is the first span and thus the root of the distributed transaction
const distributedTransaction = spanContext?.traceState?.get(CoralogixTraceState.DISTRIBUTED_TRANSACTION_IDENTIFIER) ?? spanName;

const existingTransaction = spanContext?.traceState?.get(CoralogixTraceState.TRANSACTION_IDENTIFIER);

// if span is remote, then start a new transaction, else try to use existing transaction
const transaction = spanContext?.isRemote ? spanName :
(spanContext?.traceState?.get(CoralogixTraceState.TRANSACTION_IDENTIFIER) ?? spanName)
const startsTransaction = existingTransaction === undefined || spanContext?.isRemote;

const transaction = startsTransaction ? spanName : existingTransaction;

let {attributes: resultAttributes, traceState} = result;
const {decision} = result;
Expand All @@ -40,7 +43,8 @@ export class CoralogixTransactionSampler implements Sampler {
resultAttributes = {
...(resultAttributes ?? {}),
[CoralogixAttributes.TRANSACTION_IDENTIFIER]: transaction,
[CoralogixAttributes.DISTRIBUTED_TRANSACTION_IDENTIFIER]: distributedTransaction
[CoralogixAttributes.DISTRIBUTED_TRANSACTION_IDENTIFIER]: distributedTransaction,
[CoralogixAttributes.TRANSACTION_ROOT]: startsTransaction ?? undefined
}

return {
Expand Down
93 changes: 93 additions & 0 deletions test/trace/samplers/coralogix-transaction-sampler.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,99 @@ export default describe('CoralogixTransactionSampler', () => {
});
})

describe('transaction root attribute', () => {
it('add transaction root attribute to creator of transaction', () => {
const tracerProvider = new BasicTracerProvider({
sampler: new CoralogixTransactionSampler()
});
const tracer = tracerProvider.getTracer('default');

const span1 = tracer.startSpan('one', {}, context);
context = opentelemetry.trace.setSpan(context, span1);
const span2 = tracer.startSpan('two', {}, context);
context = opentelemetry.trace.setSpan(context, span2);
const span3 = tracer.startSpan('three', {}, context);
context = opentelemetry.trace.setSpan(context, span3);

if (span1 instanceof Span && span2 instanceof Span && span3 instanceof Span) {
assert.strictEqual(span1.attributes[CoralogixAttributes.TRANSACTION_ROOT], true,
'span1 must have transaction root');
assert.ok(!(CoralogixAttributes.TRANSACTION_ROOT in span2.attributes),
'span2 must not have transaction root');
assert.ok(!(CoralogixAttributes.TRANSACTION_ROOT in span3.attributes),
'span3 must not have transaction root');
} else {
assert.ok(span1 instanceof Span, 'span1 must be instance of Span');
assert.ok(span2 instanceof Span, 'span2 must be instance of Span');
assert.ok(span3 instanceof Span, 'span3 must be instance of Span');
}
span3.end();
span2.end();
span1.end();
});

it('add transaction root attribute span after remote', () => {
const tracerProvider = new BasicTracerProvider({
sampler: new CoralogixTransactionSampler()
});
const tracer = tracerProvider.getTracer('default');

const span1 = tracer.startSpan('one', {}, context);
context = opentelemetry.trace.setSpan(context, span1);
const span2 = tracer.startSpan('two', {}, context);
context = opentelemetry.trace.setSpan(context, span2);
context = getRemoteContext(context);
const span3 = tracer.startSpan('three', {}, context);
context = opentelemetry.trace.setSpan(context, span3);
const span4 = tracer.startSpan('four', {}, context);
context = opentelemetry.trace.setSpan(context, span4);

if (span1 instanceof Span && span2 instanceof Span && span3 instanceof Span && span4 instanceof Span) {
assert.strictEqual(span1.attributes[CoralogixAttributes.TRANSACTION_ROOT], true,
'span1 must have transaction root');
assert.ok(!(CoralogixAttributes.TRANSACTION_ROOT in span2.attributes),
'span2 must not have transaction root');
assert.strictEqual(span3.attributes[CoralogixAttributes.TRANSACTION_ROOT], true,
'span3 must have transaction root');
assert.ok(!(CoralogixAttributes.TRANSACTION_ROOT in span4.attributes),
'span4 must not have transaction root');
} else {
assert.ok(span1 instanceof Span, 'span1 must be instance of Span');
assert.ok(span2 instanceof Span, 'span2 must be instance of Span');
assert.ok(span3 instanceof Span, 'span3 must be instance of Span');
assert.ok(span4 instanceof Span, 'span4 must be instance of Span');
}
span4.end();
span3.end();
span2.end();
span1.end();
});

it('span with same name as transaction span should not be root transaction', () => {
const tracerProvider = new BasicTracerProvider({
sampler: new CoralogixTransactionSampler()
});
const tracer = tracerProvider.getTracer('default');

const span1 = tracer.startSpan('one', {}, context);
context = opentelemetry.trace.setSpan(context, span1);
const span2 = tracer.startSpan('one', {}, context);
context = opentelemetry.trace.setSpan(context, span2);

if (span1 instanceof Span && span2 instanceof Span) {
assert.strictEqual(span1.attributes[CoralogixAttributes.TRANSACTION_ROOT], true,
'span1 must have transaction root');
assert.ok(!(CoralogixAttributes.TRANSACTION_ROOT in span2.attributes),
'span1 must not have transaction root');
} else {
assert.ok(span1 instanceof Span, 'span1 must be instance of Span');
assert.ok(span2 instanceof Span, 'span2 must be instance of Span');
}
span2.end();
span1.end();
});
})

const NON_SAMPLED_ATTRIBUTE_NAME = 'non_sampled';

class TestAttributeSamplingSampler implements Sampler {
Expand Down

0 comments on commit 8b973ea

Please sign in to comment.