From 99d88545e06f284037da15fa78934a784117543f Mon Sep 17 00:00:00 2001 From: Bartlomiej Obecny Date: Fri, 10 Jul 2020 14:38:53 +0200 Subject: [PATCH 01/19] feat: adding proto over http for collector exporter --- .nycrc | 1 + .../docker/collector-config.yaml | 8 +- .../docker/docker-compose.yaml | 6 - examples/collector-exporter-node/package.json | 3 +- examples/collector-exporter-node/start.js | 3 +- .../README.md | 27 +- .../opentelemetry-exporter-collector/gen.sh | 13 + .../collector/trace/v1/trace_service_pb.js | 323 +++ .../proto/common/v1/common_pb.js | 692 ++++++ .../proto/resource/v1/resource_pb.js | 229 ++ .../opentelemetry/proto/trace/v1/trace_pb.js | 2067 +++++++++++++++++ .../package.json | 9 +- .../src/enums.ts | 1 + .../platform/node/CollectorTraceExporter.ts | 37 +- .../src/platform/node/README.md | 7 + .../src/platform/node/transformSpansProto.ts | 313 +++ .../src/platform/node/util.ts | 59 + .../src/platform/node/utilWithJson.ts | 56 +- .../src/platform/node/utilWithJsonProto.ts | 61 + .../test/node/CollectorTraceExporter.test.ts | 2 +- .../test/node/transformSpansProto.test.ts | 383 +++ .../tsconfig.json | 1 + 22 files changed, 4237 insertions(+), 64 deletions(-) create mode 100755 packages/opentelemetry-exporter-collector/gen.sh create mode 100644 packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/collector/trace/v1/trace_service_pb.js create mode 100644 packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/common/v1/common_pb.js create mode 100644 packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/resource/v1/resource_pb.js create mode 100644 packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/trace/v1/trace_pb.js create mode 100644 packages/opentelemetry-exporter-collector/src/platform/node/transformSpansProto.ts create mode 100644 packages/opentelemetry-exporter-collector/src/platform/node/utilWithJsonProto.ts create mode 100644 packages/opentelemetry-exporter-collector/test/node/transformSpansProto.test.ts diff --git a/.nycrc b/.nycrc index 47b8c170df..53a2f2262d 100644 --- a/.nycrc +++ b/.nycrc @@ -5,6 +5,7 @@ "exclude": [ "**/*.d.ts", "build/**/*.*", + "generated/**/*.*", "src/index.ts", "src/platform/**/index.ts", "src/platform/browser/*.ts", diff --git a/examples/collector-exporter-node/docker/collector-config.yaml b/examples/collector-exporter-node/docker/collector-config.yaml index 8ea773375b..7e0cd7e759 100644 --- a/examples/collector-exporter-node/docker/collector-config.yaml +++ b/examples/collector-exporter-node/docker/collector-config.yaml @@ -1,5 +1,11 @@ receivers: - otlp: {} + otlp: + {} +# keep it when upgrading to version 0.5+ +# protocols: +# grpc: +# http: +# endpoint: localhost:55680 exporters: zipkin: diff --git a/examples/collector-exporter-node/docker/docker-compose.yaml b/examples/collector-exporter-node/docker/docker-compose.yaml index 53c635a0f4..df43b97e33 100644 --- a/examples/collector-exporter-node/docker/docker-compose.yaml +++ b/examples/collector-exporter-node/docker/docker-compose.yaml @@ -3,8 +3,6 @@ services: # Collector collector: image: otel/opentelemetry-collector:0.4.0 - networks: - - otelcol command: ["--config=/conf/collector-config.yaml", "--log-level=DEBUG"] volumes: - ./collector-config.yaml:/conf/collector-config.yaml @@ -15,10 +13,6 @@ services: # Zipkin zipkin-all-in-one: image: openzipkin/zipkin:latest - networks: - - otelcol ports: - "9411:9411" -networks: - otelcol: diff --git a/examples/collector-exporter-node/package.json b/examples/collector-exporter-node/package.json index 5f5d7b39e6..ac987ef149 100644 --- a/examples/collector-exporter-node/package.json +++ b/examples/collector-exporter-node/package.json @@ -6,7 +6,8 @@ "main": "index.js", "scripts": { "start": "node ./start.js", - "docker:start": "cd ./docker && docker-compose down && docker-compose up -d", + "docker:start": "cd ./docker && docker-compose down && docker-compose up", + "docker:startd": "cd ./docker && docker-compose down && docker-compose up -d", "docker:stop": "cd ./docker && docker-compose down" }, "repository": { diff --git a/examples/collector-exporter-node/start.js b/examples/collector-exporter-node/start.js index 3f8f939653..dd24a94c7d 100644 --- a/examples/collector-exporter-node/start.js +++ b/examples/collector-exporter-node/start.js @@ -9,7 +9,8 @@ const exporter = new CollectorTraceExporter({ // headers: { // foo: 'bar' // }, - protocolNode: CollectorProtocolNode.HTTP_JSON, + protocolNode: CollectorProtocolNode.HTTP_JSON_PROTO, + // protocolNode: CollectorProtocolNode.HTTP_JSON, }); const provider = new BasicTracerProvider(); diff --git a/packages/opentelemetry-exporter-collector/README.md b/packages/opentelemetry-exporter-collector/README.md index 8cfda2f5a2..89431bdbaf 100644 --- a/packages/opentelemetry-exporter-collector/README.md +++ b/packages/opentelemetry-exporter-collector/README.md @@ -132,10 +132,33 @@ provider.register(); ``` +## Usage in Node - PROTO over http + +```js +const { BasicTracerProvider, SimpleSpanProcessor } = require('@opentelemetry/tracing'); +const { CollectorExporter, CollectorTransportNode } = require('@opentelemetry/exporter-collector'); + +const collectorOptions = { + protocolNode: CollectorTransportNode.HTTP_PROTO, + serviceName: 'basic-service', + url: '', // url is optional and can be omitted - default is http://localhost:55680/v1/trace + headers: { + foo: 'bar' + }, //an optional object containing custom headers to be sent with each request will only work with json over http +}; + +const provider = new BasicTracerProvider(); +const exporter = new CollectorExporter(collectorOptions); +provider.addSpanProcessor(new SimpleSpanProcessor(exporter)); + +provider.register(); + +``` + ## Running opentelemetry-collector locally to see the traces -1. Go to examples/basic-tracer-node -2. run `npm run collector:docker:ot` +1. Go to examples/collector-exporter-node +2. run `npm run docker:start` 3. Open page at `http://localhost:9411/zipkin/` to observe the traces ## Useful links diff --git a/packages/opentelemetry-exporter-collector/gen.sh b/packages/opentelemetry-exporter-collector/gen.sh new file mode 100755 index 0000000000..7404879bb9 --- /dev/null +++ b/packages/opentelemetry-exporter-collector/gen.sh @@ -0,0 +1,13 @@ +clear +git submodule sync --recursive +git submodule update --init --recursive + +OUT_DIR="./generated" + +protoc \ + --js_out="import_style=commonjs,binary:${OUT_DIR}" \ + --proto_path="src/platform/node/protos/" \ + opentelemetry/proto/common/v1/common.proto \ + opentelemetry/proto/resource/v1/resource.proto \ + opentelemetry/proto/trace/v1/trace.proto \ + opentelemetry/proto/collector/trace/v1/trace_service.proto \ diff --git a/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/collector/trace/v1/trace_service_pb.js b/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/collector/trace/v1/trace_service_pb.js new file mode 100644 index 0000000000..606e2dd104 --- /dev/null +++ b/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/collector/trace/v1/trace_service_pb.js @@ -0,0 +1,323 @@ +// source: opentelemetry/proto/collector/trace/v1/trace_service.proto +// source: opentelemetry/proto/collector/trace/v1/trace_service.proto +/** + * @fileoverview + * @enhanceable + * @suppress {messageConventions} JS Compiler reports an error if a variable or + * field starts with 'MSG_' and isn't a translatable message. + * @public + */ +// GENERATED CODE -- DO NOT EDIT! + +var jspb = require('google-protobuf'); +var goog = jspb; +var global = Function('return this')(); + +var opentelemetry_proto_trace_v1_trace_pb = require('../../../../../opentelemetry/proto/trace/v1/trace_pb.js'); +goog.object.extend(proto, opentelemetry_proto_trace_v1_trace_pb); +goog.exportSymbol('proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest', null, global); +goog.exportSymbol('proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse', null, global); +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.repeatedFields_, null); +}; +goog.inherits(proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.displayName = 'proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse.displayName = 'proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse'; +} + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.repeatedFields_ = [1]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.prototype.toObject = function(opt_includeInstance) { + return proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.toObject = function(includeInstance, msg) { + var f, obj = { + resourceSpansList: jspb.Message.toObjectList(msg.getResourceSpansList(), + opentelemetry_proto_trace_v1_trace_pb.ResourceSpans.toObject, includeInstance) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest} + */ +proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest; + return proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest} + */ +proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new opentelemetry_proto_trace_v1_trace_pb.ResourceSpans; + reader.readMessage(value,opentelemetry_proto_trace_v1_trace_pb.ResourceSpans.deserializeBinaryFromReader); + msg.addResourceSpans(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getResourceSpansList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 1, + f, + opentelemetry_proto_trace_v1_trace_pb.ResourceSpans.serializeBinaryToWriter + ); + } +}; + + +/** + * repeated opentelemetry.proto.trace.v1.ResourceSpans resource_spans = 1; + * @return {!Array} + */ +proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.prototype.getResourceSpansList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, opentelemetry_proto_trace_v1_trace_pb.ResourceSpans, 1)); +}; + + +/** + * @param {!Array} value + * @return {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest} returns this +*/ +proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.prototype.setResourceSpansList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 1, value); +}; + + +/** + * @param {!proto.opentelemetry.proto.trace.v1.ResourceSpans=} opt_value + * @param {number=} opt_index + * @return {!proto.opentelemetry.proto.trace.v1.ResourceSpans} + */ +proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.prototype.addResourceSpans = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.opentelemetry.proto.trace.v1.ResourceSpans, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest} returns this + */ +proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.prototype.clearResourceSpansList = function() { + return this.setResourceSpansList([]); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse.prototype.toObject = function(opt_includeInstance) { + return proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse.toObject = function(includeInstance, msg) { + var f, obj = { + + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse} + */ +proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse; + return proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse} + */ +proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse.serializeBinaryToWriter = function(message, writer) { + var f = undefined; +}; + + +goog.object.extend(exports, proto.opentelemetry.proto.collector.trace.v1); diff --git a/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/common/v1/common_pb.js b/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/common/v1/common_pb.js new file mode 100644 index 0000000000..796ad90f6a --- /dev/null +++ b/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/common/v1/common_pb.js @@ -0,0 +1,692 @@ +// source: opentelemetry/proto/common/v1/common.proto +/** + * @fileoverview + * @enhanceable + * @suppress {messageConventions} JS Compiler reports an error if a variable or + * field starts with 'MSG_' and isn't a translatable message. + * @public + */ +// GENERATED CODE -- DO NOT EDIT! + +var jspb = require('google-protobuf'); +var goog = jspb; +var global = Function('return this')(); + +goog.exportSymbol('proto.opentelemetry.proto.common.v1.AttributeKeyValue', null, global); +goog.exportSymbol('proto.opentelemetry.proto.common.v1.AttributeKeyValue.ValueType', null, global); +goog.exportSymbol('proto.opentelemetry.proto.common.v1.InstrumentationLibrary', null, global); +goog.exportSymbol('proto.opentelemetry.proto.common.v1.StringKeyValue', null, global); +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.opentelemetry.proto.common.v1.AttributeKeyValue = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.opentelemetry.proto.common.v1.AttributeKeyValue, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.opentelemetry.proto.common.v1.AttributeKeyValue.displayName = 'proto.opentelemetry.proto.common.v1.AttributeKeyValue'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.opentelemetry.proto.common.v1.StringKeyValue = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.opentelemetry.proto.common.v1.StringKeyValue, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.opentelemetry.proto.common.v1.StringKeyValue.displayName = 'proto.opentelemetry.proto.common.v1.StringKeyValue'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.opentelemetry.proto.common.v1.InstrumentationLibrary = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.opentelemetry.proto.common.v1.InstrumentationLibrary, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.opentelemetry.proto.common.v1.InstrumentationLibrary.displayName = 'proto.opentelemetry.proto.common.v1.InstrumentationLibrary'; +} + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.toObject = function(opt_includeInstance) { + return proto.opentelemetry.proto.common.v1.AttributeKeyValue.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.common.v1.AttributeKeyValue.toObject = function(includeInstance, msg) { + var f, obj = { + key: jspb.Message.getFieldWithDefault(msg, 1, ""), + type: jspb.Message.getFieldWithDefault(msg, 2, 0), + stringValue: jspb.Message.getFieldWithDefault(msg, 3, ""), + intValue: jspb.Message.getFieldWithDefault(msg, 4, 0), + doubleValue: jspb.Message.getFloatingPointFieldWithDefault(msg, 5, 0.0), + boolValue: jspb.Message.getBooleanFieldWithDefault(msg, 6, false) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} + */ +proto.opentelemetry.proto.common.v1.AttributeKeyValue.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.opentelemetry.proto.common.v1.AttributeKeyValue; + return proto.opentelemetry.proto.common.v1.AttributeKeyValue.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} + */ +proto.opentelemetry.proto.common.v1.AttributeKeyValue.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setKey(value); + break; + case 2: + var value = /** @type {!proto.opentelemetry.proto.common.v1.AttributeKeyValue.ValueType} */ (reader.readEnum()); + msg.setType(value); + break; + case 3: + var value = /** @type {string} */ (reader.readString()); + msg.setStringValue(value); + break; + case 4: + var value = /** @type {number} */ (reader.readInt64()); + msg.setIntValue(value); + break; + case 5: + var value = /** @type {number} */ (reader.readDouble()); + msg.setDoubleValue(value); + break; + case 6: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setBoolValue(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.opentelemetry.proto.common.v1.AttributeKeyValue.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.common.v1.AttributeKeyValue.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getKey(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getType(); + if (f !== 0.0) { + writer.writeEnum( + 2, + f + ); + } + f = message.getStringValue(); + if (f.length > 0) { + writer.writeString( + 3, + f + ); + } + f = message.getIntValue(); + if (f !== 0) { + writer.writeInt64( + 4, + f + ); + } + f = message.getDoubleValue(); + if (f !== 0.0) { + writer.writeDouble( + 5, + f + ); + } + f = message.getBoolValue(); + if (f) { + writer.writeBool( + 6, + f + ); + } +}; + + +/** + * @enum {number} + */ +proto.opentelemetry.proto.common.v1.AttributeKeyValue.ValueType = { + STRING: 0, + INT: 1, + DOUBLE: 2, + BOOL: 3 +}; + +/** + * optional string key = 1; + * @return {string} + */ +proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.getKey = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} returns this + */ +proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.setKey = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional ValueType type = 2; + * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue.ValueType} + */ +proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.getType = function() { + return /** @type {!proto.opentelemetry.proto.common.v1.AttributeKeyValue.ValueType} */ (jspb.Message.getFieldWithDefault(this, 2, 0)); +}; + + +/** + * @param {!proto.opentelemetry.proto.common.v1.AttributeKeyValue.ValueType} value + * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} returns this + */ +proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.setType = function(value) { + return jspb.Message.setProto3EnumField(this, 2, value); +}; + + +/** + * optional string string_value = 3; + * @return {string} + */ +proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.getStringValue = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +}; + + +/** + * @param {string} value + * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} returns this + */ +proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.setStringValue = function(value) { + return jspb.Message.setProto3StringField(this, 3, value); +}; + + +/** + * optional int64 int_value = 4; + * @return {number} + */ +proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.getIntValue = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} returns this + */ +proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.setIntValue = function(value) { + return jspb.Message.setProto3IntField(this, 4, value); +}; + + +/** + * optional double double_value = 5; + * @return {number} + */ +proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.getDoubleValue = function() { + return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 5, 0.0)); +}; + + +/** + * @param {number} value + * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} returns this + */ +proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.setDoubleValue = function(value) { + return jspb.Message.setProto3FloatField(this, 5, value); +}; + + +/** + * optional bool bool_value = 6; + * @return {boolean} + */ +proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.getBoolValue = function() { + return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 6, false)); +}; + + +/** + * @param {boolean} value + * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} returns this + */ +proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.setBoolValue = function(value) { + return jspb.Message.setProto3BooleanField(this, 6, value); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.opentelemetry.proto.common.v1.StringKeyValue.prototype.toObject = function(opt_includeInstance) { + return proto.opentelemetry.proto.common.v1.StringKeyValue.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.opentelemetry.proto.common.v1.StringKeyValue} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.common.v1.StringKeyValue.toObject = function(includeInstance, msg) { + var f, obj = { + key: jspb.Message.getFieldWithDefault(msg, 1, ""), + value: jspb.Message.getFieldWithDefault(msg, 2, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.opentelemetry.proto.common.v1.StringKeyValue} + */ +proto.opentelemetry.proto.common.v1.StringKeyValue.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.opentelemetry.proto.common.v1.StringKeyValue; + return proto.opentelemetry.proto.common.v1.StringKeyValue.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.opentelemetry.proto.common.v1.StringKeyValue} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.opentelemetry.proto.common.v1.StringKeyValue} + */ +proto.opentelemetry.proto.common.v1.StringKeyValue.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setKey(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setValue(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.opentelemetry.proto.common.v1.StringKeyValue.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.opentelemetry.proto.common.v1.StringKeyValue.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.opentelemetry.proto.common.v1.StringKeyValue} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.common.v1.StringKeyValue.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getKey(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getValue(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } +}; + + +/** + * optional string key = 1; + * @return {string} + */ +proto.opentelemetry.proto.common.v1.StringKeyValue.prototype.getKey = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.opentelemetry.proto.common.v1.StringKeyValue} returns this + */ +proto.opentelemetry.proto.common.v1.StringKeyValue.prototype.setKey = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string value = 2; + * @return {string} + */ +proto.opentelemetry.proto.common.v1.StringKeyValue.prototype.getValue = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.opentelemetry.proto.common.v1.StringKeyValue} returns this + */ +proto.opentelemetry.proto.common.v1.StringKeyValue.prototype.setValue = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.opentelemetry.proto.common.v1.InstrumentationLibrary.prototype.toObject = function(opt_includeInstance) { + return proto.opentelemetry.proto.common.v1.InstrumentationLibrary.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.opentelemetry.proto.common.v1.InstrumentationLibrary} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.common.v1.InstrumentationLibrary.toObject = function(includeInstance, msg) { + var f, obj = { + name: jspb.Message.getFieldWithDefault(msg, 1, ""), + version: jspb.Message.getFieldWithDefault(msg, 2, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.opentelemetry.proto.common.v1.InstrumentationLibrary} + */ +proto.opentelemetry.proto.common.v1.InstrumentationLibrary.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.opentelemetry.proto.common.v1.InstrumentationLibrary; + return proto.opentelemetry.proto.common.v1.InstrumentationLibrary.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.opentelemetry.proto.common.v1.InstrumentationLibrary} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.opentelemetry.proto.common.v1.InstrumentationLibrary} + */ +proto.opentelemetry.proto.common.v1.InstrumentationLibrary.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setName(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setVersion(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.opentelemetry.proto.common.v1.InstrumentationLibrary.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.opentelemetry.proto.common.v1.InstrumentationLibrary.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.opentelemetry.proto.common.v1.InstrumentationLibrary} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.common.v1.InstrumentationLibrary.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getName(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getVersion(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } +}; + + +/** + * optional string name = 1; + * @return {string} + */ +proto.opentelemetry.proto.common.v1.InstrumentationLibrary.prototype.getName = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.opentelemetry.proto.common.v1.InstrumentationLibrary} returns this + */ +proto.opentelemetry.proto.common.v1.InstrumentationLibrary.prototype.setName = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string version = 2; + * @return {string} + */ +proto.opentelemetry.proto.common.v1.InstrumentationLibrary.prototype.getVersion = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.opentelemetry.proto.common.v1.InstrumentationLibrary} returns this + */ +proto.opentelemetry.proto.common.v1.InstrumentationLibrary.prototype.setVersion = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + +goog.object.extend(exports, proto.opentelemetry.proto.common.v1); diff --git a/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/resource/v1/resource_pb.js b/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/resource/v1/resource_pb.js new file mode 100644 index 0000000000..d03e6a365e --- /dev/null +++ b/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/resource/v1/resource_pb.js @@ -0,0 +1,229 @@ +// source: opentelemetry/proto/resource/v1/resource.proto +/** + * @fileoverview + * @enhanceable + * @suppress {messageConventions} JS Compiler reports an error if a variable or + * field starts with 'MSG_' and isn't a translatable message. + * @public + */ +// GENERATED CODE -- DO NOT EDIT! + +var jspb = require('google-protobuf'); +var goog = jspb; +var global = Function('return this')(); + +var opentelemetry_proto_common_v1_common_pb = require('../../../../opentelemetry/proto/common/v1/common_pb.js'); +goog.object.extend(proto, opentelemetry_proto_common_v1_common_pb); +goog.exportSymbol('proto.opentelemetry.proto.resource.v1.Resource', null, global); +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.opentelemetry.proto.resource.v1.Resource = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.opentelemetry.proto.resource.v1.Resource.repeatedFields_, null); +}; +goog.inherits(proto.opentelemetry.proto.resource.v1.Resource, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.opentelemetry.proto.resource.v1.Resource.displayName = 'proto.opentelemetry.proto.resource.v1.Resource'; +} + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.opentelemetry.proto.resource.v1.Resource.repeatedFields_ = [1]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.opentelemetry.proto.resource.v1.Resource.prototype.toObject = function(opt_includeInstance) { + return proto.opentelemetry.proto.resource.v1.Resource.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.opentelemetry.proto.resource.v1.Resource} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.resource.v1.Resource.toObject = function(includeInstance, msg) { + var f, obj = { + attributesList: jspb.Message.toObjectList(msg.getAttributesList(), + opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.toObject, includeInstance), + droppedAttributesCount: jspb.Message.getFieldWithDefault(msg, 2, 0) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.opentelemetry.proto.resource.v1.Resource} + */ +proto.opentelemetry.proto.resource.v1.Resource.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.opentelemetry.proto.resource.v1.Resource; + return proto.opentelemetry.proto.resource.v1.Resource.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.opentelemetry.proto.resource.v1.Resource} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.opentelemetry.proto.resource.v1.Resource} + */ +proto.opentelemetry.proto.resource.v1.Resource.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new opentelemetry_proto_common_v1_common_pb.AttributeKeyValue; + reader.readMessage(value,opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.deserializeBinaryFromReader); + msg.addAttributes(value); + break; + case 2: + var value = /** @type {number} */ (reader.readUint32()); + msg.setDroppedAttributesCount(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.opentelemetry.proto.resource.v1.Resource.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.opentelemetry.proto.resource.v1.Resource.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.opentelemetry.proto.resource.v1.Resource} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.resource.v1.Resource.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getAttributesList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 1, + f, + opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.serializeBinaryToWriter + ); + } + f = message.getDroppedAttributesCount(); + if (f !== 0) { + writer.writeUint32( + 2, + f + ); + } +}; + + +/** + * repeated opentelemetry.proto.common.v1.AttributeKeyValue attributes = 1; + * @return {!Array} + */ +proto.opentelemetry.proto.resource.v1.Resource.prototype.getAttributesList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, opentelemetry_proto_common_v1_common_pb.AttributeKeyValue, 1)); +}; + + +/** + * @param {!Array} value + * @return {!proto.opentelemetry.proto.resource.v1.Resource} returns this +*/ +proto.opentelemetry.proto.resource.v1.Resource.prototype.setAttributesList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 1, value); +}; + + +/** + * @param {!proto.opentelemetry.proto.common.v1.AttributeKeyValue=} opt_value + * @param {number=} opt_index + * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} + */ +proto.opentelemetry.proto.resource.v1.Resource.prototype.addAttributes = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.opentelemetry.proto.common.v1.AttributeKeyValue, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.opentelemetry.proto.resource.v1.Resource} returns this + */ +proto.opentelemetry.proto.resource.v1.Resource.prototype.clearAttributesList = function() { + return this.setAttributesList([]); +}; + + +/** + * optional uint32 dropped_attributes_count = 2; + * @return {number} + */ +proto.opentelemetry.proto.resource.v1.Resource.prototype.getDroppedAttributesCount = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.opentelemetry.proto.resource.v1.Resource} returns this + */ +proto.opentelemetry.proto.resource.v1.Resource.prototype.setDroppedAttributesCount = function(value) { + return jspb.Message.setProto3IntField(this, 2, value); +}; + + +goog.object.extend(exports, proto.opentelemetry.proto.resource.v1); diff --git a/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/trace/v1/trace_pb.js b/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/trace/v1/trace_pb.js new file mode 100644 index 0000000000..42a4524c1f --- /dev/null +++ b/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/trace/v1/trace_pb.js @@ -0,0 +1,2067 @@ +// source: opentelemetry/proto/trace/v1/trace.proto +/** + * @fileoverview + * @enhanceable + * @suppress {messageConventions} JS Compiler reports an error if a variable or + * field starts with 'MSG_' and isn't a translatable message. + * @public + */ +// GENERATED CODE -- DO NOT EDIT! + +var jspb = require('google-protobuf'); +var goog = jspb; +var global = Function('return this')(); + +var opentelemetry_proto_common_v1_common_pb = require('../../../../opentelemetry/proto/common/v1/common_pb.js'); +goog.object.extend(proto, opentelemetry_proto_common_v1_common_pb); +var opentelemetry_proto_resource_v1_resource_pb = require('../../../../opentelemetry/proto/resource/v1/resource_pb.js'); +goog.object.extend(proto, opentelemetry_proto_resource_v1_resource_pb); +goog.exportSymbol('proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans', null, global); +goog.exportSymbol('proto.opentelemetry.proto.trace.v1.ResourceSpans', null, global); +goog.exportSymbol('proto.opentelemetry.proto.trace.v1.Span', null, global); +goog.exportSymbol('proto.opentelemetry.proto.trace.v1.Span.Event', null, global); +goog.exportSymbol('proto.opentelemetry.proto.trace.v1.Span.Link', null, global); +goog.exportSymbol('proto.opentelemetry.proto.trace.v1.Span.SpanKind', null, global); +goog.exportSymbol('proto.opentelemetry.proto.trace.v1.Status', null, global); +goog.exportSymbol('proto.opentelemetry.proto.trace.v1.Status.StatusCode', null, global); +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.opentelemetry.proto.trace.v1.ResourceSpans = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.opentelemetry.proto.trace.v1.ResourceSpans.repeatedFields_, null); +}; +goog.inherits(proto.opentelemetry.proto.trace.v1.ResourceSpans, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.opentelemetry.proto.trace.v1.ResourceSpans.displayName = 'proto.opentelemetry.proto.trace.v1.ResourceSpans'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.repeatedFields_, null); +}; +goog.inherits(proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.displayName = 'proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.opentelemetry.proto.trace.v1.Span = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.opentelemetry.proto.trace.v1.Span.repeatedFields_, null); +}; +goog.inherits(proto.opentelemetry.proto.trace.v1.Span, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.opentelemetry.proto.trace.v1.Span.displayName = 'proto.opentelemetry.proto.trace.v1.Span'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.opentelemetry.proto.trace.v1.Span.Event = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.opentelemetry.proto.trace.v1.Span.Event.repeatedFields_, null); +}; +goog.inherits(proto.opentelemetry.proto.trace.v1.Span.Event, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.opentelemetry.proto.trace.v1.Span.Event.displayName = 'proto.opentelemetry.proto.trace.v1.Span.Event'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.opentelemetry.proto.trace.v1.Span.Link = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.opentelemetry.proto.trace.v1.Span.Link.repeatedFields_, null); +}; +goog.inherits(proto.opentelemetry.proto.trace.v1.Span.Link, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.opentelemetry.proto.trace.v1.Span.Link.displayName = 'proto.opentelemetry.proto.trace.v1.Span.Link'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.opentelemetry.proto.trace.v1.Status = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.opentelemetry.proto.trace.v1.Status, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.opentelemetry.proto.trace.v1.Status.displayName = 'proto.opentelemetry.proto.trace.v1.Status'; +} + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.opentelemetry.proto.trace.v1.ResourceSpans.repeatedFields_ = [2]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.opentelemetry.proto.trace.v1.ResourceSpans.prototype.toObject = function(opt_includeInstance) { + return proto.opentelemetry.proto.trace.v1.ResourceSpans.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.opentelemetry.proto.trace.v1.ResourceSpans} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.trace.v1.ResourceSpans.toObject = function(includeInstance, msg) { + var f, obj = { + resource: (f = msg.getResource()) && opentelemetry_proto_resource_v1_resource_pb.Resource.toObject(includeInstance, f), + instrumentationLibrarySpansList: jspb.Message.toObjectList(msg.getInstrumentationLibrarySpansList(), + proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.toObject, includeInstance) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.opentelemetry.proto.trace.v1.ResourceSpans} + */ +proto.opentelemetry.proto.trace.v1.ResourceSpans.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.opentelemetry.proto.trace.v1.ResourceSpans; + return proto.opentelemetry.proto.trace.v1.ResourceSpans.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.opentelemetry.proto.trace.v1.ResourceSpans} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.opentelemetry.proto.trace.v1.ResourceSpans} + */ +proto.opentelemetry.proto.trace.v1.ResourceSpans.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new opentelemetry_proto_resource_v1_resource_pb.Resource; + reader.readMessage(value,opentelemetry_proto_resource_v1_resource_pb.Resource.deserializeBinaryFromReader); + msg.setResource(value); + break; + case 2: + var value = new proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans; + reader.readMessage(value,proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.deserializeBinaryFromReader); + msg.addInstrumentationLibrarySpans(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.opentelemetry.proto.trace.v1.ResourceSpans.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.opentelemetry.proto.trace.v1.ResourceSpans.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.opentelemetry.proto.trace.v1.ResourceSpans} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.trace.v1.ResourceSpans.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getResource(); + if (f != null) { + writer.writeMessage( + 1, + f, + opentelemetry_proto_resource_v1_resource_pb.Resource.serializeBinaryToWriter + ); + } + f = message.getInstrumentationLibrarySpansList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 2, + f, + proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.serializeBinaryToWriter + ); + } +}; + + +/** + * optional opentelemetry.proto.resource.v1.Resource resource = 1; + * @return {?proto.opentelemetry.proto.resource.v1.Resource} + */ +proto.opentelemetry.proto.trace.v1.ResourceSpans.prototype.getResource = function() { + return /** @type{?proto.opentelemetry.proto.resource.v1.Resource} */ ( + jspb.Message.getWrapperField(this, opentelemetry_proto_resource_v1_resource_pb.Resource, 1)); +}; + + +/** + * @param {?proto.opentelemetry.proto.resource.v1.Resource|undefined} value + * @return {!proto.opentelemetry.proto.trace.v1.ResourceSpans} returns this +*/ +proto.opentelemetry.proto.trace.v1.ResourceSpans.prototype.setResource = function(value) { + return jspb.Message.setWrapperField(this, 1, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.opentelemetry.proto.trace.v1.ResourceSpans} returns this + */ +proto.opentelemetry.proto.trace.v1.ResourceSpans.prototype.clearResource = function() { + return this.setResource(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.opentelemetry.proto.trace.v1.ResourceSpans.prototype.hasResource = function() { + return jspb.Message.getField(this, 1) != null; +}; + + +/** + * repeated InstrumentationLibrarySpans instrumentation_library_spans = 2; + * @return {!Array} + */ +proto.opentelemetry.proto.trace.v1.ResourceSpans.prototype.getInstrumentationLibrarySpansList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans, 2)); +}; + + +/** + * @param {!Array} value + * @return {!proto.opentelemetry.proto.trace.v1.ResourceSpans} returns this +*/ +proto.opentelemetry.proto.trace.v1.ResourceSpans.prototype.setInstrumentationLibrarySpansList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 2, value); +}; + + +/** + * @param {!proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans=} opt_value + * @param {number=} opt_index + * @return {!proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans} + */ +proto.opentelemetry.proto.trace.v1.ResourceSpans.prototype.addInstrumentationLibrarySpans = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 2, opt_value, proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.opentelemetry.proto.trace.v1.ResourceSpans} returns this + */ +proto.opentelemetry.proto.trace.v1.ResourceSpans.prototype.clearInstrumentationLibrarySpansList = function() { + return this.setInstrumentationLibrarySpansList([]); +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.repeatedFields_ = [2]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.prototype.toObject = function(opt_includeInstance) { + return proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.toObject = function(includeInstance, msg) { + var f, obj = { + instrumentationLibrary: (f = msg.getInstrumentationLibrary()) && opentelemetry_proto_common_v1_common_pb.InstrumentationLibrary.toObject(includeInstance, f), + spansList: jspb.Message.toObjectList(msg.getSpansList(), + proto.opentelemetry.proto.trace.v1.Span.toObject, includeInstance) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans} + */ +proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans; + return proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans} + */ +proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new opentelemetry_proto_common_v1_common_pb.InstrumentationLibrary; + reader.readMessage(value,opentelemetry_proto_common_v1_common_pb.InstrumentationLibrary.deserializeBinaryFromReader); + msg.setInstrumentationLibrary(value); + break; + case 2: + var value = new proto.opentelemetry.proto.trace.v1.Span; + reader.readMessage(value,proto.opentelemetry.proto.trace.v1.Span.deserializeBinaryFromReader); + msg.addSpans(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getInstrumentationLibrary(); + if (f != null) { + writer.writeMessage( + 1, + f, + opentelemetry_proto_common_v1_common_pb.InstrumentationLibrary.serializeBinaryToWriter + ); + } + f = message.getSpansList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 2, + f, + proto.opentelemetry.proto.trace.v1.Span.serializeBinaryToWriter + ); + } +}; + + +/** + * optional opentelemetry.proto.common.v1.InstrumentationLibrary instrumentation_library = 1; + * @return {?proto.opentelemetry.proto.common.v1.InstrumentationLibrary} + */ +proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.prototype.getInstrumentationLibrary = function() { + return /** @type{?proto.opentelemetry.proto.common.v1.InstrumentationLibrary} */ ( + jspb.Message.getWrapperField(this, opentelemetry_proto_common_v1_common_pb.InstrumentationLibrary, 1)); +}; + + +/** + * @param {?proto.opentelemetry.proto.common.v1.InstrumentationLibrary|undefined} value + * @return {!proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans} returns this +*/ +proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.prototype.setInstrumentationLibrary = function(value) { + return jspb.Message.setWrapperField(this, 1, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans} returns this + */ +proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.prototype.clearInstrumentationLibrary = function() { + return this.setInstrumentationLibrary(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.prototype.hasInstrumentationLibrary = function() { + return jspb.Message.getField(this, 1) != null; +}; + + +/** + * repeated Span spans = 2; + * @return {!Array} + */ +proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.prototype.getSpansList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.opentelemetry.proto.trace.v1.Span, 2)); +}; + + +/** + * @param {!Array} value + * @return {!proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans} returns this +*/ +proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.prototype.setSpansList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 2, value); +}; + + +/** + * @param {!proto.opentelemetry.proto.trace.v1.Span=} opt_value + * @param {number=} opt_index + * @return {!proto.opentelemetry.proto.trace.v1.Span} + */ +proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.prototype.addSpans = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 2, opt_value, proto.opentelemetry.proto.trace.v1.Span, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans} returns this + */ +proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.prototype.clearSpansList = function() { + return this.setSpansList([]); +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.opentelemetry.proto.trace.v1.Span.repeatedFields_ = [9,11,13]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.toObject = function(opt_includeInstance) { + return proto.opentelemetry.proto.trace.v1.Span.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.opentelemetry.proto.trace.v1.Span} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.trace.v1.Span.toObject = function(includeInstance, msg) { + var f, obj = { + traceId: msg.getTraceId_asB64(), + spanId: msg.getSpanId_asB64(), + traceState: jspb.Message.getFieldWithDefault(msg, 3, ""), + parentSpanId: msg.getParentSpanId_asB64(), + name: jspb.Message.getFieldWithDefault(msg, 5, ""), + kind: jspb.Message.getFieldWithDefault(msg, 6, 0), + startTimeUnixNano: jspb.Message.getFieldWithDefault(msg, 7, 0), + endTimeUnixNano: jspb.Message.getFieldWithDefault(msg, 8, 0), + attributesList: jspb.Message.toObjectList(msg.getAttributesList(), + opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.toObject, includeInstance), + droppedAttributesCount: jspb.Message.getFieldWithDefault(msg, 10, 0), + eventsList: jspb.Message.toObjectList(msg.getEventsList(), + proto.opentelemetry.proto.trace.v1.Span.Event.toObject, includeInstance), + droppedEventsCount: jspb.Message.getFieldWithDefault(msg, 12, 0), + linksList: jspb.Message.toObjectList(msg.getLinksList(), + proto.opentelemetry.proto.trace.v1.Span.Link.toObject, includeInstance), + droppedLinksCount: jspb.Message.getFieldWithDefault(msg, 14, 0), + status: (f = msg.getStatus()) && proto.opentelemetry.proto.trace.v1.Status.toObject(includeInstance, f) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.opentelemetry.proto.trace.v1.Span} + */ +proto.opentelemetry.proto.trace.v1.Span.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.opentelemetry.proto.trace.v1.Span; + return proto.opentelemetry.proto.trace.v1.Span.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.opentelemetry.proto.trace.v1.Span} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.opentelemetry.proto.trace.v1.Span} + */ +proto.opentelemetry.proto.trace.v1.Span.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setTraceId(value); + break; + case 2: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setSpanId(value); + break; + case 3: + var value = /** @type {string} */ (reader.readString()); + msg.setTraceState(value); + break; + case 4: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setParentSpanId(value); + break; + case 5: + var value = /** @type {string} */ (reader.readString()); + msg.setName(value); + break; + case 6: + var value = /** @type {!proto.opentelemetry.proto.trace.v1.Span.SpanKind} */ (reader.readEnum()); + msg.setKind(value); + break; + case 7: + var value = /** @type {number} */ (reader.readFixed64()); + msg.setStartTimeUnixNano(value); + break; + case 8: + var value = /** @type {number} */ (reader.readFixed64()); + msg.setEndTimeUnixNano(value); + break; + case 9: + var value = new opentelemetry_proto_common_v1_common_pb.AttributeKeyValue; + reader.readMessage(value,opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.deserializeBinaryFromReader); + msg.addAttributes(value); + break; + case 10: + var value = /** @type {number} */ (reader.readUint32()); + msg.setDroppedAttributesCount(value); + break; + case 11: + var value = new proto.opentelemetry.proto.trace.v1.Span.Event; + reader.readMessage(value,proto.opentelemetry.proto.trace.v1.Span.Event.deserializeBinaryFromReader); + msg.addEvents(value); + break; + case 12: + var value = /** @type {number} */ (reader.readUint32()); + msg.setDroppedEventsCount(value); + break; + case 13: + var value = new proto.opentelemetry.proto.trace.v1.Span.Link; + reader.readMessage(value,proto.opentelemetry.proto.trace.v1.Span.Link.deserializeBinaryFromReader); + msg.addLinks(value); + break; + case 14: + var value = /** @type {number} */ (reader.readUint32()); + msg.setDroppedLinksCount(value); + break; + case 15: + var value = new proto.opentelemetry.proto.trace.v1.Status; + reader.readMessage(value,proto.opentelemetry.proto.trace.v1.Status.deserializeBinaryFromReader); + msg.setStatus(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.opentelemetry.proto.trace.v1.Span.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.opentelemetry.proto.trace.v1.Span} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.trace.v1.Span.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getTraceId_asU8(); + if (f.length > 0) { + writer.writeBytes( + 1, + f + ); + } + f = message.getSpanId_asU8(); + if (f.length > 0) { + writer.writeBytes( + 2, + f + ); + } + f = message.getTraceState(); + if (f.length > 0) { + writer.writeString( + 3, + f + ); + } + f = message.getParentSpanId_asU8(); + if (f.length > 0) { + writer.writeBytes( + 4, + f + ); + } + f = message.getName(); + if (f.length > 0) { + writer.writeString( + 5, + f + ); + } + f = message.getKind(); + if (f !== 0.0) { + writer.writeEnum( + 6, + f + ); + } + f = message.getStartTimeUnixNano(); + if (f !== 0) { + writer.writeFixed64( + 7, + f + ); + } + f = message.getEndTimeUnixNano(); + if (f !== 0) { + writer.writeFixed64( + 8, + f + ); + } + f = message.getAttributesList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 9, + f, + opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.serializeBinaryToWriter + ); + } + f = message.getDroppedAttributesCount(); + if (f !== 0) { + writer.writeUint32( + 10, + f + ); + } + f = message.getEventsList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 11, + f, + proto.opentelemetry.proto.trace.v1.Span.Event.serializeBinaryToWriter + ); + } + f = message.getDroppedEventsCount(); + if (f !== 0) { + writer.writeUint32( + 12, + f + ); + } + f = message.getLinksList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 13, + f, + proto.opentelemetry.proto.trace.v1.Span.Link.serializeBinaryToWriter + ); + } + f = message.getDroppedLinksCount(); + if (f !== 0) { + writer.writeUint32( + 14, + f + ); + } + f = message.getStatus(); + if (f != null) { + writer.writeMessage( + 15, + f, + proto.opentelemetry.proto.trace.v1.Status.serializeBinaryToWriter + ); + } +}; + + +/** + * @enum {number} + */ +proto.opentelemetry.proto.trace.v1.Span.SpanKind = { + SPAN_KIND_UNSPECIFIED: 0, + INTERNAL: 1, + SERVER: 2, + CLIENT: 3, + PRODUCER: 4, + CONSUMER: 5 +}; + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.opentelemetry.proto.trace.v1.Span.Event.repeatedFields_ = [3]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.opentelemetry.proto.trace.v1.Span.Event.prototype.toObject = function(opt_includeInstance) { + return proto.opentelemetry.proto.trace.v1.Span.Event.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.opentelemetry.proto.trace.v1.Span.Event} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.trace.v1.Span.Event.toObject = function(includeInstance, msg) { + var f, obj = { + timeUnixNano: jspb.Message.getFieldWithDefault(msg, 1, 0), + name: jspb.Message.getFieldWithDefault(msg, 2, ""), + attributesList: jspb.Message.toObjectList(msg.getAttributesList(), + opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.toObject, includeInstance), + droppedAttributesCount: jspb.Message.getFieldWithDefault(msg, 4, 0) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.opentelemetry.proto.trace.v1.Span.Event} + */ +proto.opentelemetry.proto.trace.v1.Span.Event.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.opentelemetry.proto.trace.v1.Span.Event; + return proto.opentelemetry.proto.trace.v1.Span.Event.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.opentelemetry.proto.trace.v1.Span.Event} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.opentelemetry.proto.trace.v1.Span.Event} + */ +proto.opentelemetry.proto.trace.v1.Span.Event.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {number} */ (reader.readFixed64()); + msg.setTimeUnixNano(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setName(value); + break; + case 3: + var value = new opentelemetry_proto_common_v1_common_pb.AttributeKeyValue; + reader.readMessage(value,opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.deserializeBinaryFromReader); + msg.addAttributes(value); + break; + case 4: + var value = /** @type {number} */ (reader.readUint32()); + msg.setDroppedAttributesCount(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.opentelemetry.proto.trace.v1.Span.Event.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.opentelemetry.proto.trace.v1.Span.Event.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.opentelemetry.proto.trace.v1.Span.Event} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.trace.v1.Span.Event.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getTimeUnixNano(); + if (f !== 0) { + writer.writeFixed64( + 1, + f + ); + } + f = message.getName(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } + f = message.getAttributesList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 3, + f, + opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.serializeBinaryToWriter + ); + } + f = message.getDroppedAttributesCount(); + if (f !== 0) { + writer.writeUint32( + 4, + f + ); + } +}; + + +/** + * optional fixed64 time_unix_nano = 1; + * @return {number} + */ +proto.opentelemetry.proto.trace.v1.Span.Event.prototype.getTimeUnixNano = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.opentelemetry.proto.trace.v1.Span.Event} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.Event.prototype.setTimeUnixNano = function(value) { + return jspb.Message.setProto3IntField(this, 1, value); +}; + + +/** + * optional string name = 2; + * @return {string} + */ +proto.opentelemetry.proto.trace.v1.Span.Event.prototype.getName = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.opentelemetry.proto.trace.v1.Span.Event} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.Event.prototype.setName = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + +/** + * repeated opentelemetry.proto.common.v1.AttributeKeyValue attributes = 3; + * @return {!Array} + */ +proto.opentelemetry.proto.trace.v1.Span.Event.prototype.getAttributesList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, opentelemetry_proto_common_v1_common_pb.AttributeKeyValue, 3)); +}; + + +/** + * @param {!Array} value + * @return {!proto.opentelemetry.proto.trace.v1.Span.Event} returns this +*/ +proto.opentelemetry.proto.trace.v1.Span.Event.prototype.setAttributesList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 3, value); +}; + + +/** + * @param {!proto.opentelemetry.proto.common.v1.AttributeKeyValue=} opt_value + * @param {number=} opt_index + * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} + */ +proto.opentelemetry.proto.trace.v1.Span.Event.prototype.addAttributes = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 3, opt_value, proto.opentelemetry.proto.common.v1.AttributeKeyValue, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.opentelemetry.proto.trace.v1.Span.Event} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.Event.prototype.clearAttributesList = function() { + return this.setAttributesList([]); +}; + + +/** + * optional uint32 dropped_attributes_count = 4; + * @return {number} + */ +proto.opentelemetry.proto.trace.v1.Span.Event.prototype.getDroppedAttributesCount = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.opentelemetry.proto.trace.v1.Span.Event} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.Event.prototype.setDroppedAttributesCount = function(value) { + return jspb.Message.setProto3IntField(this, 4, value); +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.opentelemetry.proto.trace.v1.Span.Link.repeatedFields_ = [4]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.opentelemetry.proto.trace.v1.Span.Link.prototype.toObject = function(opt_includeInstance) { + return proto.opentelemetry.proto.trace.v1.Span.Link.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.opentelemetry.proto.trace.v1.Span.Link} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.trace.v1.Span.Link.toObject = function(includeInstance, msg) { + var f, obj = { + traceId: msg.getTraceId_asB64(), + spanId: msg.getSpanId_asB64(), + traceState: jspb.Message.getFieldWithDefault(msg, 3, ""), + attributesList: jspb.Message.toObjectList(msg.getAttributesList(), + opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.toObject, includeInstance), + droppedAttributesCount: jspb.Message.getFieldWithDefault(msg, 5, 0) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.opentelemetry.proto.trace.v1.Span.Link} + */ +proto.opentelemetry.proto.trace.v1.Span.Link.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.opentelemetry.proto.trace.v1.Span.Link; + return proto.opentelemetry.proto.trace.v1.Span.Link.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.opentelemetry.proto.trace.v1.Span.Link} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.opentelemetry.proto.trace.v1.Span.Link} + */ +proto.opentelemetry.proto.trace.v1.Span.Link.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setTraceId(value); + break; + case 2: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setSpanId(value); + break; + case 3: + var value = /** @type {string} */ (reader.readString()); + msg.setTraceState(value); + break; + case 4: + var value = new opentelemetry_proto_common_v1_common_pb.AttributeKeyValue; + reader.readMessage(value,opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.deserializeBinaryFromReader); + msg.addAttributes(value); + break; + case 5: + var value = /** @type {number} */ (reader.readUint32()); + msg.setDroppedAttributesCount(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.opentelemetry.proto.trace.v1.Span.Link.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.opentelemetry.proto.trace.v1.Span.Link.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.opentelemetry.proto.trace.v1.Span.Link} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.trace.v1.Span.Link.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getTraceId_asU8(); + if (f.length > 0) { + writer.writeBytes( + 1, + f + ); + } + f = message.getSpanId_asU8(); + if (f.length > 0) { + writer.writeBytes( + 2, + f + ); + } + f = message.getTraceState(); + if (f.length > 0) { + writer.writeString( + 3, + f + ); + } + f = message.getAttributesList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 4, + f, + opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.serializeBinaryToWriter + ); + } + f = message.getDroppedAttributesCount(); + if (f !== 0) { + writer.writeUint32( + 5, + f + ); + } +}; + + +/** + * optional bytes trace_id = 1; + * @return {!(string|Uint8Array)} + */ +proto.opentelemetry.proto.trace.v1.Span.Link.prototype.getTraceId = function() { + return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * optional bytes trace_id = 1; + * This is a type-conversion wrapper around `getTraceId()` + * @return {string} + */ +proto.opentelemetry.proto.trace.v1.Span.Link.prototype.getTraceId_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getTraceId())); +}; + + +/** + * optional bytes trace_id = 1; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getTraceId()` + * @return {!Uint8Array} + */ +proto.opentelemetry.proto.trace.v1.Span.Link.prototype.getTraceId_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getTraceId())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.opentelemetry.proto.trace.v1.Span.Link} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.Link.prototype.setTraceId = function(value) { + return jspb.Message.setProto3BytesField(this, 1, value); +}; + + +/** + * optional bytes span_id = 2; + * @return {!(string|Uint8Array)} + */ +proto.opentelemetry.proto.trace.v1.Span.Link.prototype.getSpanId = function() { + return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * optional bytes span_id = 2; + * This is a type-conversion wrapper around `getSpanId()` + * @return {string} + */ +proto.opentelemetry.proto.trace.v1.Span.Link.prototype.getSpanId_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getSpanId())); +}; + + +/** + * optional bytes span_id = 2; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getSpanId()` + * @return {!Uint8Array} + */ +proto.opentelemetry.proto.trace.v1.Span.Link.prototype.getSpanId_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getSpanId())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.opentelemetry.proto.trace.v1.Span.Link} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.Link.prototype.setSpanId = function(value) { + return jspb.Message.setProto3BytesField(this, 2, value); +}; + + +/** + * optional string trace_state = 3; + * @return {string} + */ +proto.opentelemetry.proto.trace.v1.Span.Link.prototype.getTraceState = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +}; + + +/** + * @param {string} value + * @return {!proto.opentelemetry.proto.trace.v1.Span.Link} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.Link.prototype.setTraceState = function(value) { + return jspb.Message.setProto3StringField(this, 3, value); +}; + + +/** + * repeated opentelemetry.proto.common.v1.AttributeKeyValue attributes = 4; + * @return {!Array} + */ +proto.opentelemetry.proto.trace.v1.Span.Link.prototype.getAttributesList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, opentelemetry_proto_common_v1_common_pb.AttributeKeyValue, 4)); +}; + + +/** + * @param {!Array} value + * @return {!proto.opentelemetry.proto.trace.v1.Span.Link} returns this +*/ +proto.opentelemetry.proto.trace.v1.Span.Link.prototype.setAttributesList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 4, value); +}; + + +/** + * @param {!proto.opentelemetry.proto.common.v1.AttributeKeyValue=} opt_value + * @param {number=} opt_index + * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} + */ +proto.opentelemetry.proto.trace.v1.Span.Link.prototype.addAttributes = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 4, opt_value, proto.opentelemetry.proto.common.v1.AttributeKeyValue, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.opentelemetry.proto.trace.v1.Span.Link} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.Link.prototype.clearAttributesList = function() { + return this.setAttributesList([]); +}; + + +/** + * optional uint32 dropped_attributes_count = 5; + * @return {number} + */ +proto.opentelemetry.proto.trace.v1.Span.Link.prototype.getDroppedAttributesCount = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 5, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.opentelemetry.proto.trace.v1.Span.Link} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.Link.prototype.setDroppedAttributesCount = function(value) { + return jspb.Message.setProto3IntField(this, 5, value); +}; + + +/** + * optional bytes trace_id = 1; + * @return {!(string|Uint8Array)} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.getTraceId = function() { + return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * optional bytes trace_id = 1; + * This is a type-conversion wrapper around `getTraceId()` + * @return {string} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.getTraceId_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getTraceId())); +}; + + +/** + * optional bytes trace_id = 1; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getTraceId()` + * @return {!Uint8Array} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.getTraceId_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getTraceId())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.setTraceId = function(value) { + return jspb.Message.setProto3BytesField(this, 1, value); +}; + + +/** + * optional bytes span_id = 2; + * @return {!(string|Uint8Array)} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.getSpanId = function() { + return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * optional bytes span_id = 2; + * This is a type-conversion wrapper around `getSpanId()` + * @return {string} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.getSpanId_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getSpanId())); +}; + + +/** + * optional bytes span_id = 2; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getSpanId()` + * @return {!Uint8Array} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.getSpanId_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getSpanId())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.setSpanId = function(value) { + return jspb.Message.setProto3BytesField(this, 2, value); +}; + + +/** + * optional string trace_state = 3; + * @return {string} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.getTraceState = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +}; + + +/** + * @param {string} value + * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.setTraceState = function(value) { + return jspb.Message.setProto3StringField(this, 3, value); +}; + + +/** + * optional bytes parent_span_id = 4; + * @return {!(string|Uint8Array)} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.getParentSpanId = function() { + return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 4, "")); +}; + + +/** + * optional bytes parent_span_id = 4; + * This is a type-conversion wrapper around `getParentSpanId()` + * @return {string} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.getParentSpanId_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getParentSpanId())); +}; + + +/** + * optional bytes parent_span_id = 4; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getParentSpanId()` + * @return {!Uint8Array} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.getParentSpanId_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getParentSpanId())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.setParentSpanId = function(value) { + return jspb.Message.setProto3BytesField(this, 4, value); +}; + + +/** + * optional string name = 5; + * @return {string} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.getName = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 5, "")); +}; + + +/** + * @param {string} value + * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.setName = function(value) { + return jspb.Message.setProto3StringField(this, 5, value); +}; + + +/** + * optional SpanKind kind = 6; + * @return {!proto.opentelemetry.proto.trace.v1.Span.SpanKind} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.getKind = function() { + return /** @type {!proto.opentelemetry.proto.trace.v1.Span.SpanKind} */ (jspb.Message.getFieldWithDefault(this, 6, 0)); +}; + + +/** + * @param {!proto.opentelemetry.proto.trace.v1.Span.SpanKind} value + * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.setKind = function(value) { + return jspb.Message.setProto3EnumField(this, 6, value); +}; + + +/** + * optional fixed64 start_time_unix_nano = 7; + * @return {number} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.getStartTimeUnixNano = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 7, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.setStartTimeUnixNano = function(value) { + return jspb.Message.setProto3IntField(this, 7, value); +}; + + +/** + * optional fixed64 end_time_unix_nano = 8; + * @return {number} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.getEndTimeUnixNano = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 8, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.setEndTimeUnixNano = function(value) { + return jspb.Message.setProto3IntField(this, 8, value); +}; + + +/** + * repeated opentelemetry.proto.common.v1.AttributeKeyValue attributes = 9; + * @return {!Array} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.getAttributesList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, opentelemetry_proto_common_v1_common_pb.AttributeKeyValue, 9)); +}; + + +/** + * @param {!Array} value + * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this +*/ +proto.opentelemetry.proto.trace.v1.Span.prototype.setAttributesList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 9, value); +}; + + +/** + * @param {!proto.opentelemetry.proto.common.v1.AttributeKeyValue=} opt_value + * @param {number=} opt_index + * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.addAttributes = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 9, opt_value, proto.opentelemetry.proto.common.v1.AttributeKeyValue, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.clearAttributesList = function() { + return this.setAttributesList([]); +}; + + +/** + * optional uint32 dropped_attributes_count = 10; + * @return {number} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.getDroppedAttributesCount = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 10, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.setDroppedAttributesCount = function(value) { + return jspb.Message.setProto3IntField(this, 10, value); +}; + + +/** + * repeated Event events = 11; + * @return {!Array} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.getEventsList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.opentelemetry.proto.trace.v1.Span.Event, 11)); +}; + + +/** + * @param {!Array} value + * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this +*/ +proto.opentelemetry.proto.trace.v1.Span.prototype.setEventsList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 11, value); +}; + + +/** + * @param {!proto.opentelemetry.proto.trace.v1.Span.Event=} opt_value + * @param {number=} opt_index + * @return {!proto.opentelemetry.proto.trace.v1.Span.Event} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.addEvents = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 11, opt_value, proto.opentelemetry.proto.trace.v1.Span.Event, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.clearEventsList = function() { + return this.setEventsList([]); +}; + + +/** + * optional uint32 dropped_events_count = 12; + * @return {number} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.getDroppedEventsCount = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 12, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.setDroppedEventsCount = function(value) { + return jspb.Message.setProto3IntField(this, 12, value); +}; + + +/** + * repeated Link links = 13; + * @return {!Array} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.getLinksList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.opentelemetry.proto.trace.v1.Span.Link, 13)); +}; + + +/** + * @param {!Array} value + * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this +*/ +proto.opentelemetry.proto.trace.v1.Span.prototype.setLinksList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 13, value); +}; + + +/** + * @param {!proto.opentelemetry.proto.trace.v1.Span.Link=} opt_value + * @param {number=} opt_index + * @return {!proto.opentelemetry.proto.trace.v1.Span.Link} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.addLinks = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 13, opt_value, proto.opentelemetry.proto.trace.v1.Span.Link, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.clearLinksList = function() { + return this.setLinksList([]); +}; + + +/** + * optional uint32 dropped_links_count = 14; + * @return {number} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.getDroppedLinksCount = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 14, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.setDroppedLinksCount = function(value) { + return jspb.Message.setProto3IntField(this, 14, value); +}; + + +/** + * optional Status status = 15; + * @return {?proto.opentelemetry.proto.trace.v1.Status} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.getStatus = function() { + return /** @type{?proto.opentelemetry.proto.trace.v1.Status} */ ( + jspb.Message.getWrapperField(this, proto.opentelemetry.proto.trace.v1.Status, 15)); +}; + + +/** + * @param {?proto.opentelemetry.proto.trace.v1.Status|undefined} value + * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this +*/ +proto.opentelemetry.proto.trace.v1.Span.prototype.setStatus = function(value) { + return jspb.Message.setWrapperField(this, 15, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.clearStatus = function() { + return this.setStatus(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.opentelemetry.proto.trace.v1.Span.prototype.hasStatus = function() { + return jspb.Message.getField(this, 15) != null; +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.opentelemetry.proto.trace.v1.Status.prototype.toObject = function(opt_includeInstance) { + return proto.opentelemetry.proto.trace.v1.Status.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.opentelemetry.proto.trace.v1.Status} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.trace.v1.Status.toObject = function(includeInstance, msg) { + var f, obj = { + code: jspb.Message.getFieldWithDefault(msg, 1, 0), + message: jspb.Message.getFieldWithDefault(msg, 2, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.opentelemetry.proto.trace.v1.Status} + */ +proto.opentelemetry.proto.trace.v1.Status.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.opentelemetry.proto.trace.v1.Status; + return proto.opentelemetry.proto.trace.v1.Status.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.opentelemetry.proto.trace.v1.Status} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.opentelemetry.proto.trace.v1.Status} + */ +proto.opentelemetry.proto.trace.v1.Status.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {!proto.opentelemetry.proto.trace.v1.Status.StatusCode} */ (reader.readEnum()); + msg.setCode(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setMessage(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.opentelemetry.proto.trace.v1.Status.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.opentelemetry.proto.trace.v1.Status.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.opentelemetry.proto.trace.v1.Status} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.opentelemetry.proto.trace.v1.Status.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getCode(); + if (f !== 0.0) { + writer.writeEnum( + 1, + f + ); + } + f = message.getMessage(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } +}; + + +/** + * @enum {number} + */ +proto.opentelemetry.proto.trace.v1.Status.StatusCode = { + OK: 0, + CANCELLED: 1, + UNKNOWNERROR: 2, + INVALIDARGUMENT: 3, + DEADLINEEXCEEDED: 4, + NOTFOUND: 5, + ALREADYEXISTS: 6, + PERMISSIONDENIED: 7, + RESOURCEEXHAUSTED: 8, + FAILEDPRECONDITION: 9, + ABORTED: 10, + OUTOFRANGE: 11, + UNIMPLEMENTED: 12, + INTERNALERROR: 13, + UNAVAILABLE: 14, + DATALOSS: 15, + UNAUTHENTICATED: 16 +}; + +/** + * optional StatusCode code = 1; + * @return {!proto.opentelemetry.proto.trace.v1.Status.StatusCode} + */ +proto.opentelemetry.proto.trace.v1.Status.prototype.getCode = function() { + return /** @type {!proto.opentelemetry.proto.trace.v1.Status.StatusCode} */ (jspb.Message.getFieldWithDefault(this, 1, 0)); +}; + + +/** + * @param {!proto.opentelemetry.proto.trace.v1.Status.StatusCode} value + * @return {!proto.opentelemetry.proto.trace.v1.Status} returns this + */ +proto.opentelemetry.proto.trace.v1.Status.prototype.setCode = function(value) { + return jspb.Message.setProto3EnumField(this, 1, value); +}; + + +/** + * optional string message = 2; + * @return {string} + */ +proto.opentelemetry.proto.trace.v1.Status.prototype.getMessage = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.opentelemetry.proto.trace.v1.Status} returns this + */ +proto.opentelemetry.proto.trace.v1.Status.prototype.setMessage = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + +goog.object.extend(exports, proto.opentelemetry.proto.trace.v1); diff --git a/packages/opentelemetry-exporter-collector/package.json b/packages/opentelemetry-exporter-collector/package.json index d25876c93b..9edc6d7fbc 100644 --- a/packages/opentelemetry-exporter-collector/package.json +++ b/packages/opentelemetry-exporter-collector/package.json @@ -16,16 +16,18 @@ "codecov:browser": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../", "precompile": "tsc --version", "compile": "npm run version:update && tsc -p .", - "postcompile": "npm run submodule && npm run protos:copy", + "generate:http-proto": "rimraf ./generated/* && ./gen.sh", + "postcompile": "npm run submodule && npm run protos:copy && npm run generated:copy", "prepare": "npm run compile", "protos:copy": "cpx src/platform/node/protos/opentelemetry/**/*.* build/src/platform/node/protos/opentelemetry", + "generated:copy": "cpx generated/**/*.* build/generated", "submodule": "git submodule sync --recursive && git submodule update --init --recursive", "tdd": "npm run test -- --watch-extensions ts --watch", "tdd:browser": "karma start", "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts' --exclude 'test/browser/**/*.ts'", "test:browser": "nyc karma start --single-run", "version:update": "node ../../scripts/version-update.js", - "watch": "npm run protos:copy && tsc -w" + "watch": "npm run protos:copy && npm run generated:copy && tsc -w" }, "keywords": [ "opentelemetry", @@ -55,6 +57,7 @@ }, "devDependencies": { "@babel/core": "7.10.3", + "@types/google-protobuf": "^3.7.2", "@types/mocha": "7.0.2", "@types/node": "14.0.14", "@types/sinon": "9.0.4", @@ -83,7 +86,7 @@ "webpack-merge": "4.2.2" }, "dependencies": { - "@grpc/proto-loader": "^0.5.3", + "@grpc/proto-loader": "^0.5.4", "@opentelemetry/api": "^0.9.0", "@opentelemetry/core": "^0.9.0", "@opentelemetry/resources": "^0.9.0", diff --git a/packages/opentelemetry-exporter-collector/src/enums.ts b/packages/opentelemetry-exporter-collector/src/enums.ts index 08c2fd9f2b..8e8e27a299 100644 --- a/packages/opentelemetry-exporter-collector/src/enums.ts +++ b/packages/opentelemetry-exporter-collector/src/enums.ts @@ -21,4 +21,5 @@ export enum CollectorProtocolNode { GRPC, HTTP_JSON, + HTTP_PROTO, } diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/CollectorTraceExporter.ts b/packages/opentelemetry-exporter-collector/src/platform/node/CollectorTraceExporter.ts index 4cdaf9e41d..936ffc7dd1 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/CollectorTraceExporter.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/node/CollectorTraceExporter.ts @@ -37,6 +37,11 @@ import { onInitWithJson, sendSpansUsingJson, } from './utilWithJson'; +import { + DEFAULT_COLLECTOR_URL_JSON_PROTO, + onInitWithJsonProto, + sendSpansUsingJsonProto, +} from './utilWithJsonProto'; /** * Collector Trace Exporter for Node @@ -63,16 +68,20 @@ export class CollectorTraceExporter extends CollectorTraceExporterBase< typeof config.protocolNode !== 'undefined' ? config.protocolNode : CollectorProtocolNode.GRPC; - if (this._protocol === CollectorProtocolNode.HTTP_JSON) { - this.logger.debug('CollectorExporter - using json over http'); - if (config.metadata) { - this.logger.warn('Metadata cannot be set when using json'); - } - } else { + if (this._protocol === CollectorProtocolNode.GRPC) { this.logger.debug('CollectorExporter - using grpc'); if (config.headers) { this.logger.warn('Headers cannot be set when using grpc'); } + } else { + if (this._protocol === CollectorProtocolNode.HTTP_JSON) { + this.logger.debug('CollectorExporter - using json over http'); + } else { + this.logger.debug('CollectorExporter - using proto over http'); + } + if (config.metadata) { + this.logger.warn('Metadata cannot be set when using http'); + } } this.metadata = config.metadata; this.headers = @@ -91,6 +100,8 @@ export class CollectorTraceExporter extends CollectorTraceExporterBase< if (config.protocolNode === CollectorProtocolNode.HTTP_JSON) { onInitWithJson(this, config); + } else if (config.protocolNode === CollectorProtocolNode.HTTP_PROTO) { + onInitWithJsonProto(this, config); } else { onInitWithGrpc(this, config); } @@ -107,6 +118,8 @@ export class CollectorTraceExporter extends CollectorTraceExporterBase< } if (this._protocol === CollectorProtocolNode.HTTP_JSON) { sendSpansUsingJson(this, spans, onSuccess, onError); + } else if (this._protocol === CollectorProtocolNode.HTTP_PROTO) { + sendSpansUsingJsonProto(this, spans, onSuccess, onError); } else { sendSpansUsingGrpc(this, spans, onSuccess, onError); } @@ -114,9 +127,15 @@ export class CollectorTraceExporter extends CollectorTraceExporterBase< getDefaultUrl(config: CollectorExporterConfigNode): string { if (!config.url) { - return config.protocolNode === CollectorProtocolNode.HTTP_JSON - ? DEFAULT_COLLECTOR_URL_JSON - : DEFAULT_COLLECTOR_URL_GRPC; + if (config.protocolNode === CollectorProtocolNode.HTTP_JSON) { + return DEFAULT_COLLECTOR_URL_JSON; + } else if ( + config.protocolNode === CollectorProtocolNode.HTTP_PROTO + ) { + return DEFAULT_COLLECTOR_URL_JSON_PROTO; + } else { + return DEFAULT_COLLECTOR_URL_GRPC; + } } return config.url; } diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/README.md b/packages/opentelemetry-exporter-collector/src/platform/node/README.md index 76ff2c2c49..d5c2d50a0a 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/README.md +++ b/packages/opentelemetry-exporter-collector/src/platform/node/README.md @@ -44,3 +44,10 @@ the latest sha when this guide was written is `b54688569186e0b862bf7462a983ccf2c ``` 9. If you look now at git log you will notice that the folder `protos` has been changed and it will show what was the previous sha and what is current one + +10. After upgrading protos you should regenerate proto files for js. To do that go run +```shell script +npm run generate:http-proto +``` +After this command it should generate a new js files in folder "generated". +Make sure it compiles correctly. diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/transformSpansProto.ts b/packages/opentelemetry-exporter-collector/src/platform/node/transformSpansProto.ts new file mode 100644 index 0000000000..30f7e9e4ff --- /dev/null +++ b/packages/opentelemetry-exporter-collector/src/platform/node/transformSpansProto.ts @@ -0,0 +1,313 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 + * + * https://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. + */ + +/* eslint @typescript-eslint/no-var-requires: 0 */ + +// import * as pgTrace from '../../../generated/opentelemetry/proto/trace/v1/trace'; +// import * as pgResource from '../../../generated/opentelemetry/proto/resource/v1/resource'; +// import * as pgCommon from '../../../generated/opentelemetry/proto/common/v1/common'; +// import * as pgCollector from '../../../generated/opentelemetry/proto/collector/trace/v1/trace_service'; +const pgTrace = require('../../../generated/opentelemetry/proto/trace/v1/trace_pb'); +const pgResource = require('../../../generated/opentelemetry/proto/resource/v1/resource_pb'); +const pgCommon = require('../../../generated/opentelemetry/proto/common/v1/common_pb'); +const pgCollector = require('../../../generated/opentelemetry/proto/collector/trace/v1/trace_service_pb'); + +import { + Attributes, + Link, + SpanKind, + Status, + TimedEvent, + TraceState, +} from '@opentelemetry/api'; +import * as core from '@opentelemetry/core'; +import { Resource } from '@opentelemetry/resources'; +import { ReadableSpan } from '@opentelemetry/tracing'; +import { CollectorTraceExporterBase } from '../../CollectorTraceExporterBase'; +import { groupSpansByResourceAndLibrary } from '../../transform'; +import { COLLECTOR_SPAN_KIND_MAPPING, opentelemetryProto } from '../../types'; +import ValueType = opentelemetryProto.common.v1.ValueType; +import { InstrumentationLibrary } from '@opentelemetry/core'; +import { CollectorExporterConfigNode } from './types'; + +/** + * Converts attributes + * @param attributes + */ +export function toCollectorAttributes(attributes: Attributes) { + //: pgCommon.opentelemetry.proto.common.v1.AttributeKeyValue[] { + return Object.keys(attributes).map(key => { + return toCollectorAttributeKeyValue(key, attributes[key]); + }); +} + +/** + * Converts key and value to AttributeKeyValue + * @param value event value + */ +export function toCollectorAttributeKeyValue(key: string, value: unknown) { + //: pgCommon.opentelemetry.proto.common.v1.AttributeKeyValue { + const attributeKeyValue = new pgCommon.AttributeKeyValue(); + attributeKeyValue.setKey(key); + + if (typeof value === 'string') { + attributeKeyValue.setStringValue(value); + attributeKeyValue.setType(ValueType.STRING); + } else if (typeof value === 'boolean') { + attributeKeyValue.setBoolValue(value); + attributeKeyValue.setType(ValueType.BOOL); + } else if (typeof value === 'number') { + // all numbers will be treated as double + attributeKeyValue.setDoubleValue(value); + attributeKeyValue.setType(ValueType.DOUBLE); + } + return attributeKeyValue; +} + +/** + * + * Converts events + * @param events array of events + */ +export function toCollectorEvents(timedEvents: TimedEvent[]) { + //: pgTrace.opentelemetry.proto.trace.v1.Span.Event[] { + return timedEvents.map(timedEvent => { + const timeUnixNano = core.hrTimeToNanoseconds(timedEvent.time); + const name = timedEvent.name; + const attributes = toCollectorAttributes(timedEvent.attributes || {}); + const droppedAttributesCount = 0; + const protoEvent = new pgTrace.Span.Event(); + protoEvent.setTimeUnixNano(timeUnixNano); + protoEvent.setName(name); + protoEvent.setAttributesList(attributes); + protoEvent.setDroppedAttributesCount(droppedAttributesCount); + + return protoEvent; + }); +} + +/** + * Converts links + * @param span + */ +export function toCollectorLinks(span: ReadableSpan) { + //: pgTrace.opentelemetry.proto.trace.v1.Span.Link[] { + return span.links.map((link: Link) => { + const protoLink = new pgTrace.Span.Link(); + protoLink.setTraceId(hexToBuffer(link.context.traceId)); + protoLink.setSpanId(hexToBuffer(link.context.spanId)); + protoLink.setAttributesList(toCollectorAttributes(link.attributes || {})); + protoLink.setDroppedAttributesCount(0); + return protoLink; + }); +} + +export function toCollectorStatus(status: Status) { + //: pgTrace.opentelemetry.proto.trace.v1.Status { + const protoStatus = new pgTrace.Status(); + protoStatus.setCode(status.code); + protoStatus.setMessage(status.message); + return protoStatus; +} + +/** + * Converts span + * @param span + */ +export function toCollectorSpan(span: ReadableSpan) { + //: pgTrace.opentelemetry.proto.trace.v1.Span { + const protoSpan = new pgTrace.Span(); + + protoSpan.setTraceId(hexToBuffer(span.spanContext.traceId)); + protoSpan.setSpanId(hexToBuffer(span.spanContext.spanId)); + if (span.parentSpanId) { + protoSpan.setParentSpanId(hexToBuffer(span.parentSpanId)); + } + protoSpan.setTraceState(toCollectorTraceState(span.spanContext.traceState)); + protoSpan.setName(span.name); + protoSpan.setKind(toCollectorKind(span.kind)); + protoSpan.setStartTimeUnixNano(core.hrTimeToNanoseconds(span.startTime)); + protoSpan.setEndTimeUnixNano(core.hrTimeToNanoseconds(span.endTime)); + + protoSpan.setAttributesList(toCollectorAttributes(span.attributes)); + protoSpan.setDroppedAttributesCount(0); + + protoSpan.setEventsList(toCollectorEvents(span.events)); + protoSpan.setDroppedEventsCount(0); + + protoSpan.setStatus(toCollectorStatus(span.status)); + + protoSpan.setLinksList(toCollectorLinks(span)); + protoSpan.setDroppedLinksCount(0); + + return protoSpan; + + // return new pgTrace.Span({ + // trace_id: hexToBuffer(span.spanContext.traceId), + // span_id: hexToBuffer(span.spanContext.spanId), + // parent_span_id: span.parentSpanId + // ? hexToBuffer(span.parentSpanId) + // : undefined, + // trace_state: toCollectorTraceState(span.spanContext.traceState), + // name: span.name, + // kind: toCollectorKind(span.kind), + // start_time_unix_nano: core.hrTimeToNanoseconds(span.startTime), + // end_time_unix_nano: core.hrTimeToNanoseconds(span.endTime), + // attributes: toCollectorAttributes(span.attributes), + // dropped_attributes_count: 0, + // events: toCollectorEvents(span.events), + // dropped_events_count: 0, + // status: toCollectorStatus(span.status), + // links: toCollectorLinks(span), + // dropped_links_count: 0, + // }); +} + +/** + * Converts resource + * @param resource + * @param additionalAttributes + */ +export function toCollectorResource( + resource?: Resource, + additionalAttributes: { [key: string]: unknown } = {} +) { + //: pgResource.opentelemetry.proto.resource.v1.Resource { + // pgResource.opentelemetry.proto.resource.v1.Resource + // pgTrace.opentelemetry.proto. trace.v1.ResourceSpans + const attr = Object.assign( + {}, + additionalAttributes, + resource ? resource.labels : {} + ); + const resourceProto = new pgResource.Resource(); + const attributes = toCollectorAttributes(attr); + resourceProto.setAttributesList(attributes); + resourceProto.setDroppedAttributesCount(0); + return resourceProto; +} + +/** + * Converts span kind + * @param kind + */ +export function toCollectorKind(kind: SpanKind) { + //: pgTrace.opentelemetry.proto.trace.v1.Span.SpanKind { + const collectorKind = COLLECTOR_SPAN_KIND_MAPPING[kind]; + return typeof collectorKind === 'number' + ? collectorKind + : opentelemetryProto.trace.v1.Span.SpanKind.SPAN_KIND_UNSPECIFIED; +} + +/** + * Converts traceState + * @param traceState + */ +export function toCollectorTraceState(traceState?: TraceState) { + //: string | undefined { + if (!traceState) { + return undefined; + } + return traceState.serialize(); +} + +/** + * Prepares trace service request to be sent to collector + * @param spans spans + * @param collectorTraceExporter + * @param [name] Instrumentation Library Name + */ +export function toCollectorExportTraceServiceRequest< + T extends CollectorExporterConfigNode +>( + spans: ReadableSpan[], + collectorTraceExporter: CollectorTraceExporterBase +) { + //: pgCollector.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest { + const groupedSpans: Map< + Resource, + Map + > = groupSpansByResourceAndLibrary(spans); + + const additionalAttributes = Object.assign( + {}, + collectorTraceExporter.attributes || {}, + { + 'service.name': collectorTraceExporter.serviceName, + } + ); + + const exportTraceServiceRequest = new pgCollector.ExportTraceServiceRequest(); + const resourceSpans = toCollectorResourceSpans( + groupedSpans, + additionalAttributes + ); + exportTraceServiceRequest.setResourceSpansList(resourceSpans); + + return exportTraceServiceRequest; +} + +function toCollectorInstrumentationLibrarySpans( + instrumentationLibrary: InstrumentationLibrary, + spans: ReadableSpan[] +) { + //: pgTrace.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans { + const instrumentationLibrarySpans = new pgTrace.InstrumentationLibrarySpans(); + + const protoSpans = spans.map(toCollectorSpan); + instrumentationLibrarySpans.setSpansList(protoSpans); + + const protoInstrumentationLibrary = new pgCommon.InstrumentationLibrary(); + protoInstrumentationLibrary.setName(instrumentationLibrary.name); + protoInstrumentationLibrary.setVersion(instrumentationLibrary.version); + instrumentationLibrarySpans.setInstrumentationLibrary( + protoInstrumentationLibrary + ); + + return instrumentationLibrarySpans; +} + +function toCollectorResourceSpans( + groupedSpans: Map>, + baseAttributes: Attributes +) { + //: pgTrace.opentelemetry.proto.trace.v1.ResourceSpans[] { + return Array.from(groupedSpans, ([resource, libSpans]) => { + const resourceSpans = new pgTrace.ResourceSpans(); + const res = toCollectorResource(resource, baseAttributes); + resourceSpans.setResource(res); + const instrumentationLibrarySpans = Array.from( + libSpans, + ([instrumentationLibrary, spans]) => + toCollectorInstrumentationLibrarySpans(instrumentationLibrary, spans) + ); + resourceSpans.setInstrumentationLibrarySpansList( + instrumentationLibrarySpans + ); + return resourceSpans; + }); +} + +function hexToBuffer(hexStr: string): Uint8Array { + const hexStrLen = hexStr.length; + let hexAsciiCharsStr = ''; + for (let i = 0; i < hexStrLen; i += 2) { + const hexPair = hexStr.substring(i, i + 2); + const hexVal = parseInt(hexPair, 16); + hexAsciiCharsStr += String.fromCharCode(hexVal); + } + return Buffer.from(hexAsciiCharsStr, 'ascii'); +} diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/util.ts b/packages/opentelemetry-exporter-collector/src/platform/node/util.ts index 9ad59d5690..4629aab2e3 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/util.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/node/util.ts @@ -13,6 +13,65 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import * as url from 'url'; +import * as http from 'http'; +import * as https from 'https'; +import * as collectorTypes from '../../types'; +import { CollectorTraceExporter } from './CollectorTraceExporter'; + export function removeProtocol(url: string): string { return url.replace(/^https?:\/\//, ''); } + +/** + * Sends data using http + * @param collector + * @param data + * @param contentType + * @param onSuccess + * @param onError + */ +export function sendDataUsingHttp( + collector: CollectorTraceExporter, + data: string | Buffer, + contentType: string, + onSuccess: () => void, + onError: (error: collectorTypes.CollectorExporterError) => void +): void { + const parsedUrl = new url.URL(collector.url); + + const options = { + hostname: parsedUrl.hostname, + port: parsedUrl.port, + path: parsedUrl.pathname, + method: 'POST', + headers: { + 'Content-Length': Buffer.byteLength(data), + 'Content-Type': contentType, + ...collector.headers, + }, + }; + + const request = parsedUrl.protocol === 'http:' ? http.request : https.request; + const req = request(options, (res: http.IncomingMessage) => { + if (res.statusCode && res.statusCode < 299) { + collector.logger.debug(`statusCode: ${res.statusCode}`); + onSuccess(); + } else { + collector.logger.error(`statusCode: ${res.statusCode}`); + onError({ + code: res.statusCode, + message: res.statusMessage, + }); + } + }); + + req.on('error', (error: Error) => { + collector.logger.error('error', error.message); + onError({ + message: error.message, + }); + }); + req.write(data); + req.end(); +} diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJson.ts b/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJson.ts index a37638ac12..7badf20bd5 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJson.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJson.ts @@ -14,15 +14,12 @@ * limitations under the License. */ -import * as url from 'url'; -import * as http from 'http'; -import * as https from 'https'; - import { ReadableSpan } from '@opentelemetry/tracing'; import * as collectorTypes from '../../types'; -import { toCollectorExportTraceServiceRequest } from '../../transform'; import { CollectorTraceExporter } from './CollectorTraceExporter'; +import { toCollectorExportTraceServiceRequest } from '../../transform'; import { CollectorExporterConfigNode } from './types'; +import { sendDataUsingHttp } from './util'; export const DEFAULT_COLLECTOR_URL_JSON = 'http://localhost:55680/v1/trace'; @@ -33,6 +30,13 @@ export function onInitWithJson( // nothing to be done for json yet } +/** + * Send spans using json over http + * @param collector + * @param spans + * @param onSuccess + * @param onError + */ export function sendSpansUsingJson( collector: CollectorTraceExporter, spans: ReadableSpan[], @@ -45,40 +49,12 @@ export function sendSpansUsingJson( ); const body = JSON.stringify(exportTraceServiceRequest); - const parsedUrl = new url.URL(collector.url); - const options = { - hostname: parsedUrl.hostname, - port: parsedUrl.port, - path: parsedUrl.pathname, - method: 'POST', - headers: { - 'Content-Length': Buffer.byteLength(body), - 'Content-Type': 'application/json', - ...collector.headers, - }, - }; - - const request = parsedUrl.protocol === 'http:' ? http.request : https.request; - const req = request(options, (res: http.IncomingMessage) => { - if (res.statusCode && res.statusCode < 299) { - collector.logger.debug(`statusCode: ${res.statusCode}`); - onSuccess(); - } else { - collector.logger.error(`statusCode: ${res.statusCode}`); - onError({ - code: res.statusCode, - message: res.statusMessage, - }); - } - }); - - req.on('error', (error: Error) => { - collector.logger.error('error', error.message); - onError({ - message: error.message, - }); - }); - req.write(body); - req.end(); + return sendDataUsingHttp( + collector, + body, + 'application/json', + onSuccess, + onError + ); } diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJsonProto.ts b/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJsonProto.ts new file mode 100644 index 0000000000..e4777cbaba --- /dev/null +++ b/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJsonProto.ts @@ -0,0 +1,61 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 + * + * https://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. + */ + +import { ReadableSpan } from '@opentelemetry/tracing'; +import * as collectorTypes from '../../types'; +import { CollectorTraceExporter } from './CollectorTraceExporter'; +import { toCollectorExportTraceServiceRequest } from './transformSpansProto'; +import { CollectorExporterConfigNode } from './types'; +import { sendDataUsingHttp } from './util'; + +export const DEFAULT_COLLECTOR_URL_JSON_PROTO = + 'http://localhost:55680/v1/trace'; + +export function onInitWithJsonProto( + _collector: CollectorTraceExporter, + _config: CollectorExporterConfigNode +): void { + // nothing to be done for json proto yet +} + +/** + * Send spans using proto over http + * @param collector + * @param spans + * @param onSuccess + * @param onError + */ +export function sendSpansUsingJsonProto( + collector: CollectorTraceExporter, + spans: ReadableSpan[], + onSuccess: () => void, + onError: (error: collectorTypes.CollectorExporterError) => void +): void { + const exportTraceServiceRequest = toCollectorExportTraceServiceRequest( + spans, + collector + ); + + const body = exportTraceServiceRequest.serializeBinary(); + + return sendDataUsingHttp( + collector, + Buffer.from(body), + 'application/x-protobuf', + onSuccess, + onError + ); +} diff --git a/packages/opentelemetry-exporter-collector/test/node/CollectorTraceExporter.test.ts b/packages/opentelemetry-exporter-collector/test/node/CollectorTraceExporter.test.ts index 91e89fc02f..9cadd1574c 100644 --- a/packages/opentelemetry-exporter-collector/test/node/CollectorTraceExporter.test.ts +++ b/packages/opentelemetry-exporter-collector/test/node/CollectorTraceExporter.test.ts @@ -168,7 +168,7 @@ const testCollectorExporter = (params: TestParams) => protocolNode: CollectorProtocolNode.HTTP_JSON, }); const args = spyLoggerWarn.args[0]; - assert.strictEqual(args[0], 'Metadata cannot be set when using json'); + assert.strictEqual(args[0], 'Metadata cannot be set when using http'); }); }); diff --git a/packages/opentelemetry-exporter-collector/test/node/transformSpansProto.test.ts b/packages/opentelemetry-exporter-collector/test/node/transformSpansProto.test.ts new file mode 100644 index 0000000000..e89ce0d385 --- /dev/null +++ b/packages/opentelemetry-exporter-collector/test/node/transformSpansProto.test.ts @@ -0,0 +1,383 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 + * + * https://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. + */ + +import { Attributes, TimedEvent } from '@opentelemetry/api'; +import * as assert from 'assert'; +import * as transform from '../../src/platform/node/transformSpansProto'; +import { opentelemetryProto } from '../../src/types'; +import { mockedReadableSpan } from '../helper'; +import { Resource } from '@opentelemetry/resources'; + +describe('transform - spans proto', () => { + describe('toCollectorAttributes', () => { + it('should convert attribute string', () => { + const attributes: Attributes = { + foo: 'bar', + }; + assert.deepStrictEqual( + transform.toCollectorAttributes(attributes)[0].toObject(), + { + key: 'foo', + type: 0, + stringValue: 'bar', + intValue: 0, + doubleValue: 0, + boolValue: false, + } + ); + }); + + it('should convert attribute integer', () => { + const attributes: Attributes = { + foo: 13, + }; + assert.deepStrictEqual( + transform.toCollectorAttributes(attributes)[0].toObject(), + { + key: 'foo', + type: 2, + stringValue: '', + intValue: 0, + doubleValue: 13, + boolValue: false, + } + ); + }); + + it('should convert attribute boolean', () => { + const attributes: Attributes = { + foo: true, + }; + assert.deepStrictEqual( + transform.toCollectorAttributes(attributes)[0].toObject(), + { + key: 'foo', + type: 3, + stringValue: '', + intValue: 0, + doubleValue: 0, + boolValue: true, + } + ); + }); + + it('should convert attribute double', () => { + const attributes: Attributes = { + foo: 1.34, + }; + assert.deepStrictEqual( + transform.toCollectorAttributes(attributes)[0].toObject(), + { + key: 'foo', + type: 2, + stringValue: '', + intValue: 0, + doubleValue: 1.34, + boolValue: false, + } + ); + }); + }); + + describe('toCollectorEvents', () => { + it('should convert events to otc events', () => { + const events: TimedEvent[] = [ + { name: 'foo', time: [123, 123], attributes: { a: 'b' } }, + { + name: 'foo2', + time: [321, 321], + attributes: { c: 'd' }, + }, + ]; + const protoEvents = transform.toCollectorEvents(events); + const event1 = protoEvents[0].toObject(); + const event2 = protoEvents[1].toObject(); + assert.deepStrictEqual(event1, { + timeUnixNano: 123000000123, + name: 'foo', + attributesList: [ + { + key: 'a', + type: 0, + stringValue: 'b', + intValue: 0, + doubleValue: 0, + boolValue: false, + }, + ], + droppedAttributesCount: 0, + }); + assert.deepStrictEqual(event2, { + timeUnixNano: 321000000321, + name: 'foo2', + attributesList: [ + { + key: 'c', + type: 0, + stringValue: 'd', + intValue: 0, + doubleValue: 0, + boolValue: false, + }, + ], + droppedAttributesCount: 0, + }); + }); + }); + + describe('toCollectorSpan', () => { + const span = transform.toCollectorSpan(mockedReadableSpan).toObject(); + it('should convert attributes', () => { + assert.deepStrictEqual(span.attributesList, [ + { + key: 'component', + type: 0, + stringValue: 'document-load', + intValue: 0, + doubleValue: 0, + boolValue: false, + }, + ]); + }); + it('should convert events', () => { + assert.deepStrictEqual(span.eventsList, [ + { + timeUnixNano: 1574120165429803000, + name: 'fetchStart', + attributesList: [], + droppedAttributesCount: 0, + }, + { + timeUnixNano: 1574120165429803000, + name: 'domainLookupStart', + attributesList: [], + droppedAttributesCount: 0, + }, + { + timeUnixNano: 1574120165429803000, + name: 'domainLookupEnd', + attributesList: [], + droppedAttributesCount: 0, + }, + { + timeUnixNano: 1574120165429803000, + name: 'connectStart', + attributesList: [], + droppedAttributesCount: 0, + }, + { + timeUnixNano: 1574120165429803000, + name: 'connectEnd', + attributesList: [], + droppedAttributesCount: 0, + }, + { + timeUnixNano: 1574120165435513000, + name: 'requestStart', + attributesList: [], + droppedAttributesCount: 0, + }, + { + timeUnixNano: 1574120165436923100, + name: 'responseStart', + attributesList: [], + droppedAttributesCount: 0, + }, + { + timeUnixNano: 1574120165438688000, + name: 'responseEnd', + attributesList: [], + droppedAttributesCount: 0, + }, + ]); + }); + it('should convert links', () => { + assert.deepStrictEqual(span.linksList, [ + { + traceId: 'HxAI3I4nDoXECg18OTmyeA==', + spanId: 'eKiRUJiGQ4g=', + traceState: '', + attributesList: [ + { + key: 'component', + type: 0, + stringValue: 'document-load', + intValue: 0, + doubleValue: 0, + boolValue: false, + }, + ], + droppedAttributesCount: 0, + }, + ]); + }); + it('should convert trace id', () => { + assert.deepStrictEqual( + span.traceId, + 'HxAI3I4nDoXECg18OTmyeA==', + 'traceId is wrong' + ); + assert.deepStrictEqual(span.spanId, 'XhByYfZPpT4=', 'spanId is wrong'); + assert.deepStrictEqual( + span.parentSpanId, + 'eKiRUJiGQ4g=', + 'parentIdArr is wrong' + ); + assert.strictEqual(span.name, 'documentFetch', 'name is wrong'); + assert.strictEqual( + span.kind, + opentelemetryProto.trace.v1.Span.SpanKind.INTERNAL, + 'kind is wrong' + ); + assert.strictEqual( + span.startTimeUnixNano, + 1574120165429803008, + 'startTimeUnixNano is wrong' + ); + assert.strictEqual( + span.endTimeUnixNano, + 1574120165438688000, + 'endTimeUnixNano is wrong' + ); + assert.strictEqual( + span.droppedAttributesCount, + 0, + 'droppedAttributesCount is wrong' + ); + assert.strictEqual( + span.droppedEventsCount, + 0, + 'droppedEventsCount is wrong' + ); + assert.strictEqual( + span.droppedLinksCount, + 0, + 'droppedLinksCount is wrong' + ); + assert.deepStrictEqual( + span.status, + { code: 0, message: '' }, + 'status is' + ' wrong' + ); + }); + it('should convert span id', () => { + assert.deepStrictEqual(span.spanId, 'XhByYfZPpT4=', 'spanId is wrong'); + }); + it('should convert parent id', () => { + assert.deepStrictEqual( + span.parentSpanId, + 'eKiRUJiGQ4g=', + 'parentIdArr is wrong' + ); + }); + it('should convert name', () => { + assert.strictEqual(span.name, 'documentFetch', 'name is wrong'); + }); + it('should convert kind', () => { + assert.strictEqual( + span.kind, + opentelemetryProto.trace.v1.Span.SpanKind.INTERNAL, + 'kind is wrong' + ); + }); + it('should convert start time', () => { + assert.strictEqual( + span.startTimeUnixNano, + 1574120165429803008, + 'startTimeUnixNano is wrong' + ); + }); + it('should convert end time', () => { + assert.strictEqual( + span.endTimeUnixNano, + 1574120165438688000, + 'endTimeUnixNano is wrong' + ); + }); + it('should convert droppedAttributesCount', () => { + assert.strictEqual( + span.droppedAttributesCount, + 0, + 'droppedAttributesCount is wrong' + ); + }); + + it('should convert droppedEventsCount', () => { + assert.strictEqual( + span.droppedEventsCount, + 0, + 'droppedEventsCount is wrong' + ); + }); + + it('should convert droppedLinksCount', () => { + assert.strictEqual( + span.droppedLinksCount, + 0, + 'droppedLinksCount is wrong' + ); + }); + + it('should convert status', () => { + assert.deepStrictEqual( + span.status, + { code: 0, message: '' }, + 'status is' + ' wrong' + ); + }); + }); + + describe('toCollectorResource', () => { + it('should convert resource', () => { + const resource = transform.toCollectorResource( + new Resource({ + service: 'ui', + version: 1.0, + success: true, + }) + ); + assert.deepStrictEqual(resource.toObject(), { + attributesList: [ + { + key: 'service', + type: 0, + stringValue: 'ui', + intValue: 0, + doubleValue: 0, + boolValue: false, + }, + { + key: 'version', + type: 2, + stringValue: '', + intValue: 0, + doubleValue: 1, + boolValue: false, + }, + { + key: 'success', + type: 3, + stringValue: '', + intValue: 0, + doubleValue: 0, + boolValue: true, + }, + ], + droppedAttributesCount: 0, + }); + }); + }); +}); diff --git a/packages/opentelemetry-exporter-collector/tsconfig.json b/packages/opentelemetry-exporter-collector/tsconfig.json index a2042cd68b..8d3779eda9 100644 --- a/packages/opentelemetry-exporter-collector/tsconfig.json +++ b/packages/opentelemetry-exporter-collector/tsconfig.json @@ -5,6 +5,7 @@ "outDir": "build" }, "include": [ + "generated/**/*.js", "src/**/*.ts", "test/**/*.ts" ] From 6638c32b5f8f4ecfb9a3b1acc8a61c32b2257a81 Mon Sep 17 00:00:00 2001 From: Bartlomiej Obecny Date: Fri, 10 Jul 2020 14:44:05 +0200 Subject: [PATCH 02/19] chore: lint --- .../src/platform/node/README.md | 2 ++ .../src/platform/node/transformSpansProto.ts | 20 ------------------- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/README.md b/packages/opentelemetry-exporter-collector/src/platform/node/README.md index d5c2d50a0a..4dec5ba87b 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/README.md +++ b/packages/opentelemetry-exporter-collector/src/platform/node/README.md @@ -46,8 +46,10 @@ the latest sha when this guide was written is `b54688569186e0b862bf7462a983ccf2c 9. If you look now at git log you will notice that the folder `protos` has been changed and it will show what was the previous sha and what is current one 10. After upgrading protos you should regenerate proto files for js. To do that go run + ```shell script npm run generate:http-proto ``` + After this command it should generate a new js files in folder "generated". Make sure it compiles correctly. diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/transformSpansProto.ts b/packages/opentelemetry-exporter-collector/src/platform/node/transformSpansProto.ts index 30f7e9e4ff..7d96424658 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/transformSpansProto.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/node/transformSpansProto.ts @@ -154,26 +154,6 @@ export function toCollectorSpan(span: ReadableSpan) { protoSpan.setDroppedLinksCount(0); return protoSpan; - - // return new pgTrace.Span({ - // trace_id: hexToBuffer(span.spanContext.traceId), - // span_id: hexToBuffer(span.spanContext.spanId), - // parent_span_id: span.parentSpanId - // ? hexToBuffer(span.parentSpanId) - // : undefined, - // trace_state: toCollectorTraceState(span.spanContext.traceState), - // name: span.name, - // kind: toCollectorKind(span.kind), - // start_time_unix_nano: core.hrTimeToNanoseconds(span.startTime), - // end_time_unix_nano: core.hrTimeToNanoseconds(span.endTime), - // attributes: toCollectorAttributes(span.attributes), - // dropped_attributes_count: 0, - // events: toCollectorEvents(span.events), - // dropped_events_count: 0, - // status: toCollectorStatus(span.status), - // links: toCollectorLinks(span), - // dropped_links_count: 0, - // }); } /** From dbdd707258eb6800457dac197020fe7b048d13ee Mon Sep 17 00:00:00 2001 From: Bartlomiej Obecny Date: Fri, 10 Jul 2020 14:53:21 +0200 Subject: [PATCH 03/19] chore: lint --- .../src/platform/node/CollectorTraceExporter.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/CollectorTraceExporter.ts b/packages/opentelemetry-exporter-collector/src/platform/node/CollectorTraceExporter.ts index 936ffc7dd1..ea2e93687b 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/CollectorTraceExporter.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/node/CollectorTraceExporter.ts @@ -129,9 +129,7 @@ export class CollectorTraceExporter extends CollectorTraceExporterBase< if (!config.url) { if (config.protocolNode === CollectorProtocolNode.HTTP_JSON) { return DEFAULT_COLLECTOR_URL_JSON; - } else if ( - config.protocolNode === CollectorProtocolNode.HTTP_PROTO - ) { + } else if (config.protocolNode === CollectorProtocolNode.HTTP_PROTO) { return DEFAULT_COLLECTOR_URL_JSON_PROTO; } else { return DEFAULT_COLLECTOR_URL_GRPC; From 32a01c558dc7581c329e6d261ced1ed300ae0d6b Mon Sep 17 00:00:00 2001 From: Bartlomiej Obecny Date: Fri, 10 Jul 2020 14:57:37 +0200 Subject: [PATCH 04/19] chore: fixing transport type in example --- examples/collector-exporter-node/start.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/collector-exporter-node/start.js b/examples/collector-exporter-node/start.js index dd24a94c7d..138b6b41ec 100644 --- a/examples/collector-exporter-node/start.js +++ b/examples/collector-exporter-node/start.js @@ -9,7 +9,7 @@ const exporter = new CollectorTraceExporter({ // headers: { // foo: 'bar' // }, - protocolNode: CollectorProtocolNode.HTTP_JSON_PROTO, + protocolNode: CollectorProtocolNode.HTTP_PROTO, // protocolNode: CollectorProtocolNode.HTTP_JSON, }); From 0b7dc817e76f727f4097596cc7eba794deefab5d Mon Sep 17 00:00:00 2001 From: Bartlomiej Obecny Date: Fri, 10 Jul 2020 15:05:47 +0200 Subject: [PATCH 05/19] chore: adding generated to files in package.json --- packages/opentelemetry-exporter-collector/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/opentelemetry-exporter-collector/package.json b/packages/opentelemetry-exporter-collector/package.json index 9edc6d7fbc..673ef3dba2 100644 --- a/packages/opentelemetry-exporter-collector/package.json +++ b/packages/opentelemetry-exporter-collector/package.json @@ -48,6 +48,7 @@ "build/src/**/*.js.map", "build/src/**/*.d.ts", "build/src/**/*.proto", + "build/generated/**/*.js", "doc", "LICENSE", "README.md" From 11c5a5618bb855e7dfab958bf259d7ed4964eadd Mon Sep 17 00:00:00 2001 From: Bartlomiej Obecny Date: Mon, 13 Jul 2020 21:28:24 +0200 Subject: [PATCH 06/19] chore: adding more info about protoc --- .../src/platform/node/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/README.md b/packages/opentelemetry-exporter-collector/src/platform/node/README.md index 4dec5ba87b..5827349a43 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/README.md +++ b/packages/opentelemetry-exporter-collector/src/platform/node/README.md @@ -45,7 +45,8 @@ the latest sha when this guide was written is `b54688569186e0b862bf7462a983ccf2c 9. If you look now at git log you will notice that the folder `protos` has been changed and it will show what was the previous sha and what is current one -10. After upgrading protos you should regenerate proto files for js. To do that go run +10. After upgrading protos you should regenerate proto files for js. +**You need to have protocol buffers installed to be able to generate them**. ```shell script npm run generate:http-proto From bfeaec7af89953b2e1912fc5ab982788e907de96 Mon Sep 17 00:00:00 2001 From: Bartlomiej Obecny Date: Tue, 14 Jul 2020 00:21:50 +0200 Subject: [PATCH 07/19] chore: replacing google-protobuf with protobufjs --- .nycrc | 1 - .../opentelemetry-exporter-collector/gen.sh | 13 - .../collector/trace/v1/trace_service_pb.js | 323 --- .../proto/common/v1/common_pb.js | 692 ------ .../proto/resource/v1/resource_pb.js | 229 -- .../opentelemetry/proto/trace/v1/trace_pb.js | 2067 ----------------- .../package.json | 8 +- .../src/platform/node/README.md | 8 - .../src/platform/node/transformSpansProto.ts | 293 --- .../src/platform/node/utilWithJsonProto.ts | 49 +- .../test/helper.ts | 131 ++ .../node/CollectorExporterWithProto.test.ts | 188 ++ .../test/node/transformSpansProto.test.ts | 383 --- .../tsconfig.json | 1 - 14 files changed, 361 insertions(+), 4025 deletions(-) delete mode 100755 packages/opentelemetry-exporter-collector/gen.sh delete mode 100644 packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/collector/trace/v1/trace_service_pb.js delete mode 100644 packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/common/v1/common_pb.js delete mode 100644 packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/resource/v1/resource_pb.js delete mode 100644 packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/trace/v1/trace_pb.js delete mode 100644 packages/opentelemetry-exporter-collector/src/platform/node/transformSpansProto.ts create mode 100644 packages/opentelemetry-exporter-collector/test/node/CollectorExporterWithProto.test.ts delete mode 100644 packages/opentelemetry-exporter-collector/test/node/transformSpansProto.test.ts diff --git a/.nycrc b/.nycrc index 53a2f2262d..47b8c170df 100644 --- a/.nycrc +++ b/.nycrc @@ -5,7 +5,6 @@ "exclude": [ "**/*.d.ts", "build/**/*.*", - "generated/**/*.*", "src/index.ts", "src/platform/**/index.ts", "src/platform/browser/*.ts", diff --git a/packages/opentelemetry-exporter-collector/gen.sh b/packages/opentelemetry-exporter-collector/gen.sh deleted file mode 100755 index 7404879bb9..0000000000 --- a/packages/opentelemetry-exporter-collector/gen.sh +++ /dev/null @@ -1,13 +0,0 @@ -clear -git submodule sync --recursive -git submodule update --init --recursive - -OUT_DIR="./generated" - -protoc \ - --js_out="import_style=commonjs,binary:${OUT_DIR}" \ - --proto_path="src/platform/node/protos/" \ - opentelemetry/proto/common/v1/common.proto \ - opentelemetry/proto/resource/v1/resource.proto \ - opentelemetry/proto/trace/v1/trace.proto \ - opentelemetry/proto/collector/trace/v1/trace_service.proto \ diff --git a/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/collector/trace/v1/trace_service_pb.js b/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/collector/trace/v1/trace_service_pb.js deleted file mode 100644 index 606e2dd104..0000000000 --- a/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/collector/trace/v1/trace_service_pb.js +++ /dev/null @@ -1,323 +0,0 @@ -// source: opentelemetry/proto/collector/trace/v1/trace_service.proto -// source: opentelemetry/proto/collector/trace/v1/trace_service.proto -/** - * @fileoverview - * @enhanceable - * @suppress {messageConventions} JS Compiler reports an error if a variable or - * field starts with 'MSG_' and isn't a translatable message. - * @public - */ -// GENERATED CODE -- DO NOT EDIT! - -var jspb = require('google-protobuf'); -var goog = jspb; -var global = Function('return this')(); - -var opentelemetry_proto_trace_v1_trace_pb = require('../../../../../opentelemetry/proto/trace/v1/trace_pb.js'); -goog.object.extend(proto, opentelemetry_proto_trace_v1_trace_pb); -goog.exportSymbol('proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest', null, global); -goog.exportSymbol('proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse', null, global); -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.repeatedFields_, null); -}; -goog.inherits(proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.displayName = 'proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest'; -} -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); -}; -goog.inherits(proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse.displayName = 'proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse'; -} - -/** - * List of repeated fields within this message type. - * @private {!Array} - * @const - */ -proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.repeatedFields_ = [1]; - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.prototype.toObject = function(opt_includeInstance) { - return proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.toObject = function(includeInstance, msg) { - var f, obj = { - resourceSpansList: jspb.Message.toObjectList(msg.getResourceSpansList(), - opentelemetry_proto_trace_v1_trace_pb.ResourceSpans.toObject, includeInstance) - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest} - */ -proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest; - return proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest} - */ -proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = new opentelemetry_proto_trace_v1_trace_pb.ResourceSpans; - reader.readMessage(value,opentelemetry_proto_trace_v1_trace_pb.ResourceSpans.deserializeBinaryFromReader); - msg.addResourceSpans(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getResourceSpansList(); - if (f.length > 0) { - writer.writeRepeatedMessage( - 1, - f, - opentelemetry_proto_trace_v1_trace_pb.ResourceSpans.serializeBinaryToWriter - ); - } -}; - - -/** - * repeated opentelemetry.proto.trace.v1.ResourceSpans resource_spans = 1; - * @return {!Array} - */ -proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.prototype.getResourceSpansList = function() { - return /** @type{!Array} */ ( - jspb.Message.getRepeatedWrapperField(this, opentelemetry_proto_trace_v1_trace_pb.ResourceSpans, 1)); -}; - - -/** - * @param {!Array} value - * @return {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest} returns this -*/ -proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.prototype.setResourceSpansList = function(value) { - return jspb.Message.setRepeatedWrapperField(this, 1, value); -}; - - -/** - * @param {!proto.opentelemetry.proto.trace.v1.ResourceSpans=} opt_value - * @param {number=} opt_index - * @return {!proto.opentelemetry.proto.trace.v1.ResourceSpans} - */ -proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.prototype.addResourceSpans = function(opt_value, opt_index) { - return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.opentelemetry.proto.trace.v1.ResourceSpans, opt_index); -}; - - -/** - * Clears the list making it empty but non-null. - * @return {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest} returns this - */ -proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest.prototype.clearResourceSpansList = function() { - return this.setResourceSpansList([]); -}; - - - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse.prototype.toObject = function(opt_includeInstance) { - return proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse.toObject = function(includeInstance, msg) { - var f, obj = { - - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse} - */ -proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse; - return proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse} - */ -proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse.serializeBinaryToWriter = function(message, writer) { - var f = undefined; -}; - - -goog.object.extend(exports, proto.opentelemetry.proto.collector.trace.v1); diff --git a/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/common/v1/common_pb.js b/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/common/v1/common_pb.js deleted file mode 100644 index 796ad90f6a..0000000000 --- a/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/common/v1/common_pb.js +++ /dev/null @@ -1,692 +0,0 @@ -// source: opentelemetry/proto/common/v1/common.proto -/** - * @fileoverview - * @enhanceable - * @suppress {messageConventions} JS Compiler reports an error if a variable or - * field starts with 'MSG_' and isn't a translatable message. - * @public - */ -// GENERATED CODE -- DO NOT EDIT! - -var jspb = require('google-protobuf'); -var goog = jspb; -var global = Function('return this')(); - -goog.exportSymbol('proto.opentelemetry.proto.common.v1.AttributeKeyValue', null, global); -goog.exportSymbol('proto.opentelemetry.proto.common.v1.AttributeKeyValue.ValueType', null, global); -goog.exportSymbol('proto.opentelemetry.proto.common.v1.InstrumentationLibrary', null, global); -goog.exportSymbol('proto.opentelemetry.proto.common.v1.StringKeyValue', null, global); -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.opentelemetry.proto.common.v1.AttributeKeyValue = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); -}; -goog.inherits(proto.opentelemetry.proto.common.v1.AttributeKeyValue, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.opentelemetry.proto.common.v1.AttributeKeyValue.displayName = 'proto.opentelemetry.proto.common.v1.AttributeKeyValue'; -} -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.opentelemetry.proto.common.v1.StringKeyValue = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); -}; -goog.inherits(proto.opentelemetry.proto.common.v1.StringKeyValue, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.opentelemetry.proto.common.v1.StringKeyValue.displayName = 'proto.opentelemetry.proto.common.v1.StringKeyValue'; -} -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.opentelemetry.proto.common.v1.InstrumentationLibrary = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); -}; -goog.inherits(proto.opentelemetry.proto.common.v1.InstrumentationLibrary, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.opentelemetry.proto.common.v1.InstrumentationLibrary.displayName = 'proto.opentelemetry.proto.common.v1.InstrumentationLibrary'; -} - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.toObject = function(opt_includeInstance) { - return proto.opentelemetry.proto.common.v1.AttributeKeyValue.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.common.v1.AttributeKeyValue.toObject = function(includeInstance, msg) { - var f, obj = { - key: jspb.Message.getFieldWithDefault(msg, 1, ""), - type: jspb.Message.getFieldWithDefault(msg, 2, 0), - stringValue: jspb.Message.getFieldWithDefault(msg, 3, ""), - intValue: jspb.Message.getFieldWithDefault(msg, 4, 0), - doubleValue: jspb.Message.getFloatingPointFieldWithDefault(msg, 5, 0.0), - boolValue: jspb.Message.getBooleanFieldWithDefault(msg, 6, false) - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} - */ -proto.opentelemetry.proto.common.v1.AttributeKeyValue.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.opentelemetry.proto.common.v1.AttributeKeyValue; - return proto.opentelemetry.proto.common.v1.AttributeKeyValue.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} - */ -proto.opentelemetry.proto.common.v1.AttributeKeyValue.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {string} */ (reader.readString()); - msg.setKey(value); - break; - case 2: - var value = /** @type {!proto.opentelemetry.proto.common.v1.AttributeKeyValue.ValueType} */ (reader.readEnum()); - msg.setType(value); - break; - case 3: - var value = /** @type {string} */ (reader.readString()); - msg.setStringValue(value); - break; - case 4: - var value = /** @type {number} */ (reader.readInt64()); - msg.setIntValue(value); - break; - case 5: - var value = /** @type {number} */ (reader.readDouble()); - msg.setDoubleValue(value); - break; - case 6: - var value = /** @type {boolean} */ (reader.readBool()); - msg.setBoolValue(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.opentelemetry.proto.common.v1.AttributeKeyValue.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.common.v1.AttributeKeyValue.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getKey(); - if (f.length > 0) { - writer.writeString( - 1, - f - ); - } - f = message.getType(); - if (f !== 0.0) { - writer.writeEnum( - 2, - f - ); - } - f = message.getStringValue(); - if (f.length > 0) { - writer.writeString( - 3, - f - ); - } - f = message.getIntValue(); - if (f !== 0) { - writer.writeInt64( - 4, - f - ); - } - f = message.getDoubleValue(); - if (f !== 0.0) { - writer.writeDouble( - 5, - f - ); - } - f = message.getBoolValue(); - if (f) { - writer.writeBool( - 6, - f - ); - } -}; - - -/** - * @enum {number} - */ -proto.opentelemetry.proto.common.v1.AttributeKeyValue.ValueType = { - STRING: 0, - INT: 1, - DOUBLE: 2, - BOOL: 3 -}; - -/** - * optional string key = 1; - * @return {string} - */ -proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.getKey = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); -}; - - -/** - * @param {string} value - * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} returns this - */ -proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.setKey = function(value) { - return jspb.Message.setProto3StringField(this, 1, value); -}; - - -/** - * optional ValueType type = 2; - * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue.ValueType} - */ -proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.getType = function() { - return /** @type {!proto.opentelemetry.proto.common.v1.AttributeKeyValue.ValueType} */ (jspb.Message.getFieldWithDefault(this, 2, 0)); -}; - - -/** - * @param {!proto.opentelemetry.proto.common.v1.AttributeKeyValue.ValueType} value - * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} returns this - */ -proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.setType = function(value) { - return jspb.Message.setProto3EnumField(this, 2, value); -}; - - -/** - * optional string string_value = 3; - * @return {string} - */ -proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.getStringValue = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); -}; - - -/** - * @param {string} value - * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} returns this - */ -proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.setStringValue = function(value) { - return jspb.Message.setProto3StringField(this, 3, value); -}; - - -/** - * optional int64 int_value = 4; - * @return {number} - */ -proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.getIntValue = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0)); -}; - - -/** - * @param {number} value - * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} returns this - */ -proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.setIntValue = function(value) { - return jspb.Message.setProto3IntField(this, 4, value); -}; - - -/** - * optional double double_value = 5; - * @return {number} - */ -proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.getDoubleValue = function() { - return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 5, 0.0)); -}; - - -/** - * @param {number} value - * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} returns this - */ -proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.setDoubleValue = function(value) { - return jspb.Message.setProto3FloatField(this, 5, value); -}; - - -/** - * optional bool bool_value = 6; - * @return {boolean} - */ -proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.getBoolValue = function() { - return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 6, false)); -}; - - -/** - * @param {boolean} value - * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} returns this - */ -proto.opentelemetry.proto.common.v1.AttributeKeyValue.prototype.setBoolValue = function(value) { - return jspb.Message.setProto3BooleanField(this, 6, value); -}; - - - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.opentelemetry.proto.common.v1.StringKeyValue.prototype.toObject = function(opt_includeInstance) { - return proto.opentelemetry.proto.common.v1.StringKeyValue.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.opentelemetry.proto.common.v1.StringKeyValue} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.common.v1.StringKeyValue.toObject = function(includeInstance, msg) { - var f, obj = { - key: jspb.Message.getFieldWithDefault(msg, 1, ""), - value: jspb.Message.getFieldWithDefault(msg, 2, "") - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.opentelemetry.proto.common.v1.StringKeyValue} - */ -proto.opentelemetry.proto.common.v1.StringKeyValue.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.opentelemetry.proto.common.v1.StringKeyValue; - return proto.opentelemetry.proto.common.v1.StringKeyValue.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.opentelemetry.proto.common.v1.StringKeyValue} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.opentelemetry.proto.common.v1.StringKeyValue} - */ -proto.opentelemetry.proto.common.v1.StringKeyValue.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {string} */ (reader.readString()); - msg.setKey(value); - break; - case 2: - var value = /** @type {string} */ (reader.readString()); - msg.setValue(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.opentelemetry.proto.common.v1.StringKeyValue.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.opentelemetry.proto.common.v1.StringKeyValue.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.opentelemetry.proto.common.v1.StringKeyValue} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.common.v1.StringKeyValue.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getKey(); - if (f.length > 0) { - writer.writeString( - 1, - f - ); - } - f = message.getValue(); - if (f.length > 0) { - writer.writeString( - 2, - f - ); - } -}; - - -/** - * optional string key = 1; - * @return {string} - */ -proto.opentelemetry.proto.common.v1.StringKeyValue.prototype.getKey = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); -}; - - -/** - * @param {string} value - * @return {!proto.opentelemetry.proto.common.v1.StringKeyValue} returns this - */ -proto.opentelemetry.proto.common.v1.StringKeyValue.prototype.setKey = function(value) { - return jspb.Message.setProto3StringField(this, 1, value); -}; - - -/** - * optional string value = 2; - * @return {string} - */ -proto.opentelemetry.proto.common.v1.StringKeyValue.prototype.getValue = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); -}; - - -/** - * @param {string} value - * @return {!proto.opentelemetry.proto.common.v1.StringKeyValue} returns this - */ -proto.opentelemetry.proto.common.v1.StringKeyValue.prototype.setValue = function(value) { - return jspb.Message.setProto3StringField(this, 2, value); -}; - - - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.opentelemetry.proto.common.v1.InstrumentationLibrary.prototype.toObject = function(opt_includeInstance) { - return proto.opentelemetry.proto.common.v1.InstrumentationLibrary.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.opentelemetry.proto.common.v1.InstrumentationLibrary} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.common.v1.InstrumentationLibrary.toObject = function(includeInstance, msg) { - var f, obj = { - name: jspb.Message.getFieldWithDefault(msg, 1, ""), - version: jspb.Message.getFieldWithDefault(msg, 2, "") - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.opentelemetry.proto.common.v1.InstrumentationLibrary} - */ -proto.opentelemetry.proto.common.v1.InstrumentationLibrary.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.opentelemetry.proto.common.v1.InstrumentationLibrary; - return proto.opentelemetry.proto.common.v1.InstrumentationLibrary.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.opentelemetry.proto.common.v1.InstrumentationLibrary} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.opentelemetry.proto.common.v1.InstrumentationLibrary} - */ -proto.opentelemetry.proto.common.v1.InstrumentationLibrary.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {string} */ (reader.readString()); - msg.setName(value); - break; - case 2: - var value = /** @type {string} */ (reader.readString()); - msg.setVersion(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.opentelemetry.proto.common.v1.InstrumentationLibrary.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.opentelemetry.proto.common.v1.InstrumentationLibrary.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.opentelemetry.proto.common.v1.InstrumentationLibrary} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.common.v1.InstrumentationLibrary.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getName(); - if (f.length > 0) { - writer.writeString( - 1, - f - ); - } - f = message.getVersion(); - if (f.length > 0) { - writer.writeString( - 2, - f - ); - } -}; - - -/** - * optional string name = 1; - * @return {string} - */ -proto.opentelemetry.proto.common.v1.InstrumentationLibrary.prototype.getName = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); -}; - - -/** - * @param {string} value - * @return {!proto.opentelemetry.proto.common.v1.InstrumentationLibrary} returns this - */ -proto.opentelemetry.proto.common.v1.InstrumentationLibrary.prototype.setName = function(value) { - return jspb.Message.setProto3StringField(this, 1, value); -}; - - -/** - * optional string version = 2; - * @return {string} - */ -proto.opentelemetry.proto.common.v1.InstrumentationLibrary.prototype.getVersion = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); -}; - - -/** - * @param {string} value - * @return {!proto.opentelemetry.proto.common.v1.InstrumentationLibrary} returns this - */ -proto.opentelemetry.proto.common.v1.InstrumentationLibrary.prototype.setVersion = function(value) { - return jspb.Message.setProto3StringField(this, 2, value); -}; - - -goog.object.extend(exports, proto.opentelemetry.proto.common.v1); diff --git a/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/resource/v1/resource_pb.js b/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/resource/v1/resource_pb.js deleted file mode 100644 index d03e6a365e..0000000000 --- a/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/resource/v1/resource_pb.js +++ /dev/null @@ -1,229 +0,0 @@ -// source: opentelemetry/proto/resource/v1/resource.proto -/** - * @fileoverview - * @enhanceable - * @suppress {messageConventions} JS Compiler reports an error if a variable or - * field starts with 'MSG_' and isn't a translatable message. - * @public - */ -// GENERATED CODE -- DO NOT EDIT! - -var jspb = require('google-protobuf'); -var goog = jspb; -var global = Function('return this')(); - -var opentelemetry_proto_common_v1_common_pb = require('../../../../opentelemetry/proto/common/v1/common_pb.js'); -goog.object.extend(proto, opentelemetry_proto_common_v1_common_pb); -goog.exportSymbol('proto.opentelemetry.proto.resource.v1.Resource', null, global); -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.opentelemetry.proto.resource.v1.Resource = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, proto.opentelemetry.proto.resource.v1.Resource.repeatedFields_, null); -}; -goog.inherits(proto.opentelemetry.proto.resource.v1.Resource, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.opentelemetry.proto.resource.v1.Resource.displayName = 'proto.opentelemetry.proto.resource.v1.Resource'; -} - -/** - * List of repeated fields within this message type. - * @private {!Array} - * @const - */ -proto.opentelemetry.proto.resource.v1.Resource.repeatedFields_ = [1]; - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.opentelemetry.proto.resource.v1.Resource.prototype.toObject = function(opt_includeInstance) { - return proto.opentelemetry.proto.resource.v1.Resource.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.opentelemetry.proto.resource.v1.Resource} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.resource.v1.Resource.toObject = function(includeInstance, msg) { - var f, obj = { - attributesList: jspb.Message.toObjectList(msg.getAttributesList(), - opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.toObject, includeInstance), - droppedAttributesCount: jspb.Message.getFieldWithDefault(msg, 2, 0) - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.opentelemetry.proto.resource.v1.Resource} - */ -proto.opentelemetry.proto.resource.v1.Resource.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.opentelemetry.proto.resource.v1.Resource; - return proto.opentelemetry.proto.resource.v1.Resource.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.opentelemetry.proto.resource.v1.Resource} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.opentelemetry.proto.resource.v1.Resource} - */ -proto.opentelemetry.proto.resource.v1.Resource.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = new opentelemetry_proto_common_v1_common_pb.AttributeKeyValue; - reader.readMessage(value,opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.deserializeBinaryFromReader); - msg.addAttributes(value); - break; - case 2: - var value = /** @type {number} */ (reader.readUint32()); - msg.setDroppedAttributesCount(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.opentelemetry.proto.resource.v1.Resource.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.opentelemetry.proto.resource.v1.Resource.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.opentelemetry.proto.resource.v1.Resource} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.resource.v1.Resource.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getAttributesList(); - if (f.length > 0) { - writer.writeRepeatedMessage( - 1, - f, - opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.serializeBinaryToWriter - ); - } - f = message.getDroppedAttributesCount(); - if (f !== 0) { - writer.writeUint32( - 2, - f - ); - } -}; - - -/** - * repeated opentelemetry.proto.common.v1.AttributeKeyValue attributes = 1; - * @return {!Array} - */ -proto.opentelemetry.proto.resource.v1.Resource.prototype.getAttributesList = function() { - return /** @type{!Array} */ ( - jspb.Message.getRepeatedWrapperField(this, opentelemetry_proto_common_v1_common_pb.AttributeKeyValue, 1)); -}; - - -/** - * @param {!Array} value - * @return {!proto.opentelemetry.proto.resource.v1.Resource} returns this -*/ -proto.opentelemetry.proto.resource.v1.Resource.prototype.setAttributesList = function(value) { - return jspb.Message.setRepeatedWrapperField(this, 1, value); -}; - - -/** - * @param {!proto.opentelemetry.proto.common.v1.AttributeKeyValue=} opt_value - * @param {number=} opt_index - * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} - */ -proto.opentelemetry.proto.resource.v1.Resource.prototype.addAttributes = function(opt_value, opt_index) { - return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.opentelemetry.proto.common.v1.AttributeKeyValue, opt_index); -}; - - -/** - * Clears the list making it empty but non-null. - * @return {!proto.opentelemetry.proto.resource.v1.Resource} returns this - */ -proto.opentelemetry.proto.resource.v1.Resource.prototype.clearAttributesList = function() { - return this.setAttributesList([]); -}; - - -/** - * optional uint32 dropped_attributes_count = 2; - * @return {number} - */ -proto.opentelemetry.proto.resource.v1.Resource.prototype.getDroppedAttributesCount = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0)); -}; - - -/** - * @param {number} value - * @return {!proto.opentelemetry.proto.resource.v1.Resource} returns this - */ -proto.opentelemetry.proto.resource.v1.Resource.prototype.setDroppedAttributesCount = function(value) { - return jspb.Message.setProto3IntField(this, 2, value); -}; - - -goog.object.extend(exports, proto.opentelemetry.proto.resource.v1); diff --git a/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/trace/v1/trace_pb.js b/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/trace/v1/trace_pb.js deleted file mode 100644 index 42a4524c1f..0000000000 --- a/packages/opentelemetry-exporter-collector/generated/opentelemetry/proto/trace/v1/trace_pb.js +++ /dev/null @@ -1,2067 +0,0 @@ -// source: opentelemetry/proto/trace/v1/trace.proto -/** - * @fileoverview - * @enhanceable - * @suppress {messageConventions} JS Compiler reports an error if a variable or - * field starts with 'MSG_' and isn't a translatable message. - * @public - */ -// GENERATED CODE -- DO NOT EDIT! - -var jspb = require('google-protobuf'); -var goog = jspb; -var global = Function('return this')(); - -var opentelemetry_proto_common_v1_common_pb = require('../../../../opentelemetry/proto/common/v1/common_pb.js'); -goog.object.extend(proto, opentelemetry_proto_common_v1_common_pb); -var opentelemetry_proto_resource_v1_resource_pb = require('../../../../opentelemetry/proto/resource/v1/resource_pb.js'); -goog.object.extend(proto, opentelemetry_proto_resource_v1_resource_pb); -goog.exportSymbol('proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans', null, global); -goog.exportSymbol('proto.opentelemetry.proto.trace.v1.ResourceSpans', null, global); -goog.exportSymbol('proto.opentelemetry.proto.trace.v1.Span', null, global); -goog.exportSymbol('proto.opentelemetry.proto.trace.v1.Span.Event', null, global); -goog.exportSymbol('proto.opentelemetry.proto.trace.v1.Span.Link', null, global); -goog.exportSymbol('proto.opentelemetry.proto.trace.v1.Span.SpanKind', null, global); -goog.exportSymbol('proto.opentelemetry.proto.trace.v1.Status', null, global); -goog.exportSymbol('proto.opentelemetry.proto.trace.v1.Status.StatusCode', null, global); -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.opentelemetry.proto.trace.v1.ResourceSpans = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, proto.opentelemetry.proto.trace.v1.ResourceSpans.repeatedFields_, null); -}; -goog.inherits(proto.opentelemetry.proto.trace.v1.ResourceSpans, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.opentelemetry.proto.trace.v1.ResourceSpans.displayName = 'proto.opentelemetry.proto.trace.v1.ResourceSpans'; -} -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.repeatedFields_, null); -}; -goog.inherits(proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.displayName = 'proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans'; -} -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.opentelemetry.proto.trace.v1.Span = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, proto.opentelemetry.proto.trace.v1.Span.repeatedFields_, null); -}; -goog.inherits(proto.opentelemetry.proto.trace.v1.Span, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.opentelemetry.proto.trace.v1.Span.displayName = 'proto.opentelemetry.proto.trace.v1.Span'; -} -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.opentelemetry.proto.trace.v1.Span.Event = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, proto.opentelemetry.proto.trace.v1.Span.Event.repeatedFields_, null); -}; -goog.inherits(proto.opentelemetry.proto.trace.v1.Span.Event, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.opentelemetry.proto.trace.v1.Span.Event.displayName = 'proto.opentelemetry.proto.trace.v1.Span.Event'; -} -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.opentelemetry.proto.trace.v1.Span.Link = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, proto.opentelemetry.proto.trace.v1.Span.Link.repeatedFields_, null); -}; -goog.inherits(proto.opentelemetry.proto.trace.v1.Span.Link, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.opentelemetry.proto.trace.v1.Span.Link.displayName = 'proto.opentelemetry.proto.trace.v1.Span.Link'; -} -/** - * Generated by JsPbCodeGenerator. - * @param {Array=} opt_data Optional initial data array, typically from a - * server response, or constructed directly in Javascript. The array is used - * in place and becomes part of the constructed object. It is not cloned. - * If no data is provided, the constructed object will be empty, but still - * valid. - * @extends {jspb.Message} - * @constructor - */ -proto.opentelemetry.proto.trace.v1.Status = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); -}; -goog.inherits(proto.opentelemetry.proto.trace.v1.Status, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.opentelemetry.proto.trace.v1.Status.displayName = 'proto.opentelemetry.proto.trace.v1.Status'; -} - -/** - * List of repeated fields within this message type. - * @private {!Array} - * @const - */ -proto.opentelemetry.proto.trace.v1.ResourceSpans.repeatedFields_ = [2]; - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.opentelemetry.proto.trace.v1.ResourceSpans.prototype.toObject = function(opt_includeInstance) { - return proto.opentelemetry.proto.trace.v1.ResourceSpans.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.opentelemetry.proto.trace.v1.ResourceSpans} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.trace.v1.ResourceSpans.toObject = function(includeInstance, msg) { - var f, obj = { - resource: (f = msg.getResource()) && opentelemetry_proto_resource_v1_resource_pb.Resource.toObject(includeInstance, f), - instrumentationLibrarySpansList: jspb.Message.toObjectList(msg.getInstrumentationLibrarySpansList(), - proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.toObject, includeInstance) - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.opentelemetry.proto.trace.v1.ResourceSpans} - */ -proto.opentelemetry.proto.trace.v1.ResourceSpans.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.opentelemetry.proto.trace.v1.ResourceSpans; - return proto.opentelemetry.proto.trace.v1.ResourceSpans.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.opentelemetry.proto.trace.v1.ResourceSpans} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.opentelemetry.proto.trace.v1.ResourceSpans} - */ -proto.opentelemetry.proto.trace.v1.ResourceSpans.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = new opentelemetry_proto_resource_v1_resource_pb.Resource; - reader.readMessage(value,opentelemetry_proto_resource_v1_resource_pb.Resource.deserializeBinaryFromReader); - msg.setResource(value); - break; - case 2: - var value = new proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans; - reader.readMessage(value,proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.deserializeBinaryFromReader); - msg.addInstrumentationLibrarySpans(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.opentelemetry.proto.trace.v1.ResourceSpans.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.opentelemetry.proto.trace.v1.ResourceSpans.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.opentelemetry.proto.trace.v1.ResourceSpans} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.trace.v1.ResourceSpans.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getResource(); - if (f != null) { - writer.writeMessage( - 1, - f, - opentelemetry_proto_resource_v1_resource_pb.Resource.serializeBinaryToWriter - ); - } - f = message.getInstrumentationLibrarySpansList(); - if (f.length > 0) { - writer.writeRepeatedMessage( - 2, - f, - proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.serializeBinaryToWriter - ); - } -}; - - -/** - * optional opentelemetry.proto.resource.v1.Resource resource = 1; - * @return {?proto.opentelemetry.proto.resource.v1.Resource} - */ -proto.opentelemetry.proto.trace.v1.ResourceSpans.prototype.getResource = function() { - return /** @type{?proto.opentelemetry.proto.resource.v1.Resource} */ ( - jspb.Message.getWrapperField(this, opentelemetry_proto_resource_v1_resource_pb.Resource, 1)); -}; - - -/** - * @param {?proto.opentelemetry.proto.resource.v1.Resource|undefined} value - * @return {!proto.opentelemetry.proto.trace.v1.ResourceSpans} returns this -*/ -proto.opentelemetry.proto.trace.v1.ResourceSpans.prototype.setResource = function(value) { - return jspb.Message.setWrapperField(this, 1, value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.opentelemetry.proto.trace.v1.ResourceSpans} returns this - */ -proto.opentelemetry.proto.trace.v1.ResourceSpans.prototype.clearResource = function() { - return this.setResource(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.opentelemetry.proto.trace.v1.ResourceSpans.prototype.hasResource = function() { - return jspb.Message.getField(this, 1) != null; -}; - - -/** - * repeated InstrumentationLibrarySpans instrumentation_library_spans = 2; - * @return {!Array} - */ -proto.opentelemetry.proto.trace.v1.ResourceSpans.prototype.getInstrumentationLibrarySpansList = function() { - return /** @type{!Array} */ ( - jspb.Message.getRepeatedWrapperField(this, proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans, 2)); -}; - - -/** - * @param {!Array} value - * @return {!proto.opentelemetry.proto.trace.v1.ResourceSpans} returns this -*/ -proto.opentelemetry.proto.trace.v1.ResourceSpans.prototype.setInstrumentationLibrarySpansList = function(value) { - return jspb.Message.setRepeatedWrapperField(this, 2, value); -}; - - -/** - * @param {!proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans=} opt_value - * @param {number=} opt_index - * @return {!proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans} - */ -proto.opentelemetry.proto.trace.v1.ResourceSpans.prototype.addInstrumentationLibrarySpans = function(opt_value, opt_index) { - return jspb.Message.addToRepeatedWrapperField(this, 2, opt_value, proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans, opt_index); -}; - - -/** - * Clears the list making it empty but non-null. - * @return {!proto.opentelemetry.proto.trace.v1.ResourceSpans} returns this - */ -proto.opentelemetry.proto.trace.v1.ResourceSpans.prototype.clearInstrumentationLibrarySpansList = function() { - return this.setInstrumentationLibrarySpansList([]); -}; - - - -/** - * List of repeated fields within this message type. - * @private {!Array} - * @const - */ -proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.repeatedFields_ = [2]; - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.prototype.toObject = function(opt_includeInstance) { - return proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.toObject = function(includeInstance, msg) { - var f, obj = { - instrumentationLibrary: (f = msg.getInstrumentationLibrary()) && opentelemetry_proto_common_v1_common_pb.InstrumentationLibrary.toObject(includeInstance, f), - spansList: jspb.Message.toObjectList(msg.getSpansList(), - proto.opentelemetry.proto.trace.v1.Span.toObject, includeInstance) - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans} - */ -proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans; - return proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans} - */ -proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = new opentelemetry_proto_common_v1_common_pb.InstrumentationLibrary; - reader.readMessage(value,opentelemetry_proto_common_v1_common_pb.InstrumentationLibrary.deserializeBinaryFromReader); - msg.setInstrumentationLibrary(value); - break; - case 2: - var value = new proto.opentelemetry.proto.trace.v1.Span; - reader.readMessage(value,proto.opentelemetry.proto.trace.v1.Span.deserializeBinaryFromReader); - msg.addSpans(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getInstrumentationLibrary(); - if (f != null) { - writer.writeMessage( - 1, - f, - opentelemetry_proto_common_v1_common_pb.InstrumentationLibrary.serializeBinaryToWriter - ); - } - f = message.getSpansList(); - if (f.length > 0) { - writer.writeRepeatedMessage( - 2, - f, - proto.opentelemetry.proto.trace.v1.Span.serializeBinaryToWriter - ); - } -}; - - -/** - * optional opentelemetry.proto.common.v1.InstrumentationLibrary instrumentation_library = 1; - * @return {?proto.opentelemetry.proto.common.v1.InstrumentationLibrary} - */ -proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.prototype.getInstrumentationLibrary = function() { - return /** @type{?proto.opentelemetry.proto.common.v1.InstrumentationLibrary} */ ( - jspb.Message.getWrapperField(this, opentelemetry_proto_common_v1_common_pb.InstrumentationLibrary, 1)); -}; - - -/** - * @param {?proto.opentelemetry.proto.common.v1.InstrumentationLibrary|undefined} value - * @return {!proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans} returns this -*/ -proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.prototype.setInstrumentationLibrary = function(value) { - return jspb.Message.setWrapperField(this, 1, value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans} returns this - */ -proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.prototype.clearInstrumentationLibrary = function() { - return this.setInstrumentationLibrary(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.prototype.hasInstrumentationLibrary = function() { - return jspb.Message.getField(this, 1) != null; -}; - - -/** - * repeated Span spans = 2; - * @return {!Array} - */ -proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.prototype.getSpansList = function() { - return /** @type{!Array} */ ( - jspb.Message.getRepeatedWrapperField(this, proto.opentelemetry.proto.trace.v1.Span, 2)); -}; - - -/** - * @param {!Array} value - * @return {!proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans} returns this -*/ -proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.prototype.setSpansList = function(value) { - return jspb.Message.setRepeatedWrapperField(this, 2, value); -}; - - -/** - * @param {!proto.opentelemetry.proto.trace.v1.Span=} opt_value - * @param {number=} opt_index - * @return {!proto.opentelemetry.proto.trace.v1.Span} - */ -proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.prototype.addSpans = function(opt_value, opt_index) { - return jspb.Message.addToRepeatedWrapperField(this, 2, opt_value, proto.opentelemetry.proto.trace.v1.Span, opt_index); -}; - - -/** - * Clears the list making it empty but non-null. - * @return {!proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans} returns this - */ -proto.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans.prototype.clearSpansList = function() { - return this.setSpansList([]); -}; - - - -/** - * List of repeated fields within this message type. - * @private {!Array} - * @const - */ -proto.opentelemetry.proto.trace.v1.Span.repeatedFields_ = [9,11,13]; - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.toObject = function(opt_includeInstance) { - return proto.opentelemetry.proto.trace.v1.Span.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.opentelemetry.proto.trace.v1.Span} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.trace.v1.Span.toObject = function(includeInstance, msg) { - var f, obj = { - traceId: msg.getTraceId_asB64(), - spanId: msg.getSpanId_asB64(), - traceState: jspb.Message.getFieldWithDefault(msg, 3, ""), - parentSpanId: msg.getParentSpanId_asB64(), - name: jspb.Message.getFieldWithDefault(msg, 5, ""), - kind: jspb.Message.getFieldWithDefault(msg, 6, 0), - startTimeUnixNano: jspb.Message.getFieldWithDefault(msg, 7, 0), - endTimeUnixNano: jspb.Message.getFieldWithDefault(msg, 8, 0), - attributesList: jspb.Message.toObjectList(msg.getAttributesList(), - opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.toObject, includeInstance), - droppedAttributesCount: jspb.Message.getFieldWithDefault(msg, 10, 0), - eventsList: jspb.Message.toObjectList(msg.getEventsList(), - proto.opentelemetry.proto.trace.v1.Span.Event.toObject, includeInstance), - droppedEventsCount: jspb.Message.getFieldWithDefault(msg, 12, 0), - linksList: jspb.Message.toObjectList(msg.getLinksList(), - proto.opentelemetry.proto.trace.v1.Span.Link.toObject, includeInstance), - droppedLinksCount: jspb.Message.getFieldWithDefault(msg, 14, 0), - status: (f = msg.getStatus()) && proto.opentelemetry.proto.trace.v1.Status.toObject(includeInstance, f) - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.opentelemetry.proto.trace.v1.Span} - */ -proto.opentelemetry.proto.trace.v1.Span.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.opentelemetry.proto.trace.v1.Span; - return proto.opentelemetry.proto.trace.v1.Span.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.opentelemetry.proto.trace.v1.Span} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.opentelemetry.proto.trace.v1.Span} - */ -proto.opentelemetry.proto.trace.v1.Span.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {!Uint8Array} */ (reader.readBytes()); - msg.setTraceId(value); - break; - case 2: - var value = /** @type {!Uint8Array} */ (reader.readBytes()); - msg.setSpanId(value); - break; - case 3: - var value = /** @type {string} */ (reader.readString()); - msg.setTraceState(value); - break; - case 4: - var value = /** @type {!Uint8Array} */ (reader.readBytes()); - msg.setParentSpanId(value); - break; - case 5: - var value = /** @type {string} */ (reader.readString()); - msg.setName(value); - break; - case 6: - var value = /** @type {!proto.opentelemetry.proto.trace.v1.Span.SpanKind} */ (reader.readEnum()); - msg.setKind(value); - break; - case 7: - var value = /** @type {number} */ (reader.readFixed64()); - msg.setStartTimeUnixNano(value); - break; - case 8: - var value = /** @type {number} */ (reader.readFixed64()); - msg.setEndTimeUnixNano(value); - break; - case 9: - var value = new opentelemetry_proto_common_v1_common_pb.AttributeKeyValue; - reader.readMessage(value,opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.deserializeBinaryFromReader); - msg.addAttributes(value); - break; - case 10: - var value = /** @type {number} */ (reader.readUint32()); - msg.setDroppedAttributesCount(value); - break; - case 11: - var value = new proto.opentelemetry.proto.trace.v1.Span.Event; - reader.readMessage(value,proto.opentelemetry.proto.trace.v1.Span.Event.deserializeBinaryFromReader); - msg.addEvents(value); - break; - case 12: - var value = /** @type {number} */ (reader.readUint32()); - msg.setDroppedEventsCount(value); - break; - case 13: - var value = new proto.opentelemetry.proto.trace.v1.Span.Link; - reader.readMessage(value,proto.opentelemetry.proto.trace.v1.Span.Link.deserializeBinaryFromReader); - msg.addLinks(value); - break; - case 14: - var value = /** @type {number} */ (reader.readUint32()); - msg.setDroppedLinksCount(value); - break; - case 15: - var value = new proto.opentelemetry.proto.trace.v1.Status; - reader.readMessage(value,proto.opentelemetry.proto.trace.v1.Status.deserializeBinaryFromReader); - msg.setStatus(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.opentelemetry.proto.trace.v1.Span.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.opentelemetry.proto.trace.v1.Span} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.trace.v1.Span.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getTraceId_asU8(); - if (f.length > 0) { - writer.writeBytes( - 1, - f - ); - } - f = message.getSpanId_asU8(); - if (f.length > 0) { - writer.writeBytes( - 2, - f - ); - } - f = message.getTraceState(); - if (f.length > 0) { - writer.writeString( - 3, - f - ); - } - f = message.getParentSpanId_asU8(); - if (f.length > 0) { - writer.writeBytes( - 4, - f - ); - } - f = message.getName(); - if (f.length > 0) { - writer.writeString( - 5, - f - ); - } - f = message.getKind(); - if (f !== 0.0) { - writer.writeEnum( - 6, - f - ); - } - f = message.getStartTimeUnixNano(); - if (f !== 0) { - writer.writeFixed64( - 7, - f - ); - } - f = message.getEndTimeUnixNano(); - if (f !== 0) { - writer.writeFixed64( - 8, - f - ); - } - f = message.getAttributesList(); - if (f.length > 0) { - writer.writeRepeatedMessage( - 9, - f, - opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.serializeBinaryToWriter - ); - } - f = message.getDroppedAttributesCount(); - if (f !== 0) { - writer.writeUint32( - 10, - f - ); - } - f = message.getEventsList(); - if (f.length > 0) { - writer.writeRepeatedMessage( - 11, - f, - proto.opentelemetry.proto.trace.v1.Span.Event.serializeBinaryToWriter - ); - } - f = message.getDroppedEventsCount(); - if (f !== 0) { - writer.writeUint32( - 12, - f - ); - } - f = message.getLinksList(); - if (f.length > 0) { - writer.writeRepeatedMessage( - 13, - f, - proto.opentelemetry.proto.trace.v1.Span.Link.serializeBinaryToWriter - ); - } - f = message.getDroppedLinksCount(); - if (f !== 0) { - writer.writeUint32( - 14, - f - ); - } - f = message.getStatus(); - if (f != null) { - writer.writeMessage( - 15, - f, - proto.opentelemetry.proto.trace.v1.Status.serializeBinaryToWriter - ); - } -}; - - -/** - * @enum {number} - */ -proto.opentelemetry.proto.trace.v1.Span.SpanKind = { - SPAN_KIND_UNSPECIFIED: 0, - INTERNAL: 1, - SERVER: 2, - CLIENT: 3, - PRODUCER: 4, - CONSUMER: 5 -}; - - -/** - * List of repeated fields within this message type. - * @private {!Array} - * @const - */ -proto.opentelemetry.proto.trace.v1.Span.Event.repeatedFields_ = [3]; - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.opentelemetry.proto.trace.v1.Span.Event.prototype.toObject = function(opt_includeInstance) { - return proto.opentelemetry.proto.trace.v1.Span.Event.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.opentelemetry.proto.trace.v1.Span.Event} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.trace.v1.Span.Event.toObject = function(includeInstance, msg) { - var f, obj = { - timeUnixNano: jspb.Message.getFieldWithDefault(msg, 1, 0), - name: jspb.Message.getFieldWithDefault(msg, 2, ""), - attributesList: jspb.Message.toObjectList(msg.getAttributesList(), - opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.toObject, includeInstance), - droppedAttributesCount: jspb.Message.getFieldWithDefault(msg, 4, 0) - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.opentelemetry.proto.trace.v1.Span.Event} - */ -proto.opentelemetry.proto.trace.v1.Span.Event.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.opentelemetry.proto.trace.v1.Span.Event; - return proto.opentelemetry.proto.trace.v1.Span.Event.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.opentelemetry.proto.trace.v1.Span.Event} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.opentelemetry.proto.trace.v1.Span.Event} - */ -proto.opentelemetry.proto.trace.v1.Span.Event.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {number} */ (reader.readFixed64()); - msg.setTimeUnixNano(value); - break; - case 2: - var value = /** @type {string} */ (reader.readString()); - msg.setName(value); - break; - case 3: - var value = new opentelemetry_proto_common_v1_common_pb.AttributeKeyValue; - reader.readMessage(value,opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.deserializeBinaryFromReader); - msg.addAttributes(value); - break; - case 4: - var value = /** @type {number} */ (reader.readUint32()); - msg.setDroppedAttributesCount(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.opentelemetry.proto.trace.v1.Span.Event.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.opentelemetry.proto.trace.v1.Span.Event.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.opentelemetry.proto.trace.v1.Span.Event} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.trace.v1.Span.Event.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getTimeUnixNano(); - if (f !== 0) { - writer.writeFixed64( - 1, - f - ); - } - f = message.getName(); - if (f.length > 0) { - writer.writeString( - 2, - f - ); - } - f = message.getAttributesList(); - if (f.length > 0) { - writer.writeRepeatedMessage( - 3, - f, - opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.serializeBinaryToWriter - ); - } - f = message.getDroppedAttributesCount(); - if (f !== 0) { - writer.writeUint32( - 4, - f - ); - } -}; - - -/** - * optional fixed64 time_unix_nano = 1; - * @return {number} - */ -proto.opentelemetry.proto.trace.v1.Span.Event.prototype.getTimeUnixNano = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0)); -}; - - -/** - * @param {number} value - * @return {!proto.opentelemetry.proto.trace.v1.Span.Event} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.Event.prototype.setTimeUnixNano = function(value) { - return jspb.Message.setProto3IntField(this, 1, value); -}; - - -/** - * optional string name = 2; - * @return {string} - */ -proto.opentelemetry.proto.trace.v1.Span.Event.prototype.getName = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); -}; - - -/** - * @param {string} value - * @return {!proto.opentelemetry.proto.trace.v1.Span.Event} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.Event.prototype.setName = function(value) { - return jspb.Message.setProto3StringField(this, 2, value); -}; - - -/** - * repeated opentelemetry.proto.common.v1.AttributeKeyValue attributes = 3; - * @return {!Array} - */ -proto.opentelemetry.proto.trace.v1.Span.Event.prototype.getAttributesList = function() { - return /** @type{!Array} */ ( - jspb.Message.getRepeatedWrapperField(this, opentelemetry_proto_common_v1_common_pb.AttributeKeyValue, 3)); -}; - - -/** - * @param {!Array} value - * @return {!proto.opentelemetry.proto.trace.v1.Span.Event} returns this -*/ -proto.opentelemetry.proto.trace.v1.Span.Event.prototype.setAttributesList = function(value) { - return jspb.Message.setRepeatedWrapperField(this, 3, value); -}; - - -/** - * @param {!proto.opentelemetry.proto.common.v1.AttributeKeyValue=} opt_value - * @param {number=} opt_index - * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} - */ -proto.opentelemetry.proto.trace.v1.Span.Event.prototype.addAttributes = function(opt_value, opt_index) { - return jspb.Message.addToRepeatedWrapperField(this, 3, opt_value, proto.opentelemetry.proto.common.v1.AttributeKeyValue, opt_index); -}; - - -/** - * Clears the list making it empty but non-null. - * @return {!proto.opentelemetry.proto.trace.v1.Span.Event} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.Event.prototype.clearAttributesList = function() { - return this.setAttributesList([]); -}; - - -/** - * optional uint32 dropped_attributes_count = 4; - * @return {number} - */ -proto.opentelemetry.proto.trace.v1.Span.Event.prototype.getDroppedAttributesCount = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0)); -}; - - -/** - * @param {number} value - * @return {!proto.opentelemetry.proto.trace.v1.Span.Event} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.Event.prototype.setDroppedAttributesCount = function(value) { - return jspb.Message.setProto3IntField(this, 4, value); -}; - - - -/** - * List of repeated fields within this message type. - * @private {!Array} - * @const - */ -proto.opentelemetry.proto.trace.v1.Span.Link.repeatedFields_ = [4]; - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.opentelemetry.proto.trace.v1.Span.Link.prototype.toObject = function(opt_includeInstance) { - return proto.opentelemetry.proto.trace.v1.Span.Link.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.opentelemetry.proto.trace.v1.Span.Link} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.trace.v1.Span.Link.toObject = function(includeInstance, msg) { - var f, obj = { - traceId: msg.getTraceId_asB64(), - spanId: msg.getSpanId_asB64(), - traceState: jspb.Message.getFieldWithDefault(msg, 3, ""), - attributesList: jspb.Message.toObjectList(msg.getAttributesList(), - opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.toObject, includeInstance), - droppedAttributesCount: jspb.Message.getFieldWithDefault(msg, 5, 0) - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.opentelemetry.proto.trace.v1.Span.Link} - */ -proto.opentelemetry.proto.trace.v1.Span.Link.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.opentelemetry.proto.trace.v1.Span.Link; - return proto.opentelemetry.proto.trace.v1.Span.Link.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.opentelemetry.proto.trace.v1.Span.Link} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.opentelemetry.proto.trace.v1.Span.Link} - */ -proto.opentelemetry.proto.trace.v1.Span.Link.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {!Uint8Array} */ (reader.readBytes()); - msg.setTraceId(value); - break; - case 2: - var value = /** @type {!Uint8Array} */ (reader.readBytes()); - msg.setSpanId(value); - break; - case 3: - var value = /** @type {string} */ (reader.readString()); - msg.setTraceState(value); - break; - case 4: - var value = new opentelemetry_proto_common_v1_common_pb.AttributeKeyValue; - reader.readMessage(value,opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.deserializeBinaryFromReader); - msg.addAttributes(value); - break; - case 5: - var value = /** @type {number} */ (reader.readUint32()); - msg.setDroppedAttributesCount(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.opentelemetry.proto.trace.v1.Span.Link.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.opentelemetry.proto.trace.v1.Span.Link.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.opentelemetry.proto.trace.v1.Span.Link} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.trace.v1.Span.Link.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getTraceId_asU8(); - if (f.length > 0) { - writer.writeBytes( - 1, - f - ); - } - f = message.getSpanId_asU8(); - if (f.length > 0) { - writer.writeBytes( - 2, - f - ); - } - f = message.getTraceState(); - if (f.length > 0) { - writer.writeString( - 3, - f - ); - } - f = message.getAttributesList(); - if (f.length > 0) { - writer.writeRepeatedMessage( - 4, - f, - opentelemetry_proto_common_v1_common_pb.AttributeKeyValue.serializeBinaryToWriter - ); - } - f = message.getDroppedAttributesCount(); - if (f !== 0) { - writer.writeUint32( - 5, - f - ); - } -}; - - -/** - * optional bytes trace_id = 1; - * @return {!(string|Uint8Array)} - */ -proto.opentelemetry.proto.trace.v1.Span.Link.prototype.getTraceId = function() { - return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 1, "")); -}; - - -/** - * optional bytes trace_id = 1; - * This is a type-conversion wrapper around `getTraceId()` - * @return {string} - */ -proto.opentelemetry.proto.trace.v1.Span.Link.prototype.getTraceId_asB64 = function() { - return /** @type {string} */ (jspb.Message.bytesAsB64( - this.getTraceId())); -}; - - -/** - * optional bytes trace_id = 1; - * Note that Uint8Array is not supported on all browsers. - * @see http://caniuse.com/Uint8Array - * This is a type-conversion wrapper around `getTraceId()` - * @return {!Uint8Array} - */ -proto.opentelemetry.proto.trace.v1.Span.Link.prototype.getTraceId_asU8 = function() { - return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( - this.getTraceId())); -}; - - -/** - * @param {!(string|Uint8Array)} value - * @return {!proto.opentelemetry.proto.trace.v1.Span.Link} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.Link.prototype.setTraceId = function(value) { - return jspb.Message.setProto3BytesField(this, 1, value); -}; - - -/** - * optional bytes span_id = 2; - * @return {!(string|Uint8Array)} - */ -proto.opentelemetry.proto.trace.v1.Span.Link.prototype.getSpanId = function() { - return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 2, "")); -}; - - -/** - * optional bytes span_id = 2; - * This is a type-conversion wrapper around `getSpanId()` - * @return {string} - */ -proto.opentelemetry.proto.trace.v1.Span.Link.prototype.getSpanId_asB64 = function() { - return /** @type {string} */ (jspb.Message.bytesAsB64( - this.getSpanId())); -}; - - -/** - * optional bytes span_id = 2; - * Note that Uint8Array is not supported on all browsers. - * @see http://caniuse.com/Uint8Array - * This is a type-conversion wrapper around `getSpanId()` - * @return {!Uint8Array} - */ -proto.opentelemetry.proto.trace.v1.Span.Link.prototype.getSpanId_asU8 = function() { - return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( - this.getSpanId())); -}; - - -/** - * @param {!(string|Uint8Array)} value - * @return {!proto.opentelemetry.proto.trace.v1.Span.Link} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.Link.prototype.setSpanId = function(value) { - return jspb.Message.setProto3BytesField(this, 2, value); -}; - - -/** - * optional string trace_state = 3; - * @return {string} - */ -proto.opentelemetry.proto.trace.v1.Span.Link.prototype.getTraceState = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); -}; - - -/** - * @param {string} value - * @return {!proto.opentelemetry.proto.trace.v1.Span.Link} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.Link.prototype.setTraceState = function(value) { - return jspb.Message.setProto3StringField(this, 3, value); -}; - - -/** - * repeated opentelemetry.proto.common.v1.AttributeKeyValue attributes = 4; - * @return {!Array} - */ -proto.opentelemetry.proto.trace.v1.Span.Link.prototype.getAttributesList = function() { - return /** @type{!Array} */ ( - jspb.Message.getRepeatedWrapperField(this, opentelemetry_proto_common_v1_common_pb.AttributeKeyValue, 4)); -}; - - -/** - * @param {!Array} value - * @return {!proto.opentelemetry.proto.trace.v1.Span.Link} returns this -*/ -proto.opentelemetry.proto.trace.v1.Span.Link.prototype.setAttributesList = function(value) { - return jspb.Message.setRepeatedWrapperField(this, 4, value); -}; - - -/** - * @param {!proto.opentelemetry.proto.common.v1.AttributeKeyValue=} opt_value - * @param {number=} opt_index - * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} - */ -proto.opentelemetry.proto.trace.v1.Span.Link.prototype.addAttributes = function(opt_value, opt_index) { - return jspb.Message.addToRepeatedWrapperField(this, 4, opt_value, proto.opentelemetry.proto.common.v1.AttributeKeyValue, opt_index); -}; - - -/** - * Clears the list making it empty but non-null. - * @return {!proto.opentelemetry.proto.trace.v1.Span.Link} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.Link.prototype.clearAttributesList = function() { - return this.setAttributesList([]); -}; - - -/** - * optional uint32 dropped_attributes_count = 5; - * @return {number} - */ -proto.opentelemetry.proto.trace.v1.Span.Link.prototype.getDroppedAttributesCount = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 5, 0)); -}; - - -/** - * @param {number} value - * @return {!proto.opentelemetry.proto.trace.v1.Span.Link} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.Link.prototype.setDroppedAttributesCount = function(value) { - return jspb.Message.setProto3IntField(this, 5, value); -}; - - -/** - * optional bytes trace_id = 1; - * @return {!(string|Uint8Array)} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.getTraceId = function() { - return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 1, "")); -}; - - -/** - * optional bytes trace_id = 1; - * This is a type-conversion wrapper around `getTraceId()` - * @return {string} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.getTraceId_asB64 = function() { - return /** @type {string} */ (jspb.Message.bytesAsB64( - this.getTraceId())); -}; - - -/** - * optional bytes trace_id = 1; - * Note that Uint8Array is not supported on all browsers. - * @see http://caniuse.com/Uint8Array - * This is a type-conversion wrapper around `getTraceId()` - * @return {!Uint8Array} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.getTraceId_asU8 = function() { - return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( - this.getTraceId())); -}; - - -/** - * @param {!(string|Uint8Array)} value - * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.setTraceId = function(value) { - return jspb.Message.setProto3BytesField(this, 1, value); -}; - - -/** - * optional bytes span_id = 2; - * @return {!(string|Uint8Array)} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.getSpanId = function() { - return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 2, "")); -}; - - -/** - * optional bytes span_id = 2; - * This is a type-conversion wrapper around `getSpanId()` - * @return {string} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.getSpanId_asB64 = function() { - return /** @type {string} */ (jspb.Message.bytesAsB64( - this.getSpanId())); -}; - - -/** - * optional bytes span_id = 2; - * Note that Uint8Array is not supported on all browsers. - * @see http://caniuse.com/Uint8Array - * This is a type-conversion wrapper around `getSpanId()` - * @return {!Uint8Array} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.getSpanId_asU8 = function() { - return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( - this.getSpanId())); -}; - - -/** - * @param {!(string|Uint8Array)} value - * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.setSpanId = function(value) { - return jspb.Message.setProto3BytesField(this, 2, value); -}; - - -/** - * optional string trace_state = 3; - * @return {string} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.getTraceState = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); -}; - - -/** - * @param {string} value - * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.setTraceState = function(value) { - return jspb.Message.setProto3StringField(this, 3, value); -}; - - -/** - * optional bytes parent_span_id = 4; - * @return {!(string|Uint8Array)} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.getParentSpanId = function() { - return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 4, "")); -}; - - -/** - * optional bytes parent_span_id = 4; - * This is a type-conversion wrapper around `getParentSpanId()` - * @return {string} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.getParentSpanId_asB64 = function() { - return /** @type {string} */ (jspb.Message.bytesAsB64( - this.getParentSpanId())); -}; - - -/** - * optional bytes parent_span_id = 4; - * Note that Uint8Array is not supported on all browsers. - * @see http://caniuse.com/Uint8Array - * This is a type-conversion wrapper around `getParentSpanId()` - * @return {!Uint8Array} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.getParentSpanId_asU8 = function() { - return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( - this.getParentSpanId())); -}; - - -/** - * @param {!(string|Uint8Array)} value - * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.setParentSpanId = function(value) { - return jspb.Message.setProto3BytesField(this, 4, value); -}; - - -/** - * optional string name = 5; - * @return {string} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.getName = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 5, "")); -}; - - -/** - * @param {string} value - * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.setName = function(value) { - return jspb.Message.setProto3StringField(this, 5, value); -}; - - -/** - * optional SpanKind kind = 6; - * @return {!proto.opentelemetry.proto.trace.v1.Span.SpanKind} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.getKind = function() { - return /** @type {!proto.opentelemetry.proto.trace.v1.Span.SpanKind} */ (jspb.Message.getFieldWithDefault(this, 6, 0)); -}; - - -/** - * @param {!proto.opentelemetry.proto.trace.v1.Span.SpanKind} value - * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.setKind = function(value) { - return jspb.Message.setProto3EnumField(this, 6, value); -}; - - -/** - * optional fixed64 start_time_unix_nano = 7; - * @return {number} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.getStartTimeUnixNano = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 7, 0)); -}; - - -/** - * @param {number} value - * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.setStartTimeUnixNano = function(value) { - return jspb.Message.setProto3IntField(this, 7, value); -}; - - -/** - * optional fixed64 end_time_unix_nano = 8; - * @return {number} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.getEndTimeUnixNano = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 8, 0)); -}; - - -/** - * @param {number} value - * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.setEndTimeUnixNano = function(value) { - return jspb.Message.setProto3IntField(this, 8, value); -}; - - -/** - * repeated opentelemetry.proto.common.v1.AttributeKeyValue attributes = 9; - * @return {!Array} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.getAttributesList = function() { - return /** @type{!Array} */ ( - jspb.Message.getRepeatedWrapperField(this, opentelemetry_proto_common_v1_common_pb.AttributeKeyValue, 9)); -}; - - -/** - * @param {!Array} value - * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this -*/ -proto.opentelemetry.proto.trace.v1.Span.prototype.setAttributesList = function(value) { - return jspb.Message.setRepeatedWrapperField(this, 9, value); -}; - - -/** - * @param {!proto.opentelemetry.proto.common.v1.AttributeKeyValue=} opt_value - * @param {number=} opt_index - * @return {!proto.opentelemetry.proto.common.v1.AttributeKeyValue} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.addAttributes = function(opt_value, opt_index) { - return jspb.Message.addToRepeatedWrapperField(this, 9, opt_value, proto.opentelemetry.proto.common.v1.AttributeKeyValue, opt_index); -}; - - -/** - * Clears the list making it empty but non-null. - * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.clearAttributesList = function() { - return this.setAttributesList([]); -}; - - -/** - * optional uint32 dropped_attributes_count = 10; - * @return {number} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.getDroppedAttributesCount = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 10, 0)); -}; - - -/** - * @param {number} value - * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.setDroppedAttributesCount = function(value) { - return jspb.Message.setProto3IntField(this, 10, value); -}; - - -/** - * repeated Event events = 11; - * @return {!Array} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.getEventsList = function() { - return /** @type{!Array} */ ( - jspb.Message.getRepeatedWrapperField(this, proto.opentelemetry.proto.trace.v1.Span.Event, 11)); -}; - - -/** - * @param {!Array} value - * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this -*/ -proto.opentelemetry.proto.trace.v1.Span.prototype.setEventsList = function(value) { - return jspb.Message.setRepeatedWrapperField(this, 11, value); -}; - - -/** - * @param {!proto.opentelemetry.proto.trace.v1.Span.Event=} opt_value - * @param {number=} opt_index - * @return {!proto.opentelemetry.proto.trace.v1.Span.Event} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.addEvents = function(opt_value, opt_index) { - return jspb.Message.addToRepeatedWrapperField(this, 11, opt_value, proto.opentelemetry.proto.trace.v1.Span.Event, opt_index); -}; - - -/** - * Clears the list making it empty but non-null. - * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.clearEventsList = function() { - return this.setEventsList([]); -}; - - -/** - * optional uint32 dropped_events_count = 12; - * @return {number} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.getDroppedEventsCount = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 12, 0)); -}; - - -/** - * @param {number} value - * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.setDroppedEventsCount = function(value) { - return jspb.Message.setProto3IntField(this, 12, value); -}; - - -/** - * repeated Link links = 13; - * @return {!Array} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.getLinksList = function() { - return /** @type{!Array} */ ( - jspb.Message.getRepeatedWrapperField(this, proto.opentelemetry.proto.trace.v1.Span.Link, 13)); -}; - - -/** - * @param {!Array} value - * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this -*/ -proto.opentelemetry.proto.trace.v1.Span.prototype.setLinksList = function(value) { - return jspb.Message.setRepeatedWrapperField(this, 13, value); -}; - - -/** - * @param {!proto.opentelemetry.proto.trace.v1.Span.Link=} opt_value - * @param {number=} opt_index - * @return {!proto.opentelemetry.proto.trace.v1.Span.Link} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.addLinks = function(opt_value, opt_index) { - return jspb.Message.addToRepeatedWrapperField(this, 13, opt_value, proto.opentelemetry.proto.trace.v1.Span.Link, opt_index); -}; - - -/** - * Clears the list making it empty but non-null. - * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.clearLinksList = function() { - return this.setLinksList([]); -}; - - -/** - * optional uint32 dropped_links_count = 14; - * @return {number} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.getDroppedLinksCount = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 14, 0)); -}; - - -/** - * @param {number} value - * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.setDroppedLinksCount = function(value) { - return jspb.Message.setProto3IntField(this, 14, value); -}; - - -/** - * optional Status status = 15; - * @return {?proto.opentelemetry.proto.trace.v1.Status} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.getStatus = function() { - return /** @type{?proto.opentelemetry.proto.trace.v1.Status} */ ( - jspb.Message.getWrapperField(this, proto.opentelemetry.proto.trace.v1.Status, 15)); -}; - - -/** - * @param {?proto.opentelemetry.proto.trace.v1.Status|undefined} value - * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this -*/ -proto.opentelemetry.proto.trace.v1.Span.prototype.setStatus = function(value) { - return jspb.Message.setWrapperField(this, 15, value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.opentelemetry.proto.trace.v1.Span} returns this - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.clearStatus = function() { - return this.setStatus(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.opentelemetry.proto.trace.v1.Span.prototype.hasStatus = function() { - return jspb.Message.getField(this, 15) != null; -}; - - - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.opentelemetry.proto.trace.v1.Status.prototype.toObject = function(opt_includeInstance) { - return proto.opentelemetry.proto.trace.v1.Status.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.opentelemetry.proto.trace.v1.Status} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.trace.v1.Status.toObject = function(includeInstance, msg) { - var f, obj = { - code: jspb.Message.getFieldWithDefault(msg, 1, 0), - message: jspb.Message.getFieldWithDefault(msg, 2, "") - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.opentelemetry.proto.trace.v1.Status} - */ -proto.opentelemetry.proto.trace.v1.Status.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.opentelemetry.proto.trace.v1.Status; - return proto.opentelemetry.proto.trace.v1.Status.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.opentelemetry.proto.trace.v1.Status} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.opentelemetry.proto.trace.v1.Status} - */ -proto.opentelemetry.proto.trace.v1.Status.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {!proto.opentelemetry.proto.trace.v1.Status.StatusCode} */ (reader.readEnum()); - msg.setCode(value); - break; - case 2: - var value = /** @type {string} */ (reader.readString()); - msg.setMessage(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.opentelemetry.proto.trace.v1.Status.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.opentelemetry.proto.trace.v1.Status.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.opentelemetry.proto.trace.v1.Status} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.opentelemetry.proto.trace.v1.Status.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getCode(); - if (f !== 0.0) { - writer.writeEnum( - 1, - f - ); - } - f = message.getMessage(); - if (f.length > 0) { - writer.writeString( - 2, - f - ); - } -}; - - -/** - * @enum {number} - */ -proto.opentelemetry.proto.trace.v1.Status.StatusCode = { - OK: 0, - CANCELLED: 1, - UNKNOWNERROR: 2, - INVALIDARGUMENT: 3, - DEADLINEEXCEEDED: 4, - NOTFOUND: 5, - ALREADYEXISTS: 6, - PERMISSIONDENIED: 7, - RESOURCEEXHAUSTED: 8, - FAILEDPRECONDITION: 9, - ABORTED: 10, - OUTOFRANGE: 11, - UNIMPLEMENTED: 12, - INTERNALERROR: 13, - UNAVAILABLE: 14, - DATALOSS: 15, - UNAUTHENTICATED: 16 -}; - -/** - * optional StatusCode code = 1; - * @return {!proto.opentelemetry.proto.trace.v1.Status.StatusCode} - */ -proto.opentelemetry.proto.trace.v1.Status.prototype.getCode = function() { - return /** @type {!proto.opentelemetry.proto.trace.v1.Status.StatusCode} */ (jspb.Message.getFieldWithDefault(this, 1, 0)); -}; - - -/** - * @param {!proto.opentelemetry.proto.trace.v1.Status.StatusCode} value - * @return {!proto.opentelemetry.proto.trace.v1.Status} returns this - */ -proto.opentelemetry.proto.trace.v1.Status.prototype.setCode = function(value) { - return jspb.Message.setProto3EnumField(this, 1, value); -}; - - -/** - * optional string message = 2; - * @return {string} - */ -proto.opentelemetry.proto.trace.v1.Status.prototype.getMessage = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); -}; - - -/** - * @param {string} value - * @return {!proto.opentelemetry.proto.trace.v1.Status} returns this - */ -proto.opentelemetry.proto.trace.v1.Status.prototype.setMessage = function(value) { - return jspb.Message.setProto3StringField(this, 2, value); -}; - - -goog.object.extend(exports, proto.opentelemetry.proto.trace.v1); diff --git a/packages/opentelemetry-exporter-collector/package.json b/packages/opentelemetry-exporter-collector/package.json index 673ef3dba2..f1401ebbad 100644 --- a/packages/opentelemetry-exporter-collector/package.json +++ b/packages/opentelemetry-exporter-collector/package.json @@ -16,18 +16,16 @@ "codecov:browser": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../", "precompile": "tsc --version", "compile": "npm run version:update && tsc -p .", - "generate:http-proto": "rimraf ./generated/* && ./gen.sh", - "postcompile": "npm run submodule && npm run protos:copy && npm run generated:copy", + "postcompile": "npm run submodule && npm run protos:copy", "prepare": "npm run compile", "protos:copy": "cpx src/platform/node/protos/opentelemetry/**/*.* build/src/platform/node/protos/opentelemetry", - "generated:copy": "cpx generated/**/*.* build/generated", "submodule": "git submodule sync --recursive && git submodule update --init --recursive", "tdd": "npm run test -- --watch-extensions ts --watch", "tdd:browser": "karma start", "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts' --exclude 'test/browser/**/*.ts'", "test:browser": "nyc karma start --single-run", "version:update": "node ../../scripts/version-update.js", - "watch": "npm run protos:copy && npm run generated:copy && tsc -w" + "watch": "npm run protos:copy && tsc -w" }, "keywords": [ "opentelemetry", @@ -93,7 +91,7 @@ "@opentelemetry/resources": "^0.9.0", "@opentelemetry/metrics": "^0.9.0", "@opentelemetry/tracing": "^0.9.0", - "google-protobuf": "^3.11.4", + "protobufjs": "^6.9.0", "grpc": "^1.24.2" } } diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/README.md b/packages/opentelemetry-exporter-collector/src/platform/node/README.md index 5827349a43..fe7705795e 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/README.md +++ b/packages/opentelemetry-exporter-collector/src/platform/node/README.md @@ -45,12 +45,4 @@ the latest sha when this guide was written is `b54688569186e0b862bf7462a983ccf2c 9. If you look now at git log you will notice that the folder `protos` has been changed and it will show what was the previous sha and what is current one -10. After upgrading protos you should regenerate proto files for js. -**You need to have protocol buffers installed to be able to generate them**. - -```shell script -npm run generate:http-proto -``` - -After this command it should generate a new js files in folder "generated". Make sure it compiles correctly. diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/transformSpansProto.ts b/packages/opentelemetry-exporter-collector/src/platform/node/transformSpansProto.ts deleted file mode 100644 index 7d96424658..0000000000 --- a/packages/opentelemetry-exporter-collector/src/platform/node/transformSpansProto.ts +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * - * 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 - * - * https://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. - */ - -/* eslint @typescript-eslint/no-var-requires: 0 */ - -// import * as pgTrace from '../../../generated/opentelemetry/proto/trace/v1/trace'; -// import * as pgResource from '../../../generated/opentelemetry/proto/resource/v1/resource'; -// import * as pgCommon from '../../../generated/opentelemetry/proto/common/v1/common'; -// import * as pgCollector from '../../../generated/opentelemetry/proto/collector/trace/v1/trace_service'; -const pgTrace = require('../../../generated/opentelemetry/proto/trace/v1/trace_pb'); -const pgResource = require('../../../generated/opentelemetry/proto/resource/v1/resource_pb'); -const pgCommon = require('../../../generated/opentelemetry/proto/common/v1/common_pb'); -const pgCollector = require('../../../generated/opentelemetry/proto/collector/trace/v1/trace_service_pb'); - -import { - Attributes, - Link, - SpanKind, - Status, - TimedEvent, - TraceState, -} from '@opentelemetry/api'; -import * as core from '@opentelemetry/core'; -import { Resource } from '@opentelemetry/resources'; -import { ReadableSpan } from '@opentelemetry/tracing'; -import { CollectorTraceExporterBase } from '../../CollectorTraceExporterBase'; -import { groupSpansByResourceAndLibrary } from '../../transform'; -import { COLLECTOR_SPAN_KIND_MAPPING, opentelemetryProto } from '../../types'; -import ValueType = opentelemetryProto.common.v1.ValueType; -import { InstrumentationLibrary } from '@opentelemetry/core'; -import { CollectorExporterConfigNode } from './types'; - -/** - * Converts attributes - * @param attributes - */ -export function toCollectorAttributes(attributes: Attributes) { - //: pgCommon.opentelemetry.proto.common.v1.AttributeKeyValue[] { - return Object.keys(attributes).map(key => { - return toCollectorAttributeKeyValue(key, attributes[key]); - }); -} - -/** - * Converts key and value to AttributeKeyValue - * @param value event value - */ -export function toCollectorAttributeKeyValue(key: string, value: unknown) { - //: pgCommon.opentelemetry.proto.common.v1.AttributeKeyValue { - const attributeKeyValue = new pgCommon.AttributeKeyValue(); - attributeKeyValue.setKey(key); - - if (typeof value === 'string') { - attributeKeyValue.setStringValue(value); - attributeKeyValue.setType(ValueType.STRING); - } else if (typeof value === 'boolean') { - attributeKeyValue.setBoolValue(value); - attributeKeyValue.setType(ValueType.BOOL); - } else if (typeof value === 'number') { - // all numbers will be treated as double - attributeKeyValue.setDoubleValue(value); - attributeKeyValue.setType(ValueType.DOUBLE); - } - return attributeKeyValue; -} - -/** - * - * Converts events - * @param events array of events - */ -export function toCollectorEvents(timedEvents: TimedEvent[]) { - //: pgTrace.opentelemetry.proto.trace.v1.Span.Event[] { - return timedEvents.map(timedEvent => { - const timeUnixNano = core.hrTimeToNanoseconds(timedEvent.time); - const name = timedEvent.name; - const attributes = toCollectorAttributes(timedEvent.attributes || {}); - const droppedAttributesCount = 0; - const protoEvent = new pgTrace.Span.Event(); - protoEvent.setTimeUnixNano(timeUnixNano); - protoEvent.setName(name); - protoEvent.setAttributesList(attributes); - protoEvent.setDroppedAttributesCount(droppedAttributesCount); - - return protoEvent; - }); -} - -/** - * Converts links - * @param span - */ -export function toCollectorLinks(span: ReadableSpan) { - //: pgTrace.opentelemetry.proto.trace.v1.Span.Link[] { - return span.links.map((link: Link) => { - const protoLink = new pgTrace.Span.Link(); - protoLink.setTraceId(hexToBuffer(link.context.traceId)); - protoLink.setSpanId(hexToBuffer(link.context.spanId)); - protoLink.setAttributesList(toCollectorAttributes(link.attributes || {})); - protoLink.setDroppedAttributesCount(0); - return protoLink; - }); -} - -export function toCollectorStatus(status: Status) { - //: pgTrace.opentelemetry.proto.trace.v1.Status { - const protoStatus = new pgTrace.Status(); - protoStatus.setCode(status.code); - protoStatus.setMessage(status.message); - return protoStatus; -} - -/** - * Converts span - * @param span - */ -export function toCollectorSpan(span: ReadableSpan) { - //: pgTrace.opentelemetry.proto.trace.v1.Span { - const protoSpan = new pgTrace.Span(); - - protoSpan.setTraceId(hexToBuffer(span.spanContext.traceId)); - protoSpan.setSpanId(hexToBuffer(span.spanContext.spanId)); - if (span.parentSpanId) { - protoSpan.setParentSpanId(hexToBuffer(span.parentSpanId)); - } - protoSpan.setTraceState(toCollectorTraceState(span.spanContext.traceState)); - protoSpan.setName(span.name); - protoSpan.setKind(toCollectorKind(span.kind)); - protoSpan.setStartTimeUnixNano(core.hrTimeToNanoseconds(span.startTime)); - protoSpan.setEndTimeUnixNano(core.hrTimeToNanoseconds(span.endTime)); - - protoSpan.setAttributesList(toCollectorAttributes(span.attributes)); - protoSpan.setDroppedAttributesCount(0); - - protoSpan.setEventsList(toCollectorEvents(span.events)); - protoSpan.setDroppedEventsCount(0); - - protoSpan.setStatus(toCollectorStatus(span.status)); - - protoSpan.setLinksList(toCollectorLinks(span)); - protoSpan.setDroppedLinksCount(0); - - return protoSpan; -} - -/** - * Converts resource - * @param resource - * @param additionalAttributes - */ -export function toCollectorResource( - resource?: Resource, - additionalAttributes: { [key: string]: unknown } = {} -) { - //: pgResource.opentelemetry.proto.resource.v1.Resource { - // pgResource.opentelemetry.proto.resource.v1.Resource - // pgTrace.opentelemetry.proto. trace.v1.ResourceSpans - const attr = Object.assign( - {}, - additionalAttributes, - resource ? resource.labels : {} - ); - const resourceProto = new pgResource.Resource(); - const attributes = toCollectorAttributes(attr); - resourceProto.setAttributesList(attributes); - resourceProto.setDroppedAttributesCount(0); - return resourceProto; -} - -/** - * Converts span kind - * @param kind - */ -export function toCollectorKind(kind: SpanKind) { - //: pgTrace.opentelemetry.proto.trace.v1.Span.SpanKind { - const collectorKind = COLLECTOR_SPAN_KIND_MAPPING[kind]; - return typeof collectorKind === 'number' - ? collectorKind - : opentelemetryProto.trace.v1.Span.SpanKind.SPAN_KIND_UNSPECIFIED; -} - -/** - * Converts traceState - * @param traceState - */ -export function toCollectorTraceState(traceState?: TraceState) { - //: string | undefined { - if (!traceState) { - return undefined; - } - return traceState.serialize(); -} - -/** - * Prepares trace service request to be sent to collector - * @param spans spans - * @param collectorTraceExporter - * @param [name] Instrumentation Library Name - */ -export function toCollectorExportTraceServiceRequest< - T extends CollectorExporterConfigNode ->( - spans: ReadableSpan[], - collectorTraceExporter: CollectorTraceExporterBase -) { - //: pgCollector.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest { - const groupedSpans: Map< - Resource, - Map - > = groupSpansByResourceAndLibrary(spans); - - const additionalAttributes = Object.assign( - {}, - collectorTraceExporter.attributes || {}, - { - 'service.name': collectorTraceExporter.serviceName, - } - ); - - const exportTraceServiceRequest = new pgCollector.ExportTraceServiceRequest(); - const resourceSpans = toCollectorResourceSpans( - groupedSpans, - additionalAttributes - ); - exportTraceServiceRequest.setResourceSpansList(resourceSpans); - - return exportTraceServiceRequest; -} - -function toCollectorInstrumentationLibrarySpans( - instrumentationLibrary: InstrumentationLibrary, - spans: ReadableSpan[] -) { - //: pgTrace.opentelemetry.proto.trace.v1.InstrumentationLibrarySpans { - const instrumentationLibrarySpans = new pgTrace.InstrumentationLibrarySpans(); - - const protoSpans = spans.map(toCollectorSpan); - instrumentationLibrarySpans.setSpansList(protoSpans); - - const protoInstrumentationLibrary = new pgCommon.InstrumentationLibrary(); - protoInstrumentationLibrary.setName(instrumentationLibrary.name); - protoInstrumentationLibrary.setVersion(instrumentationLibrary.version); - instrumentationLibrarySpans.setInstrumentationLibrary( - protoInstrumentationLibrary - ); - - return instrumentationLibrarySpans; -} - -function toCollectorResourceSpans( - groupedSpans: Map>, - baseAttributes: Attributes -) { - //: pgTrace.opentelemetry.proto.trace.v1.ResourceSpans[] { - return Array.from(groupedSpans, ([resource, libSpans]) => { - const resourceSpans = new pgTrace.ResourceSpans(); - const res = toCollectorResource(resource, baseAttributes); - resourceSpans.setResource(res); - const instrumentationLibrarySpans = Array.from( - libSpans, - ([instrumentationLibrary, spans]) => - toCollectorInstrumentationLibrarySpans(instrumentationLibrary, spans) - ); - resourceSpans.setInstrumentationLibrarySpansList( - instrumentationLibrarySpans - ); - return resourceSpans; - }); -} - -function hexToBuffer(hexStr: string): Uint8Array { - const hexStrLen = hexStr.length; - let hexAsciiCharsStr = ''; - for (let i = 0; i < hexStrLen; i += 2) { - const hexPair = hexStr.substring(i, i + 2); - const hexVal = parseInt(hexPair, 16); - hexAsciiCharsStr += String.fromCharCode(hexVal); - } - return Buffer.from(hexAsciiCharsStr, 'ascii'); -} diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJsonProto.ts b/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJsonProto.ts index e4777cbaba..ae7ffa2b60 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJsonProto.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJsonProto.ts @@ -15,20 +15,42 @@ */ import { ReadableSpan } from '@opentelemetry/tracing'; +import * as path from 'path'; +import { Type } from 'protobufjs'; +import * as protobufjs from 'protobufjs'; +import { toCollectorExportTraceServiceRequest } from '../../transform'; import * as collectorTypes from '../../types'; import { CollectorTraceExporter } from './CollectorTraceExporter'; -import { toCollectorExportTraceServiceRequest } from './transformSpansProto'; import { CollectorExporterConfigNode } from './types'; import { sendDataUsingHttp } from './util'; export const DEFAULT_COLLECTOR_URL_JSON_PROTO = 'http://localhost:55680/v1/trace'; +let ExportTraceServiceRequestProto: Type | undefined; + +export function getExportTraceServiceRequestProto(): Type | undefined { + return ExportTraceServiceRequestProto; +} + export function onInitWithJsonProto( _collector: CollectorTraceExporter, _config: CollectorExporterConfigNode ): void { - // nothing to be done for json proto yet + const dir = path.resolve(__dirname, 'protos'); + const root = new protobufjs.Root(); + root.resolvePath = function (origin, target) { + return `${dir}/${target}`; + }; + const proto = root.loadSync([ + 'opentelemetry/proto/common/v1/common.proto', + 'opentelemetry/proto/resource/v1/resource.proto', + 'opentelemetry/proto/trace/v1/trace.proto', + 'opentelemetry/proto/collector/trace/v1/trace_service.proto', + ]); + ExportTraceServiceRequestProto = proto?.lookupType( + 'ExportTraceServiceRequest' + ); } /** @@ -49,13 +71,20 @@ export function sendSpansUsingJsonProto( collector ); - const body = exportTraceServiceRequest.serializeBinary(); - - return sendDataUsingHttp( - collector, - Buffer.from(body), - 'application/x-protobuf', - onSuccess, - onError + const message = ExportTraceServiceRequestProto?.create( + exportTraceServiceRequest ); + + if (message) { + const body = ExportTraceServiceRequestProto?.encode(message).finish(); + if (body) { + sendDataUsingHttp( + collector, + Buffer.from(body), + 'application/x-protobuf', + onSuccess, + onError + ); + } + } } diff --git a/packages/opentelemetry-exporter-collector/test/helper.ts b/packages/opentelemetry-exporter-collector/test/helper.ts index 7607beab93..b726141042 100644 --- a/packages/opentelemetry-exporter-collector/test/helper.ts +++ b/packages/opentelemetry-exporter-collector/test/helper.ts @@ -425,6 +425,57 @@ export function ensureEventsAreCorrect( ); } +export function ensureProtoEventsAreCorrect( + events: opentelemetryProto.trace.v1.Span.Event[] +) { + assert.deepStrictEqual( + events, + [ + { + timeUnixNano: '1574120165429803008', + name: 'fetchStart', + droppedAttributesCount: 0, + }, + { + timeUnixNano: '1574120165429803008', + name: 'domainLookupStart', + droppedAttributesCount: 0, + }, + { + timeUnixNano: '1574120165429803008', + name: 'domainLookupEnd', + droppedAttributesCount: 0, + }, + { + timeUnixNano: '1574120165429803008', + name: 'connectStart', + droppedAttributesCount: 0, + }, + { + timeUnixNano: '1574120165429803008', + name: 'connectEnd', + droppedAttributesCount: 0, + }, + { + timeUnixNano: '1574120165435513088', + name: 'requestStart', + droppedAttributesCount: 0, + }, + { + timeUnixNano: '1574120165436923136', + name: 'responseStart', + droppedAttributesCount: 0, + }, + { + timeUnixNano: '1574120165438688000', + name: 'responseEnd', + droppedAttributesCount: 0, + }, + ], + 'events are incorrect' + ); +} + export function ensureAttributesAreCorrect( attributes: opentelemetryProto.common.v1.AttributeKeyValue[] ) { @@ -441,6 +492,22 @@ export function ensureAttributesAreCorrect( ); } +export function ensureProtoAttributesAreCorrect( + attributes: opentelemetryProto.common.v1.AttributeKeyValue[] +) { + assert.deepStrictEqual( + attributes, + [ + { + key: 'component', + type: 'STRING', + stringValue: 'document-load', + }, + ], + 'attributes are incorrect' + ); +} + export function ensureLinksAreCorrect( attributes: opentelemetryProto.trace.v1.Span.Link[] ) { @@ -464,6 +531,29 @@ export function ensureLinksAreCorrect( ); } +export function ensureProtoLinksAreCorrect( + attributes: opentelemetryProto.trace.v1.Span.Link[] +) { + assert.deepStrictEqual( + attributes, + [ + { + traceId: traceIdBase64, + spanId: parentIdBase64, + attributes: [ + { + key: 'component', + type: 'STRING', + stringValue: 'document-load', + }, + ], + droppedAttributesCount: 0, + }, + ], + 'links are incorrect' + ); +} + export function ensureSpanIsCorrect( span: collectorTypes.opentelemetryProto.trace.v1.Span ) { @@ -509,6 +599,47 @@ export function ensureSpanIsCorrect( assert.deepStrictEqual(span.status, { code: 0 }, 'status is wrong'); } +export function ensureProtoSpanIsCorrect( + span: collectorTypes.opentelemetryProto.trace.v1.Span +) { + if (span.attributes) { + ensureProtoAttributesAreCorrect(span.attributes); + } + if (span.events) { + ensureProtoEventsAreCorrect(span.events); + } + if (span.links) { + ensureProtoLinksAreCorrect(span.links); + } + assert.deepStrictEqual(span.traceId, traceIdBase64, 'traceId is wrong'); + assert.deepStrictEqual(span.spanId, spanIdBase64, 'spanId is wrong'); + assert.deepStrictEqual( + span.parentSpanId, + parentIdBase64, + 'parentIdArr is wrong' + ); + assert.strictEqual(span.name, 'documentFetch', 'name is wrong'); + assert.strictEqual(span.kind, 'INTERNAL', 'kind is wrong'); + assert.strictEqual( + span.startTimeUnixNano, + '1574120165429803008', + 'startTimeUnixNano is wrong' + ); + assert.strictEqual( + span.endTimeUnixNano, + '1574120165438688000', + 'endTimeUnixNano is wrong' + ); + assert.strictEqual( + span.droppedAttributesCount, + 0, + 'droppedAttributesCount is wrong' + ); + assert.strictEqual(span.droppedEventsCount, 0, 'droppedEventsCount is wrong'); + assert.strictEqual(span.droppedLinksCount, 0, 'droppedLinksCount is wrong'); + assert.deepStrictEqual(span.status, { code: 'Ok' }, 'status is wrong'); +} + export function ensureExportedSpanIsCorrect( span: collectorTypes.opentelemetryProto.trace.v1.Span ) { diff --git a/packages/opentelemetry-exporter-collector/test/node/CollectorExporterWithProto.test.ts b/packages/opentelemetry-exporter-collector/test/node/CollectorExporterWithProto.test.ts new file mode 100644 index 0000000000..bf009167cb --- /dev/null +++ b/packages/opentelemetry-exporter-collector/test/node/CollectorExporterWithProto.test.ts @@ -0,0 +1,188 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 + * + * https://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. + */ + +import * as core from '@opentelemetry/core'; +import { ReadableSpan } from '@opentelemetry/tracing'; +import * as http from 'http'; +import * as assert from 'assert'; +import * as sinon from 'sinon'; +import { CollectorProtocolNode } from '../../src/enums'; +import { CollectorTraceExporter } from '../../src/platform/node'; +import { CollectorExporterConfigNode } from '../../src/platform/node/types'; +import { getExportTraceServiceRequestProto } from '../../src/platform/node/utilWithJsonProto'; +import * as collectorTypes from '../../src/types'; + +import { + ensureExportTraceServiceRequestIsSet, + ensureProtoSpanIsCorrect, + mockedReadableSpan, +} from '../helper'; + +const fakeRequest = { + end: function () {}, + on: function () {}, + write: function () {}, +}; + +const mockRes = { + statusCode: 200, +}; + +const mockResError = { + statusCode: 400, +}; + +describe('CollectorExporter - node with proto over http', () => { + let collectorExporter: CollectorTraceExporter; + let collectorExporterConfig: CollectorExporterConfigNode; + let spyRequest: sinon.SinonSpy; + let spyWrite: sinon.SinonSpy; + let spans: ReadableSpan[]; + describe('export', () => { + beforeEach(() => { + spyRequest = sinon.stub(http, 'request').returns(fakeRequest as any); + spyWrite = sinon.stub(fakeRequest, 'write'); + collectorExporterConfig = { + headers: { + foo: 'bar', + }, + protocolNode: CollectorProtocolNode.HTTP_PROTO, + hostname: 'foo', + logger: new core.NoopLogger(), + serviceName: 'bar', + attributes: {}, + url: 'http://foo.bar.com', + }; + collectorExporter = new CollectorTraceExporter(collectorExporterConfig); + spans = []; + spans.push(Object.assign({}, mockedReadableSpan)); + }); + afterEach(() => { + spyRequest.restore(); + spyWrite.restore(); + }); + + it('should open the connection', done => { + collectorExporter.export(spans, () => {}); + + setTimeout(() => { + const args = spyRequest.args[0]; + const options = args[0]; + + assert.strictEqual(options.hostname, 'foo.bar.com'); + assert.strictEqual(options.method, 'POST'); + assert.strictEqual(options.path, '/'); + done(); + }); + }); + + it('should set custom headers', done => { + collectorExporter.export(spans, () => {}); + + setTimeout(() => { + const args = spyRequest.args[0]; + const options = args[0]; + assert.strictEqual(options.headers['foo'], 'bar'); + done(); + }); + }); + + it('should successfully send the spans', done => { + collectorExporter.export(spans, () => {}); + + setTimeout(() => { + const writeArgs = spyWrite.args[0]; + const ExportTraceServiceRequestProto = getExportTraceServiceRequestProto(); + const data = ExportTraceServiceRequestProto?.decode(writeArgs[0]); + const json = data?.toJSON() as collectorTypes.opentelemetryProto.collector.trace.v1.ExportTraceServiceRequest; + const span1 = + json.resourceSpans[0].instrumentationLibrarySpans[0].spans[0]; + assert.ok(typeof span1 !== 'undefined', "span doesn't exist"); + if (span1) { + ensureProtoSpanIsCorrect(span1); + } + + ensureExportTraceServiceRequestIsSet(json); + + done(); + }); + }); + + it('should log the successful message', done => { + const spyLoggerDebug = sinon.stub(collectorExporter.logger, 'debug'); + const spyLoggerError = sinon.stub(collectorExporter.logger, 'error'); + + const responseSpy = sinon.spy(); + collectorExporter.export(spans, responseSpy); + + setTimeout(() => { + const args = spyRequest.args[0]; + const callback = args[1]; + callback(mockRes); + setTimeout(() => { + const response: any = spyLoggerDebug.args[1][0]; + assert.strictEqual(response, 'statusCode: 200'); + assert.strictEqual(spyLoggerError.args.length, 0); + assert.strictEqual(responseSpy.args[0][0], 0); + done(); + }); + }); + }); + + it('should log the error message', done => { + const spyLoggerError = sinon.stub(collectorExporter.logger, 'error'); + + const responseSpy = sinon.spy(); + collectorExporter.export(spans, responseSpy); + + setTimeout(() => { + const args = spyRequest.args[0]; + const callback = args[1]; + callback(mockResError); + setTimeout(() => { + const response: any = spyLoggerError.args[0][0]; + assert.strictEqual(response, 'statusCode: 400'); + + assert.strictEqual(responseSpy.args[0][0], 1); + done(); + }); + }); + }); + }); + describe('CollectorTraceExporter - node (getDefaultUrl)', () => { + it('should default to localhost', done => { + const collectorExporter = new CollectorTraceExporter({ + protocolNode: CollectorProtocolNode.HTTP_PROTO, + }); + setTimeout(() => { + assert.strictEqual( + collectorExporter['url'], + 'http://localhost:55680/v1/trace' + ); + done(); + }); + }); + + it('should keep the URL if included', done => { + const url = 'http://foo.bar.com'; + const collectorExporter = new CollectorTraceExporter({ url }); + setTimeout(() => { + assert.strictEqual(collectorExporter['url'], url); + done(); + }); + }); + }); +}); diff --git a/packages/opentelemetry-exporter-collector/test/node/transformSpansProto.test.ts b/packages/opentelemetry-exporter-collector/test/node/transformSpansProto.test.ts deleted file mode 100644 index e89ce0d385..0000000000 --- a/packages/opentelemetry-exporter-collector/test/node/transformSpansProto.test.ts +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * - * 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 - * - * https://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. - */ - -import { Attributes, TimedEvent } from '@opentelemetry/api'; -import * as assert from 'assert'; -import * as transform from '../../src/platform/node/transformSpansProto'; -import { opentelemetryProto } from '../../src/types'; -import { mockedReadableSpan } from '../helper'; -import { Resource } from '@opentelemetry/resources'; - -describe('transform - spans proto', () => { - describe('toCollectorAttributes', () => { - it('should convert attribute string', () => { - const attributes: Attributes = { - foo: 'bar', - }; - assert.deepStrictEqual( - transform.toCollectorAttributes(attributes)[0].toObject(), - { - key: 'foo', - type: 0, - stringValue: 'bar', - intValue: 0, - doubleValue: 0, - boolValue: false, - } - ); - }); - - it('should convert attribute integer', () => { - const attributes: Attributes = { - foo: 13, - }; - assert.deepStrictEqual( - transform.toCollectorAttributes(attributes)[0].toObject(), - { - key: 'foo', - type: 2, - stringValue: '', - intValue: 0, - doubleValue: 13, - boolValue: false, - } - ); - }); - - it('should convert attribute boolean', () => { - const attributes: Attributes = { - foo: true, - }; - assert.deepStrictEqual( - transform.toCollectorAttributes(attributes)[0].toObject(), - { - key: 'foo', - type: 3, - stringValue: '', - intValue: 0, - doubleValue: 0, - boolValue: true, - } - ); - }); - - it('should convert attribute double', () => { - const attributes: Attributes = { - foo: 1.34, - }; - assert.deepStrictEqual( - transform.toCollectorAttributes(attributes)[0].toObject(), - { - key: 'foo', - type: 2, - stringValue: '', - intValue: 0, - doubleValue: 1.34, - boolValue: false, - } - ); - }); - }); - - describe('toCollectorEvents', () => { - it('should convert events to otc events', () => { - const events: TimedEvent[] = [ - { name: 'foo', time: [123, 123], attributes: { a: 'b' } }, - { - name: 'foo2', - time: [321, 321], - attributes: { c: 'd' }, - }, - ]; - const protoEvents = transform.toCollectorEvents(events); - const event1 = protoEvents[0].toObject(); - const event2 = protoEvents[1].toObject(); - assert.deepStrictEqual(event1, { - timeUnixNano: 123000000123, - name: 'foo', - attributesList: [ - { - key: 'a', - type: 0, - stringValue: 'b', - intValue: 0, - doubleValue: 0, - boolValue: false, - }, - ], - droppedAttributesCount: 0, - }); - assert.deepStrictEqual(event2, { - timeUnixNano: 321000000321, - name: 'foo2', - attributesList: [ - { - key: 'c', - type: 0, - stringValue: 'd', - intValue: 0, - doubleValue: 0, - boolValue: false, - }, - ], - droppedAttributesCount: 0, - }); - }); - }); - - describe('toCollectorSpan', () => { - const span = transform.toCollectorSpan(mockedReadableSpan).toObject(); - it('should convert attributes', () => { - assert.deepStrictEqual(span.attributesList, [ - { - key: 'component', - type: 0, - stringValue: 'document-load', - intValue: 0, - doubleValue: 0, - boolValue: false, - }, - ]); - }); - it('should convert events', () => { - assert.deepStrictEqual(span.eventsList, [ - { - timeUnixNano: 1574120165429803000, - name: 'fetchStart', - attributesList: [], - droppedAttributesCount: 0, - }, - { - timeUnixNano: 1574120165429803000, - name: 'domainLookupStart', - attributesList: [], - droppedAttributesCount: 0, - }, - { - timeUnixNano: 1574120165429803000, - name: 'domainLookupEnd', - attributesList: [], - droppedAttributesCount: 0, - }, - { - timeUnixNano: 1574120165429803000, - name: 'connectStart', - attributesList: [], - droppedAttributesCount: 0, - }, - { - timeUnixNano: 1574120165429803000, - name: 'connectEnd', - attributesList: [], - droppedAttributesCount: 0, - }, - { - timeUnixNano: 1574120165435513000, - name: 'requestStart', - attributesList: [], - droppedAttributesCount: 0, - }, - { - timeUnixNano: 1574120165436923100, - name: 'responseStart', - attributesList: [], - droppedAttributesCount: 0, - }, - { - timeUnixNano: 1574120165438688000, - name: 'responseEnd', - attributesList: [], - droppedAttributesCount: 0, - }, - ]); - }); - it('should convert links', () => { - assert.deepStrictEqual(span.linksList, [ - { - traceId: 'HxAI3I4nDoXECg18OTmyeA==', - spanId: 'eKiRUJiGQ4g=', - traceState: '', - attributesList: [ - { - key: 'component', - type: 0, - stringValue: 'document-load', - intValue: 0, - doubleValue: 0, - boolValue: false, - }, - ], - droppedAttributesCount: 0, - }, - ]); - }); - it('should convert trace id', () => { - assert.deepStrictEqual( - span.traceId, - 'HxAI3I4nDoXECg18OTmyeA==', - 'traceId is wrong' - ); - assert.deepStrictEqual(span.spanId, 'XhByYfZPpT4=', 'spanId is wrong'); - assert.deepStrictEqual( - span.parentSpanId, - 'eKiRUJiGQ4g=', - 'parentIdArr is wrong' - ); - assert.strictEqual(span.name, 'documentFetch', 'name is wrong'); - assert.strictEqual( - span.kind, - opentelemetryProto.trace.v1.Span.SpanKind.INTERNAL, - 'kind is wrong' - ); - assert.strictEqual( - span.startTimeUnixNano, - 1574120165429803008, - 'startTimeUnixNano is wrong' - ); - assert.strictEqual( - span.endTimeUnixNano, - 1574120165438688000, - 'endTimeUnixNano is wrong' - ); - assert.strictEqual( - span.droppedAttributesCount, - 0, - 'droppedAttributesCount is wrong' - ); - assert.strictEqual( - span.droppedEventsCount, - 0, - 'droppedEventsCount is wrong' - ); - assert.strictEqual( - span.droppedLinksCount, - 0, - 'droppedLinksCount is wrong' - ); - assert.deepStrictEqual( - span.status, - { code: 0, message: '' }, - 'status is' + ' wrong' - ); - }); - it('should convert span id', () => { - assert.deepStrictEqual(span.spanId, 'XhByYfZPpT4=', 'spanId is wrong'); - }); - it('should convert parent id', () => { - assert.deepStrictEqual( - span.parentSpanId, - 'eKiRUJiGQ4g=', - 'parentIdArr is wrong' - ); - }); - it('should convert name', () => { - assert.strictEqual(span.name, 'documentFetch', 'name is wrong'); - }); - it('should convert kind', () => { - assert.strictEqual( - span.kind, - opentelemetryProto.trace.v1.Span.SpanKind.INTERNAL, - 'kind is wrong' - ); - }); - it('should convert start time', () => { - assert.strictEqual( - span.startTimeUnixNano, - 1574120165429803008, - 'startTimeUnixNano is wrong' - ); - }); - it('should convert end time', () => { - assert.strictEqual( - span.endTimeUnixNano, - 1574120165438688000, - 'endTimeUnixNano is wrong' - ); - }); - it('should convert droppedAttributesCount', () => { - assert.strictEqual( - span.droppedAttributesCount, - 0, - 'droppedAttributesCount is wrong' - ); - }); - - it('should convert droppedEventsCount', () => { - assert.strictEqual( - span.droppedEventsCount, - 0, - 'droppedEventsCount is wrong' - ); - }); - - it('should convert droppedLinksCount', () => { - assert.strictEqual( - span.droppedLinksCount, - 0, - 'droppedLinksCount is wrong' - ); - }); - - it('should convert status', () => { - assert.deepStrictEqual( - span.status, - { code: 0, message: '' }, - 'status is' + ' wrong' - ); - }); - }); - - describe('toCollectorResource', () => { - it('should convert resource', () => { - const resource = transform.toCollectorResource( - new Resource({ - service: 'ui', - version: 1.0, - success: true, - }) - ); - assert.deepStrictEqual(resource.toObject(), { - attributesList: [ - { - key: 'service', - type: 0, - stringValue: 'ui', - intValue: 0, - doubleValue: 0, - boolValue: false, - }, - { - key: 'version', - type: 2, - stringValue: '', - intValue: 0, - doubleValue: 1, - boolValue: false, - }, - { - key: 'success', - type: 3, - stringValue: '', - intValue: 0, - doubleValue: 0, - boolValue: true, - }, - ], - droppedAttributesCount: 0, - }); - }); - }); -}); diff --git a/packages/opentelemetry-exporter-collector/tsconfig.json b/packages/opentelemetry-exporter-collector/tsconfig.json index 8d3779eda9..a2042cd68b 100644 --- a/packages/opentelemetry-exporter-collector/tsconfig.json +++ b/packages/opentelemetry-exporter-collector/tsconfig.json @@ -5,7 +5,6 @@ "outDir": "build" }, "include": [ - "generated/**/*.js", "src/**/*.ts", "test/**/*.ts" ] From 18b0745c002b531284cd0e87b4f20e8cdb6f369f Mon Sep 17 00:00:00 2001 From: Bartlomiej Obecny Date: Tue, 14 Jul 2020 01:01:04 +0200 Subject: [PATCH 08/19] chore: cleanup --- packages/opentelemetry-exporter-collector/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/opentelemetry-exporter-collector/package.json b/packages/opentelemetry-exporter-collector/package.json index 91d8ff6518..1d44de7308 100644 --- a/packages/opentelemetry-exporter-collector/package.json +++ b/packages/opentelemetry-exporter-collector/package.json @@ -46,7 +46,6 @@ "build/src/**/*.js.map", "build/src/**/*.d.ts", "build/src/**/*.proto", - "build/generated/**/*.js", "doc", "LICENSE", "README.md" From 5a0cbc527ef1f97681491bdc3f71084d71c311e3 Mon Sep 17 00:00:00 2001 From: Bartlomiej Obecny Date: Tue, 14 Jul 2020 20:51:42 +0200 Subject: [PATCH 09/19] chore: updating proto --- .../opentelemetry-exporter-collector/src/platform/node/protos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/protos b/packages/opentelemetry-exporter-collector/src/platform/node/protos index b546885691..9ffeee0ec5 160000 --- a/packages/opentelemetry-exporter-collector/src/platform/node/protos +++ b/packages/opentelemetry-exporter-collector/src/platform/node/protos @@ -1 +1 @@ -Subproject commit b54688569186e0b862bf7462a983ccf2c50c0547 +Subproject commit 9ffeee0ec532efe02285af84880deb2a53a3eab1 From 84afac3ac5a02fb15a482c262eda85b6a2c309a2 Mon Sep 17 00:00:00 2001 From: Bartlomiej Obecny Date: Fri, 17 Jul 2020 17:22:57 +0200 Subject: [PATCH 10/19] chore: updating proto --- .../docker/collector-config.yaml | 14 ++-- .../docker/docker-compose.yaml | 13 +++- examples/collector-exporter-node/package.json | 3 + examples/collector-exporter-node/start.js | 77 +++++++++++++++++- .../examples/user-interaction/index.js | 2 +- lerna.json | 2 + .../src/trace/instrumentation/Plugin.ts | 9 ++- .../browser/CollectorTraceExporter.ts | 13 +++- .../src/platform/node/util.ts | 17 +++- .../src/platform/node/utilWithJson.ts | 2 +- .../src/platform/node/utilWithJsonProto.ts | 22 +++++- .../src/transform.ts | 78 +++++++++++++------ .../src/types.ts | 33 +++++--- .../test/helper.ts | 13 +--- 14 files changed, 235 insertions(+), 63 deletions(-) diff --git a/examples/collector-exporter-node/docker/collector-config.yaml b/examples/collector-exporter-node/docker/collector-config.yaml index 7e0cd7e759..f104677f7e 100644 --- a/examples/collector-exporter-node/docker/collector-config.yaml +++ b/examples/collector-exporter-node/docker/collector-config.yaml @@ -1,15 +1,15 @@ receivers: otlp: - {} -# keep it when upgrading to version 0.5+ -# protocols: -# grpc: -# http: -# endpoint: localhost:55680 + protocols: + grpc: + http: + cors_allowed_origins: + - http://* + - https://* exporters: zipkin: - url: "http://zipkin-all-in-one:9411/api/v2/spans" + endpoint: "http://zipkin-all-in-one:9411/api/v2/spans" processors: batch: diff --git a/examples/collector-exporter-node/docker/docker-compose.yaml b/examples/collector-exporter-node/docker/docker-compose.yaml index df43b97e33..f109ccd0e8 100644 --- a/examples/collector-exporter-node/docker/docker-compose.yaml +++ b/examples/collector-exporter-node/docker/docker-compose.yaml @@ -2,17 +2,26 @@ version: "3" services: # Collector collector: - image: otel/opentelemetry-collector:0.4.0 + image: otel/opentelemetry-collector:latest +# image: otel/opentelemetry-collector:0.6.0 command: ["--config=/conf/collector-config.yaml", "--log-level=DEBUG"] + networks: + - otelcol volumes: - ./collector-config.yaml:/conf/collector-config.yaml ports: - "55680:55680" + - "55681:55681" depends_on: - zipkin-all-in-one + # Zipkin zipkin-all-in-one: - image: openzipkin/zipkin:latest + image: openzipkin/zipkin:master + networks: + - otelcol ports: - "9411:9411" +networks: + otelcol: diff --git a/examples/collector-exporter-node/package.json b/examples/collector-exporter-node/package.json index ac987ef149..a753835c4b 100644 --- a/examples/collector-exporter-node/package.json +++ b/examples/collector-exporter-node/package.json @@ -6,6 +6,7 @@ "main": "index.js", "scripts": { "start": "node ./start.js", + "start:grpc": "node ./grpc_tmp.js", "docker:start": "cd ./docker && docker-compose down && docker-compose up", "docker:startd": "cd ./docker && docker-compose down && docker-compose up -d", "docker:stop": "cd ./docker && docker-compose down" @@ -27,6 +28,8 @@ "url": "https://github.com/open-telemetry/opentelemetry-js/issues" }, "dependencies": { + "grpc": "^1.25.0-pre1", + "@grpc/proto-loader": "^0.6.0-pre4", "@opentelemetry/api": "^0.9.0", "@opentelemetry/core": "^0.9.0", "@opentelemetry/exporter-collector": "^0.9.0", diff --git a/examples/collector-exporter-node/start.js b/examples/collector-exporter-node/start.js index 138b6b41ec..e5731bcd14 100644 --- a/examples/collector-exporter-node/start.js +++ b/examples/collector-exporter-node/start.js @@ -1,4 +1,69 @@ 'use strict'; +const backslash = "\\"; +const doubleQuote = '"'; +const lineFeed = "\n"; +const textN = "n"; +const space = " "; +const arr1 = ['one', space, backslash, backslash, doubleQuote, doubleQuote, backslash, textN, backslash, textN, space, 'end', backslash, textN]; +const arr2 = ['two', backslash, textN, space, backslash, backslash, doubleQuote, space, backslash, backslash, doubleQuote, space, 'end']; +function replaceSpec(arr) { + const newArr = []; + for (let i = 0, j = arr.length; i < j; i++) { + if (arr[i] === backslash) { + newArr.push(arr[i]); + newArr.push(arr[i]); + } else if (arr[i] === doubleQuote) { + newArr.push(backslash); + newArr.push(arr[i]); + } else if (arr[i] === lineFeed) { + newArr.push(backslash); + newArr.push(textN); + } else { + newArr.push(arr[i]); + } + } + return newArr; +} +const line1 = arr1.join(''); +const line2 = arr2.join(''); +const text = line1 + lineFeed + line2; + +const shouldBe1 = + replaceSpec(arr1).join('') + + replaceSpec([lineFeed]).join('') + + replaceSpec(arr2).join(''); +// ensure the same test with already concatenated chars +const shouldBe2 = + replaceSpec(line1.split('')).join('') + + replaceSpec([lineFeed]).join('') + + replaceSpec(line2.split('')).join(''); + +// convert existing text +const shouldBe3 = + replaceSpec(text.split('')).join(''); + +function escapeString(str) { + return str.replace(/\n/g, '\\n').replace(/\\(?!n)/g, '\\\\'); +} +function escapeLabelValue(str) { + if (typeof str !== 'string') { + str = String(str); + } + return escapeString(str).replace(/"/g, '\\"'); +} +var result = escapeLabelValue(text); +console.log('line1', line1); +console.log('line2', line2); +console.log('text', text); +console.log('result', result); + +console.log('shouldBe1', shouldBe1); +console.log('shouldBe2', shouldBe2); +console.log('shouldBe3', shouldBe3); +// both conversion works fine +console.log(shouldBe2 === shouldBe1); +console.log(shouldBe3 === shouldBe1); +console.log(result === shouldBe1); const opentelemetry = require('@opentelemetry/api'); const { BasicTracerProvider, ConsoleSpanExporter, SimpleSpanProcessor } = require('@opentelemetry/tracing'); @@ -9,8 +74,8 @@ const exporter = new CollectorTraceExporter({ // headers: { // foo: 'bar' // }, - protocolNode: CollectorProtocolNode.HTTP_PROTO, - // protocolNode: CollectorProtocolNode.HTTP_JSON, + // protocolNode: CollectorProtocolNode.HTTP_PROTO, + protocolNode: CollectorProtocolNode.HTTP_JSON, }); const provider = new BasicTracerProvider(); @@ -48,6 +113,14 @@ function doWork(parent) { // Set attributes to the span. span.setAttribute('key', 'value'); + span.setAttribute('mapAndArrayValue', [ + 0, 1, 2.25, 'otel', { + foo: 'bar', + baz: 'json', + array: [1, 2, 'boom'], + }, + ]); + // Annotate our span to capture metadata about our operation span.addEvent('invoking doWork'); diff --git a/examples/tracer-web/examples/user-interaction/index.js b/examples/tracer-web/examples/user-interaction/index.js index b15f85a99e..a193a7d17b 100644 --- a/examples/tracer-web/examples/user-interaction/index.js +++ b/examples/tracer-web/examples/user-interaction/index.js @@ -10,7 +10,7 @@ const providerWithZone = new WebTracerProvider({ plugins: [ new UserInteractionPlugin(), new XMLHttpRequestPlugin({ - ignoreUrls: [/localhost:8090\/sockjs-node/], + ignoreUrls: [/localhost/], propagateTraceHeaderCorsUrls: [ 'http://localhost:8090' ] diff --git a/lerna.json b/lerna.json index f5d062d573..6042d0654f 100644 --- a/lerna.json +++ b/lerna.json @@ -2,6 +2,8 @@ "lerna": "3.13.4", "npmClient": "npm", "packages": [ + "examples/collector-exporter-node", + "examples/tracer-web", "benchmark/*", "metapackages/*", "packages/*" diff --git a/packages/opentelemetry-api/src/trace/instrumentation/Plugin.ts b/packages/opentelemetry-api/src/trace/instrumentation/Plugin.ts index 11d96fed2b..9ba12f8705 100644 --- a/packages/opentelemetry-api/src/trace/instrumentation/Plugin.ts +++ b/packages/opentelemetry-api/src/trace/instrumentation/Plugin.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { MeterProvider } from '../..'; import { Logger } from '../../common/Logger'; import { TracerProvider } from '../tracer_provider'; @@ -42,7 +43,7 @@ export interface Plugin { */ enable( moduleExports: T, - TracerProvider: TracerProvider, + TracerProvider: Providers, logger: Logger, config?: PluginConfig ): T; @@ -51,6 +52,12 @@ export interface Plugin { disable(): void; } +export interface BothProviders { + tracer: TracerProvider; + meter: MeterProvider; +} +export type Providers = BothProviders | TracerProvider; + export interface PluginConfig { /** * Whether to enable the plugin. diff --git a/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorTraceExporter.ts b/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorTraceExporter.ts index 661f1e9b87..033b3dd601 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorTraceExporter.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorTraceExporter.ts @@ -21,7 +21,7 @@ import { CollectorExporterConfigBrowser } from './types'; import * as collectorTypes from '../../types'; import { parseHeaders } from '../../util'; -const DEFAULT_COLLECTOR_URL = 'http://localhost:55680/v1/trace'; +const DEFAULT_COLLECTOR_URL = 'http://localhost:55681/v1/trace'; /** * Collector Exporter for Web @@ -40,10 +40,17 @@ export class CollectorTraceExporter extends CollectorTraceExporterBase< */ constructor(config: CollectorExporterConfigBrowser = {}) { super(config); - this._headers = - parseHeaders(config.headers, this.logger) || this.DEFAULT_HEADERS; this._useXHR = !!config.headers || typeof navigator.sendBeacon !== 'function'; + this._useXHR = true; + if (this._useXHR) { + this._headers = { + ...parseHeaders(config.headers, this.logger), + ...this.DEFAULT_HEADERS + } + } else { + this._headers = {}; + } } onInit(): void { diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/util.ts b/packages/opentelemetry-exporter-collector/src/platform/node/util.ts index 4629aab2e3..0e69985d1a 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/util.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/node/util.ts @@ -18,6 +18,7 @@ import * as http from 'http'; import * as https from 'https'; import * as collectorTypes from '../../types'; import { CollectorTraceExporter } from './CollectorTraceExporter'; +// const axios = require('axios'); export function removeProtocol(url: string): string { return url.replace(/^https?:\/\//, ''); @@ -38,8 +39,22 @@ export function sendDataUsingHttp( onSuccess: () => void, onError: (error: collectorTypes.CollectorExporterError) => void ): void { - const parsedUrl = new url.URL(collector.url); + // axios({ + // method: 'post', + // url: collector.url, + // data: data, + // headers: { + // 'Content-Type': contentType, + // 'Content-Length': Buffer.byteLength(data), + // ...collector.headers, + // } + // }).then((response: any) => { + // console.log('ok'); + // }).catch(((error: any)=> { + // console.log('error', error.response.statusText, error.response.data.message); + // })) + const parsedUrl = new url.URL(collector.url); const options = { hostname: parsedUrl.hostname, port: parsedUrl.port, diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJson.ts b/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJson.ts index 7badf20bd5..50e922c2aa 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJson.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJson.ts @@ -21,7 +21,7 @@ import { toCollectorExportTraceServiceRequest } from '../../transform'; import { CollectorExporterConfigNode } from './types'; import { sendDataUsingHttp } from './util'; -export const DEFAULT_COLLECTOR_URL_JSON = 'http://localhost:55680/v1/trace'; +export const DEFAULT_COLLECTOR_URL_JSON = 'http://localhost:55681/v1/trace'; export function onInitWithJson( _collector: CollectorTraceExporter, diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJsonProto.ts b/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJsonProto.ts index ae7ffa2b60..2f5c94fee0 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJsonProto.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJsonProto.ts @@ -25,9 +25,10 @@ import { CollectorExporterConfigNode } from './types'; import { sendDataUsingHttp } from './util'; export const DEFAULT_COLLECTOR_URL_JSON_PROTO = - 'http://localhost:55680/v1/trace'; + 'http://localhost:55681/v1/trace'; let ExportTraceServiceRequestProto: Type | undefined; +let proto: any; export function getExportTraceServiceRequestProto(): Type | undefined { return ExportTraceServiceRequestProto; @@ -42,7 +43,7 @@ export function onInitWithJsonProto( root.resolvePath = function (origin, target) { return `${dir}/${target}`; }; - const proto = root.loadSync([ + proto = root.loadSync([ 'opentelemetry/proto/common/v1/common.proto', 'opentelemetry/proto/resource/v1/resource.proto', 'opentelemetry/proto/trace/v1/trace.proto', @@ -75,8 +76,25 @@ export function sendSpansUsingJsonProto( exportTraceServiceRequest ); + // function check(obj: any) { + // const AnyValue = proto?.lookupType('AnyValue'); + // const aMessage = AnyValue.create(obj); + // const aData = AnyValue.decode(AnyValue.encode(aMessage).finish()); + // return aData.toJSON(); + // } if (message) { + // console.log(check({stringValue: 'bartek', key: 'foo', value: 'stringValue'})); + // console.log(check({key: 'bartek'})); + // console.log(check({key: 'test', stringValue: 'bartek'})); + // console.log(check({key: 'test', type: 0, stringValue: 'bartek'})); + // console.log(check({key: 'test', type: 'STRING', stringValue: 'bartek'})); + // console.log(check({key: 'test', value: {stringValue: 'bartek'}})); + // console.log(check({key: 'test', value: {stringValue: 'bartek', type: 0}})); + const body = ExportTraceServiceRequestProto?.encode(message).finish(); + // const data = ExportTraceServiceRequestProto?.decode(body as Uint8Array); + // const json = data?.toJSON(); + // console.log(json); if (body) { sendDataUsingHttp( collector, diff --git a/packages/opentelemetry-exporter-collector/src/transform.ts b/packages/opentelemetry-exporter-collector/src/transform.ts index c5aca6b9dd..ca52449e6e 100644 --- a/packages/opentelemetry-exporter-collector/src/transform.ts +++ b/packages/opentelemetry-exporter-collector/src/transform.ts @@ -30,47 +30,80 @@ import { opentelemetryProto, CollectorExporterConfigBase, } from './types'; -import ValueType = opentelemetryProto.common.v1.ValueType; /** - * Converts attributes + * Converts attributes to KeyValue array * @param attributes */ export function toCollectorAttributes( attributes: Attributes -): opentelemetryProto.common.v1.AttributeKeyValue[] { +): opentelemetryProto.common.v1.KeyValue[] { return Object.keys(attributes).map(key => { return toCollectorAttributeKeyValue(key, attributes[key]); }); } /** - * Converts key and value to AttributeKeyValue + * Converts array of unknown value to ArrayValue + * @param values + */ +export function toCollectorArrayValue( + values: unknown[] +): opentelemetryProto.common.v1.ArrayValue { + return { + values: values.map(value => toCollectorAnyValue(value)) + }; +} + +/** + * Converts attributes to KeyValueList + * @param attributes + */ +export function toCollectorKeyValueList( + attributes: Attributes +): opentelemetryProto.common.v1.KeyValueList { + return { + values: toCollectorAttributes(attributes) + }; +} + +/** + * Converts key and unknown value to KeyValue * @param value event value */ export function toCollectorAttributeKeyValue( key: string, value: unknown -): opentelemetryProto.common.v1.AttributeKeyValue { - let aType: opentelemetryProto.common.v1.ValueType = ValueType.STRING; - const AttributeKeyValue: opentelemetryProto.common.v1.AttributeKeyValue = { +): opentelemetryProto.common.v1.KeyValue { + const anyValue = toCollectorAnyValue(value); + return { key, - type: 0, + value: anyValue, }; +} + +/** + * Converts unknown value to AnyValue + * @param value + */ +export function toCollectorAnyValue( + value: unknown +): opentelemetryProto.common.v1.AnyValue { + const anyValue: opentelemetryProto.common.v1.AnyValue = {}; if (typeof value === 'string') { - AttributeKeyValue.stringValue = value; + anyValue.stringValue = value; } else if (typeof value === 'boolean') { - aType = ValueType.BOOL; - AttributeKeyValue.boolValue = value; + anyValue.boolValue = value; } else if (typeof value === 'number') { + // all numbers will be treated as double - aType = ValueType.DOUBLE; - AttributeKeyValue.doubleValue = value; + anyValue.doubleValue = value; + } else if (Array.isArray(value)) { + anyValue.arrayValue = toCollectorArrayValue(value); + } else if (value) { + anyValue.kvlistValue = toCollectorKeyValueList(value as Attributes); } - - AttributeKeyValue.type = aType; - - return AttributeKeyValue; + return anyValue; } /** @@ -195,16 +228,13 @@ export function toCollectorTraceState( * @param spans spans * @param collectorExporterBase */ -export function toCollectorExportTraceServiceRequest< - T extends CollectorExporterConfigBase ->( +export function toCollectorExportTraceServiceRequest( spans: ReadableSpan[], collectorTraceExporterBase: CollectorTraceExporterBase ): opentelemetryProto.collector.trace.v1.ExportTraceServiceRequest { - const groupedSpans: Map< - Resource, - Map - > = groupSpansByResourceAndLibrary(spans); + const groupedSpans: Map> = groupSpansByResourceAndLibrary( + spans); const additionalAttributes = Object.assign( {}, diff --git a/packages/opentelemetry-exporter-collector/src/types.ts b/packages/opentelemetry-exporter-collector/src/types.ts index 40eb5755d8..767c6c401f 100644 --- a/packages/opentelemetry-exporter-collector/src/types.ts +++ b/packages/opentelemetry-exporter-collector/src/types.ts @@ -41,7 +41,7 @@ export namespace opentelemetryProto { export namespace resource.v1 { export interface Resource { - attributes: opentelemetryProto.common.v1.AttributeKeyValue[]; + attributes: opentelemetryProto.common.v1.KeyValue[]; droppedAttributesCount: number; } } @@ -152,7 +152,7 @@ export namespace opentelemetryProto { export interface Event { timeUnixNano: number; name: string; - attributes?: opentelemetryProto.common.v1.AttributeKeyValue[]; + attributes?: opentelemetryProto.common.v1.KeyValue[]; droppedAttributesCount: number; } @@ -160,7 +160,7 @@ export namespace opentelemetryProto { traceId: string; spanId: string; traceState?: opentelemetryProto.trace.v1.Span.TraceState; - attributes?: opentelemetryProto.common.v1.AttributeKeyValue[]; + attributes?: opentelemetryProto.common.v1.KeyValue[]; droppedAttributesCount: number; } @@ -206,7 +206,7 @@ export namespace opentelemetryProto { kind?: opentelemetryProto.trace.v1.Span.SpanKind; startTimeUnixNano?: number; endTimeUnixNano?: number; - attributes?: opentelemetryProto.common.v1.AttributeKeyValue[]; + attributes?: opentelemetryProto.common.v1.KeyValue[]; droppedAttributesCount: number; events?: opentelemetryProto.trace.v1.Span.Event[]; droppedEventsCount: number; @@ -224,13 +224,26 @@ export namespace opentelemetryProto { } } export namespace common.v1 { - export interface AttributeKeyValue { + export interface KeyValue { key: string; - type: opentelemetryProto.common.v1.ValueType; - stringValue?: string; - intValue?: number; - doubleValue?: number; - boolValue?: boolean; + value: AnyValue + } + + export type ArrayValue = { + values: AnyValue[]; + } + + export interface KeyValueList { + values: KeyValue[]; + } + + export type AnyValue = { + stringValue?: string, + boolValue?: boolean, + intValue?: number, + doubleValue?: number, + arrayValue?: ArrayValue, + kvlistValue?: KeyValueList, } export interface InstrumentationLibrary { diff --git a/packages/opentelemetry-exporter-collector/test/helper.ts b/packages/opentelemetry-exporter-collector/test/helper.ts index 2a2ec9053d..a97adc9703 100644 --- a/packages/opentelemetry-exporter-collector/test/helper.ts +++ b/packages/opentelemetry-exporter-collector/test/helper.ts @@ -394,7 +394,7 @@ export function ensureExportedEventsAreCorrect( } export function ensureExportedAttributesAreCorrect( - attributes: opentelemetryProto.common.v1.AttributeKeyValue[] + attributes: opentelemetryProto.common.v1.KeyValue[] ) { assert.deepStrictEqual( attributes, @@ -550,14 +550,13 @@ export function ensureProtoEventsAreCorrect( } export function ensureAttributesAreCorrect( - attributes: opentelemetryProto.common.v1.AttributeKeyValue[] + attributes: opentelemetryProto.common.v1.KeyValue[] ) { assert.deepStrictEqual( attributes, [ { key: 'component', - type: 0, stringValue: 'document-load', }, ], @@ -566,7 +565,7 @@ export function ensureAttributesAreCorrect( } export function ensureProtoAttributesAreCorrect( - attributes: opentelemetryProto.common.v1.AttributeKeyValue[] + attributes: opentelemetryProto.common.v1.KeyValue[] ) { assert.deepStrictEqual( attributes, @@ -593,7 +592,6 @@ export function ensureLinksAreCorrect( attributes: [ { key: 'component', - type: 0, stringValue: 'document-load', }, ], @@ -774,18 +772,15 @@ export function ensureWebResourceIsCorrect( attributes: [ { key: 'service.name', - type: 0, stringValue: 'bar', }, { key: 'service', - type: 0, stringValue: 'ui', }, - { key: 'version', type: 2, doubleValue: 1 }, + { key: 'version', doubleValue: 1 }, { key: 'cost', - type: 2, doubleValue: 112.12, }, ], From 7448693842ca2ff117c1ba2f5731b74729555f82 Mon Sep 17 00:00:00 2001 From: Bartlomiej Obecny Date: Tue, 21 Jul 2020 19:13:09 +0200 Subject: [PATCH 11/19] chore: merge branch 'collector_proto' into proto_update --- .../platform/browser/CollectorTraceExporter.ts | 6 +++--- .../platform/node/CollectorMetricExporter.ts | 4 ++-- .../platform/node/CollectorTraceExporter.ts | 6 +++--- .../src/platform/node/utilWithGrpc.ts | 2 -- .../src/platform/node/utilWithJson.ts | 2 -- .../src/platform/node/utilWithJsonProto.ts | 7 ++----- .../src/transform.ts | 16 +++++++++------- .../src/types.ts | 18 +++++++++--------- .../test/node/CollectorMetricExporter.test.ts | 1 - 9 files changed, 28 insertions(+), 34 deletions(-) diff --git a/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorTraceExporter.ts b/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorTraceExporter.ts index 191332e500..6cffdcad00 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorTraceExporter.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorTraceExporter.ts @@ -22,8 +22,8 @@ import * as collectorTypes from '../../types'; import { sendWithBeacon, sendWithXhr } from './util'; import { parseHeaders } from '../../util'; -const DEFAULT_COLLECTOR_URL = 'http://localhost:55681/v1/trace'; const DEFAULT_SERVICE_NAME = 'collector-trace-exporter'; +const DEFAULT_COLLECTOR_URL = 'http://localhost:55681/v1/trace'; /** * Collector Trace Exporter for Web @@ -52,8 +52,8 @@ export class CollectorTraceExporter if (this._useXHR) { this._headers = { ...parseHeaders(config.headers, this.logger), - ...this.DEFAULT_HEADERS - } + ...this.DEFAULT_HEADERS, + }; } else { this._headers = {}; } diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/CollectorMetricExporter.ts b/packages/opentelemetry-exporter-collector/src/platform/node/CollectorMetricExporter.ts index cf84576055..3f0aa3c8de 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/CollectorMetricExporter.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/node/CollectorMetricExporter.ts @@ -21,10 +21,10 @@ import { CollectorExporterConfigNode } from './types'; import { CollectorProtocolNode } from '../../enums'; import { CollectorExporterNodeBase } from './CollectorExporterNodeBase'; import { toCollectorExportMetricServiceRequest } from '../../transformMetrics'; -import { DEFAULT_COLLECTOR_URL_GRPC } from './utilWithGrpc'; -import { DEFAULT_COLLECTOR_URL_JSON } from './utilWithJson'; const DEFAULT_SERVICE_NAME = 'collector-metric-exporter'; +const DEFAULT_COLLECTOR_URL_GRPC = 'localhost:55680'; +const DEFAULT_COLLECTOR_URL_JSON = 'http://localhost:55681/v1/metrics'; /** * Collector Metric Exporter for Node diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/CollectorTraceExporter.ts b/packages/opentelemetry-exporter-collector/src/platform/node/CollectorTraceExporter.ts index aa167fcd77..45f7194f55 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/CollectorTraceExporter.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/node/CollectorTraceExporter.ts @@ -21,11 +21,11 @@ import * as collectorTypes from '../../types'; import { CollectorProtocolNode } from '../../enums'; import { CollectorExporterConfigNode } from './types'; import { toCollectorExportTraceServiceRequest } from '../../transform'; -import { DEFAULT_COLLECTOR_URL_GRPC } from './utilWithGrpc'; const DEFAULT_SERVICE_NAME = 'collector-trace-exporter'; -const DEFAULT_COLLECTOR_URL_JSON = 'http://localhost:55680/v1/trace'; -const DEFAULT_COLLECTOR_URL_JSON_PROTO = 'http://localhost:55680/v1/trace'; +const DEFAULT_COLLECTOR_URL_GRPC = 'localhost:55680'; +const DEFAULT_COLLECTOR_URL_JSON = 'http://localhost:55681/v1/trace'; +const DEFAULT_COLLECTOR_URL_JSON_PROTO = 'http://localhost:55681/v1/trace'; /** * Collector Trace Exporter for Node diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/utilWithGrpc.ts b/packages/opentelemetry-exporter-collector/src/platform/node/utilWithGrpc.ts index fb02809e6d..8d1e3d1e33 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/utilWithGrpc.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/node/utilWithGrpc.ts @@ -24,8 +24,6 @@ import { CollectorExporterConfigNode, GRPCQueueItem } from './types'; import { removeProtocol } from './util'; import { CollectorExporterNodeBase } from './CollectorExporterNodeBase'; -export const DEFAULT_COLLECTOR_URL_GRPC = 'localhost:55680'; - export function initWithGrpc( collector: CollectorExporterNodeBase, config: CollectorExporterConfigNode diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJson.ts b/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJson.ts index d1407058cf..38da393cfe 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJson.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJson.ts @@ -19,8 +19,6 @@ import { CollectorExporterNodeBase } from './CollectorExporterNodeBase'; import { CollectorExporterConfigNode } from './types'; import { sendDataUsingHttp } from './util'; -export const DEFAULT_COLLECTOR_URL_JSON = 'http://localhost:55681/v1/trace'; - export function initWithJson( _collector: CollectorExporterNodeBase, _config: CollectorExporterConfigNode diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJsonProto.ts b/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJsonProto.ts index 7b7c2112d4..e44246200e 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJsonProto.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJsonProto.ts @@ -22,9 +22,6 @@ import { CollectorExporterNodeBase } from './CollectorExporterNodeBase'; import { CollectorExporterConfigNode } from './types'; import { sendDataUsingHttp } from './util'; -export const DEFAULT_COLLECTOR_URL_JSON_PROTO = - 'http://localhost:55681/v1/trace'; - let ExportTraceServiceRequestProto: Type | undefined; let proto: any; @@ -74,7 +71,7 @@ export function sendWithJsonProto( } } else { onError({ - message: 'No proto' - }) + message: 'No proto', + }); } } diff --git a/packages/opentelemetry-exporter-collector/src/transform.ts b/packages/opentelemetry-exporter-collector/src/transform.ts index 38f22b1032..4c11bf8c4a 100644 --- a/packages/opentelemetry-exporter-collector/src/transform.ts +++ b/packages/opentelemetry-exporter-collector/src/transform.ts @@ -51,7 +51,7 @@ export function toCollectorArrayValue( values: unknown[] ): opentelemetryProto.common.v1.ArrayValue { return { - values: values.map(value => toCollectorAnyValue(value)) + values: values.map(value => toCollectorAnyValue(value)), }; } @@ -63,7 +63,7 @@ export function toCollectorKeyValueList( attributes: Attributes ): opentelemetryProto.common.v1.KeyValueList { return { - values: toCollectorAttributes(attributes) + values: toCollectorAttributes(attributes), }; } @@ -95,7 +95,6 @@ export function toCollectorAnyValue( } else if (typeof value === 'boolean') { anyValue.boolValue = value; } else if (typeof value === 'number') { - // all numbers will be treated as double anyValue.doubleValue = value; } else if (Array.isArray(value)) { @@ -228,7 +227,9 @@ export function toCollectorTraceState( * @param spans spans * @param collectorExporterBase */ -export function toCollectorExportTraceServiceRequest( +export function toCollectorExportTraceServiceRequest< + T extends CollectorExporterConfigBase +>( spans: ReadableSpan[], collectorTraceExporterBase: CollectorExporterBase< T, @@ -236,9 +237,10 @@ export function toCollectorExportTraceServiceRequest ): opentelemetryProto.collector.trace.v1.ExportTraceServiceRequest { - const groupedSpans: Map> = groupSpansByResourceAndLibrary( - spans); + const groupedSpans: Map< + Resource, + Map + > = groupSpansByResourceAndLibrary(spans); const additionalAttributes = Object.assign( {}, diff --git a/packages/opentelemetry-exporter-collector/src/types.ts b/packages/opentelemetry-exporter-collector/src/types.ts index ffd5dd304c..5d95654fb0 100644 --- a/packages/opentelemetry-exporter-collector/src/types.ts +++ b/packages/opentelemetry-exporter-collector/src/types.ts @@ -227,25 +227,25 @@ export namespace opentelemetryProto { export namespace common.v1 { export interface KeyValue { key: string; - value: AnyValue + value: AnyValue; } export type ArrayValue = { values: AnyValue[]; - } + }; export interface KeyValueList { values: KeyValue[]; } export type AnyValue = { - stringValue?: string, - boolValue?: boolean, - intValue?: number, - doubleValue?: number, - arrayValue?: ArrayValue, - kvlistValue?: KeyValueList, - } + stringValue?: string; + boolValue?: boolean; + intValue?: number; + doubleValue?: number; + arrayValue?: ArrayValue; + kvlistValue?: KeyValueList; + }; export interface InstrumentationLibrary { name: string; diff --git a/packages/opentelemetry-exporter-collector/test/node/CollectorMetricExporter.test.ts b/packages/opentelemetry-exporter-collector/test/node/CollectorMetricExporter.test.ts index 2129c3df78..300c257593 100644 --- a/packages/opentelemetry-exporter-collector/test/node/CollectorMetricExporter.test.ts +++ b/packages/opentelemetry-exporter-collector/test/node/CollectorMetricExporter.test.ts @@ -174,7 +174,6 @@ const testCollectorMetricExporter = (params: TestParams) => assert.strictEqual(args[0], 'Headers cannot be set when using grpc'); }); it('should warn about metadata when using json', () => { - const metadata = new grpc.Metadata(); metadata.set('k', 'v'); const logger = new ConsoleLogger(LogLevel.DEBUG); From c321638d3782fdd953b6b2708029c4e7037d79e2 Mon Sep 17 00:00:00 2001 From: Bartlomiej Obecny Date: Wed, 22 Jul 2020 14:58:58 +0200 Subject: [PATCH 12/19] chore: merge branch 'master' into proto_update --- README.md | 2 + examples/.eslintrc | 3 +- .../docker/docker-compose.yaml | 4 +- examples/collector-exporter-node/package.json | 1 - examples/collector-exporter-node/start.js | 69 +- examples/grpc-js/README.md | 71 ++ examples/grpc-js/client.js | 46 ++ examples/grpc-js/helloworld_grpc_pb.js | 64 ++ examples/grpc-js/helloworld_pb.js | 332 ++++++++ examples/grpc-js/images/jaeger.png | Bin 0 -> 534713 bytes examples/grpc-js/images/zipkin.png | Bin 0 -> 110330 bytes examples/grpc-js/package.json | 44 ++ examples/grpc-js/server.js | 38 + examples/grpc-js/tracer.js | 38 + examples/grpc/helloworld_grpc_pb.js | 11 - examples/grpc/helloworld_pb.js | 10 - .../src/trace/instrumentation/Plugin.ts | 9 +- .../src/platform/browser/environment.ts | 2 +- .../src/platform/node/environment.ts | 2 +- .../src/utils/environment.ts | 2 +- .../browser/CollectorTraceExporter.ts | 1 - .../src/platform/node/README.md | 4 +- .../src/platform/node/util.ts | 3 +- .../src/platform/node/utilWithJson.ts | 4 +- .../src/platform/node/utilWithJsonProto.ts | 7 +- .../opentelemetry-grpc-utils/.eslintignore | 1 + .../opentelemetry-grpc-utils/.eslintrc.js | 7 + packages/opentelemetry-grpc-utils/.npmignore | 4 + packages/opentelemetry-grpc-utils/LICENSE | 201 +++++ packages/opentelemetry-grpc-utils/README.md | 69 ++ .../opentelemetry-grpc-utils/package.json | 75 ++ .../src/version.ts} | 10 +- .../test/fixtures/grpc-test.proto | 0 .../test/grpcUtils.test.ts | 722 ++++++++++++++++++ .../opentelemetry-grpc-utils/test/index.ts | 16 + .../test/utils/assertionUtils.ts | 7 +- .../opentelemetry-grpc-utils/tsconfig.json | 11 + .../opentelemetry-plugin-grpc-js/package.json | 3 + .../src/client/index.ts | 18 + .../src/client/loadPackageDefinition.ts | 69 ++ .../src/client/patchClient.ts | 49 ++ .../src/client/utils.ts | 244 ++++++ .../src/grpcJs.ts | 74 +- .../src/server/clientStreamAndUnary.ts | 66 ++ .../src/server/index.ts | 17 + .../src/server/patchServer.ts | 154 ++++ .../src/server/serverStreamAndBidi.ts | 86 +++ .../opentelemetry-plugin-grpc-js/src/types.ts | 54 ++ .../opentelemetry-plugin-grpc-js/src/utils.ts | 46 ++ .../test/grpcJs.test.ts | 23 + .../opentelemetry-plugin-grpc/package.json | 1 + .../test/grpc.test.ts | 654 +--------------- 52 files changed, 2663 insertions(+), 785 deletions(-) create mode 100644 examples/grpc-js/README.md create mode 100644 examples/grpc-js/client.js create mode 100644 examples/grpc-js/helloworld_grpc_pb.js create mode 100644 examples/grpc-js/helloworld_pb.js create mode 100644 examples/grpc-js/images/jaeger.png create mode 100644 examples/grpc-js/images/zipkin.png create mode 100644 examples/grpc-js/package.json create mode 100644 examples/grpc-js/server.js create mode 100644 examples/grpc-js/tracer.js create mode 100644 packages/opentelemetry-grpc-utils/.eslintignore create mode 100644 packages/opentelemetry-grpc-utils/.eslintrc.js create mode 100644 packages/opentelemetry-grpc-utils/.npmignore create mode 100644 packages/opentelemetry-grpc-utils/LICENSE create mode 100644 packages/opentelemetry-grpc-utils/README.md create mode 100644 packages/opentelemetry-grpc-utils/package.json rename packages/{opentelemetry-plugin-grpc-js/src/enums/AttributeNames.ts => opentelemetry-grpc-utils/src/version.ts} (69%) rename packages/{opentelemetry-plugin-grpc => opentelemetry-grpc-utils}/test/fixtures/grpc-test.proto (100%) create mode 100644 packages/opentelemetry-grpc-utils/test/grpcUtils.test.ts create mode 100644 packages/opentelemetry-grpc-utils/test/index.ts rename packages/{opentelemetry-plugin-grpc => opentelemetry-grpc-utils}/test/utils/assertionUtils.ts (92%) create mode 100644 packages/opentelemetry-grpc-utils/tsconfig.json create mode 100644 packages/opentelemetry-plugin-grpc-js/src/client/index.ts create mode 100644 packages/opentelemetry-plugin-grpc-js/src/client/loadPackageDefinition.ts create mode 100644 packages/opentelemetry-plugin-grpc-js/src/client/patchClient.ts create mode 100644 packages/opentelemetry-plugin-grpc-js/src/client/utils.ts create mode 100644 packages/opentelemetry-plugin-grpc-js/src/server/clientStreamAndUnary.ts create mode 100644 packages/opentelemetry-plugin-grpc-js/src/server/index.ts create mode 100644 packages/opentelemetry-plugin-grpc-js/src/server/patchServer.ts create mode 100644 packages/opentelemetry-plugin-grpc-js/src/server/serverStreamAndBidi.ts create mode 100644 packages/opentelemetry-plugin-grpc-js/src/types.ts create mode 100644 packages/opentelemetry-plugin-grpc-js/src/utils.ts create mode 100644 packages/opentelemetry-plugin-grpc-js/test/grpcJs.test.ts diff --git a/README.md b/README.md index 2072fda1d4..2a0659be6d 100644 --- a/README.md +++ b/README.md @@ -183,6 +183,7 @@ OpenTelemetry can collect tracing data automatically using plugins. Vendors/User ##### Core - [@opentelemetry/plugin-grpc][otel-plugin-grpc] +- [@opentelemetry/plugin-grpc-js][otel-plugin-grpc-js] - [@opentelemetry/plugin-http][otel-plugin-http] - [@opentelemetry/plugin-https][otel-plugin-https] @@ -242,6 +243,7 @@ Apache 2.0 - See [LICENSE][license-url] for more information. [otel-plugin-fetch]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-plugin-fetch [otel-plugin-grpc]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-plugin-grpc +[otel-plugin-grpc-js]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-plugin-grpc-js [otel-plugin-http]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-plugin-http [otel-plugin-https]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-plugin-https [otel-plugin-xml-http-request]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-plugin-xml-http-request diff --git a/examples/.eslintrc b/examples/.eslintrc index 5feabb97f5..6000f93619 100644 --- a/examples/.eslintrc +++ b/examples/.eslintrc @@ -12,5 +12,6 @@ "no-console": "off", "import/no-unresolved": "off", "no-unused-vars": ["error", { "argsIgnorePattern": "^_" }] - } + }, + "ignorePatterns": "**/*_pb.js" } diff --git a/examples/collector-exporter-node/docker/docker-compose.yaml b/examples/collector-exporter-node/docker/docker-compose.yaml index f109ccd0e8..7b1872f086 100644 --- a/examples/collector-exporter-node/docker/docker-compose.yaml +++ b/examples/collector-exporter-node/docker/docker-compose.yaml @@ -17,11 +17,9 @@ services: # Zipkin zipkin-all-in-one: - image: openzipkin/zipkin:master + image: openzipkin/zipkin:latest networks: - otelcol ports: - "9411:9411" -networks: - otelcol: diff --git a/examples/collector-exporter-node/package.json b/examples/collector-exporter-node/package.json index a753835c4b..5b2e910953 100644 --- a/examples/collector-exporter-node/package.json +++ b/examples/collector-exporter-node/package.json @@ -6,7 +6,6 @@ "main": "index.js", "scripts": { "start": "node ./start.js", - "start:grpc": "node ./grpc_tmp.js", "docker:start": "cd ./docker && docker-compose down && docker-compose up", "docker:startd": "cd ./docker && docker-compose down && docker-compose up -d", "docker:stop": "cd ./docker && docker-compose down" diff --git a/examples/collector-exporter-node/start.js b/examples/collector-exporter-node/start.js index e5731bcd14..4a2e3c6fa6 100644 --- a/examples/collector-exporter-node/start.js +++ b/examples/collector-exporter-node/start.js @@ -1,69 +1,4 @@ 'use strict'; -const backslash = "\\"; -const doubleQuote = '"'; -const lineFeed = "\n"; -const textN = "n"; -const space = " "; -const arr1 = ['one', space, backslash, backslash, doubleQuote, doubleQuote, backslash, textN, backslash, textN, space, 'end', backslash, textN]; -const arr2 = ['two', backslash, textN, space, backslash, backslash, doubleQuote, space, backslash, backslash, doubleQuote, space, 'end']; -function replaceSpec(arr) { - const newArr = []; - for (let i = 0, j = arr.length; i < j; i++) { - if (arr[i] === backslash) { - newArr.push(arr[i]); - newArr.push(arr[i]); - } else if (arr[i] === doubleQuote) { - newArr.push(backslash); - newArr.push(arr[i]); - } else if (arr[i] === lineFeed) { - newArr.push(backslash); - newArr.push(textN); - } else { - newArr.push(arr[i]); - } - } - return newArr; -} -const line1 = arr1.join(''); -const line2 = arr2.join(''); -const text = line1 + lineFeed + line2; - -const shouldBe1 = - replaceSpec(arr1).join('') + - replaceSpec([lineFeed]).join('') + - replaceSpec(arr2).join(''); -// ensure the same test with already concatenated chars -const shouldBe2 = - replaceSpec(line1.split('')).join('') + - replaceSpec([lineFeed]).join('') + - replaceSpec(line2.split('')).join(''); - -// convert existing text -const shouldBe3 = - replaceSpec(text.split('')).join(''); - -function escapeString(str) { - return str.replace(/\n/g, '\\n').replace(/\\(?!n)/g, '\\\\'); -} -function escapeLabelValue(str) { - if (typeof str !== 'string') { - str = String(str); - } - return escapeString(str).replace(/"/g, '\\"'); -} -var result = escapeLabelValue(text); -console.log('line1', line1); -console.log('line2', line2); -console.log('text', text); -console.log('result', result); - -console.log('shouldBe1', shouldBe1); -console.log('shouldBe2', shouldBe2); -console.log('shouldBe3', shouldBe3); -// both conversion works fine -console.log(shouldBe2 === shouldBe1); -console.log(shouldBe3 === shouldBe1); -console.log(result === shouldBe1); const opentelemetry = require('@opentelemetry/api'); const { BasicTracerProvider, ConsoleSpanExporter, SimpleSpanProcessor } = require('@opentelemetry/tracing'); @@ -74,8 +9,8 @@ const exporter = new CollectorTraceExporter({ // headers: { // foo: 'bar' // }, - // protocolNode: CollectorProtocolNode.HTTP_PROTO, - protocolNode: CollectorProtocolNode.HTTP_JSON, + protocolNode: CollectorProtocolNode.HTTP_PROTO, + // protocolNode: CollectorProtocolNode.HTTP_JSON, }); const provider = new BasicTracerProvider(); diff --git a/examples/grpc-js/README.md b/examples/grpc-js/README.md new file mode 100644 index 0000000000..00012cbbf5 --- /dev/null +++ b/examples/grpc-js/README.md @@ -0,0 +1,71 @@ +# Overview + +OpenTelemetry gRPC Instrumentation allows the user to automatically collect trace data and export them to the backend of choice (we can use Zipkin or Jaeger for this example), to give observability to distributed systems. + +## Installation + +```sh +# from this directory +npm install +``` + +Setup [Zipkin Tracing](https://zipkin.io/pages/quickstart.html) +or +Setup [Jaeger Tracing](https://www.jaegertracing.io/docs/latest/getting-started/#all-in-one) + +## Run the Application + +### Zipkin + +- Run the server + + ```sh + # from this directory + npm run zipkin:server + ``` + +- Run the client + + ```sh + # from this directory + npm run zipkin:client + ``` + +#### Zipkin UI + +`zipkin:server` script should output the `traceid` in the terminal (e.g `traceid: 4815c3d576d930189725f1f1d1bdfcc6`). +Go to Zipkin with your browser (e.g + +

+ +### Jaeger + +- Run the server + + ```sh + # from this directory + npm run jaeger:server + ``` + +- Run the client + + ```sh + # from this directory + npm run jaeger:client + ``` + +#### Jaeger UI + +`jaeger:server` script should output the `traceid` in the terminal (e.g `traceid: 4815c3d576d930189725f1f1d1bdfcc6`). +Go to Jaeger with your browser (e.g + +

+ +## Useful links + +- For more information on OpenTelemetry, visit: +- For more information on OpenTelemetry for Node.js, visit: + +## LICENSE + +Apache License 2.0 diff --git a/examples/grpc-js/client.js b/examples/grpc-js/client.js new file mode 100644 index 0000000000..ee4090260e --- /dev/null +++ b/examples/grpc-js/client.js @@ -0,0 +1,46 @@ +'use strict'; + +const tracer = require('./tracer')('example-grpc-client'); +// eslint-disable-next-line import/order +const grpc = require('@grpc/grpc-js'); +const messages = require('./helloworld_pb'); +const services = require('./helloworld_grpc_pb'); + +const PORT = 50051; + +/** Send a test gRPC Hello Request to the Greeter Service (server.js) */ +function main() { + // span corresponds to outgoing requests. Here, we have manually created + // the span, which is created to track work that happens outside of the + // request lifecycle entirely. + const span = tracer.startSpan('client.js:main()'); + tracer.withSpan(span, () => { + console.log('Client traceId ', span.context().traceId); + const client = new services.GreeterClient( + `localhost:${PORT}`, + grpc.credentials.createInsecure(), + ); + const request = new messages.HelloRequest(); + let user; + if (process.argv.length >= 3) { + // eslint-disable-next-line prefer-destructuring + user = process.argv[2]; + } else { + user = 'world'; + } + request.setName(user); + client.sayHello(request, (err, response) => { + span.end(); + if (err) throw err; + console.log('Greeting:', response.getMessage()); + }); + }); + + // The process must live for at least the interval past any traces that + // must be exported, or some risk being lost if they are recorded after the + // last export. + console.log('Sleeping 5 seconds before shutdown to ensure all records are flushed.'); + setTimeout(() => { console.log('Completed.'); }, 5000); +} + +main(); diff --git a/examples/grpc-js/helloworld_grpc_pb.js b/examples/grpc-js/helloworld_grpc_pb.js new file mode 100644 index 0000000000..1e39a0f46a --- /dev/null +++ b/examples/grpc-js/helloworld_grpc_pb.js @@ -0,0 +1,64 @@ +// GENERATED CODE -- DO NOT EDIT! + +// Original file comments: +// Copyright 2015 gRPC authors. +// +// 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. +// + +'use strict'; + +const grpc = require('grpc'); +const helloworld_pb = require('./helloworld_pb.js'); + +function serialize_HelloReply(arg) { + if (!(arg instanceof helloworld_pb.HelloReply)) { + throw new Error('Expected argument of type HelloReply'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_HelloReply(buffer_arg) { + return helloworld_pb.HelloReply.deserializeBinary(new Uint8Array(buffer_arg)); +} + +function serialize_HelloRequest(arg) { + if (!(arg instanceof helloworld_pb.HelloRequest)) { + throw new Error('Expected argument of type HelloRequest'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_HelloRequest(buffer_arg) { + return helloworld_pb.HelloRequest.deserializeBinary( + new Uint8Array(buffer_arg), + ); +} + +// The greeting service definition. +const GreeterService = (exports.GreeterService = { + // Sends a greeting + sayHello: { + path: '/helloworld.Greeter/SayHello', + requestStream: false, + responseStream: false, + requestType: helloworld_pb.HelloRequest, + responseType: helloworld_pb.HelloReply, + requestSerialize: serialize_HelloRequest, + requestDeserialize: deserialize_HelloRequest, + responseSerialize: serialize_HelloReply, + responseDeserialize: deserialize_HelloReply, + }, +}); + +exports.GreeterClient = grpc.makeGenericClientConstructor(GreeterService); diff --git a/examples/grpc-js/helloworld_pb.js b/examples/grpc-js/helloworld_pb.js new file mode 100644 index 0000000000..066acd68e8 --- /dev/null +++ b/examples/grpc-js/helloworld_pb.js @@ -0,0 +1,332 @@ +/** + * @fileoverview + * @enhanceable + * @public + */ +// GENERATED CODE -- DO NOT EDIT! + +const jspb = require('google-protobuf'); + +const goog = jspb; +const global = Function('return this')(); + +goog.exportSymbol('proto.helloworld.HelloReply', null, global); +goog.exportSymbol('proto.helloworld.HelloRequest', null, global); + +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.helloworld.HelloRequest = function (opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.helloworld.HelloRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + proto.helloworld.HelloRequest.displayName = 'proto.helloworld.HelloRequest'; +} + +if (jspb.Message.GENERATE_TO_OBJECT) { + /** + * Creates an object representation of this proto suitable for use in Soy templates. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. + * @param {boolean=} opt_includeInstance Whether to include the JSPB instance + * for transitional soy proto support: http://goto/soy-param-migration + * @return {!Object} + */ + proto.helloworld.HelloRequest.prototype.toObject = function ( + opt_includeInstance, + ) { + return proto.helloworld.HelloRequest.toObject(opt_includeInstance, this); + }; + + /** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Whether to include the JSPB + * instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.helloworld.HelloRequest} msg The msg instance to transform. + * @return {!Object} + */ + proto.helloworld.HelloRequest.toObject = function (includeInstance, msg) { + let f; + + const obj = { + name: msg.getName(), + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; + }; +} + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.helloworld.HelloRequest} + */ +proto.helloworld.HelloRequest.deserializeBinary = function (bytes) { + const reader = new jspb.BinaryReader(bytes); + const msg = new proto.helloworld.HelloRequest(); + return proto.helloworld.HelloRequest.deserializeBinaryFromReader(msg, reader); +}; + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.helloworld.HelloRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.helloworld.HelloRequest} + */ +proto.helloworld.HelloRequest.deserializeBinaryFromReader = function ( + msg, + reader, +) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + const field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setName(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + +/** + * Class method variant: serializes the given message to binary data + * (in protobuf wire format), writing to the given BinaryWriter. + * @param {!proto.helloworld.HelloRequest} message + * @param {!jspb.BinaryWriter} writer + */ +proto.helloworld.HelloRequest.serializeBinaryToWriter = function ( + message, + writer, +) { + message.serializeBinaryToWriter(writer); +}; + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.helloworld.HelloRequest.prototype.serializeBinary = function () { + const writer = new jspb.BinaryWriter(); + this.serializeBinaryToWriter(writer); + return writer.getResultBuffer(); +}; + +/** + * Serializes the message to binary data (in protobuf wire format), + * writing to the given BinaryWriter. + * @param {!jspb.BinaryWriter} writer + */ +proto.helloworld.HelloRequest.prototype.serializeBinaryToWriter = function ( + writer, +) { + let f; + f = this.getName(); + if (f.length > 0) { + writer.writeString(1, f); + } +}; + +/** + * Creates a deep clone of this proto. No data is shared with the original. + * @return {!proto.helloworld.HelloRequest} The clone. + */ +proto.helloworld.HelloRequest.prototype.cloneMessage = function () { + return /** @type {!proto.helloworld.HelloRequest} */ (jspb.Message.cloneMessage( + this, + )); +}; + +/** + * optional string name = 1; + * @return {string} + */ +proto.helloworld.HelloRequest.prototype.getName = function () { + return /** @type {string} */ (jspb.Message.getFieldProto3(this, 1, '')); +}; + +/** @param {string} value */ +proto.helloworld.HelloRequest.prototype.setName = function (value) { + jspb.Message.setField(this, 1, value); +}; + +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.helloworld.HelloReply = function (opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.helloworld.HelloReply, jspb.Message); +if (goog.DEBUG && !COMPILED) { + proto.helloworld.HelloReply.displayName = 'proto.helloworld.HelloReply'; +} + +if (jspb.Message.GENERATE_TO_OBJECT) { + /** + * Creates an object representation of this proto suitable for use in Soy templates. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. + * @param {boolean=} opt_includeInstance Whether to include the JSPB instance + * for transitional soy proto support: http://goto/soy-param-migration + * @return {!Object} + */ + proto.helloworld.HelloReply.prototype.toObject = function ( + opt_includeInstance, + ) { + return proto.helloworld.HelloReply.toObject(opt_includeInstance, this); + }; + + /** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Whether to include the JSPB + * instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.helloworld.HelloReply} msg The msg instance to transform. + * @return {!Object} + */ + proto.helloworld.HelloReply.toObject = function (includeInstance, msg) { + let f; + + const obj = { + message: msg.getMessage(), + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; + }; +} + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.helloworld.HelloReply} + */ +proto.helloworld.HelloReply.deserializeBinary = function (bytes) { + const reader = new jspb.BinaryReader(bytes); + const msg = new proto.helloworld.HelloReply(); + return proto.helloworld.HelloReply.deserializeBinaryFromReader(msg, reader); +}; + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.helloworld.HelloReply} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.helloworld.HelloReply} + */ +proto.helloworld.HelloReply.deserializeBinaryFromReader = function ( + msg, + reader, +) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + const field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setMessage(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + +/** + * Class method variant: serializes the given message to binary data + * (in protobuf wire format), writing to the given BinaryWriter. + * @param {!proto.helloworld.HelloReply} message + * @param {!jspb.BinaryWriter} writer + */ +proto.helloworld.HelloReply.serializeBinaryToWriter = function ( + message, + writer, +) { + message.serializeBinaryToWriter(writer); +}; + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.helloworld.HelloReply.prototype.serializeBinary = function () { + const writer = new jspb.BinaryWriter(); + this.serializeBinaryToWriter(writer); + return writer.getResultBuffer(); +}; + +/** + * Serializes the message to binary data (in protobuf wire format), + * writing to the given BinaryWriter. + * @param {!jspb.BinaryWriter} writer + */ +proto.helloworld.HelloReply.prototype.serializeBinaryToWriter = function ( + writer, +) { + let f; + f = this.getMessage(); + if (f.length > 0) { + writer.writeString(1, f); + } +}; + +/** + * Creates a deep clone of this proto. No data is shared with the original. + * @return {!proto.helloworld.HelloReply} The clone. + */ +proto.helloworld.HelloReply.prototype.cloneMessage = function () { + return /** @type {!proto.helloworld.HelloReply} */ (jspb.Message.cloneMessage( + this, + )); +}; + +/** + * optional string message = 1; + * @return {string} + */ +proto.helloworld.HelloReply.prototype.getMessage = function () { + return /** @type {string} */ (jspb.Message.getFieldProto3(this, 1, '')); +}; + +/** @param {string} value */ +proto.helloworld.HelloReply.prototype.setMessage = function (value) { + jspb.Message.setField(this, 1, value); +}; + +goog.object.extend(exports, proto.helloworld); diff --git a/examples/grpc-js/images/jaeger.png b/examples/grpc-js/images/jaeger.png new file mode 100644 index 0000000000000000000000000000000000000000..20eead3ba3377dadbe0b6d7b0204e5a917c4782c GIT binary patch literal 534713 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

Q-@$O99S>b`kSSyWR&nly>;wgQ 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%0A{pd-eX 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

i9$U#@N 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

#rsc>mPv8`spdTkcb*l2p1mC+g6;E8`Y2FHo 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 z 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 z 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⁢)=*==ZkeoK%p$wR$Y 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" + }, + "author": "OpenTelemetry Authors", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/open-telemetry/opentelemetry-js/issues" + }, + "dependencies": { + "@grpc/grpc-js": "^1.0.5", + "@opentelemetry/api": "^0.8.3", + "@opentelemetry/exporter-jaeger": "^0.8.3", + "@opentelemetry/exporter-zipkin": "^0.8.3", + "@opentelemetry/node": "^0.8.3", + "@opentelemetry/plugin-grpc-js": "^0.8.3", + "@opentelemetry/tracing": "^0.8.3", + "google-protobuf": "^3.9.2" + }, + "homepage": "https://github.com/open-telemetry/opentelemetry-js#readme", + "devDependencies": { + "cross-env": "^6.0.0" + } +} diff --git a/examples/grpc-js/server.js b/examples/grpc-js/server.js new file mode 100644 index 0000000000..1b9d533172 --- /dev/null +++ b/examples/grpc-js/server.js @@ -0,0 +1,38 @@ +'use strict'; + +const tracer = require('./tracer')(('example-grpc-server')); +// eslint-disable-next-line import/order +const grpc = require('grpc'); + +const messages = require('./helloworld_pb'); +const services = require('./helloworld_grpc_pb'); + +const PORT = 50051; + +/** Starts a gRPC server that receives requests on sample server port. */ +function startServer() { + // Creates a server + const server = new grpc.Server(); + server.addService(services.GreeterService, { sayHello }); + server.bind(`0.0.0.0:${PORT}`, grpc.ServerCredentials.createInsecure()); + console.log(`binding server on 0.0.0.0:${PORT}`); + server.start(); +} + +function sayHello(call, callback) { + const currentSpan = tracer.getCurrentSpan(); + // display traceid in the terminal + console.log(`traceid: ${currentSpan.context().traceId}`); + const span = tracer.startSpan('server.js:sayHello()', { + parent: currentSpan, + kind: 1, // server + attributes: { key: 'value' }, + }); + span.addEvent(`invoking sayHello() to ${call.request.getName()}`); + const reply = new messages.HelloReply(); + reply.setMessage(`Hello ${call.request.getName()}`); + callback(null, reply); + span.end(); +} + +startServer(); diff --git a/examples/grpc-js/tracer.js b/examples/grpc-js/tracer.js new file mode 100644 index 0000000000..e5c1d2871a --- /dev/null +++ b/examples/grpc-js/tracer.js @@ -0,0 +1,38 @@ +'use strict'; + +const opentelemetry = require('@opentelemetry/api'); +const { NodeTracerProvider } = require('@opentelemetry/node'); +const { SimpleSpanProcessor } = require('@opentelemetry/tracing'); +const { JaegerExporter } = require('@opentelemetry/exporter-jaeger'); +const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin'); + +const EXPORTER = process.env.EXPORTER || ''; + +module.exports = (serviceName) => { + const provider = new NodeTracerProvider({ + plugins: { + '@grpc/grpc-js': { + enabled: true, + path: '@opentelemetry/plugin-grpc-js', + }, + }, + }); + + let exporter; + if (EXPORTER.toLowerCase().startsWith('z')) { + exporter = new ZipkinExporter({ + serviceName, + }); + } else { + exporter = new JaegerExporter({ + serviceName, + }); + } + + provider.addSpanProcessor(new SimpleSpanProcessor(exporter)); + + // Initialize the OpenTelemetry APIs to use the NodeTracerProvider bindings + provider.register(); + + return opentelemetry.trace.getTracer('grpc-js-example'); +}; diff --git a/examples/grpc/helloworld_grpc_pb.js b/examples/grpc/helloworld_grpc_pb.js index c32727f8da..1e39a0f46a 100644 --- a/examples/grpc/helloworld_grpc_pb.js +++ b/examples/grpc/helloworld_grpc_pb.js @@ -1,14 +1,3 @@ -/* eslint-disable no-multi-assign */ -/* eslint-disable prefer-const */ -/* eslint-disable no-var */ -/* eslint-disable vars-on-top */ -/* eslint-disable no-unused-vars */ -/* eslint-disable func-names */ -/* eslint-disable camelcase */ -/* eslint-disable no-undef */ -/* eslint-disable no-new-func */ -/* eslint-disable strict */ - // GENERATED CODE -- DO NOT EDIT! // Original file comments: diff --git a/examples/grpc/helloworld_pb.js b/examples/grpc/helloworld_pb.js index 8247c5842c..066acd68e8 100644 --- a/examples/grpc/helloworld_pb.js +++ b/examples/grpc/helloworld_pb.js @@ -1,13 +1,3 @@ -/* eslint-disable prefer-const */ -/* eslint-disable no-var */ -/* eslint-disable vars-on-top */ -/* eslint-disable no-unused-vars */ -/* eslint-disable func-names */ -/* eslint-disable camelcase */ -/* eslint-disable no-undef */ -/* eslint-disable no-new-func */ -/* eslint-disable strict */ - /** * @fileoverview * @enhanceable diff --git a/packages/opentelemetry-api/src/trace/instrumentation/Plugin.ts b/packages/opentelemetry-api/src/trace/instrumentation/Plugin.ts index 9ba12f8705..11d96fed2b 100644 --- a/packages/opentelemetry-api/src/trace/instrumentation/Plugin.ts +++ b/packages/opentelemetry-api/src/trace/instrumentation/Plugin.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -import { MeterProvider } from '../..'; import { Logger } from '../../common/Logger'; import { TracerProvider } from '../tracer_provider'; @@ -43,7 +42,7 @@ export interface Plugin { */ enable( moduleExports: T, - TracerProvider: Providers, + TracerProvider: TracerProvider, logger: Logger, config?: PluginConfig ): T; @@ -52,12 +51,6 @@ export interface Plugin { disable(): void; } -export interface BothProviders { - tracer: TracerProvider; - meter: MeterProvider; -} -export type Providers = BothProviders | TracerProvider; - export interface PluginConfig { /** * Whether to enable the plugin. diff --git a/packages/opentelemetry-core/src/platform/browser/environment.ts b/packages/opentelemetry-core/src/platform/browser/environment.ts index 54a2a6c571..e1671f40c0 100644 --- a/packages/opentelemetry-core/src/platform/browser/environment.ts +++ b/packages/opentelemetry-core/src/platform/browser/environment.ts @@ -24,7 +24,7 @@ import { /** * Gets the environment variables */ -export function getEnv(): ENVIRONMENT { +export function getEnv(): Required { const _window = window as typeof window & ENVIRONMENT_MAP; const globalEnv = parseEnvironment(_window); return Object.assign({}, DEFAULT_ENVIRONMENT, globalEnv); diff --git a/packages/opentelemetry-core/src/platform/node/environment.ts b/packages/opentelemetry-core/src/platform/node/environment.ts index f3595cd9af..db35828e6b 100644 --- a/packages/opentelemetry-core/src/platform/node/environment.ts +++ b/packages/opentelemetry-core/src/platform/node/environment.ts @@ -24,7 +24,7 @@ import { /** * Gets the environment variables */ -export function getEnv(): ENVIRONMENT { +export function getEnv(): Required { const processEnv = parseEnvironment(process.env as ENVIRONMENT_MAP); return Object.assign({}, DEFAULT_ENVIRONMENT, processEnv); } diff --git a/packages/opentelemetry-core/src/utils/environment.ts b/packages/opentelemetry-core/src/utils/environment.ts index be56f892c0..9ada4030cd 100644 --- a/packages/opentelemetry-core/src/utils/environment.ts +++ b/packages/opentelemetry-core/src/utils/environment.ts @@ -35,7 +35,7 @@ const ENVIRONMENT_NUMBERS: Partial[] = [ /** * Default environment variables */ -export const DEFAULT_ENVIRONMENT: ENVIRONMENT = { +export const DEFAULT_ENVIRONMENT: Required = { OTEL_NO_PATCH_MODULES: '', OTEL_LOG_LEVEL: LogLevel.ERROR, OTEL_SAMPLING_PROBABILITY: 1, diff --git a/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorTraceExporter.ts b/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorTraceExporter.ts index 6cffdcad00..146fc121c4 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorTraceExporter.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorTraceExporter.ts @@ -48,7 +48,6 @@ export class CollectorTraceExporter super(config); this._useXHR = !!config.headers || typeof navigator.sendBeacon !== 'function'; - this._useXHR = true; if (this._useXHR) { this._headers = { ...parseHeaders(config.headers, this.logger), diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/README.md b/packages/opentelemetry-exporter-collector/src/platform/node/README.md index fe7705795e..66ca6c5f99 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/README.md +++ b/packages/opentelemetry-exporter-collector/src/platform/node/README.md @@ -43,6 +43,4 @@ the latest sha when this guide was written is `b54688569186e0b862bf7462a983ccf2c git commit -am "chore: updating submodule for opentelemetry-proto" ``` -9. If you look now at git log you will notice that the folder `protos` has been changed and it will show what was the previous sha and what is current one - -Make sure it compiles correctly. +9. If you look now at git log you will notice that the folder `protos` has been changed and it will show what was the previous sha and what is current one. diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/util.ts b/packages/opentelemetry-exporter-collector/src/platform/node/util.ts index 6007224b8d..c7a7e24a57 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/util.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/node/util.ts @@ -31,7 +31,7 @@ export function removeProtocol(url: string): string { * @param onSuccess * @param onError */ -export function sendDataUsingHttp( +export function sendWithHttp( collector: CollectorExporterNodeBase, data: string | Buffer, contentType: string, @@ -39,6 +39,7 @@ export function sendDataUsingHttp( onError: (error: collectorTypes.CollectorExporterError) => void ): void { const parsedUrl = new url.URL(collector.url); + const options = { hostname: parsedUrl.hostname, port: parsedUrl.port, diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJson.ts b/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJson.ts index 38da393cfe..72e2c3198b 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJson.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJson.ts @@ -17,7 +17,7 @@ import * as collectorTypes from '../../types'; import { CollectorExporterNodeBase } from './CollectorExporterNodeBase'; import { CollectorExporterConfigNode } from './types'; -import { sendDataUsingHttp } from './util'; +import { sendWithHttp } from './util'; export function initWithJson( _collector: CollectorExporterNodeBase, @@ -34,7 +34,7 @@ export function sendWithJson( ): void { const serviceRequest = collector.convert(objects); - sendDataUsingHttp( + sendWithHttp( collector, JSON.stringify(serviceRequest), 'application/json', diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJsonProto.ts b/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJsonProto.ts index e44246200e..15025ed56e 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJsonProto.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/node/utilWithJsonProto.ts @@ -20,10 +20,9 @@ import * as protobufjs from 'protobufjs'; import * as collectorTypes from '../../types'; import { CollectorExporterNodeBase } from './CollectorExporterNodeBase'; import { CollectorExporterConfigNode } from './types'; -import { sendDataUsingHttp } from './util'; +import { sendWithHttp } from './util'; let ExportTraceServiceRequestProto: Type | undefined; -let proto: any; export function getExportTraceServiceRequestProto(): Type | undefined { return ExportTraceServiceRequestProto; @@ -38,7 +37,7 @@ export function initWithJsonProto( root.resolvePath = function (origin, target) { return `${dir}/${target}`; }; - proto = root.loadSync([ + const proto = root.loadSync([ 'opentelemetry/proto/common/v1/common.proto', 'opentelemetry/proto/resource/v1/resource.proto', 'opentelemetry/proto/trace/v1/trace.proto', @@ -61,7 +60,7 @@ export function sendWithJsonProto( if (message) { const body = ExportTraceServiceRequestProto?.encode(message).finish(); if (body) { - sendDataUsingHttp( + sendWithHttp( collector, Buffer.from(body), 'application/x-protobuf', diff --git a/packages/opentelemetry-grpc-utils/.eslintignore b/packages/opentelemetry-grpc-utils/.eslintignore new file mode 100644 index 0000000000..378eac25d3 --- /dev/null +++ b/packages/opentelemetry-grpc-utils/.eslintignore @@ -0,0 +1 @@ +build diff --git a/packages/opentelemetry-grpc-utils/.eslintrc.js b/packages/opentelemetry-grpc-utils/.eslintrc.js new file mode 100644 index 0000000000..f726f3becb --- /dev/null +++ b/packages/opentelemetry-grpc-utils/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + "env": { + "mocha": true, + "node": true + }, + ...require('../../eslint.config.js') +} diff --git a/packages/opentelemetry-grpc-utils/.npmignore b/packages/opentelemetry-grpc-utils/.npmignore new file mode 100644 index 0000000000..9505ba9450 --- /dev/null +++ b/packages/opentelemetry-grpc-utils/.npmignore @@ -0,0 +1,4 @@ +/bin +/coverage +/doc +/test diff --git a/packages/opentelemetry-grpc-utils/LICENSE b/packages/opentelemetry-grpc-utils/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/packages/opentelemetry-grpc-utils/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/packages/opentelemetry-grpc-utils/README.md b/packages/opentelemetry-grpc-utils/README.md new file mode 100644 index 0000000000..064b5be954 --- /dev/null +++ b/packages/opentelemetry-grpc-utils/README.md @@ -0,0 +1,69 @@ +# OpenTelemetry gRPC Instrumentation for Node.js + +[![Gitter chat][gitter-image]][gitter-url] +[![NPM Published Version][npm-img]][npm-url] +[![dependencies][dependencies-image]][dependencies-url] +[![devDependencies][devDependencies-image]][devDependencies-url] +[![Apache License][license-image]][license-image] + +This module provides automatic instrumentation for [`grpc`](https://grpc.github.io/grpc/node/). Currently, version [`1.x`](https://www.npmjs.com/package/grpc?activeTab=versions) of the Node.js gRPC library is supported. + +For automatic instrumentation see the +[@opentelemetry/node](https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-node) package. + +## Installation + +```sh +npm install --save @opentelemetry/plugin-grpc +``` + +## Usage + +OpenTelemetry gRPC Instrumentation allows the user to automatically collect trace data and export them to the backend of choice, to give observability to distributed systems when working with [gRPC](https://www.npmjs.com/package/grpc). + +To load a specific plugin (**gRPC** in this case), specify it in the Node Tracer's configuration. + +```javascript +const { NodeTracerProvider } = require('@opentelemetry/node'); + +const provider = new NodeTracerProvider({ + plugins: { + grpc: { + enabled: true, + // You may use a package name or absolute path to the file. + path: '@opentelemetry/plugin-grpc', + } + } +}); +``` + +To load all of the [supported plugins](https://github.com/open-telemetry/opentelemetry-js#plugins), use below approach. Each plugin is only loaded when the module that it patches is loaded; in other words, there is no computational overhead for listing plugins for unused modules. + +```javascript +const { NodeTracerProvider } = require('@opentelemetry/node'); + +const provider = new NodeTracerProvider(); +``` + +See [examples/grpc](https://github.com/open-telemetry/opentelemetry-js/tree/master/examples/grpc) for a short example. + +## Useful links + +- For more information on OpenTelemetry, visit: +- For more about OpenTelemetry JavaScript: +- For help or feedback on this project, join us on [gitter][gitter-url] + +## License + +Apache 2.0 - See [LICENSE][license-url] for more information. + +[gitter-image]: https://badges.gitter.im/open-telemetry/opentelemetry-js.svg +[gitter-url]: https://gitter.im/open-telemetry/opentelemetry-node?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge +[license-url]: https://github.com/open-telemetry/opentelemetry-js/blob/master/LICENSE +[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat +[dependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/status.svg?path=packages/opentelemetry-plugin-grpc +[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-plugin-grpc +[devDependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/dev-status.svg?path=packages/opentelemetry-plugin-grpc +[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-plugin-grpc&type=dev +[npm-url]: https://www.npmjs.com/package/@opentelemetry/plugin-grpc +[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fplugin-grpc.svg diff --git a/packages/opentelemetry-grpc-utils/package.json b/packages/opentelemetry-grpc-utils/package.json new file mode 100644 index 0000000000..a259a5539f --- /dev/null +++ b/packages/opentelemetry-grpc-utils/package.json @@ -0,0 +1,75 @@ +{ + "name": "@opentelemetry/grpc-utils", + "version": "0.9.0", + "private": true, + "description": "OpenTelemetry grpc plugin utility functions.", + "main": "build/src/index.js", + "types": "build/src/index.d.ts", + "repository": "open-telemetry/opentelemetry-js", + "scripts": { + "test": "nyc ts-mocha -p tsconfig.json test/**/*.test.ts", + "tdd": "npm run test -- --watch-extensions ts --watch", + "clean": "rimraf build/*", + "lint": "eslint . --ext .ts", + "lint:fix": "eslint . --ext .ts --fix", + "codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../", + "precompile": "tsc --version", + "version:update": "node ../../scripts/version-update.js", + "compile": "npm run version:update && tsc -p .", + "prepare": "npm run compile" + }, + "keywords": [ + "opentelemetry", + "grpc", + "nodejs", + "tracing", + "profiling", + "plugin" + ], + "author": "OpenTelemetry Authors", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + }, + "files": [ + "build/src/**/*.js", + "build/src/**/*.d.ts", + "doc", + "LICENSE", + "README.md" + ], + "publishConfig": { + "access": "public" + }, + "devDependencies": { + "@grpc/grpc-js": "1.1.2", + "@grpc/proto-loader": "0.5.4", + "@opentelemetry/context-async-hooks": "^0.9.0", + "@opentelemetry/context-base": "^0.9.0", + "@opentelemetry/node": "^0.9.0", + "@opentelemetry/tracing": "^0.9.0", + "@types/mocha": "7.0.2", + "@types/node": "14.0.13", + "@types/semver": "7.2.0", + "@types/shimmer": "1.0.1", + "@types/sinon": "9.0.4", + "codecov": "3.7.0", + "grpc": "1.24.3", + "gts": "2.0.2", + "mocha": "7.2.0", + "node-pre-gyp": "0.15.0", + "nyc": "15.1.0", + "rimraf": "3.0.2", + "semver": "7.3.2", + "sinon": "9.0.2", + "ts-mocha": "7.0.0", + "ts-node": "8.10.2", + "typescript": "3.9.5" + }, + "dependencies": { + "@opentelemetry/api": "^0.9.0", + "@opentelemetry/core": "^0.9.0", + "@opentelemetry/semantic-conventions": "^0.9.0", + "shimmer": "^1.2.1" + } +} diff --git a/packages/opentelemetry-plugin-grpc-js/src/enums/AttributeNames.ts b/packages/opentelemetry-grpc-utils/src/version.ts similarity index 69% rename from packages/opentelemetry-plugin-grpc-js/src/enums/AttributeNames.ts rename to packages/opentelemetry-grpc-utils/src/version.ts index 3fdea85bc7..2c92beb616 100644 --- a/packages/opentelemetry-plugin-grpc-js/src/enums/AttributeNames.ts +++ b/packages/opentelemetry-grpc-utils/src/version.ts @@ -14,11 +14,5 @@ * limitations under the License. */ -export enum AttributeNames { - COMPONENT = 'component', - GRPC_KIND = 'grpc.kind', // SERVER or CLIENT - GRPC_METHOD = 'grpc.method', - GRPC_STATUS_CODE = 'grpc.status_code', - GRPC_ERROR_NAME = 'grpc.error_name', - GRPC_ERROR_MESSAGE = 'grpc.error_message', -} +// this is autogenerated file, see scripts/version-update.js +export const VERSION = '0.9.0'; diff --git a/packages/opentelemetry-plugin-grpc/test/fixtures/grpc-test.proto b/packages/opentelemetry-grpc-utils/test/fixtures/grpc-test.proto similarity index 100% rename from packages/opentelemetry-plugin-grpc/test/fixtures/grpc-test.proto rename to packages/opentelemetry-grpc-utils/test/fixtures/grpc-test.proto diff --git a/packages/opentelemetry-grpc-utils/test/grpcUtils.test.ts b/packages/opentelemetry-grpc-utils/test/grpcUtils.test.ts new file mode 100644 index 0000000000..e5f49b8b55 --- /dev/null +++ b/packages/opentelemetry-grpc-utils/test/grpcUtils.test.ts @@ -0,0 +1,722 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 + * + * https://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. + */ + +import { + context, + NoopTracerProvider, + SpanKind, + propagation, +} from '@opentelemetry/api'; +import { NoopLogger, HttpTraceContext, BasePlugin } from '@opentelemetry/core'; +import { NodeTracerProvider } from '@opentelemetry/node'; +import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks'; +import { ContextManager } from '@opentelemetry/context-base'; +import { + InMemorySpanExporter, + SimpleSpanProcessor, +} from '@opentelemetry/tracing'; +import * as assert from 'assert'; +import * as protoLoader from '@grpc/proto-loader'; +import type * as grpcNapi from 'grpc'; +import type * as grpcJs from '@grpc/grpc-js'; +import { assertPropagation, assertSpan } from './utils/assertionUtils'; +import { promisify } from 'util'; + +const PROTO_PATH = + process.cwd() + + '/node_modules/@opentelemetry/grpc-utils/test/fixtures/grpc-test.proto'; +const memoryExporter = new InMemorySpanExporter(); + +const options = { + keepCase: true, + longs: String, + enums: String, + defaults: true, + oneofs: true, +}; + +interface TestRequestResponse { + num: number; +} + +type ServiceError = grpcNapi.ServiceError | grpcJs.ServiceError; +type Client = grpcNapi.Client | grpcJs.Client; +type Server = grpcNapi.Server | grpcJs.Server; +type ServerUnaryCall = + | grpcNapi.ServerUnaryCall + | grpcJs.ServerUnaryCall; +type RequestCallback = grpcJs.requestCallback; +type ServerReadableStream = + | grpcNapi.ServerReadableStream + | grpcJs.ServerReadableStream; +type ServerWriteableStream = + | grpcNapi.ServerWriteableStream + | grpcJs.ServerWritableStream; +type ServerDuplexStream = + | grpcNapi.ServerDuplexStream + | grpcJs.ServerDuplexStream; + +type TestGrpcClient = (typeof grpcJs | typeof grpcNapi)['Client'] & { + unaryMethod: any; + UnaryMethod: any; + camelCaseMethod: any; + clientStreamMethod: any; + serverStreamMethod: any; + bidiStreamMethod: any; +}; + +// Compare two arrays using an equal function f +const arrayIsEqual = (f: any) => ([x, ...xs]: any) => ([y, ...ys]: any): any => + x === undefined && y === undefined + ? true + : Boolean(f(x)(y)) && arrayIsEqual(f)(xs)(ys); + +// Return true if two requests has the same num value +const requestEqual = (x: TestRequestResponse) => (y: TestRequestResponse) => + x.num !== undefined && x.num === y.num; + +// Check if its equal requests or array of requests +const checkEqual = (x: TestRequestResponse | TestRequestResponse[]) => ( + y: TestRequestResponse | TestRequestResponse[] +) => + x instanceof Array && y instanceof Array + ? arrayIsEqual(requestEqual)(x as any)(y as any) + : !(x instanceof Array) && !(y instanceof Array) + ? requestEqual(x)(y) + : false; + +export const runTests = ( + plugin: BasePlugin, + moduleName: string, + grpc: typeof grpcNapi | typeof grpcJs, + grpcPort: number +) => { + const MAX_ERROR_STATUS = grpc.status.UNAUTHENTICATED; + + const grpcClient = { + unaryMethod: ( + client: TestGrpcClient, + request: TestRequestResponse + ): Promise => { + return new Promise((resolve, reject) => { + return client.unaryMethod( + request, + (err: ServiceError, response: TestRequestResponse) => { + if (err) { + reject(err); + } else { + resolve(response); + } + } + ); + }); + }, + + UnaryMethod: ( + client: TestGrpcClient, + request: TestRequestResponse + ): Promise => { + return new Promise((resolve, reject) => { + return client.UnaryMethod( + request, + (err: ServiceError, response: TestRequestResponse) => { + if (err) { + reject(err); + } else { + resolve(response); + } + } + ); + }); + }, + + camelCaseMethod: ( + client: TestGrpcClient, + request: TestRequestResponse + ): Promise => { + return new Promise((resolve, reject) => { + return client.camelCaseMethod( + request, + (err: ServiceError, response: TestRequestResponse) => { + if (err) { + reject(err); + } else { + resolve(response); + } + } + ); + }); + }, + + clientStreamMethod: ( + client: TestGrpcClient, + request: TestRequestResponse[] + ): Promise => { + return new Promise((resolve, reject) => { + const writeStream = client.clientStreamMethod( + (err: ServiceError, response: TestRequestResponse) => { + if (err) { + reject(err); + } else { + resolve(response); + } + } + ); + + request.forEach(element => { + writeStream.write(element); + }); + writeStream.end(); + }); + }, + + serverStreamMethod: ( + client: TestGrpcClient, + request: TestRequestResponse + ): Promise => { + return new Promise((resolve, reject) => { + const result: TestRequestResponse[] = []; + const readStream = client.serverStreamMethod(request); + + readStream.on('data', (data: TestRequestResponse) => { + result.push(data); + }); + readStream.on('error', (err: ServiceError) => { + reject(err); + }); + readStream.on('end', () => { + resolve(result); + }); + }); + }, + + bidiStreamMethod: ( + client: TestGrpcClient, + request: TestRequestResponse[] + ): Promise => { + return new Promise((resolve, reject) => { + const result: TestRequestResponse[] = []; + const bidiStream = client.bidiStreamMethod([]); + + bidiStream.on('data', (data: TestRequestResponse) => { + result.push(data); + }); + + request.forEach(element => { + bidiStream.write(element); + }); + + bidiStream.on('error', (err: ServiceError) => { + reject(err); + }); + + bidiStream.on('end', () => { + resolve(result); + }); + + bidiStream.end(); + }); + }, + }; + + let server: Server; + let client: Client; + + const replicate = (request: TestRequestResponse) => { + const result: TestRequestResponse[] = []; + for (let i = 0; i < request.num; i++) { + result.push(request); + } + return result; + }; + + async function startServer( + grpc: typeof grpcJs | typeof grpcNapi, + proto: any + ) { + const server = new grpc.Server(); + + function getError(msg: string, code: number): ServiceError | null { + const err: ServiceError = { + ...new Error(msg), + name: msg, + message: msg, + code, + details: msg, + }; + return err; + } + + server.addService(proto.GrpcTester.service, { + // An error is emitted every time + // request.num <= MAX_ERROR_STATUS = (status.UNAUTHENTICATED) + // in those cases, erro.code = request.num + + // This method returns the request + unaryMethod(call: ServerUnaryCall, callback: RequestCallback) { + call.request.num <= MAX_ERROR_STATUS + ? callback( + getError( + 'Unary Method Error', + call.request.num + ) as grpcJs.ServiceError + ) + : callback(null, { num: call.request.num }); + }, + + // This method returns the request + camelCaseMethod(call: ServerUnaryCall, callback: RequestCallback) { + call.request.num <= MAX_ERROR_STATUS + ? callback( + getError( + 'Unary Method Error', + call.request.num + ) as grpcJs.ServiceError + ) + : callback(null, { num: call.request.num }); + }, + + // This method sums the requests + clientStreamMethod( + call: ServerReadableStream, + callback: RequestCallback + ) { + let sum = 0; + let hasError = false; + let code = grpc.status.OK; + call.on('data', (data: TestRequestResponse) => { + sum += data.num; + if (data.num <= MAX_ERROR_STATUS) { + hasError = true; + code = data.num; + } + }); + call.on('end', () => { + hasError + ? callback(getError('Client Stream Method Error', code) as any) + : callback(null, { num: sum }); + }); + }, + + // This method returns an array that replicates the request, request.num of + // times + serverStreamMethod: (call: ServerWriteableStream) => { + const result = replicate(call.request); + + if (call.request.num <= MAX_ERROR_STATUS) { + call.emit( + 'error', + getError('Server Stream Method Error', call.request.num) + ); + } else { + result.forEach(element => { + call.write(element); + }); + } + call.end(); + }, + + // This method returns the request + bidiStreamMethod: (call: ServerDuplexStream) => { + call.on('data', (data: TestRequestResponse) => { + if (data.num <= MAX_ERROR_STATUS) { + call.emit( + 'error', + getError('Server Stream Method Error', data.num) + ); + } else { + call.write(data); + } + }); + call.on('end', () => { + call.end(); + }); + }, + }); + const bindAwait = promisify(server.bindAsync); + await bindAwait.call( + server, + 'localhost:' + grpcPort, + grpc.ServerCredentials.createInsecure() as grpcJs.ServerCredentials + ); + server.start(); + return server; + } + + function createClient(grpc: typeof grpcJs | typeof grpcNapi, proto: any) { + return new proto.GrpcTester( + 'localhost:' + grpcPort, + grpc.credentials.createInsecure() + ); + } + + return describe('GrpcPlugin', () => { + let contextManager: ContextManager; + + before(() => { + propagation.setGlobalPropagator(new HttpTraceContext()); + }); + + beforeEach(() => { + contextManager = new AsyncHooksContextManager().enable(); + context.setGlobalContextManager(contextManager); + }); + + afterEach(() => { + context.disable(); + }); + + it('moduleName should be grpc', () => { + assert.deepStrictEqual(moduleName, plugin.moduleName); + }); + + describe('should patch client constructor makeClientConstructor() and makeGenericClientConstructor()', () => { + after(() => { + plugin.disable(); + }); + + it('should patch client constructor makeClientConstructor() and makeGenericClientConstructor()', () => { + plugin.enable(grpc, new NoopTracerProvider(), new NoopLogger()); + (plugin['_moduleExports'] as any).makeGenericClientConstructor({}); + assert.ok( + plugin['_moduleExports'].makeGenericClientConstructor.__wrapped + ); + }); + }); + + const requestList: TestRequestResponse[] = [{ num: 100 }, { num: 50 }]; + const resultSum = { + num: requestList.reduce((sum, x) => { + return sum + x.num; + }, 0), + }; + const methodList = [ + { + description: 'unary call', + methodName: 'UnaryMethod', + method: grpcClient.unaryMethod, + request: requestList[0], + result: requestList[0], + }, + { + description: 'Unary call', + methodName: 'UnaryMethod', + method: grpcClient.UnaryMethod, + request: requestList[0], + result: requestList[0], + }, + { + description: 'camelCase unary call', + methodName: 'camelCaseMethod', + method: grpcClient.camelCaseMethod, + request: requestList[0], + result: requestList[0], + }, + { + description: 'clientStream call', + methodName: 'ClientStreamMethod', + method: grpcClient.clientStreamMethod, + request: requestList, + result: resultSum, + }, + { + description: 'serverStream call', + methodName: 'ServerStreamMethod', + method: grpcClient.serverStreamMethod, + request: resultSum, + result: replicate(resultSum), + }, + { + description: 'bidiStream call', + methodName: 'BidiStreamMethod', + method: grpcClient.bidiStreamMethod, + request: requestList, + result: requestList, + }, + ]; + + const runTest = ( + method: typeof methodList[0], + provider: NodeTracerProvider, + checkSpans = true + ) => { + it(`should ${ + checkSpans ? 'do' : 'not' + }: create a rootSpan for client and a childSpan for server - ${ + method.description + }`, async () => { + const args = [client, method.request]; + await (method.method as any) + .apply({}, args) + .then((result: TestRequestResponse | TestRequestResponse[]) => { + assert.ok( + checkEqual(result)(method.result), + 'gRPC call returns correct values' + ); + const spans = memoryExporter.getFinishedSpans(); + if (checkSpans) { + const incomingSpan = spans[0]; + const outgoingSpan = spans[1]; + const validations = { + name: `grpc.pkg_test.GrpcTester/${method.methodName}`, + status: grpc.status.OK, + }; + + assert.strictEqual(spans.length, 2); + assertSpan( + moduleName, + incomingSpan, + SpanKind.SERVER, + validations + ); + assertSpan( + moduleName, + outgoingSpan, + SpanKind.CLIENT, + validations + ); + assertPropagation(incomingSpan, outgoingSpan); + } else { + assert.strictEqual(spans.length, 0); + } + }); + }); + + it(`should raise an error for client childSpan/server rootSpan - ${method.description} - status = OK`, () => { + const expectEmpty = memoryExporter.getFinishedSpans(); + assert.strictEqual(expectEmpty.length, 0); + + const span = provider + .getTracer('default') + .startSpan('TestSpan', { kind: SpanKind.PRODUCER }); + return provider.getTracer('default').withSpan(span, async () => { + const rootSpan = provider.getTracer('default').getCurrentSpan(); + if (!rootSpan) { + return assert.ok(false); + } + assert.deepStrictEqual(rootSpan, span); + + const args = [client, method.request]; + await (method.method as any) + .apply({}, args) + .then(() => { + // Assert + if (checkSpans) { + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 2); + const serverSpan = spans[0]; + const clientSpan = spans[1]; + const validations = { + name: `grpc.pkg_test.GrpcTester/${method.methodName}`, + status: grpc.status.OK, + }; + assertSpan( + moduleName, + serverSpan, + SpanKind.SERVER, + validations + ); + assertSpan( + moduleName, + clientSpan, + SpanKind.CLIENT, + validations + ); + assertPropagation(serverSpan, clientSpan); + assert.strictEqual( + rootSpan.context().traceId, + serverSpan.spanContext.traceId + ); + assert.strictEqual( + rootSpan.context().spanId, + clientSpan.parentSpanId + ); + } + }) + .catch((err: ServiceError) => { + assert.ok(false, err); + }); + }); + }); + }; + + const insertError = ( + request: TestRequestResponse | TestRequestResponse[] + ) => (code: number) => + request instanceof Array ? [{ num: code }, ...request] : { num: code }; + + const runErrorTest = ( + method: typeof methodList[0], + key: string, + errorCode: number, + provider: NodeTracerProvider + ) => { + it(`should raise an error for client/server rootSpans: method=${method.methodName}, status=${key}`, async () => { + const expectEmpty = memoryExporter.getFinishedSpans(); + assert.strictEqual(expectEmpty.length, 0); + + const args = [client, insertError(method.request)(errorCode)]; + + await (method.method as any) + .apply({}, args) + .then(() => { + assert.ok(false); + }) + .catch((err: ServiceError) => { + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 2, 'Expect 2 ended spans'); + + const validations = { + name: `grpc.pkg_test.GrpcTester/${method.methodName}`, + status: errorCode, + }; + const serverRoot = spans[0]; + const clientRoot = spans[1]; + assertSpan(moduleName, serverRoot, SpanKind.SERVER, validations); + assertSpan(moduleName, clientRoot, SpanKind.CLIENT, validations); + assertPropagation(serverRoot, clientRoot); + }); + }); + + it(`should raise an error for client childSpan/server rootSpan - ${method.description} - status = ${key}`, () => { + const expectEmpty = memoryExporter.getFinishedSpans(); + assert.strictEqual(expectEmpty.length, 0); + + const span = provider + .getTracer('default') + .startSpan('TestSpan', { kind: SpanKind.PRODUCER }); + return provider.getTracer('default').withSpan(span, async () => { + const rootSpan = provider.getTracer('default').getCurrentSpan(); + if (!rootSpan) { + return assert.ok(false); + } + assert.deepStrictEqual(rootSpan, span); + + const args = [client, insertError(method.request)(errorCode)]; + + await (method.method as any) + .apply({}, args) + .then(() => { + assert.ok(false); + }) + .catch((err: ServiceError) => { + // Assert + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 2); + const serverSpan = spans[0]; + const clientSpan = spans[1]; + const validations = { + name: `grpc.pkg_test.GrpcTester/${method.methodName}`, + status: errorCode, + }; + assertSpan(moduleName, serverSpan, SpanKind.SERVER, validations); + assertSpan(moduleName, clientSpan, SpanKind.CLIENT, validations); + assertPropagation(serverSpan, clientSpan); + assert.strictEqual( + rootSpan.context().traceId, + serverSpan.spanContext.traceId + ); + assert.strictEqual( + rootSpan.context().spanId, + clientSpan.parentSpanId + ); + }); + }); + }); + }; + + describe('enable()', () => { + const logger = new NoopLogger(); + const provider = new NodeTracerProvider({ logger }); + provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); + beforeEach(() => { + memoryExporter.reset(); + }); + + before(async () => { + const config = { + // TODO: add plugin options here once supported + }; + const patchedGrpc = plugin.enable(grpc, provider, logger, config); + + const packageDefinition = await protoLoader.load(PROTO_PATH, options); + const proto = patchedGrpc.loadPackageDefinition(packageDefinition) + .pkg_test; + + server = await startServer(patchedGrpc, proto); + client = createClient(patchedGrpc, proto); + }); + + after(done => { + client.close(); + server.tryShutdown(() => { + plugin.disable(); + done(); + }); + }); + + methodList.forEach(method => { + describe(`Test automatic tracing for grpc remote method ${method.description}`, () => { + runTest(method, provider); + }); + }); + + methodList.forEach(method => { + describe(`Test error raising for grpc remote ${method.description}`, () => { + Object.keys(grpc.status).forEach((statusKey: string) => { + const errorCode = Number(grpc.status[statusKey as any]); + if (errorCode > grpc.status.OK) { + runErrorTest(method, statusKey, errorCode, provider); + } + }); + }); + }); + }); + + describe('disable()', () => { + const logger = new NoopLogger(); + const provider = new NodeTracerProvider({ logger }); + provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); + beforeEach(() => { + memoryExporter.reset(); + }); + + before(async () => { + plugin.enable(grpc, provider, logger); + plugin.disable(); + + const packageDefinition = await protoLoader.load(PROTO_PATH, options); + const proto = grpc.loadPackageDefinition(packageDefinition).pkg_test; + + server = await startServer(grpc, proto); + client = createClient(grpc, proto); + }); + + after(done => { + client.close(); + server.tryShutdown(() => { + done(); + }); + }); + + methodList.map(method => { + describe(`Test automatic tracing for grpc remote method ${method.description}`, () => { + runTest(method, provider, false); + }); + }); + }); + }); +}; diff --git a/packages/opentelemetry-grpc-utils/test/index.ts b/packages/opentelemetry-grpc-utils/test/index.ts new file mode 100644 index 0000000000..169fad3841 --- /dev/null +++ b/packages/opentelemetry-grpc-utils/test/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 + * + * https://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. + */ +export * from './grpcUtils.test'; diff --git a/packages/opentelemetry-plugin-grpc/test/utils/assertionUtils.ts b/packages/opentelemetry-grpc-utils/test/utils/assertionUtils.ts similarity index 92% rename from packages/opentelemetry-plugin-grpc/test/utils/assertionUtils.ts rename to packages/opentelemetry-grpc-utils/test/utils/assertionUtils.ts index f1f0a44fa7..746f930f58 100644 --- a/packages/opentelemetry-plugin-grpc/test/utils/assertionUtils.ts +++ b/packages/opentelemetry-grpc-utils/test/utils/assertionUtils.ts @@ -16,7 +16,8 @@ import { SpanKind } from '@opentelemetry/api'; import * as assert from 'assert'; -import * as grpc from 'grpc'; +import type * as grpc from 'grpc'; +import type * as grpcJs from '@grpc/grpc-js'; import { ReadableSpan } from '@opentelemetry/tracing'; import { hrTimeToMilliseconds, @@ -24,9 +25,10 @@ import { } from '@opentelemetry/core'; export const assertSpan = ( + component: string, span: ReadableSpan, kind: SpanKind, - validations: { name: string; status: grpc.status } + validations: { name: string; status: grpc.status | grpcJs.status } ) => { assert.strictEqual(span.spanContext.traceId.length, 32); assert.strictEqual(span.spanContext.spanId.length, 16); @@ -34,7 +36,6 @@ export const assertSpan = ( assert.ok(span.endTime); assert.strictEqual(span.links.length, 0); - assert.strictEqual(span.events.length, 1); assert.ok( hrTimeToMicroseconds(span.startTime) < hrTimeToMicroseconds(span.endTime) diff --git a/packages/opentelemetry-grpc-utils/tsconfig.json b/packages/opentelemetry-grpc-utils/tsconfig.json new file mode 100644 index 0000000000..a2042cd68b --- /dev/null +++ b/packages/opentelemetry-grpc-utils/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../tsconfig.base", + "compilerOptions": { + "rootDir": ".", + "outDir": "build" + }, + "include": [ + "src/**/*.ts", + "test/**/*.ts" + ] +} diff --git a/packages/opentelemetry-plugin-grpc-js/package.json b/packages/opentelemetry-plugin-grpc-js/package.json index 07a6cc0059..5377b374f7 100644 --- a/packages/opentelemetry-plugin-grpc-js/package.json +++ b/packages/opentelemetry-plugin-grpc-js/package.json @@ -8,6 +8,7 @@ "repository": "open-telemetry/opentelemetry-js", "scripts": { "test": "nyc ts-mocha -p tsconfig.json test/**/*.test.ts", + "test:deubg": "ts-mocha --inspect-brk -p tsconfig.json test/**/*.test.ts", "tdd": "npm run test -- --watch-extensions ts --watch", "clean": "rimraf build/*", "lint": "eslint . --ext .ts", @@ -47,6 +48,7 @@ "@grpc/grpc-js": "1.1.2", "@opentelemetry/context-async-hooks": "^0.9.0", "@opentelemetry/context-base": "^0.9.0", + "@opentelemetry/grpc-utils": "^0.9.0", "@opentelemetry/node": "^0.9.0", "@opentelemetry/tracing": "^0.9.0", "@types/mocha": "8.0.0", @@ -68,6 +70,7 @@ "dependencies": { "@opentelemetry/api": "^0.9.0", "@opentelemetry/core": "^0.9.0", + "@opentelemetry/semantic-conventions": "^0.9.0", "shimmer": "1.2.1" } } diff --git a/packages/opentelemetry-plugin-grpc-js/src/client/index.ts b/packages/opentelemetry-plugin-grpc-js/src/client/index.ts new file mode 100644 index 0000000000..549cc29a6a --- /dev/null +++ b/packages/opentelemetry-plugin-grpc-js/src/client/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 + * + * https://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. + */ + +export * from './loadPackageDefinition'; +export * from './patchClient'; diff --git a/packages/opentelemetry-plugin-grpc-js/src/client/loadPackageDefinition.ts b/packages/opentelemetry-plugin-grpc-js/src/client/loadPackageDefinition.ts new file mode 100644 index 0000000000..46f0602cfa --- /dev/null +++ b/packages/opentelemetry-plugin-grpc-js/src/client/loadPackageDefinition.ts @@ -0,0 +1,69 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 + * + * https://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. + */ + +import { GrpcJsPlugin } from '../grpcJs'; +import type * as grpcJs from '@grpc/grpc-js'; +import type { PackageDefinition } from '@grpc/grpc-js/build/src/make-client'; +import * as shimmer from 'shimmer'; +import { getMethodsToWrap, getPatchedClientMethods } from './utils'; + +/** + * Entry point for client patching for grpc.loadPackageDefinition(...) + * @param this - GrpcJsPlugin + */ +export function patchLoadPackageDefinition(this: GrpcJsPlugin) { + return (original: typeof grpcJs.loadPackageDefinition) => { + const plugin = this; + + plugin._logger.debug('patching loadPackageDefinition'); + + return function patchedLoadPackageDefinition( + this: null, + packageDef: PackageDefinition + ) { + const result: grpcJs.GrpcObject = original.call( + this, + packageDef + ) as grpcJs.GrpcObject; + _patchLoadedPackage.call(plugin, result); + return result; + } as typeof grpcJs.loadPackageDefinition; + }; +} + +/** + * Utility function to patch *all* functions loaded through a proto file. + * Recursively searches for Client classes and patches all methods, reversing the + * parsing done by grpc.loadPackageDefinition + * https://github.com/grpc/grpc-node/blob/1d14203c382509c3f36132bd0244c99792cb6601/packages/grpc-js/src/make-client.ts#L200-L217 + */ +function _patchLoadedPackage( + this: GrpcJsPlugin, + result: grpcJs.GrpcObject +): void { + Object.values(result).forEach(service => { + if (typeof service === 'function') { + shimmer.massWrap( + service.prototype, + getMethodsToWrap(service, service.service), + getPatchedClientMethods.call(this) + ); + } else if (typeof service.format !== 'string') { + // GrpcObject + _patchLoadedPackage.call(this, service as grpcJs.GrpcObject); + } + }); +} diff --git a/packages/opentelemetry-plugin-grpc-js/src/client/patchClient.ts b/packages/opentelemetry-plugin-grpc-js/src/client/patchClient.ts new file mode 100644 index 0000000000..70de6e9d1d --- /dev/null +++ b/packages/opentelemetry-plugin-grpc-js/src/client/patchClient.ts @@ -0,0 +1,49 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 + * + * https://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. + */ + +import { GrpcJsPlugin } from '../grpcJs'; +import type * as grpcJs from '@grpc/grpc-js'; +import * as shimmer from 'shimmer'; +import { getMethodsToWrap, getPatchedClientMethods } from './utils'; + +type MakeClientConstructorFunction = typeof grpcJs.makeGenericClientConstructor; + +/** + * Entry point for applying client patches to `grpc.makeClientConstructor(...)` equivalents + * @param this GrpcJsPlugin + */ +export function patchClient( + this: GrpcJsPlugin +): (original: MakeClientConstructorFunction) => MakeClientConstructorFunction { + const plugin = this; + return (original: MakeClientConstructorFunction) => { + plugin._logger.debug('patching client'); + return function makeClientConstructor( + this: typeof grpcJs.Client, + methods: grpcJs.ServiceDefinition, + serviceName: string, + options?: object + ) { + const client = original.call(this, methods, serviceName, options); + shimmer.massWrap( + client.prototype, + getMethodsToWrap(client, methods), + getPatchedClientMethods.call(plugin) + ); + return client; + }; + }; +} diff --git a/packages/opentelemetry-plugin-grpc-js/src/client/utils.ts b/packages/opentelemetry-plugin-grpc-js/src/client/utils.ts new file mode 100644 index 0000000000..f1b177ccf6 --- /dev/null +++ b/packages/opentelemetry-plugin-grpc-js/src/client/utils.ts @@ -0,0 +1,244 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 + * + * https://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. + */ + +import { GrpcJsPlugin } from '../grpcJs'; +import type { GrpcClientFunc, SendUnaryDataCallback } from '../types'; +import { + SpanKind, + Span, + CanonicalCode, + Status, + propagation, +} from '@opentelemetry/api'; +import { RpcAttribute } from '@opentelemetry/semantic-conventions'; +import type * as grpcJs from '@grpc/grpc-js'; +import { + grpcStatusCodeToSpanStatus, + grpcStatusCodeToCanonicalCode, + CALL_SPAN_ENDED, +} from '../utils'; +import { EventEmitter } from 'events'; + +/** + * Parse a package method list and return a list of methods to patch + * with both possible casings e.g. "TestMethod" & "testMethod" + */ +export function getMethodsToWrap( + client: typeof grpcJs.Client, + methods: { [key: string]: { originalName?: string } } +): string[] { + const methodList: string[] = []; + + // For a method defined in .proto as "UnaryMethod" + Object.entries(methods).forEach(([name, { originalName }]) => { + methodList.push(name); // adds camel case method name: "unaryMethod" + if ( + originalName && + // eslint-disable-next-line no-prototype-builtins + client.prototype.hasOwnProperty(originalName) && + name !== originalName // do not add duplicates + ) { + // adds original method name: "UnaryMethod", + methodList.push(originalName); + } + }); + + return methodList; +} + +/** + * Parse initial client call properties and start a span to trace its execution + */ +export function getPatchedClientMethods( + this: GrpcJsPlugin +): (original: GrpcClientFunc) => () => EventEmitter { + const plugin = this; + return (original: GrpcClientFunc) => { + plugin._logger.debug('patch all client methods'); + return function clientMethodTrace(this: grpcJs.Client) { + const name = `grpc.${original.path.replace('/', '')}`; + const args = [...arguments]; + const span = plugin.tracer.startSpan(name, { + kind: SpanKind.CLIENT, + }); + return plugin.tracer.withSpan(span, () => + makeGrpcClientRemoteCall(original, args, this, plugin)(span) + ); + }; + }; +} + +/** + * Execute grpc client call. Apply completitionspan properties and end the + * span on callback or receiving an emitted event. + */ +export function makeGrpcClientRemoteCall( + original: GrpcClientFunc, + args: unknown[], + self: grpcJs.Client, + plugin: GrpcJsPlugin +): (span: Span) => EventEmitter { + /** + * Patches a callback so that the current span for this trace is also ended + * when the callback is invoked. + */ + function patchedCallback( + span: Span, + callback: SendUnaryDataCallback + ) { + const wrappedFn: SendUnaryDataCallback = ( + err: grpcJs.ServiceError | null, + res + ) => { + if (err) { + if (err.code) { + span.setStatus(grpcStatusCodeToSpanStatus(err.code)); + span.setAttribute(RpcAttribute.GRPC_STATUS_CODE, err.code.toString()); + } + span.setAttributes({ + [RpcAttribute.GRPC_ERROR_NAME]: err.name, + [RpcAttribute.GRPC_ERROR_MESSAGE]: err.message, + }); + } else { + span.setStatus({ code: CanonicalCode.OK }); + span.setAttribute( + RpcAttribute.GRPC_STATUS_CODE, + CanonicalCode.OK.toString() + ); + } + + span.end(); + callback(err, res); + }; + return plugin.tracer.bind(wrappedFn); + } + + return (span: Span) => { + const metadata = getMetadata.call(plugin, original, args); + // if unary or clientStream + if (!original.responseStream) { + const callbackFuncIndex = args.findIndex(arg => { + return typeof arg === 'function'; + }); + if (callbackFuncIndex !== -1) { + args[callbackFuncIndex] = patchedCallback( + span, + args[callbackFuncIndex] as SendUnaryDataCallback + ); + } + } + + span.setAttributes({ + [RpcAttribute.GRPC_METHOD]: original.path, + [RpcAttribute.GRPC_KIND]: SpanKind.CLIENT, + }); + + setSpanContext(metadata); + const call = original.apply(self, args); + + // if server stream or bidi + if (original.responseStream) { + // Both error and status events can be emitted + // the first one emitted set spanEnded to true + let spanEnded = false; + const endSpan = () => { + if (!spanEnded) { + span.end(); + spanEnded = true; + } + }; + plugin.tracer.bind(call); + call.on('error', (err: grpcJs.ServiceError) => { + if (call[CALL_SPAN_ENDED]) { + return; + } + call[CALL_SPAN_ENDED] = true; + + span.setStatus({ + code: grpcStatusCodeToCanonicalCode(err.code), + message: err.message, + }); + span.setAttributes({ + [RpcAttribute.GRPC_ERROR_NAME]: err.name, + [RpcAttribute.GRPC_ERROR_MESSAGE]: err.message, + }); + + endSpan(); + }); + + call.on('status', (status: Status) => { + if (call[CALL_SPAN_ENDED]) { + return; + } + call[CALL_SPAN_ENDED] = true; + + span.setStatus(grpcStatusCodeToSpanStatus(status.code)); + + endSpan(); + }); + } + return call; + }; +} + +/** + * Returns the metadata argument from user provided arguments (`args`) + */ +function getMetadata( + this: GrpcJsPlugin, + original: GrpcClientFunc, + args: Array +): grpcJs.Metadata { + let metadata: grpcJs.Metadata; + + // This finds an instance of Metadata among the arguments. + // A possible issue that could occur is if the 'options' parameter from + // the user contains an '_internal_repr' as well as a 'getMap' function, + // but this is an extremely rare case. + let metadataIndex = args.findIndex((arg: unknown | grpcJs.Metadata) => { + return ( + arg && + typeof arg === 'object' && + (arg as grpcJs.Metadata)['internalRepr'] && // changed from _internal_repr in grpc --> @grpc/grpc-js https://github.com/grpc/grpc-node/blob/95289edcaf36979cccf12797cc27335da8d01f03/packages/grpc-js/src/metadata.ts#L88 + typeof (arg as grpcJs.Metadata).getMap === 'function' + ); + }); + if (metadataIndex === -1) { + metadata = new this._moduleExports.Metadata(); + if (!original.requestStream) { + // unary or server stream + metadataIndex = 1; + } else { + // client stream or bidi + metadataIndex = 0; + } + args.splice(metadataIndex, 0, metadata); + } else { + metadata = args[metadataIndex] as grpcJs.Metadata; + } + return metadata; +} + +/** + * Inject opentelemetry trace context into `metadata` for use by another + * grpc receiver + * @param metadata + */ +export function setSpanContext(metadata: grpcJs.Metadata): void { + propagation.inject(metadata, (metadata, k, v) => + metadata.set(k, v as grpcJs.MetadataValue) + ); +} diff --git a/packages/opentelemetry-plugin-grpc-js/src/grpcJs.ts b/packages/opentelemetry-plugin-grpc-js/src/grpcJs.ts index 6a2c6e89f8..e3ec95db0c 100644 --- a/packages/opentelemetry-plugin-grpc-js/src/grpcJs.ts +++ b/packages/opentelemetry-plugin-grpc-js/src/grpcJs.ts @@ -14,11 +14,13 @@ * limitations under the License. */ +import type * as grpcJs from '@grpc/grpc-js'; import { BasePlugin } from '@opentelemetry/core'; +import * as shimmer from 'shimmer'; +import { patchClient, patchLoadPackageDefinition } from './client'; +import { patchServer } from './server'; import { VERSION } from './version'; -import * as path from 'path'; - -import * as grpcJs from '@grpc/grpc-js'; +import { Tracer, Logger } from '@opentelemetry/api'; /** * @grpc/grpc-js gRPC instrumentation plugin for Opentelemetry @@ -26,20 +28,74 @@ import * as grpcJs from '@grpc/grpc-js'; */ export class GrpcJsPlugin extends BasePlugin { static readonly component = '@grpc/grpc-js'; + readonly supportedVersions = ['1.*']; - constructor(readonly moduleName: string, readonly version: string) { + constructor(readonly moduleName: string) { super('@opentelemetry/plugin-grpc-js', VERSION); } + /** + * @internal + * Public reference to the protected BasePlugin `_tracer` instance to be used by this + * plugin's external helper functions + */ + get tracer(): Tracer { + return this._tracer; + } + + /** + * @internal + * Public reference to the protected BasePlugin `_logger` instance to be used by this + * plugin's external helper functions + */ + get logger(): Logger { + return this._logger; + } + protected patch(): typeof grpcJs { - throw new Error('Method not implemented.'); + // Patch Server methods + shimmer.wrap( + this._moduleExports.Server.prototype, + 'register', + patchServer.call(this) + ); + + // Patch Client methods + shimmer.wrap( + this._moduleExports, + 'makeClientConstructor', + patchClient.call(this) + ); + shimmer.wrap( + this._moduleExports, + 'makeGenericClientConstructor', + patchClient.call(this) + ); + shimmer.wrap( + this._moduleExports, + 'loadPackageDefinition', + patchLoadPackageDefinition.call(this) + ); + + return this._moduleExports; } + protected unpatch(): void { - throw new Error('Method not implemented.'); + this._logger.debug( + 'removing patch to %s@%s', + this.moduleName, + this.version + ); + + // Unpatch server + shimmer.unwrap(this._moduleExports.Server.prototype, 'register'); + + // Unpatch client + shimmer.unwrap(this._moduleExports, 'makeClientConstructor'); + shimmer.unwrap(this._moduleExports, 'makeGenericClientConstructor'); + shimmer.unwrap(this._moduleExports, 'loadPackageDefinition'); } } -const basedir = path.dirname(require.resolve(GrpcJsPlugin.component)); -const version = require(path.join(basedir, 'package.json')).version; -export const plugin = new GrpcJsPlugin(GrpcJsPlugin.component, version); +export const plugin = new GrpcJsPlugin(GrpcJsPlugin.component); diff --git a/packages/opentelemetry-plugin-grpc-js/src/server/clientStreamAndUnary.ts b/packages/opentelemetry-plugin-grpc-js/src/server/clientStreamAndUnary.ts new file mode 100644 index 0000000000..d839813427 --- /dev/null +++ b/packages/opentelemetry-plugin-grpc-js/src/server/clientStreamAndUnary.ts @@ -0,0 +1,66 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 + * + * https://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. + */ + +import { Span, CanonicalCode } from '@opentelemetry/api'; +import type { ServerCallWithMeta, SendUnaryDataCallback } from '../types'; +import { grpcStatusCodeToCanonicalCode } from '../utils'; +import { RpcAttribute } from '@opentelemetry/semantic-conventions'; +import type { GrpcJsPlugin } from '../grpcJs'; +import type * as grpcJs from '@grpc/grpc-js'; + +/** + * Handle patching for clientStream and unary type server handlers + */ +export function clientStreamAndUnaryHandler( + plugin: GrpcJsPlugin, + span: Span, + call: ServerCallWithMeta, + callback: SendUnaryDataCallback, + original: + | grpcJs.handleUnaryCall + | grpcJs.ClientReadableStream +): void { + const patchedCallback: SendUnaryDataCallback = ( + err: grpcJs.ServiceError | null, + value?: ResponseType + ) => { + if (err) { + if (err.code) { + span.setStatus({ + code: grpcStatusCodeToCanonicalCode(err.code), + message: err.message, + }); + span.setAttribute(RpcAttribute.GRPC_STATUS_CODE, err.code.toString()); + } + span.setAttributes({ + [RpcAttribute.GRPC_ERROR_NAME]: err.name, + [RpcAttribute.GRPC_ERROR_MESSAGE]: err.message, + }); + } else { + span.setStatus({ code: CanonicalCode.OK }); + span.setAttribute( + RpcAttribute.GRPC_STATUS_CODE, + CanonicalCode.OK.toString() + ); + } + + span.end(); + return callback(err, value); + }; + + plugin.tracer.bind(call); + return (original as Function).call({}, call, patchedCallback); +} diff --git a/packages/opentelemetry-plugin-grpc-js/src/server/index.ts b/packages/opentelemetry-plugin-grpc-js/src/server/index.ts new file mode 100644 index 0000000000..99bb1743c1 --- /dev/null +++ b/packages/opentelemetry-plugin-grpc-js/src/server/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 + * + * https://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. + */ + +export * from './patchServer'; diff --git a/packages/opentelemetry-plugin-grpc-js/src/server/patchServer.ts b/packages/opentelemetry-plugin-grpc-js/src/server/patchServer.ts new file mode 100644 index 0000000000..f75dd294a5 --- /dev/null +++ b/packages/opentelemetry-plugin-grpc-js/src/server/patchServer.ts @@ -0,0 +1,154 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 + * + * https://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. + */ + +import type * as grpcJs from '@grpc/grpc-js'; +import type { HandleCall } from '@grpc/grpc-js/build/src/server-call'; +import { GrpcJsPlugin } from '../grpcJs'; +import * as shimmer from 'shimmer'; +import { ServerCallWithMeta, SendUnaryDataCallback } from '../types'; +import { + context, + SpanOptions, + SpanKind, + propagation, + Span, +} from '@opentelemetry/api'; +import { RpcAttribute } from '@opentelemetry/semantic-conventions'; +import { clientStreamAndUnaryHandler } from './clientStreamAndUnary'; +import { serverStreamAndBidiHandler } from './serverStreamAndBidi'; + +type ServerRegisterFunction = typeof grpcJs.Server.prototype.register; + +/** + * Patch for grpc.Server.prototype.register(...) function. Provides auto-instrumentation for + * client_stream, server_stream, bidi, unary server handler calls. + */ +export function patchServer( + this: GrpcJsPlugin +): (originalRegister: ServerRegisterFunction) => ServerRegisterFunction { + return (originalRegister: ServerRegisterFunction) => { + const plugin = this; + + plugin.logger.debug('patched gRPC server'); + return function register( + this: grpcJs.Server, + name: string, + handler: HandleCall, + serialize: grpcJs.serialize, + deserialize: grpcJs.deserialize, + type: string + ): boolean { + const originalRegisterResult = originalRegister.call( + this, + name, + handler, + serialize, + deserialize, + type + ); + const handlerSet = this['handlers'].get(name); + + shimmer.wrap( + handlerSet, + 'func', + (originalFunc: HandleCall) => { + return function func( + this: typeof handlerSet, + call: ServerCallWithMeta, + callback: SendUnaryDataCallback + ) { + const self = this; + + const spanName = `grpc.${name.replace('/', '')}`; + const spanOptions: SpanOptions = { + kind: SpanKind.SERVER, + }; + + plugin.logger.debug('patch func: %s', JSON.stringify(spanOptions)); + + context.with( + propagation.extract(call.metadata, (carrier, key) => + carrier.get(key) + ), + () => { + const span = plugin.tracer + .startSpan(spanName, spanOptions) + .setAttributes({ + [RpcAttribute.GRPC_KIND]: spanOptions.kind, + }); + + plugin.tracer.withSpan(span, () => { + handleServerFunction.call( + self, + plugin, + span, + type, + originalFunc, + call, + callback + ); + }); + } + ); + }; + } + ); + return originalRegisterResult; + } as typeof grpcJs.Server.prototype.register; + }; +} + +/** + * Patch callback or EventEmitter provided by `originalFunc` and set appropriate `span` + * properties based on its result. + */ +function handleServerFunction( + this: unknown, + plugin: GrpcJsPlugin, + span: Span, + type: string, + originalFunc: HandleCall, + call: ServerCallWithMeta, + callback: SendUnaryDataCallback +): void { + switch (type) { + case 'unary': + case 'clientStream': + case 'client_stream': + return clientStreamAndUnaryHandler( + plugin, + span, + call, + callback, + originalFunc as + | grpcJs.handleUnaryCall + | grpcJs.ClientReadableStream + ); + case 'serverStream': + case 'server_stream': + case 'bidi': + return serverStreamAndBidiHandler( + plugin, + span, + call, + originalFunc as + | grpcJs.handleBidiStreamingCall + | grpcJs.handleServerStreamingCall + ); + default: + break; + } +} diff --git a/packages/opentelemetry-plugin-grpc-js/src/server/serverStreamAndBidi.ts b/packages/opentelemetry-plugin-grpc-js/src/server/serverStreamAndBidi.ts new file mode 100644 index 0000000000..1fe8a14a44 --- /dev/null +++ b/packages/opentelemetry-plugin-grpc-js/src/server/serverStreamAndBidi.ts @@ -0,0 +1,86 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 + * + * https://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. + */ + +import { Span, CanonicalCode } from '@opentelemetry/api'; +import { RpcAttribute } from '@opentelemetry/semantic-conventions'; +import type * as grpcJs from '@grpc/grpc-js'; +import type { GrpcJsPlugin } from '../grpcJs'; +import { GrpcEmitter } from '../types'; +import { CALL_SPAN_ENDED, grpcStatusCodeToCanonicalCode } from '../utils'; + +/** + * Handle patching for serverStream and Bidi type server handlers + */ +export function serverStreamAndBidiHandler( + plugin: GrpcJsPlugin, + span: Span, + call: GrpcEmitter, + original: + | grpcJs.handleBidiStreamingCall + | grpcJs.handleServerStreamingCall +): void { + let spanEnded = false; + const endSpan = () => { + if (!spanEnded) { + spanEnded = true; + span.end(); + } + }; + + plugin.tracer.bind(call); + call.on('finish', () => { + // @grpc/js does not expose a way to check if this call also emitted an error, + // e.g. call.status.code !== 0 + if (call[CALL_SPAN_ENDED]) { + return; + } + + // Set the "grpc call had an error" flag + call[CALL_SPAN_ENDED] = true; + + span.setStatus({ + code: CanonicalCode.OK, + }); + span.setAttribute( + RpcAttribute.GRPC_STATUS_CODE, + CanonicalCode.OK.toString() + ); + + endSpan(); + }); + + call.on('error', (err: grpcJs.ServiceError) => { + if (call[CALL_SPAN_ENDED]) { + return; + } + + // Set the "grpc call had an error" flag + call[CALL_SPAN_ENDED] = true; + + span.setStatus({ + code: grpcStatusCodeToCanonicalCode(err.code), + message: err.message, + }); + span.setAttributes({ + [RpcAttribute.GRPC_ERROR_NAME]: err.name, + [RpcAttribute.GRPC_ERROR_MESSAGE]: err.message, + }); + endSpan(); + }); + + // Types of parameters 'call' and 'call' are incompatible. + return (original as Function).call({}, call); +} diff --git a/packages/opentelemetry-plugin-grpc-js/src/types.ts b/packages/opentelemetry-plugin-grpc-js/src/types.ts new file mode 100644 index 0000000000..a41dbf48d3 --- /dev/null +++ b/packages/opentelemetry-plugin-grpc-js/src/types.ts @@ -0,0 +1,54 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 + * + * https://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. + */ + +import type * as grpcJs from '@grpc/grpc-js'; +import type { EventEmitter } from 'events'; +import type { CALL_SPAN_ENDED } from './utils'; + +/** + * Server Unary callback type + */ +export type SendUnaryDataCallback = grpcJs.requestCallback; + +/** + * Intersection type of all grpc server call types + */ +export type ServerCall = + | grpcJs.ServerUnaryCall + | grpcJs.ServerReadableStream + | grpcJs.ServerWritableStream + | grpcJs.ServerDuplexStream; + +/** + * {@link ServerCall} ServerCall extended with misc. missing utility types + */ +export type ServerCallWithMeta = ServerCall & { + metadata: grpcJs.Metadata; +}; + +/** + * EventEmitter with span ended symbol indicator + */ +export type GrpcEmitter = EventEmitter & { [CALL_SPAN_ENDED]?: boolean }; + +/** + * Grpc client callback function extended with missing utility types + */ +export type GrpcClientFunc = ((...args: unknown[]) => GrpcEmitter) & { + path: string; + requestStream: boolean; + responseStream: boolean; +}; diff --git a/packages/opentelemetry-plugin-grpc-js/src/utils.ts b/packages/opentelemetry-plugin-grpc-js/src/utils.ts new file mode 100644 index 0000000000..fcae256442 --- /dev/null +++ b/packages/opentelemetry-plugin-grpc-js/src/utils.ts @@ -0,0 +1,46 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 + * + * https://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. + */ + +import { CanonicalCode, Status } from '@opentelemetry/api'; +import type * as grpcTypes from '@grpc/grpc-js'; // For types only + +/** + * Symbol to include on grpc call if it has already emitted an error event. + * grpc events that emit 'error' will also emit 'finish' and so only the + * error event should be processed. + */ +export const CALL_SPAN_ENDED = Symbol('opentelemetry call span ended'); + +/** + * Convert a grpc status code to an opentelemetry Canonical code. For now, the enums are exactly the same + * @param status + */ +export const grpcStatusCodeToCanonicalCode = ( + status?: grpcTypes.status +): CanonicalCode => { + if (status !== 0 && !status) { + return CanonicalCode.UNKNOWN; + } + return status as number; +}; + +/** + * Convert grpc status code to an opentelemetry Status object. + * @param status + */ +export const grpcStatusCodeToSpanStatus = (status: number): Status => { + return { code: status }; +}; diff --git a/packages/opentelemetry-plugin-grpc-js/test/grpcJs.test.ts b/packages/opentelemetry-plugin-grpc-js/test/grpcJs.test.ts new file mode 100644 index 0000000000..7faf3e8b88 --- /dev/null +++ b/packages/opentelemetry-plugin-grpc-js/test/grpcJs.test.ts @@ -0,0 +1,23 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 + * + * https://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. + */ + +import { runTests } from '@opentelemetry/grpc-utils/test'; +import { plugin, GrpcJsPlugin } from '../src/grpcJs'; +import * as grpc from '@grpc/grpc-js'; + +describe(`#${GrpcJsPlugin.component}`, () => { + runTests(plugin, GrpcJsPlugin.component, grpc, 12346); +}); diff --git a/packages/opentelemetry-plugin-grpc/package.json b/packages/opentelemetry-plugin-grpc/package.json index a01f7c0b2c..f75165e7a4 100644 --- a/packages/opentelemetry-plugin-grpc/package.json +++ b/packages/opentelemetry-plugin-grpc/package.json @@ -44,6 +44,7 @@ "devDependencies": { "@opentelemetry/context-async-hooks": "^0.9.0", "@opentelemetry/context-base": "^0.9.0", + "@opentelemetry/grpc-utils": "^0.9.0", "@opentelemetry/node": "^0.9.0", "@opentelemetry/tracing": "^0.9.0", "@types/mocha": "8.0.0", diff --git a/packages/opentelemetry-plugin-grpc/test/grpc.test.ts b/packages/opentelemetry-plugin-grpc/test/grpc.test.ts index e5f0300d72..a4ff260c2a 100644 --- a/packages/opentelemetry-plugin-grpc/test/grpc.test.ts +++ b/packages/opentelemetry-plugin-grpc/test/grpc.test.ts @@ -14,656 +14,10 @@ * limitations under the License. */ -import { - context, - NoopTracerProvider, - SpanKind, - propagation, -} from '@opentelemetry/api'; -import { NoopLogger, HttpTraceContext } from '@opentelemetry/core'; -import { NodeTracerProvider } from '@opentelemetry/node'; -import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks'; -import { ContextManager } from '@opentelemetry/context-base'; -import { - InMemorySpanExporter, - SimpleSpanProcessor, -} from '@opentelemetry/tracing'; -import * as assert from 'assert'; +import { runTests } from '@opentelemetry/grpc-utils/test'; +import { plugin, GrpcPlugin } from '../src/grpc'; import * as grpc from 'grpc'; -import * as semver from 'semver'; -import * as sinon from 'sinon'; -import { GrpcPlugin, plugin } from '../src'; -import { SendUnaryDataCallback } from '../src/types'; -import { assertPropagation, assertSpan } from './utils/assertionUtils'; -const PROTO_PATH = __dirname + '/fixtures/grpc-test.proto'; -const memoryExporter = new InMemorySpanExporter(); - -type GrpcModule = typeof grpc; -const MAX_ERROR_STATUS = grpc.status.UNAUTHENTICATED; - -interface TestRequestResponse { - num: number; -} - -type TestGrpcClient = grpc.Client & { - unaryMethod: any; - UnaryMethod: any; - camelCaseMethod: any; - clientStreamMethod: any; - serverStreamMethod: any; - bidiStreamMethod: any; -}; - -// Compare two arrays using an equal function f -const arrayIsEqual = (f: any) => ([x, ...xs]: any) => ([y, ...ys]: any): any => - x === undefined && y === undefined - ? true - : Boolean(f(x)(y)) && arrayIsEqual(f)(xs)(ys); - -// Return true if two requests has the same num value -const requestEqual = (x: TestRequestResponse) => (y: TestRequestResponse) => - x.num !== undefined && x.num === y.num; - -// Check if its equal requests or array of requests -const checkEqual = (x: TestRequestResponse | TestRequestResponse[]) => ( - y: TestRequestResponse | TestRequestResponse[] -) => - x instanceof Array && y instanceof Array - ? arrayIsEqual(requestEqual)(x as any)(y as any) - : !(x instanceof Array) && !(y instanceof Array) - ? requestEqual(x)(y) - : false; - -const grpcClient = { - unaryMethod: ( - client: TestGrpcClient, - request: TestRequestResponse - ): Promise => { - return new Promise((resolve, reject) => { - return client.unaryMethod( - request, - (err: grpc.ServiceError, response: TestRequestResponse) => { - if (err) { - reject(err); - } else { - resolve(response); - } - } - ); - }); - }, - - camelCaseMethod: ( - client: TestGrpcClient, - request: TestRequestResponse - ): Promise => { - return new Promise((resolve, reject) => { - return client.camelCaseMethod( - request, - (err: grpc.ServiceError, response: TestRequestResponse) => { - if (err) { - reject(err); - } else { - resolve(response); - } - } - ); - }); - }, - - UnaryMethod: ( - client: TestGrpcClient, - request: TestRequestResponse - ): Promise => { - return new Promise((resolve, reject) => { - return client.UnaryMethod( - request, - (err: grpc.ServiceError, response: TestRequestResponse) => { - if (err) { - reject(err); - } else { - resolve(response); - } - } - ); - }); - }, - - clientStreamMethod: ( - client: TestGrpcClient, - request: TestRequestResponse[] - ): Promise => { - return new Promise((resolve, reject) => { - const writeStream = client.clientStreamMethod( - (err: grpc.ServiceError, response: TestRequestResponse) => { - if (err) { - reject(err); - } else { - resolve(response); - } - } - ); - - request.forEach(element => { - writeStream.write(element); - }); - writeStream.end(); - }); - }, - - serverStreamMethod: ( - client: TestGrpcClient, - request: TestRequestResponse - ): Promise => { - return new Promise((resolve, reject) => { - const result: TestRequestResponse[] = []; - const readStream = client.serverStreamMethod(request); - - readStream.on('data', (data: TestRequestResponse) => { - result.push(data); - }); - readStream.on('error', (err: grpc.ServiceError) => { - reject(err); - }); - readStream.on('end', () => { - resolve(result); - }); - }); - }, - - bidiStreamMethod: ( - client: TestGrpcClient, - request: TestRequestResponse[] - ): Promise => { - return new Promise((resolve, reject) => { - const result: TestRequestResponse[] = []; - const bidiStream = client.bidiStreamMethod([]); - - bidiStream.on('data', (data: TestRequestResponse) => { - result.push(data); - }); - - request.forEach(element => { - bidiStream.write(element); - }); - - bidiStream.on('error', (err: grpc.ServiceError) => { - reject(err); - }); - - bidiStream.on('end', () => { - resolve(result); - }); - - bidiStream.end(); - }); - }, -}; - -let server: grpc.Server; -let client: grpc.Client; -const grpcPort = 12345; - -const replicate = (request: TestRequestResponse) => { - const result: TestRequestResponse[] = []; - for (let i = 0; i < request.num; i++) { - result.push(request); - } - return result; -}; - -function startServer(grpc: GrpcModule, proto: any) { - const server = new grpc.Server(); - - function getError(msg: string, code: number): grpc.ServiceError { - const err: grpc.ServiceError = new Error(msg); - err.name = msg; - err.message = msg; - err.code = code; - return err; - } - - server.addService(proto.GrpcTester.service, { - // An error is emitted every time - // request.num <= MAX_ERROR_STATUS = (status.UNAUTHENTICATED) - // in those cases, erro.code = request.num - - // This method returns the request - unaryMethod( - call: grpc.ServerUnaryCall, - callback: SendUnaryDataCallback - ) { - call.request.num <= MAX_ERROR_STATUS - ? callback(getError('Unary Method Error', call.request.num)) - : callback(null, { num: call.request.num }); - }, - - // This method returns the request - camelCaseMethod( - call: grpc.ServerUnaryCall, - callback: SendUnaryDataCallback - ) { - call.request.num <= MAX_ERROR_STATUS - ? callback(getError('Unary Method Error', call.request.num)) - : callback(null, { num: call.request.num }); - }, - - // This method sum the requests - clientStreamMethod( - call: grpc.ServerReadableStream, - callback: SendUnaryDataCallback - ) { - let sum = 0; - let hasError = false; - let code = grpc.status.OK; - call.on('data', (data: TestRequestResponse) => { - sum += data.num; - if (data.num <= MAX_ERROR_STATUS) { - hasError = true; - code = data.num; - } - }); - call.on('end', () => { - hasError - ? callback(getError('Client Stream Method Error', code)) - : callback(null, { num: sum }); - }); - }, - - // This method returns an array that replicates the request, request.num of - // times - serverStreamMethod: (call: grpc.ServerWriteableStream) => { - const result = replicate(call.request); - - if (call.request.num <= MAX_ERROR_STATUS) { - call.emit( - 'error', - getError('Server Stream Method Error', call.request.num) - ); - } else { - result.forEach(element => { - call.write(element); - }); - } - call.end(); - }, - - // This method returns the request - bidiStreamMethod: (call: grpc.ServerDuplexStream) => { - call.on('data', (data: TestRequestResponse) => { - if (data.num <= MAX_ERROR_STATUS) { - call.emit('error', getError('Server Stream Method Error', data.num)); - } else { - call.write(data); - } - }); - call.on('end', () => { - call.end(); - }); - }, - }); - server.bind('localhost:' + grpcPort, grpc.ServerCredentials.createInsecure()); - server.start(); - return server; -} - -function createClient(grpc: GrpcModule, proto: any) { - return new proto.GrpcTester( - 'localhost:' + grpcPort, - grpc.credentials.createInsecure() - ); -} - -describe('GrpcPlugin', () => { - let contextManager: ContextManager; - - before(() => { - propagation.setGlobalPropagator(new HttpTraceContext()); - }); - - beforeEach(() => { - contextManager = new AsyncHooksContextManager().enable(); - context.setGlobalContextManager(contextManager); - }); - - afterEach(() => { - context.disable(); - }); - - it('should return a plugin', () => { - assert.ok(plugin instanceof GrpcPlugin); - }); - - it('should match version', () => { - assert.ok(semver.satisfies(plugin.version, '^1.23.3')); - }); - - it('moduleName should be grpc', () => { - assert.deepStrictEqual('grpc', plugin.moduleName); - }); - - describe('should patch client constructor makeClientConstructor() and makeGenericClientConstructor()', () => { - const clientPatchStub = sinon.stub( - plugin, - '_getPatchedClientMethods' as never - ); - after(() => { - clientPatchStub.restore(); - plugin.disable(); - }); - - it('should patch client constructor makeClientConstructor() and makeGenericClientConstructor()', () => { - plugin.enable(grpc, new NoopTracerProvider(), new NoopLogger()); - (plugin['_moduleExports'] as any).makeGenericClientConstructor({}); - assert.strictEqual(clientPatchStub.callCount, 1); - }); - }); - - const requestList: TestRequestResponse[] = [{ num: 100 }, { num: 50 }]; - const resultSum = { - num: requestList.reduce((sum, x) => { - return sum + x.num; - }, 0), - }; - const methodList = [ - { - description: 'unary call', - methodName: 'UnaryMethod', - method: grpcClient.unaryMethod, - request: requestList[0], - result: requestList[0], - }, - { - description: 'camelCase unary call', - methodName: 'camelCaseMethod', - method: grpcClient.camelCaseMethod, - request: requestList[0], - result: requestList[0], - }, - { - description: 'Unary call', - methodName: 'UnaryMethod', - method: grpcClient.UnaryMethod, - request: requestList[0], - result: requestList[0], - }, - { - description: 'clientStream call', - methodName: 'ClientStreamMethod', - method: grpcClient.clientStreamMethod, - request: requestList, - result: resultSum, - }, - { - description: 'serverStream call', - methodName: 'ServerStreamMethod', - method: grpcClient.serverStreamMethod, - request: resultSum, - result: replicate(resultSum), - }, - { - description: 'bidiStream call', - methodName: 'BidiStreamMethod', - method: grpcClient.bidiStreamMethod, - request: requestList, - result: requestList, - }, - ]; - - const runTest = ( - method: typeof methodList[0], - provider: NodeTracerProvider, - checkSpans = true - ) => { - it(`should ${ - checkSpans ? 'do' : 'not' - }: create a rootSpan for client and a childSpan for server - ${ - method.description - }`, async () => { - const args = [client, method.request]; - await (method.method as any) - .apply({}, args) - .then((result: TestRequestResponse | TestRequestResponse[]) => { - assert.ok( - checkEqual(result)(method.result), - 'gRPC call returns correct values' - ); - const spans = memoryExporter.getFinishedSpans(); - if (checkSpans) { - const incomingSpan = spans[0]; - const outgoingSpan = spans[1]; - const validations = { - name: `grpc.pkg_test.GrpcTester/${method.methodName}`, - status: grpc.status.OK, - }; - - assert.strictEqual(spans.length, 2); - assertSpan(incomingSpan, SpanKind.SERVER, validations); - assertSpan(outgoingSpan, SpanKind.CLIENT, validations); - assertPropagation(incomingSpan, outgoingSpan); - } else { - assert.strictEqual(spans.length, 0); - } - }); - }); - - it(`should raise an error for client childSpan/server rootSpan - ${method.description} - status = OK`, () => { - const expectEmpty = memoryExporter.getFinishedSpans(); - assert.strictEqual(expectEmpty.length, 0); - - const span = provider - .getTracer('default') - .startSpan('TestSpan', { kind: SpanKind.PRODUCER }); - return provider.getTracer('default').withSpan(span, async () => { - const rootSpan = provider.getTracer('default').getCurrentSpan(); - if (!rootSpan) { - return assert.ok(false); - } - assert.deepStrictEqual(rootSpan, span); - - const args = [client, method.request]; - await (method.method as any) - .apply({}, args) - .then(() => { - // Assert - if (checkSpans) { - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 2); - const serverSpan = spans[0]; - const clientSpan = spans[1]; - const validations = { - name: `grpc.pkg_test.GrpcTester/${method.methodName}`, - status: grpc.status.OK, - }; - assertSpan(serverSpan, SpanKind.SERVER, validations); - assertSpan(clientSpan, SpanKind.CLIENT, validations); - assertPropagation(serverSpan, clientSpan); - assert.strictEqual( - rootSpan.context().traceId, - serverSpan.spanContext.traceId - ); - assert.strictEqual( - rootSpan.context().spanId, - clientSpan.parentSpanId - ); - } - }) - .catch((err: grpc.ServiceError) => { - assert.ok(false, err); - }); - }); - }); - }; - - const insertError = ( - request: TestRequestResponse | TestRequestResponse[] - ) => (code: number) => - request instanceof Array - ? request.splice(0, 0, { num: code }) && request.slice(0, request.length) - : { num: code }; - - const runErrorTest = ( - method: typeof methodList[0], - key: string, - errorCode: number, - provider: NodeTracerProvider - ) => { - it(`should raise an error for client/server rootSpans: method=${method.methodName}, status=${key}`, async () => { - const expectEmpty = memoryExporter.getFinishedSpans(); - assert.strictEqual(expectEmpty.length, 0); - - const errRequest = - method.request instanceof Array - ? method.request.slice(0, method.request.length) - : method.request; - const args = [client, insertError(errRequest)(errorCode)]; - - await (method.method as any) - .apply({}, args) - .then(() => { - assert.ok(false); - }) - .catch((err: grpc.ServiceError) => { - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 2, 'Expect 2 ended spans'); - - const validations = { - name: `grpc.pkg_test.GrpcTester/${method.methodName}`, - status: errorCode, - }; - const serverRoot = spans[0]; - const clientRoot = spans[1]; - assertSpan(serverRoot, SpanKind.SERVER, validations); - assertSpan(clientRoot, SpanKind.CLIENT, validations); - assertPropagation(serverRoot, clientRoot); - }); - }); - - it(`should raise an error for client childSpan/server rootSpan - ${method.description} - status = ${key}`, () => { - const expectEmpty = memoryExporter.getFinishedSpans(); - assert.strictEqual(expectEmpty.length, 0); - - const span = provider - .getTracer('default') - .startSpan('TestSpan', { kind: SpanKind.PRODUCER }); - return provider.getTracer('default').withSpan(span, async () => { - const rootSpan = provider.getTracer('default').getCurrentSpan(); - if (!rootSpan) { - return assert.ok(false); - } - assert.deepStrictEqual(rootSpan, span); - - const errRequest = - method.request instanceof Array - ? method.request.slice(0, method.request.length) - : method.request; - const args = [client, insertError(errRequest)(errorCode)]; - - await (method.method as any) - .apply({}, args) - .then(() => { - assert.ok(false); - }) - .catch((err: grpc.ServiceError) => { - // Assert - const spans = memoryExporter.getFinishedSpans(); - assert.strictEqual(spans.length, 2); - const serverSpan = spans[0]; - const clientSpan = spans[1]; - const validations = { - name: `grpc.pkg_test.GrpcTester/${method.methodName}`, - status: errorCode, - }; - assertSpan(serverSpan, SpanKind.SERVER, validations); - assertSpan(clientSpan, SpanKind.CLIENT, validations); - assertPropagation(serverSpan, clientSpan); - assert.strictEqual( - rootSpan.context().traceId, - serverSpan.spanContext.traceId - ); - assert.strictEqual( - rootSpan.context().spanId, - clientSpan.parentSpanId - ); - }); - }); - }); - }; - - describe('enable()', () => { - const logger = new NoopLogger(); - const provider = new NodeTracerProvider({ logger }); - provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); - beforeEach(() => { - memoryExporter.reset(); - }); - - before(() => { - const config = { - // TODO: add plugin options here once supported - }; - plugin.enable(grpc, provider, logger, config); - - const proto = grpc.load(PROTO_PATH).pkg_test; - server = startServer(grpc, proto); - client = createClient(grpc, proto); - }); - - after(done => { - client.close(); - server.tryShutdown(() => { - plugin.disable(); - done(); - }); - }); - - methodList.forEach(method => { - describe(`Test automatic tracing for grpc remote method ${method.description}`, () => { - runTest(method, provider); - }); - }); - - methodList.forEach(method => { - describe(`Test error raising for grpc remote ${method.description}`, () => { - Object.keys(grpc.status).forEach((statusKey: string) => { - const errorCode = Number(grpc.status[statusKey as any]); - if (errorCode > grpc.status.OK) { - runErrorTest(method, statusKey, errorCode, provider); - } - }); - }); - }); - }); - - describe('disable()', () => { - const logger = new NoopLogger(); - const provider = new NodeTracerProvider({ logger }); - provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); - beforeEach(() => { - memoryExporter.reset(); - }); - - before(() => { - plugin.enable(grpc, provider, logger); - plugin.disable(); - - const proto = grpc.load(PROTO_PATH).pkg_test; - server = startServer(grpc, proto); - client = createClient(grpc, proto); - }); - - after(done => { - client.close(); - server.tryShutdown(() => { - done(); - }); - }); - - methodList.map(method => { - describe(`Test automatic tracing for grpc remote method ${method.description}`, () => { - runTest(method, provider, false); - }); - }); - }); +describe(`#${GrpcPlugin.component}`, () => { + runTests(plugin, GrpcPlugin.component, grpc, 12345); }); From ca84624cd1c5315b48633d096734e7a728fa455f Mon Sep 17 00:00:00 2001 From: Bartlomiej Obecny Date: Wed, 22 Jul 2020 16:54:35 +0200 Subject: [PATCH 13/19] chore: fixes for tests --- .../README.md | 6 +- .../browser/CollectorTraceExporter.test.ts | 2 +- .../test/common/transform.test.ts | 20 +- .../test/helper.ts | 263 ++++++++++++------ .../test/node/CollectorMetricExporter.test.ts | 2 +- .../CollectorMetricExporterWithJson.test.ts | 4 +- .../test/node/CollectorTraceExporter.test.ts | 4 +- .../CollectorTraceExporterWithJson.test.ts | 2 +- ...> CollectorTraceExporterWithProto.test.ts} | 2 +- 9 files changed, 194 insertions(+), 111 deletions(-) rename packages/opentelemetry-exporter-collector/test/node/{CollectorExporterWithProto.test.ts => CollectorTraceExporterWithProto.test.ts} (99%) diff --git a/packages/opentelemetry-exporter-collector/README.md b/packages/opentelemetry-exporter-collector/README.md index 89431bdbaf..c11e49d608 100644 --- a/packages/opentelemetry-exporter-collector/README.md +++ b/packages/opentelemetry-exporter-collector/README.md @@ -24,7 +24,7 @@ import { WebTracerProvider } from '@opentelemetry/web'; import { CollectorTraceExporter } from '@opentelemetry/exporter-collector'; const collectorOptions = { - url: '', // url is optional and can be omitted - default is http://localhost:55680/v1/trace + url: '', // url is optional and can be omitted - default is http://localhost:55681/v1/trace headers: {}, //an optional object containing custom headers to be sent with each request }; @@ -118,7 +118,7 @@ const { CollectorExporter, CollectorTransportNode } = require('@opentelemetry/e const collectorOptions = { protocolNode: CollectorTransportNode.HTTP_JSON, serviceName: 'basic-service', - url: '', // url is optional and can be omitted - default is http://localhost:55680/v1/trace + url: '', // url is optional and can be omitted - default is http://localhost:55681/v1/trace headers: { foo: 'bar' }, //an optional object containing custom headers to be sent with each request will only work with json over http @@ -141,7 +141,7 @@ const { CollectorExporter, CollectorTransportNode } = require('@opentelemetry/e const collectorOptions = { protocolNode: CollectorTransportNode.HTTP_PROTO, serviceName: 'basic-service', - url: '', // url is optional and can be omitted - default is http://localhost:55680/v1/trace + url: '', // url is optional and can be omitted - default is http://localhost:55681/v1/trace headers: { foo: 'bar' }, //an optional object containing custom headers to be sent with each request will only work with json over http diff --git a/packages/opentelemetry-exporter-collector/test/browser/CollectorTraceExporter.test.ts b/packages/opentelemetry-exporter-collector/test/browser/CollectorTraceExporter.test.ts index 4893ddcb98..bfb916b333 100644 --- a/packages/opentelemetry-exporter-collector/test/browser/CollectorTraceExporter.test.ts +++ b/packages/opentelemetry-exporter-collector/test/browser/CollectorTraceExporter.test.ts @@ -333,7 +333,7 @@ describe('CollectorTraceExporter - browser (getDefaultUrl)', () => { setTimeout(() => { assert.strictEqual( collectorExporter['url'], - 'http://localhost:55680/v1/trace' + 'http://localhost:55681/v1/trace' ); done(); }); diff --git a/packages/opentelemetry-exporter-collector/test/common/transform.test.ts b/packages/opentelemetry-exporter-collector/test/common/transform.test.ts index 2251d80a3f..a07bd4ec47 100644 --- a/packages/opentelemetry-exporter-collector/test/common/transform.test.ts +++ b/packages/opentelemetry-exporter-collector/test/common/transform.test.ts @@ -33,7 +33,7 @@ describe('transform', () => { foo: 'bar', }; assert.deepStrictEqual(transform.toCollectorAttributes(attributes), [ - { key: 'foo', type: 0, stringValue: 'bar' }, + { key: 'foo', value: { stringValue: 'bar' } }, ]); }); @@ -42,7 +42,7 @@ describe('transform', () => { foo: 13, }; assert.deepStrictEqual(transform.toCollectorAttributes(attributes), [ - { key: 'foo', type: 2, doubleValue: 13 }, + { key: 'foo', value: { doubleValue: 13 } }, ]); }); @@ -51,7 +51,7 @@ describe('transform', () => { foo: true, }; assert.deepStrictEqual(transform.toCollectorAttributes(attributes), [ - { key: 'foo', type: 3, boolValue: true }, + { key: 'foo', value: { boolValue: true } }, ]); }); @@ -60,7 +60,7 @@ describe('transform', () => { foo: 1.34, }; assert.deepStrictEqual(transform.toCollectorAttributes(attributes), [ - { key: 'foo', type: 2, doubleValue: 1.34 }, + { key: 'foo', value: { doubleValue: 1.34 } }, ]); }); }); @@ -79,13 +79,13 @@ describe('transform', () => { { timeUnixNano: 123000000123, name: 'foo', - attributes: [{ key: 'a', type: 0, stringValue: 'b' }], + attributes: [{ key: 'a', value: { stringValue: 'b' } }], droppedAttributesCount: 0, }, { timeUnixNano: 321000000321, name: 'foo2', - attributes: [{ key: 'c', type: 0, stringValue: 'd' }], + attributes: [{ key: 'c', value: { stringValue: 'd' } }], droppedAttributesCount: 0, }, ]); @@ -111,15 +111,13 @@ describe('transform', () => { attributes: [ { key: 'service', - type: 0, - stringValue: 'ui', + value: { stringValue: 'ui' }, }, { key: 'version', - type: 2, - doubleValue: 1, + value: { doubleValue: 1 }, }, - { key: 'success', type: 3, boolValue: true }, + { key: 'success', value: { boolValue: true } }, ], droppedAttributesCount: 0, }); diff --git a/packages/opentelemetry-exporter-collector/test/helper.ts b/packages/opentelemetry-exporter-collector/test/helper.ts index cb0506ad25..58d70d28eb 100644 --- a/packages/opentelemetry-exporter-collector/test/helper.ts +++ b/packages/opentelemetry-exporter-collector/test/helper.ts @@ -398,49 +398,87 @@ export function ensureExportedEventsAreCorrect( } export function ensureExportedAttributesAreCorrect( - attributes: opentelemetryProto.common.v1.KeyValue[] + attributes: opentelemetryProto.common.v1.KeyValue[], + usingGRPC = false ) { - assert.deepStrictEqual( - attributes, - [ - { - key: 'component', - type: 'STRING', - stringValue: 'document-load', - intValue: '0', - doubleValue: 0, - boolValue: false, - }, - ], - 'exported attributes are incorrect' - ); + if (usingGRPC) { + assert.deepStrictEqual( + attributes, + [ + { + key: 'component', + value: { + stringValue: 'document-load', + value: 'stringValue', + }, + }, + ], + 'exported attributes are incorrect' + ); + } else { + assert.deepStrictEqual( + attributes, + [ + { + key: 'component', + value: { + stringValue: 'document-load', + }, + }, + ], + 'exported attributes are incorrect' + ); + } } export function ensureExportedLinksAreCorrect( - attributes: opentelemetryProto.trace.v1.Span.Link[] + attributes: opentelemetryProto.trace.v1.Span.Link[], + usingGRPC = false ) { - assert.deepStrictEqual( - attributes, - [ - { - attributes: [ - { - key: 'component', - type: 'STRING', - stringValue: 'document-load', - intValue: '0', - doubleValue: 0, - boolValue: false, - }, - ], - traceId: Buffer.from(traceIdArr), - spanId: Buffer.from(parentIdArr), - traceState: '', - droppedAttributesCount: 0, - }, - ], - 'exported links are incorrect' - ); + if (usingGRPC) { + assert.deepStrictEqual( + attributes, + [ + { + attributes: [ + { + key: 'component', + value: { + stringValue: 'document-load', + value: 'stringValue', + }, + }, + ], + traceId: Buffer.from(traceIdArr), + spanId: Buffer.from(parentIdArr), + traceState: '', + droppedAttributesCount: 0, + }, + ], + 'exported links are incorrect' + ); + } else { + assert.deepStrictEqual( + attributes, + [ + { + attributes: [ + { + key: 'component', + value: { + stringValue: 'document-load', + }, + }, + ], + traceId: Buffer.from(traceIdArr), + spanId: Buffer.from(parentIdArr), + traceState: '', + droppedAttributesCount: 0, + }, + ], + 'exported links are incorrect' + ); + } } export function ensureEventsAreCorrect( @@ -561,7 +599,9 @@ export function ensureAttributesAreCorrect( [ { key: 'component', - stringValue: 'document-load', + value: { + stringValue: 'document-load', + }, }, ], 'attributes are incorrect' @@ -576,8 +616,9 @@ export function ensureProtoAttributesAreCorrect( [ { key: 'component', - type: 'STRING', - stringValue: 'document-load', + value: { + stringValue: 'document-load', + }, }, ], 'attributes are incorrect' @@ -596,7 +637,9 @@ export function ensureLinksAreCorrect( attributes: [ { key: 'component', - stringValue: 'document-load', + value: { + stringValue: 'document-load', + }, }, ], droppedAttributesCount: 0, @@ -618,8 +661,9 @@ export function ensureProtoLinksAreCorrect( attributes: [ { key: 'component', - type: 'STRING', - stringValue: 'document-load', + value: { + stringValue: 'document-load', + }, }, ], droppedAttributesCount: 0, @@ -716,16 +760,17 @@ export function ensureProtoSpanIsCorrect( } export function ensureExportedSpanIsCorrect( - span: collectorTypes.opentelemetryProto.trace.v1.Span + span: collectorTypes.opentelemetryProto.trace.v1.Span, + usingGRPC = false ) { if (span.attributes) { - ensureExportedAttributesAreCorrect(span.attributes); + ensureExportedAttributesAreCorrect(span.attributes, usingGRPC); } if (span.events) { ensureExportedEventsAreCorrect(span.events); } if (span.links) { - ensureExportedLinksAreCorrect(span.links); + ensureExportedLinksAreCorrect(span.links, usingGRPC); } assert.deepStrictEqual( span.traceId, @@ -776,16 +821,27 @@ export function ensureWebResourceIsCorrect( attributes: [ { key: 'service.name', - stringValue: 'bar', + value: { + stringValue: 'bar', + }, }, { key: 'service', - stringValue: 'ui', + value: { + stringValue: 'ui', + }, + }, + { + key: 'version', + value: { + doubleValue: 1, + }, }, - { key: 'version', doubleValue: 1 }, { key: 'cost', - doubleValue: 112.12, + value: { + doubleValue: 112.12, + }, }, ], droppedAttributesCount: 0, @@ -986,45 +1042,74 @@ export function ensureExportedValueRecorderIsCorrect( } export function ensureResourceIsCorrect( - resource: collectorTypes.opentelemetryProto.resource.v1.Resource + resource: collectorTypes.opentelemetryProto.resource.v1.Resource, + usingGRPC = true ) { - assert.deepStrictEqual(resource, { - attributes: [ - { - key: 'service.name', - type: 'STRING', - stringValue: 'basic-service', - intValue: '0', - doubleValue: 0, - boolValue: false, - }, - { - key: 'service', - type: 'STRING', - stringValue: 'ui', - intValue: '0', - doubleValue: 0, - boolValue: false, - }, - { - key: 'version', - type: 'DOUBLE', - stringValue: '', - intValue: '0', - doubleValue: 1, - boolValue: false, - }, - { - key: 'cost', - type: 'DOUBLE', - stringValue: '', - intValue: '0', - doubleValue: 112.12, - boolValue: false, - }, - ], - droppedAttributesCount: 0, - }); + if (usingGRPC) { + assert.deepStrictEqual(resource, { + attributes: [ + { + key: 'service.name', + value: { + stringValue: 'basic-service', + value: 'stringValue', + }, + }, + { + key: 'service', + value: { + stringValue: 'ui', + value: 'stringValue', + }, + }, + { + key: 'version', + value: { + doubleValue: 1, + value: 'doubleValue', + }, + }, + { + key: 'cost', + value: { + doubleValue: 112.12, + value: 'doubleValue', + }, + }, + ], + droppedAttributesCount: 0, + }); + } else { + assert.deepStrictEqual(resource, { + attributes: [ + { + key: 'service.name', + value: { + stringValue: 'basic-service', + }, + }, + { + key: 'service', + value: { + stringValue: 'ui', + }, + }, + { + key: 'version', + value: { + doubleValue: 1, + }, + }, + { + key: 'cost', + value: { + doubleValue: 112.12, + }, + }, + ], + droppedAttributesCount: 0, + }); + } } export function ensureExportTraceServiceRequestIsSet( diff --git a/packages/opentelemetry-exporter-collector/test/node/CollectorMetricExporter.test.ts b/packages/opentelemetry-exporter-collector/test/node/CollectorMetricExporter.test.ts index 300c257593..ee659923d4 100644 --- a/packages/opentelemetry-exporter-collector/test/node/CollectorMetricExporter.test.ts +++ b/packages/opentelemetry-exporter-collector/test/node/CollectorMetricExporter.test.ts @@ -219,7 +219,7 @@ const testCollectorMetricExporter = (params: TestParams) => "resource doesn't exist" ); if (resource) { - ensureResourceIsCorrect(resource); + ensureResourceIsCorrect(resource, true); } } if (params.metadata && reqMetadata) { diff --git a/packages/opentelemetry-exporter-collector/test/node/CollectorMetricExporterWithJson.test.ts b/packages/opentelemetry-exporter-collector/test/node/CollectorMetricExporterWithJson.test.ts index a3e61d42f8..c8f767c82b 100644 --- a/packages/opentelemetry-exporter-collector/test/node/CollectorMetricExporterWithJson.test.ts +++ b/packages/opentelemetry-exporter-collector/test/node/CollectorMetricExporterWithJson.test.ts @@ -120,7 +120,7 @@ describe('CollectorMetricExporter - node with json over http', () => { }); }); - it('should successfully send the spans', done => { + it('should successfully send metrics', done => { collectorExporter.export(metrics, () => {}); setTimeout(() => { @@ -215,7 +215,7 @@ describe('CollectorMetricExporter - node with json over http', () => { setTimeout(() => { assert.strictEqual( collectorExporter['url'], - 'http://localhost:55680/v1/metrics' + 'http://localhost:55681/v1/metrics' ); done(); }); diff --git a/packages/opentelemetry-exporter-collector/test/node/CollectorTraceExporter.test.ts b/packages/opentelemetry-exporter-collector/test/node/CollectorTraceExporter.test.ts index 9cadd1574c..4c70e068ff 100644 --- a/packages/opentelemetry-exporter-collector/test/node/CollectorTraceExporter.test.ts +++ b/packages/opentelemetry-exporter-collector/test/node/CollectorTraceExporter.test.ts @@ -187,14 +187,14 @@ const testCollectorExporter = (params: TestParams) => if (exportedData) { spans = exportedData.instrumentationLibrarySpans[0].spans; resource = exportedData.resource; - ensureExportedSpanIsCorrect(spans[0]); + ensureExportedSpanIsCorrect(spans[0], true); assert.ok( typeof resource !== 'undefined', "resource doesn't exist" ); if (resource) { - ensureResourceIsCorrect(resource); + ensureResourceIsCorrect(resource, true); } } if (params.metadata && reqMetadata) { diff --git a/packages/opentelemetry-exporter-collector/test/node/CollectorTraceExporterWithJson.test.ts b/packages/opentelemetry-exporter-collector/test/node/CollectorTraceExporterWithJson.test.ts index 105e5b346e..bb9cd8f0e9 100644 --- a/packages/opentelemetry-exporter-collector/test/node/CollectorTraceExporterWithJson.test.ts +++ b/packages/opentelemetry-exporter-collector/test/node/CollectorTraceExporterWithJson.test.ts @@ -169,7 +169,7 @@ describe('CollectorTraceExporter - node with json over http', () => { setTimeout(() => { assert.strictEqual( collectorExporter['url'], - 'http://localhost:55680/v1/trace' + 'http://localhost:55681/v1/trace' ); done(); }); diff --git a/packages/opentelemetry-exporter-collector/test/node/CollectorExporterWithProto.test.ts b/packages/opentelemetry-exporter-collector/test/node/CollectorTraceExporterWithProto.test.ts similarity index 99% rename from packages/opentelemetry-exporter-collector/test/node/CollectorExporterWithProto.test.ts rename to packages/opentelemetry-exporter-collector/test/node/CollectorTraceExporterWithProto.test.ts index bf009167cb..e847f6bea3 100644 --- a/packages/opentelemetry-exporter-collector/test/node/CollectorExporterWithProto.test.ts +++ b/packages/opentelemetry-exporter-collector/test/node/CollectorTraceExporterWithProto.test.ts @@ -170,7 +170,7 @@ describe('CollectorExporter - node with proto over http', () => { setTimeout(() => { assert.strictEqual( collectorExporter['url'], - 'http://localhost:55680/v1/trace' + 'http://localhost:55681/v1/trace' ); done(); }); From 90e995f08af17081803f7a219377832f36f34dc8 Mon Sep 17 00:00:00 2001 From: Bartlomiej Obecny Date: Wed, 22 Jul 2020 17:01:56 +0200 Subject: [PATCH 14/19] chore: fixes after merge --- .../test/helper.ts | 39 ------------------- .../node/CollectorExporterWithProto.test.ts | 2 +- 2 files changed, 1 insertion(+), 40 deletions(-) diff --git a/packages/opentelemetry-exporter-collector/test/helper.ts b/packages/opentelemetry-exporter-collector/test/helper.ts index 9267f1a431..58d70d28eb 100644 --- a/packages/opentelemetry-exporter-collector/test/helper.ts +++ b/packages/opentelemetry-exporter-collector/test/helper.ts @@ -625,22 +625,6 @@ export function ensureProtoAttributesAreCorrect( ); } -export function ensureProtoAttributesAreCorrect( - attributes: opentelemetryProto.common.v1.AttributeKeyValue[] -) { - assert.deepStrictEqual( - attributes, - [ - { - key: 'component', - type: 'STRING', - stringValue: 'document-load', - }, - ], - 'attributes are incorrect' - ); -} - export function ensureLinksAreCorrect( attributes: opentelemetryProto.trace.v1.Span.Link[] ) { @@ -689,29 +673,6 @@ export function ensureProtoLinksAreCorrect( ); } -export function ensureProtoLinksAreCorrect( - attributes: opentelemetryProto.trace.v1.Span.Link[] -) { - assert.deepStrictEqual( - attributes, - [ - { - traceId: traceIdBase64, - spanId: parentIdBase64, - attributes: [ - { - key: 'component', - type: 'STRING', - stringValue: 'document-load', - }, - ], - droppedAttributesCount: 0, - }, - ], - 'links are incorrect' - ); -} - export function ensureSpanIsCorrect( span: collectorTypes.opentelemetryProto.trace.v1.Span ) { diff --git a/packages/opentelemetry-exporter-collector/test/node/CollectorExporterWithProto.test.ts b/packages/opentelemetry-exporter-collector/test/node/CollectorExporterWithProto.test.ts index bf009167cb..e847f6bea3 100644 --- a/packages/opentelemetry-exporter-collector/test/node/CollectorExporterWithProto.test.ts +++ b/packages/opentelemetry-exporter-collector/test/node/CollectorExporterWithProto.test.ts @@ -170,7 +170,7 @@ describe('CollectorExporter - node with proto over http', () => { setTimeout(() => { assert.strictEqual( collectorExporter['url'], - 'http://localhost:55680/v1/trace' + 'http://localhost:55681/v1/trace' ); done(); }); From a61a261c94ab44a0c9f5518cf8edd1e327dc1070 Mon Sep 17 00:00:00 2001 From: Bartlomiej Obecny Date: Wed, 22 Jul 2020 17:01:56 +0200 Subject: [PATCH 15/19] chore: fixes after merge --- .../docker/collector-config.yaml | 2 +- .../docker/docker-compose.yaml | 4 ++ examples/collector-exporter-node/start.js | 2 + .../test/helper.ts | 39 ------------------- .../node/CollectorExporterWithProto.test.ts | 2 +- 5 files changed, 8 insertions(+), 41 deletions(-) diff --git a/examples/collector-exporter-node/docker/collector-config.yaml b/examples/collector-exporter-node/docker/collector-config.yaml index efa495cfd7..f104677f7e 100644 --- a/examples/collector-exporter-node/docker/collector-config.yaml +++ b/examples/collector-exporter-node/docker/collector-config.yaml @@ -9,7 +9,7 @@ receivers: exporters: zipkin: - url: "http://zipkin-all-in-one:9411/api/v2/spans" + endpoint: "http://zipkin-all-in-one:9411/api/v2/spans" processors: batch: diff --git a/examples/collector-exporter-node/docker/docker-compose.yaml b/examples/collector-exporter-node/docker/docker-compose.yaml index 3e1218d3a5..3882379ad3 100644 --- a/examples/collector-exporter-node/docker/docker-compose.yaml +++ b/examples/collector-exporter-node/docker/docker-compose.yaml @@ -18,6 +18,10 @@ services: # Zipkin zipkin-all-in-one: image: openzipkin/zipkin:latest + networks: + - otelcol ports: - "9411:9411" +networks: + otelcol: diff --git a/examples/collector-exporter-node/start.js b/examples/collector-exporter-node/start.js index 4a2e3c6fa6..4e654c7e1b 100644 --- a/examples/collector-exporter-node/start.js +++ b/examples/collector-exporter-node/start.js @@ -1,11 +1,13 @@ 'use strict'; const opentelemetry = require('@opentelemetry/api'); +// const { ConsoleLogger, LogLevel} = require('@opentelemetry/core'); const { BasicTracerProvider, ConsoleSpanExporter, SimpleSpanProcessor } = require('@opentelemetry/tracing'); const { CollectorTraceExporter, CollectorProtocolNode } = require('@opentelemetry/exporter-collector'); const exporter = new CollectorTraceExporter({ serviceName: 'basic-service', + // logger: new ConsoleLogger(LogLevel.DEBUG), // headers: { // foo: 'bar' // }, diff --git a/packages/opentelemetry-exporter-collector/test/helper.ts b/packages/opentelemetry-exporter-collector/test/helper.ts index 9267f1a431..58d70d28eb 100644 --- a/packages/opentelemetry-exporter-collector/test/helper.ts +++ b/packages/opentelemetry-exporter-collector/test/helper.ts @@ -625,22 +625,6 @@ export function ensureProtoAttributesAreCorrect( ); } -export function ensureProtoAttributesAreCorrect( - attributes: opentelemetryProto.common.v1.AttributeKeyValue[] -) { - assert.deepStrictEqual( - attributes, - [ - { - key: 'component', - type: 'STRING', - stringValue: 'document-load', - }, - ], - 'attributes are incorrect' - ); -} - export function ensureLinksAreCorrect( attributes: opentelemetryProto.trace.v1.Span.Link[] ) { @@ -689,29 +673,6 @@ export function ensureProtoLinksAreCorrect( ); } -export function ensureProtoLinksAreCorrect( - attributes: opentelemetryProto.trace.v1.Span.Link[] -) { - assert.deepStrictEqual( - attributes, - [ - { - traceId: traceIdBase64, - spanId: parentIdBase64, - attributes: [ - { - key: 'component', - type: 'STRING', - stringValue: 'document-load', - }, - ], - droppedAttributesCount: 0, - }, - ], - 'links are incorrect' - ); -} - export function ensureSpanIsCorrect( span: collectorTypes.opentelemetryProto.trace.v1.Span ) { diff --git a/packages/opentelemetry-exporter-collector/test/node/CollectorExporterWithProto.test.ts b/packages/opentelemetry-exporter-collector/test/node/CollectorExporterWithProto.test.ts index bf009167cb..e847f6bea3 100644 --- a/packages/opentelemetry-exporter-collector/test/node/CollectorExporterWithProto.test.ts +++ b/packages/opentelemetry-exporter-collector/test/node/CollectorExporterWithProto.test.ts @@ -170,7 +170,7 @@ describe('CollectorExporter - node with proto over http', () => { setTimeout(() => { assert.strictEqual( collectorExporter['url'], - 'http://localhost:55680/v1/trace' + 'http://localhost:55681/v1/trace' ); done(); }); From 48740ea3147d913f3620a9b37da7e89c724c42d3 Mon Sep 17 00:00:00 2001 From: Bartlomiej Obecny Date: Wed, 22 Jul 2020 20:16:02 +0200 Subject: [PATCH 16/19] chore: cleanup --- examples/collector-exporter-node/package.json | 2 -- lerna.json | 2 -- 2 files changed, 4 deletions(-) diff --git a/examples/collector-exporter-node/package.json b/examples/collector-exporter-node/package.json index 5b2e910953..ac987ef149 100644 --- a/examples/collector-exporter-node/package.json +++ b/examples/collector-exporter-node/package.json @@ -27,8 +27,6 @@ "url": "https://github.com/open-telemetry/opentelemetry-js/issues" }, "dependencies": { - "grpc": "^1.25.0-pre1", - "@grpc/proto-loader": "^0.6.0-pre4", "@opentelemetry/api": "^0.9.0", "@opentelemetry/core": "^0.9.0", "@opentelemetry/exporter-collector": "^0.9.0", diff --git a/lerna.json b/lerna.json index 6042d0654f..f5d062d573 100644 --- a/lerna.json +++ b/lerna.json @@ -2,8 +2,6 @@ "lerna": "3.13.4", "npmClient": "npm", "packages": [ - "examples/collector-exporter-node", - "examples/tracer-web", "benchmark/*", "metapackages/*", "packages/*" From f2fa357237ec652c9756bca9c39159b4477cab3e Mon Sep 17 00:00:00 2001 From: Bartlomiej Obecny Date: Wed, 22 Jul 2020 20:28:50 +0200 Subject: [PATCH 17/19] chore: readme --- packages/opentelemetry-exporter-collector/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/opentelemetry-exporter-collector/README.md b/packages/opentelemetry-exporter-collector/README.md index c3d1400adb..8233384dd1 100644 --- a/packages/opentelemetry-exporter-collector/README.md +++ b/packages/opentelemetry-exporter-collector/README.md @@ -121,7 +121,7 @@ const collectorOptions = { url: '', // url is optional and can be omitted - default is http://localhost:55681/v1/trace headers: { foo: 'bar' - }, //an optional object containing custom headers to be sent with each request will only work with json over http + }, //an optional object containing custom headers to be sent with each request will only work with http }; const provider = new BasicTracerProvider(); @@ -144,7 +144,7 @@ const collectorOptions = { url: '', // url is optional and can be omitted - default is http://localhost:55681/v1/trace headers: { foo: 'bar' - }, //an optional object containing custom headers to be sent with each request will only work with json over http + }, //an optional object containing custom headers to be sent with each request will only work with http }; const provider = new BasicTracerProvider(); From 21904d6d79c834db3ffb1855cade355c09b6972f Mon Sep 17 00:00:00 2001 From: Bartlomiej Obecny Date: Wed, 22 Jul 2020 20:48:48 +0200 Subject: [PATCH 18/19] chore: adding unit test for mixed values with array and maps --- .../test/common/transform.test.ts | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/packages/opentelemetry-exporter-collector/test/common/transform.test.ts b/packages/opentelemetry-exporter-collector/test/common/transform.test.ts index a07bd4ec47..cd3f48058f 100644 --- a/packages/opentelemetry-exporter-collector/test/common/transform.test.ts +++ b/packages/opentelemetry-exporter-collector/test/common/transform.test.ts @@ -63,6 +63,62 @@ describe('transform', () => { { key: 'foo', value: { doubleValue: 1.34 } }, ]); }); + it('should convert attribute mixed with maps and array', () => { + const attributes: Attributes = { + foo: [ + 0, + 1, + 2.25, + 'otel', + { + foo: 'bar', + baz: 'json', + array: [1, 2, 'boom'], + }, + ], + }; + assert.deepStrictEqual(transform.toCollectorAttributes(attributes), [ + { + key: 'foo', + value: { + arrayValue: { + values: [ + { doubleValue: 0 }, + { doubleValue: 1 }, + { doubleValue: 2.25 }, + { stringValue: 'otel' }, + { + kvlistValue: { + values: [ + { + key: 'foo', + value: { stringValue: 'bar' }, + }, + { + key: 'baz', + value: { stringValue: 'json' }, + }, + { + key: 'array', + value: { + arrayValue: { + values: [ + { doubleValue: 1 }, + { doubleValue: 2 }, + { stringValue: 'boom' }, + ], + }, + }, + }, + ], + }, + }, + ], + }, + }, + }, + ]); + }); }); describe('toCollectorEvents', () => { From 0ad57e88e1031eaabd9c431d2479091c151baa29 Mon Sep 17 00:00:00 2001 From: Bartlomiej Obecny Date: Fri, 24 Jul 2020 21:35:26 +0200 Subject: [PATCH 19/19] chore: aligning default headers with node version as when using beacon thye are ignored and when having custom they are ignored too --- .../src/platform/browser/CollectorTraceExporter.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorTraceExporter.ts b/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorTraceExporter.ts index 146fc121c4..d593e1d44d 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorTraceExporter.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorTraceExporter.ts @@ -35,9 +35,6 @@ export class CollectorTraceExporter collectorTypes.opentelemetryProto.collector.trace.v1.ExportTraceServiceRequest > implements SpanExporter { - DEFAULT_HEADERS: Record = { - [collectorTypes.OT_REQUEST_HEADER]: '1', - }; private _headers: Record; private _useXHR: boolean = false; @@ -49,10 +46,7 @@ export class CollectorTraceExporter this._useXHR = !!config.headers || typeof navigator.sendBeacon !== 'function'; if (this._useXHR) { - this._headers = { - ...parseHeaders(config.headers, this.logger), - ...this.DEFAULT_HEADERS, - }; + this._headers = parseHeaders(config.headers, this.logger); } else { this._headers = {}; }