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

feat: add support for OTel context propagation and harmonized spans (v3.x) #1659

Closed
wants to merge 67 commits into from
Closed
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
0d9c0b2
feat: use the propagation inject framework for OpenTelemetry publishes
feywind Nov 18, 2022
4f3daa9
feat: add propagation extraction to subscriber for OpenTelemetry
feywind Nov 18, 2022
80d8b65
feat: work in progress on adding sub-spans
feywind Nov 22, 2022
cbd5992
add more spans
feywind Nov 28, 2022
75acbab
wrap subscriber on() handlers to get better receive process spans
feywind Nov 30, 2022
bb6cf85
update otel core version for tests
feywind Dec 1, 2022
5cddaed
fix: change some span names for doc updates
feywind Dec 8, 2022
d523b1f
fix: move emitter wrapper out one level, to catch user functions prop…
feywind Dec 8, 2022
fbe29a2
chore: merge remote-tracking branch 'remotes/origin/main' into otel-2
feywind Dec 14, 2022
197a214
fix: don't send anything besides what's actually needed during publish
feywind Dec 14, 2022
a36cfce
fix: close the publish span at RPC time, not up front
feywind Dec 14, 2022
5c4fef6
fix: delay caching of the trace provider so the user has a chance to …
feywind Dec 14, 2022
b58557d
build: bring OTel versions back to compatible with Node 12
feywind Dec 15, 2022
4b7cf0c
fix: clean up a few more namespace pollution issues in OTel support
feywind Dec 15, 2022
45047c7
tests: manually end the publish span for tests
feywind Dec 15, 2022
3995fd0
build: update package names for recent version updates
feywind Dec 15, 2022
f2f8f57
chore: get versions of OTel that work together and with Node 12
feywind Dec 16, 2022
4a2a79e
chore: linter nit
feywind Dec 16, 2022
bb815d3
chore: another linter nit
feywind Dec 16, 2022
5d60ff3
chore: OTel sample formatting
feywind Dec 16, 2022
f8a5c09
chore: some internal renaming to reflect the function rather than nam…
feywind Dec 20, 2022
d21480d
fix: more work towards the Promise-first publish flow
feywind Dec 21, 2022
fe4947d
tests: remove unnecessary init line
feywind Dec 21, 2022
568add9
fix: add tracing support for updating the topic name in publisher spans
feywind Dec 21, 2022
5243ea9
fix: use the most up to date name for topic, subscription, and iam
feywind Dec 21, 2022
8dd13f8
fix: update telemetry spans before publishing, in case the topic name…
feywind Dec 21, 2022
60c70a8
chore: merge remote-tracking branch 'remotes/origin/main' into otel-2
feywind Dec 21, 2022
57c1673
chore: merge remote-tracking branch 'remotes/origin/main' into otel-2
feywind Jan 23, 2023
0a3b9a6
chore: merge remote-tracking branch 'remotes/origin/main' into otel-2
feywind Apr 26, 2023
bc95037
chore: calm linter qualms
feywind Apr 26, 2023
02b395b
chore: merge remote-tracking branch 'remotes/origin/main' into otel-2
feywind Apr 26, 2023
a3d66c2
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Apr 26, 2023
a1870ac
chore: merge remote-tracking branch 'remotes/origin/main' into otel-2
feywind Apr 28, 2023
50c8f74
chore: merge branch 'otel-2' of https://github.com/feywind/nodejs-pub…
feywind Apr 28, 2023
90f9ead
fix: update drain() not to promisify
feywind Apr 28, 2023
4ce3fc4
tests: update unit tests for recent promise changes to publish()
feywind Apr 28, 2023
8e18826
feat: add modAck spans during leasing
feywind May 3, 2023
569d744
docs: add more code comment docs
feywind May 3, 2023
886c0ee
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] May 3, 2023
8b7e0a9
tests: unit test fixes, also include deadline and initial parameters …
feywind May 3, 2023
4df6be6
chore: merge branch 'otel-2' of https://github.com/feywind/nodejs-pub…
feywind May 3, 2023
83830d6
fix: make sure the subscriber span ends, update sample
feywind May 8, 2023
094f08d
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] May 8, 2023
a713a2e
tests: update unit test for latest changes
feywind May 9, 2023
58c979a
chore: merge branch 'otel-2' of https://github.com/feywind/nodejs-pub…
feywind May 9, 2023
171c8f9
chore: pull promise-based publish out of OTel change
feywind May 9, 2023
2b4dd6e
chore: merge remote-tracking branch 'feywind/promise-based-publish-me…
feywind May 9, 2023
7b13da5
chore: merge remote-tracking branch 'remotes/origin/main' into otel-2
feywind May 12, 2023
f66cfcd
chore: merge remote-tracking branch 'remotes/origin/main' into otel-2
feywind May 12, 2023
2e09a3d
chore: merge remote-tracking branch 'remotes/origin/main' into otel-2
feywind Jun 12, 2023
50bd1bf
tests: update otel sample test
feywind Jun 12, 2023
0e7e5da
wip: end all telemetry spans when clear() is called
feywind Jun 14, 2023
a287386
wip: add more unit tests
feywind Jun 14, 2023
68335e5
Merge branch 'legacy-v3' into otel-2
feywind Aug 15, 2023
0f2dc41
fix: include batch size with each published message span
feywind Aug 15, 2023
1ba495a
chore: fix lint
feywind Aug 15, 2023
49b0bc3
fix: separate out the getter and setter classes
feywind Aug 15, 2023
12f400d
chore: rename span related objects in subscriber
feywind Aug 15, 2023
febcd16
chore: rename SpanMaker
feywind Aug 15, 2023
a471875
docs: improved comments and lint fixes
feywind Aug 15, 2023
a37194d
docs: more class/comment updating
feywind Aug 15, 2023
9ec1fdf
fix: missing spans caused by renames; also do more renames
feywind Aug 17, 2023
5f33931
tests: more renaming issues
feywind Aug 18, 2023
f167885
tests: add otel test for FlowControlledPublisher
feywind Aug 18, 2023
feeccf1
tests: add lease manager tests for otel
feywind Aug 18, 2023
b218d5f
tests: add SubscriberSpans unit tests
feywind Aug 21, 2023
2471c16
Merge branch 'legacy-v3' into otel-2
feywind Sep 13, 2023
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
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@
"@google-cloud/precise-date": "^3.0.0",
"@google-cloud/projectify": "^3.0.0",
"@google-cloud/promisify": "^2.0.0",
"@opentelemetry/api": "^1.0.0",
"@opentelemetry/semantic-conventions": "~1.3.0",
"@opentelemetry/api": "~1.1.0",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any particular reason these are locked down from ^?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it had to do with Node 12 compatibility. I found that there were some semver issues, in practice, though I'll be revisiting this for the 4.x version of the PR, so I'll probably recheck these for 3.x too.

