Skip to content

Commit

Permalink
Merge pull request #7 from feywind/otel-4-samples
Browse files Browse the repository at this point in the history
samples: update otel tracing sample with the correct tags and some other cleanup
  • Loading branch information
feywind authored Jul 12, 2024
2 parents 067f695 + ede295a commit c89d29c
Show file tree
Hide file tree
Showing 7 changed files with 399 additions and 56 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@
"@grpc/proto-loader": "^0.7.0",
"@opentelemetry/core": "^1.17.0",
"@opentelemetry/sdk-trace-base": "^1.17.0",
"@types/execa": "^2.0.0",
"@types/duplexify": "^3.6.4",
"@types/extend": "^3.0.0",
"@types/lodash.snakecase": "^4.1.6",
Expand Down
134 changes: 134 additions & 0 deletions samples/listenWithOpenTelemetryTracing.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// Copyright 2020-2024 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
* Google Cloud Pub/Sub API.
*
* For more information, see the README.md under /pubsub and the documentation
* at https://cloud.google.com/pubsub/docs.
*/

// sample-metadata:
// title: Subscribe with OpenTelemetry Tracing
// description: Demonstrates how to enable OpenTelemetry tracing in a subscriber.
// usage: node listenWithOpenTelemetryTracing.js <subscription-name-or-id>

const OTEL_TIMEOUT = 2;
const SUBSCRIBER_TIMEOUT = 10;

// [START pubsub_subscribe_otel_tracing]
/**
* TODO(developer): Uncomment these variables before running the sample.
*/
// const subscriptionNameOrId = 'YOUR_SUBSCRIPTION_OR_ID';

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

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

// To output to the console for testing, use the ConsoleSpanExporter.
// import {ConsoleSpanExporter} from '@opentelemetry/sdk-trace-base';

// To output to Cloud Trace, import the OpenTelemetry bridge library.
const {
TraceExporter,
} = require('@google-cloud/opentelemetry-cloud-trace-exporter');

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

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

// Log spans out to the console, for testing.
// const exporter = new ConsoleSpanExporter();

// Log spans out to Cloud Trace, for production.
const exporter = new TraceExporter();