"@opentelemetry/semantic-conventions": "~1.3.1",
"@types/duplexify": "^3.6.0",
"@types/long": "^4.0.0",
"arrify": "^2.0.0",
Expand All @@ -66,7 +66,8 @@
},
"devDependencies": {
"@grpc/proto-loader": "^0.7.0",
"@opentelemetry/tracing": "^0.24.0",
"@opentelemetry/core": "~1.3.1",
"@opentelemetry/sdk-trace-base": "~1.3.1",
"@types/execa": "^0.9.0",
"@types/extend": "^3.0.0",
"@types/lodash.snakecase": "^4.1.6",
Expand Down
222 changes: 113 additions & 109 deletions samples/openTelemetryTracing.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
/*!
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2020-2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// This is a generated sample, using the typeless sample bot. Please
// look for the source TypeScript sample (.ts) for modifications.
'use strict';

/**
* This sample demonstrates how to add OpenTelemetry tracing to the
Expand All @@ -22,8 +24,6 @@
* at https://cloud.google.com/pubsub/docs.
*/

'use strict';

// sample-metadata:
// title: OpenTelemetry Tracing
// description: Demonstrates how to enable OpenTelemetry tracing in
Expand All @@ -32,103 +32,107 @@

const SUBSCRIBER_TIMEOUT = 10;

// [START opentelemetry_tracing]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we should standardize on this region tag at some point before submitting

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think the person who originally made this just came up with one? I think maybe it deserves several samples, e.g. one for Cloud Trace, another for console output, etc.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we shouldn't do console output and just focus on Cloud Trace as the default sample (since that's also what our open telemetry team's documentation points to).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do think that's the primary thing we want to help people with, 'cause it's probably what they want to do. But I do think we ought to at least e.g. have a Medium article talking about how to output to console, Grafana, etc. Those will be useful to people too.

/**
* TODO(developer): Uncomment these variables before running the sample.
*/
// const topicNameOrId = 'YOUR_TOPIC_OR_ID';
// const subscriptionNameOrId = 'YOUR_SUBSCRIPTION_OR_ID';
// const data = 'Hello, world!";

// Imports the Google Cloud client library
const {PubSub} = require('@google-cloud/pubsub');

// Imports the OpenTelemetry API
const otel = require('@opentelemetry/sdk-trace-node');
const {diag, DiagConsoleLogger, DiagLogLevel} = require('@opentelemetry/api');
const {NodeTracerProvider} = otel;
const {
SimpleSpanProcessor,
ConsoleSpanExporter,
} = require('@opentelemetry/sdk-trace-base');

const {Resource} = require('@opentelemetry/resources');
const {
SemanticResourceAttributes,
} = require('@opentelemetry/semantic-conventions');

// Enable the diagnostic logger for OpenTelemetry
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG);

// Log spans out to the console for this test
const exporter = new ConsoleSpanExporter();

// Build a tracer provider and a span processor to do
// something with the spans we're generating.
const provider = new NodeTracerProvider({
resource: new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: 'otel example',
}),
});
const processor = new SimpleSpanProcessor(exporter);
provider.addSpanProcessor(processor);
provider.register();

// Creates a client; cache this for further use.
const pubSubClient = new PubSub();

async function publishMessage(topicNameOrId, data) {
// Publishes the message as a string, e.g. "Hello, world!" or JSON.stringify(someObject)
const dataBuffer = Buffer.from(data);
const messageId = await pubSubClient
.topic(topicNameOrId)
.publishMessage({data: dataBuffer});
console.log(`Message ${messageId} published.`);
}

async function subscriptionListen(subscriptionNameOrId) {
hongalex marked this conversation as resolved.
Show resolved Hide resolved
// Message handler for subscriber
const messageHandler = message => {
console.log(`Message ${message.id} received.`);
message.ack();

// Ensure that all spans got flushed by the exporter
console.log('Cleaning up OpenTelemetry exporter...');
exporter.shutdown().then(() => {
// Cleaned up exporter.
process.exit(0);
});
};

const errorHandler = error => {
console.log('Received error:', error);

console.log('Cleaning up OpenTelemetry exporter...');
exporter.shutdown().then(() => {
// Cleaned up exporter.
process.exit(0);
});
};

// Listens for new messages from the topic
pubSubClient.subscription(subscriptionNameOrId).on('message', messageHandler);
pubSubClient.subscription(subscriptionNameOrId).on('error', errorHandler);

// Wait a bit for the subscription to receive messages.
// For the sample only.
setTimeout(() => {
pubSubClient.subscription(subscriptionNameOrId).removeAllListeners();
}, SUBSCRIBER_TIMEOUT * 1000);
}
// [END opentelemetry_tracing]