// Build a tracer provider and a span processor to do
// something with the spans we're generating.
const provider = new NodeTracerProvider({
resource: new Resource({
[SEMRESATTRS_SERVICE_NAME]: 'otel subscriber 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 subscriptionListen(subscriptionNameOrId) {
const subscriber = pubSubClient.subscription(subscriptionNameOrId);

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

// Error handler for subscriber
const errorHandler = async error => {
console.log('Received error:', error);
};

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

// Ensures that all spans got flushed by the exporter. This function
// is in service to making sure that any buffered Pub/Sub messages
// and/or OpenTelemetry spans are properly flushed to the server
// side. In normal usage, you'd only need to do something like this
// on process shutdown.
async function shutdown() {
await subscriber.close();
await processor.forceFlush();
await new Promise(r => setTimeout(r, OTEL_TIMEOUT * 1000));
}

// Wait a bit for the subscription to receive messages, then shut down
// gracefully. This is for the sample only; normally you would not need
// this delay.
await new Promise(r =>
setTimeout(async () => {
subscriber.removeAllListeners();
await shutdown();
r();
}, SUBSCRIBER_TIMEOUT * 1000)
);
}
// [END pubsub_subscribe_otel_tracing]

function main(subscriptionNameOrId = 'YOUR_SUBSCRIPTION_NAME_OR_ID') {
subscriptionListen(subscriptionNameOrId).catch(err => {
console.error(err.message);
process.exitCode = 1;
});
}

main(...process.argv.slice(2));
11 changes: 6 additions & 5 deletions samples/openTelemetryTracing.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@

const SUBSCRIBER_TIMEOUT = 10;

// [START opentelemetry_tracing]
// [START pubsub_publish_otel_tracing]
/**
* TODO(developer): Uncomment these variables before running the sample.
*/
Expand All @@ -46,9 +46,8 @@ const SUBSCRIBER_TIMEOUT = 10;
const {PubSub} = require('@google-cloud/pubsub');

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

// To output to the console for testing, use the ConsoleSpanExporter.
Expand Down Expand Up @@ -104,7 +103,9 @@ async function subscriptionListen(subscriptionNameOrId) {
console.log(`Message ${message.id} received.`);
message.ack();

// Ensure that all spans got flushed by the exporter
// Ensure that all spans got flushed by the exporter. Note that
// this isn't required under normal circumstances; we're doing it
// here to ensure spans are flushed before closing the subscriber.
console.log('Cleaning up OpenTelemetry exporter...');
await processor.forceFlush();
await subscriber.close();
Expand All @@ -128,7 +129,7 @@ async function subscriptionListen(subscriptionNameOrId) {
subscriber.removeAllListeners();
}, SUBSCRIBER_TIMEOUT * 1000);
}
// [END opentelemetry_tracing]
// [END pubsub_publish_otel_tracing]

function main(
topicNameOrId = 'YOUR_TOPIC_NAME_OR_ID',
Expand Down
110 changes: 110 additions & 0 deletions samples/publishWithOpenTelemetryTracing.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Copyright 2020-2024 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
* Google Cloud Pub/Sub API.
*
* For more information, see the README.md under /pubsub and the documentation
* at https://cloud.google.com/pubsub/docs.
*/

// sample-metadata:
// title: Publish with OpenTelemetry Tracing
// description: Demonstrates how to enable OpenTelemetry tracing in a publisher.
// usage: node openTelemetryTracing.js <topic-name-or-id>

const OTEL_TIMEOUT = 2;

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

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

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

// To output to the console for testing, use the ConsoleSpanExporter.
// import {ConsoleSpanExporter} from '@opentelemetry/sdk-trace-base';

// To output to Cloud Trace, import the OpenTelemetry bridge library.
const {
TraceExporter,
} = require('@google-cloud/opentelemetry-cloud-trace-exporter');

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

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

// Log spans out to the console, for testing.
// const exporter = new ConsoleSpanExporter();

// Log spans out to Cloud Trace, for production.
const exporter = new TraceExporter();

// Build a tracer provider and a span processor to do
// something with the spans we're generating.
const provider = new NodeTracerProvider({
resource: new Resource({
[SEMRESATTRS_SERVICE_NAME]: 'otel publisher 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 publisher = pubSubClient.topic(topicNameOrId);
const messageId = await publisher.publishMessage({data: dataBuffer});
console.log(`Message ${messageId} published.`);

// The rest of the sample is in service to making sure that any
// buffered Pub/Sub messages and/or OpenTelemetry spans are properly
// flushed to the server side. In normal usage, you'd only need to do
// something like this on process shutdown.
await publisher.flush();
await processor.forceFlush();
await new Promise(r => setTimeout(r, OTEL_TIMEOUT * 1000));
}
// [END pubsub_publish_otel_tracing]

function main(topicNameOrId = 'YOUR_TOPIC_NAME_OR_ID', data = 'Hello, world!') {
publishMessage(topicNameOrId, data).catch(err => {
console.error(err.message);
process.exitCode = 1;
});
}

main(...process.argv.slice(2));
15 changes: 11 additions & 4 deletions samples/system-test/openTelemetryTracing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe('openTelemetry', () => {
const projectId = process.env.GCLOUD_PROJECT;
const pubsub = new PubSub({projectId});

const resources = new TestResources('quickstart');
const resources = new TestResources('otel');
const topicName = resources.generateName('ot');
const subName = resources.generateName('ot');

Expand All @@ -43,14 +43,21 @@ describe('openTelemetry', () => {
);
});

it('should run the openTelemetryTracing sample', async () => {
it('should run the WithOpenTelemetryTracing samples', async () => {
const stdout = execSync(
`${commandFor('openTelemetryTracing')} ${topicName} ${subName}`
`${commandFor('publishWithOpenTelemetryTracing')} ${topicName}`
);
assert.match(stdout, /Message .* published./);
assert.match(stdout, /Message .* received/);
assert.match(stdout, /Cloud Trace batch writing traces/);
assert.match(stdout, /batchWriteSpans successfully/);
assert.notMatch(stdout, /Received error/);

const stdoutSub = execSync(
`${commandFor('listenWithOpenTelemetryTracing')} ${subName}`
);
assert.match(stdoutSub, /Message .* received/);
assert.match(stdoutSub, /Cloud Trace batch writing traces/);
assert.match(stdoutSub, /batchWriteSpans successfully/);
assert.notMatch(stdoutSub, /Received error/);
});
});
Loading

0 comments on commit c89d29c

Please sign in to comment.