function main(
topicNameOrId = 'YOUR_TOPIC_NAME_OR_ID',
subscriptionNameOrId = 'YOUR_SUBSCRIPTION_NAME_OR_ID',
data = 'Hello, world!'
) {
// [START opentelemetry_tracing]
/**
* TODO(developer): Uncomment these variables before running the sample.
*/
// const topicNameOrId = 'YOUR_TOPIC_OR_ID';
// const subscriptionNameOrId = 'YOUR_SUBSCRIPTION_OR_ID';
// const data = 'Hello, world!";

// Imports the Google Cloud client library
const {PubSub} = require('@google-cloud/pubsub');

// Imports the OpenTelemetry API
const opentelemetry = require('@opentelemetry/api');

// Imports the OpenTelemetry span handlers and exporter
const {
SimpleSpanProcessor,
BasicTracerProvider,
ConsoleSpanExporter,
} = require('@opentelemetry/tracing');

// Set up span processing and specify the console as the span exporter
const provider = new BasicTracerProvider();
const exporter = new ConsoleSpanExporter();
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
// Enable the diagnostic logger for Opentelemetry
opentelemetry.diag.setLogger(
new opentelemetry.DiagConsoleLogger(),
opentelemetry.DiagLogLevel.INFO
);

provider.register();

// OpenTelemetry tracing is an optional feature and can be enabled by setting
// enableOpenTelemetryTracing as a publisher or subscriber option
const enableOpenTelemetryTracing = {
enableOpenTelemetryTracing: true,
};

// Creates a client; cache this for further use
const pubSubClient = new PubSub();

async function publishMessage() {
// Publishes the message as a string, e.g. "Hello, world!" or JSON.stringify(someObject)
const dataBuffer = Buffer.from(data);
const messageId = await pubSubClient
.topic(topicNameOrId, enableOpenTelemetryTracing)
.publish(dataBuffer);
console.log(`Message ${messageId} published.`);
}

async function subscriptionListen() {
// Message handler for subscriber
const messageHandler = message => {
console.log(`Message ${message.id} received.`);
message.ack();

// Ensure that all spans got flushed by the exporter
console.log('Cleaning up Opentelemetry exporter...');
exporter.shutdown().then(() => {
// Cleaned up exporter.
process.exit(0);
});
};

const errorHandler = error => {
console.log('Received error:', error);

console.log('Cleaning up Opentelemetry exporter...');
exporter.shutdown().then(() => {
// Cleaned up exporter.
process.exit(0);
});
};

// Listens for new messages from the topic
pubSubClient
.subscription(subscriptionNameOrId, enableOpenTelemetryTracing)
.on('message', messageHandler);
pubSubClient
.subscription(subscriptionNameOrId, enableOpenTelemetryTracing)
.on('error', errorHandler);

setTimeout(() => {
pubSubClient
.subscription(subscriptionNameOrId, enableOpenTelemetryTracing)
.removeAllListeners();
}, SUBSCRIBER_TIMEOUT * 1000);
}

publishMessage().then(subscriptionListen());
// [END opentelemetry_tracing]
publishMessage(topicNameOrId, data)
.then(() => subscriptionListen(subscriptionNameOrId))
.catch(err => {
console.error(err.message);
process.exitCode = 1;
});
}

main(...process.argv.slice(2));
7 changes: 5 additions & 2 deletions samples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@
},
"dependencies": {
"@google-cloud/pubsub": "^3.5.2",
"@opentelemetry/api": "^1.0.0",
"@opentelemetry/tracing": "^0.24.0",
"@opentelemetry/api": "~1.1.0",
"@opentelemetry/resources": "~1.3.1",
"@opentelemetry/sdk-trace-node": "~1.3.1",
"@opentelemetry/sdk-trace-base": "~1.3.1",
"@opentelemetry/semantic-conventions": "~1.3.1",
"avro-js": "^1.10.1",
"p-defer": "^3.0.0",
"protobufjs": "^7.0.0"
Expand Down
Loading