chore: remove stackdriver trace exporter (#859)
This commit is contained in:
		
							parent
							
								
									e31b975675
								
							
						
					
					
						commit
						e5e7179d10
					
				|  | @ -76,7 +76,6 @@ cache_2: &cache_2 | ||||||
|     - packages/opentelemetry-plugin-mysql/node_modules |     - packages/opentelemetry-plugin-mysql/node_modules | ||||||
|     - packages/opentelemetry-exporter-collector/node_modules |     - packages/opentelemetry-exporter-collector/node_modules | ||||||
|     - packages/opentelemetry-plugin-xml-http-request/node_modules |     - packages/opentelemetry-plugin-xml-http-request/node_modules | ||||||
|     - packages/opentelemetry-exporter-stackdriver-trace/node_modules |  | ||||||
|     - packages/opentelemetry-plugin-express/node_modules |     - packages/opentelemetry-plugin-express/node_modules | ||||||
|     - packages/opentelemetry-resources/node_modules |     - packages/opentelemetry-resources/node_modules | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -102,7 +102,6 @@ OpenTelemetry is vendor-agnostic and can upload data to any backend with various | ||||||
| #### Trace Exporters | #### Trace Exporters | ||||||
| - [@opentelemetry/exporter-jaeger][otel-exporter-jaeger] | - [@opentelemetry/exporter-jaeger][otel-exporter-jaeger] | ||||||
| - [@opentelemetry/exporter-zipkin][otel-exporter-zipkin] | - [@opentelemetry/exporter-zipkin][otel-exporter-zipkin] | ||||||
| - [@opentelemetry/exporter-stackdriver-trace][otel-exporter-stackdriver-trace] |  | ||||||
| - [@opentelemetry/exporter-collector][otel-exporter-collector] | - [@opentelemetry/exporter-collector][otel-exporter-collector] | ||||||
| 
 | 
 | ||||||
| #### Metric Exporters | #### Metric Exporters | ||||||
|  | @ -164,7 +163,6 @@ Apache 2.0 - See [LICENSE][license-url] for more information. | ||||||
| [otel-exporter-collector]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-exporter-collector | [otel-exporter-collector]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-exporter-collector | ||||||
| [otel-exporter-jaeger]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-exporter-jaeger | [otel-exporter-jaeger]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-exporter-jaeger | ||||||
| [otel-exporter-prometheus]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-exporter-prometheus | [otel-exporter-prometheus]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-exporter-prometheus | ||||||
| [otel-exporter-stackdriver-trace]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-exporter-stackdriver-trace |  | ||||||
| [otel-exporter-zipkin]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-exporter-zipkin | [otel-exporter-zipkin]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-exporter-zipkin | ||||||
| [otel-metrics]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-metrics | [otel-metrics]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-metrics | ||||||
| [otel-node]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-node | [otel-node]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-node | ||||||
|  |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| service_account_key.json |  | ||||||
|  | @ -1,37 +0,0 @@ | ||||||
| # Overview |  | ||||||
| 
 |  | ||||||
| This example shows how to use [@opentelemetry/tracing](https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-tracing) to instrument a simple Node.js application - e.g. a batch job - and export spans either to [Stackdriver Trace](https://cloud.google.com/trace/). |  | ||||||
| 
 |  | ||||||
| ## Installation |  | ||||||
| 
 |  | ||||||
| ```sh |  | ||||||
| $ # from this directory |  | ||||||
| $ npm install |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| ## Authenticate |  | ||||||
| 
 |  | ||||||
| If you are running in a GCP environment, the exporter will automatically authenticate as the service account of your environment. Please make sure that it has permission to access stackdriver trace. |  | ||||||
| 
 |  | ||||||
| If you are not running in a GCP environment you will need to create a service account and save the service account key json in the root of this example named `service_account_key.json`. For more information, visit <https://cloud.google.com/docs/authentication/>. |  | ||||||
| 
 |  | ||||||
| ## Run the Application |  | ||||||
| 
 |  | ||||||
| ```sh |  | ||||||
| $ # from this directory |  | ||||||
| $ npm start |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| ## View traces |  | ||||||
| 
 |  | ||||||
| https://console.cloud.google.com/traces/list?project=your-project-id |  | ||||||
| 
 |  | ||||||
| <p align="center"><img src="images/trace.png?raw=true"/></p> |  | ||||||
| 
 |  | ||||||
| ## Useful links |  | ||||||
| - For more information on OpenTelemetry, visit: <https://opentelemetry.io/> |  | ||||||
| - For more information on tracing, visit: <https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-tracing> |  | ||||||
| 
 |  | ||||||
| ## LICENSE |  | ||||||
| 
 |  | ||||||
| Apache License 2.0 |  | ||||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 261 KiB | 
|  | @ -1,64 +0,0 @@ | ||||||
| 'use strict'; |  | ||||||
| 
 |  | ||||||
| const opentelemetry = require('@opentelemetry/api'); |  | ||||||
| const { BasicTracerProvider, SimpleSpanProcessor } = require('@opentelemetry/tracing'); |  | ||||||
| const { CanonicalCode } = require('@opentelemetry/api'); |  | ||||||
| const { StackdriverTraceExporter } = require('@opentelemetry/exporter-stackdriver-trace'); |  | ||||||
| 
 |  | ||||||
| // Initialize an exporter
 |  | ||||||
| const exporter = new StackdriverTraceExporter({ |  | ||||||
|   projectId: '<PROJECT_ID>', |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| const provider = new BasicTracerProvider(); |  | ||||||
| 
 |  | ||||||
| // Configure span processor to send spans to the provided exporter
 |  | ||||||
| provider.addSpanProcessor(new SimpleSpanProcessor(exporter)); |  | ||||||
| 
 |  | ||||||
| // Initialize the OpenTelemetry APIs to use the NodeTracerProvider bindings
 |  | ||||||
| provider.register(); |  | ||||||
| const tracer = opentelemetry.trace.getTracer('stackdriver-basic'); |  | ||||||
| 
 |  | ||||||
| // Create a span. A span must be closed.
 |  | ||||||
| const root = tracer.startSpan('main'); |  | ||||||
| const related = tracer.startSpan('related', { |  | ||||||
|   links: [{ spanContext: root.context() }], |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| for (let i = 0; i < 10; i += 1) { |  | ||||||
|   doWork(root); |  | ||||||
|   doWork(related); |  | ||||||
| } |  | ||||||
| // Be sure to end the span.
 |  | ||||||
| root.setStatus({ |  | ||||||
|   code: CanonicalCode.UNKNOWN, |  | ||||||
| }); |  | ||||||
| root.end(); |  | ||||||
| related.end(); |  | ||||||
| 
 |  | ||||||
| // flush and close the connection.
 |  | ||||||
| exporter.shutdown(); |  | ||||||
| 
 |  | ||||||
| function doWork(parent) { |  | ||||||
|   // Start another span. In this example, the main method already started a
 |  | ||||||
|   // span, so that'll be the parent span, and this will be a child span.
 |  | ||||||
|   const span = tracer.startSpan('doWork', { parent }); |  | ||||||
| 
 |  | ||||||
|   // simulate some random work.
 |  | ||||||
|   const work = Math.floor(Math.random() * 40000000); |  | ||||||
|   for (let i = 0; i <= work; i += 1) { |  | ||||||
|     // empty
 |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   if (work % 2 === 1) { |  | ||||||
|     span.setStatus({ |  | ||||||
|       code: CanonicalCode.UNKNOWN, |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   // Set attributes to the span.
 |  | ||||||
|   span.setAttribute('key', 'value'); |  | ||||||
| 
 |  | ||||||
|   // Annotate our span to capture metadata about our operation
 |  | ||||||
|   span.addEvent('invoking doWork').end(); |  | ||||||
| } |  | ||||||
|  | @ -1,37 +0,0 @@ | ||||||
| { |  | ||||||
|   "name": "example-stackdriver-trace", |  | ||||||
|   "private": true, |  | ||||||
|   "version": "0.4.0", |  | ||||||
|   "description": "Example of using @opentelemetry/exporter-stackdriver-trace in Node.js", |  | ||||||
|   "main": "index.js", |  | ||||||
|   "scripts": { |  | ||||||
|     "start": "cross-env GOOGLE_APPLICATION_CREDENTIALS=service_account_key.json node ./index.js" |  | ||||||
|   }, |  | ||||||
|   "repository": { |  | ||||||
|     "type": "git", |  | ||||||
|     "url": "git+ssh://git@github.com/open-telemetry/opentelemetry-js.git" |  | ||||||
|   }, |  | ||||||
|   "keywords": [ |  | ||||||
|     "opentelemetry", |  | ||||||
|     "http", |  | ||||||
|     "tracing" |  | ||||||
|   ], |  | ||||||
|   "engines": { |  | ||||||
|     "node": ">=8" |  | ||||||
|   }, |  | ||||||
|   "author": "OpenTelemetry Authors", |  | ||||||
|   "license": "Apache-2.0", |  | ||||||
|   "bugs": { |  | ||||||
|     "url": "https://github.com/open-telemetry/opentelemetry-js/issues" |  | ||||||
|   }, |  | ||||||
|   "dependencies": { |  | ||||||
|     "@opentelemetry/api": "^0.4.0", |  | ||||||
|     "@opentelemetry/exporter-stackdriver-trace": "^0.4.0", |  | ||||||
|     "@opentelemetry/tracing": "^0.4.0", |  | ||||||
|     "@opentelemetry/api": "^0.4.0" |  | ||||||
|   }, |  | ||||||
|   "homepage": "https://github.com/open-telemetry/opentelemetry-js#readme", |  | ||||||
|   "devDependencies": { |  | ||||||
|     "cross-env": "^6.0.0" |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  | @ -1,4 +0,0 @@ | ||||||
| /bin |  | ||||||
| /coverage |  | ||||||
| /doc |  | ||||||
| /test |  | ||||||
|  | @ -1,201 +0,0 @@ | ||||||
|                                  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. |  | ||||||
|  | @ -1,92 +0,0 @@ | ||||||
| # OpenTelemetry Stackdriver Trace Exporter |  | ||||||
| [![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] |  | ||||||
| 
 |  | ||||||
| OpenTelemetry Stackdriver Trace Exporter allows the user to send collected traces to Stackdriver. |  | ||||||
| 
 |  | ||||||
| [Stackdriver Trace](https://cloud.google.com/trace) is a distributed tracing system. It helps gather timing data needed to troubleshoot latency problems in microservice architectures. It manages both the collection and lookup of this data. |  | ||||||
| 
 |  | ||||||
| ## Setup |  | ||||||
| 
 |  | ||||||
| Stackdriver Trace is a managed service provided by Google Cloud Platform. |  | ||||||
| 
 |  | ||||||
| ### Installation |  | ||||||
| 
 |  | ||||||
| Install the npm package `@opentelemetry/exporter-stackdriver-trace` |  | ||||||
| 
 |  | ||||||
| ```shell |  | ||||||
| $ npm install @opentelemetry/exporter-stackdriver-trace |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| ## Usage |  | ||||||
| 
 |  | ||||||
| Install the exporter on your application, register the exporter, and start tracing. If you are running in a GCP environment, the exporter will automatically authenticate using the environment's service account. If not, you will need to follow the instructions in [Authentication](#Authentication). |  | ||||||
| 
 |  | ||||||
| ```js |  | ||||||
| const { StackdriverTraceExporter } = require('@opentelemetry/exporter-stackdriver-trace'); |  | ||||||
| 
 |  | ||||||
| const exporter = new StackdriverTraceExporter({ |  | ||||||
|   // If you are not in a GCP environment, you will need to provide your |  | ||||||
|   // service account key here. See the Authentication section below. |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| tracer.addSpanProcessor(new BatchSpanProcessor(exporter)); |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| You can use the built-in `SimpleSpanProcessor` or `BatchSpanProcessor`, or write your own. |  | ||||||
| 
 |  | ||||||
| - [SimpleSpanProcessor](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/sdk-tracing.md#simple-processor): The implementation of `SpanProcessor` that passes ended span directly to the configured `SpanExporter`. |  | ||||||
| - [BatchSpanProcessor](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/sdk-tracing.md#batching-processor): The implementation of the `SpanProcessor` that batches ended spans and pushes them to the configured `SpanExporter`. It is recommended to use this `SpanProcessor` for better performance and optimization. |  | ||||||
| 
 |  | ||||||
| ## Viewing your traces |  | ||||||
| 
 |  | ||||||
| Visit the google cloud trace UI at https://console.cloud.google.com/traces/list?project=your-gcp-project-id |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| ## Authentication |  | ||||||
| 
 |  | ||||||
| The Stackdriver Trace exporter supports authentication using service accounts. These can either be defined in a keyfile (usually called `service_account_key.json` or similar), or by the environment. If your application runs in a GCP environment, such as Compute Engine, you don't need to provide any application credentials. The client library will find the credentials by itself. For more information, go to <https://cloud.google.com/docs/authentication/>. |  | ||||||
| 
 |  | ||||||
| ### Service account key |  | ||||||
| 
 |  | ||||||
| If you are not running in a GCP environment, you will need to give the service account credentials to the exporter. |  | ||||||
| 
 |  | ||||||
| ```js |  | ||||||
| const { StackdriverTraceExporter } = require('@opentelemetry/exporter-stackdriver-trace'); |  | ||||||
| 
 |  | ||||||
| const exporter = new StackdriverTraceExporter({ |  | ||||||
|   /** option 1. provide a service account key json */ |  | ||||||
|   keyFile: './service_account_key.json', |  | ||||||
|   keyFileName: './service_account_key.json', |  | ||||||
| 
 |  | ||||||
|   /** option 2. provide credentials directly */ |  | ||||||
|   credentials: { |  | ||||||
|     client_email: string, |  | ||||||
|     private_key: string, |  | ||||||
|   }, |  | ||||||
| }); |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| ## Useful links |  | ||||||
| - For more information on OpenTelemetry, visit: <https://opentelemetry.io/> |  | ||||||
| - For more about OpenTelemetry JavaScript: <https://github.com/open-telemetry/opentelemetry-js> |  | ||||||
| - Learn more about Stackdriver Trace at https://cloud.google.com/trace |  | ||||||
| - 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-exporter-stackdriver-trace |  | ||||||
| [dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-exporter-stackdriver-trace |  | ||||||
| [devDependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/dev-status.svg?path=packages/opentelemetry-exporter-stackdriver-trace |  | ||||||
| [devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-exporter-stackdriver-trace&type=dev |  | ||||||
| [npm-url]: https://www.npmjs.com/package/@opentelemetry/exporter-stackdriver-trace |  | ||||||
| [npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fexporter-stackdriver-trace.svg |  | ||||||
|  | @ -1,70 +0,0 @@ | ||||||
| { |  | ||||||
|   "name": "@opentelemetry/exporter-stackdriver-trace", |  | ||||||
|   "version": "0.4.0", |  | ||||||
|   "description": "OpenTelemetry StackDriver Trace Exporter allows the user to send collected traces to StackDriver Trace.", |  | ||||||
|   "main": "build/src/index.js", |  | ||||||
|   "types": "build/src/index.d.ts", |  | ||||||
|   "repository": "open-telemetry/opentelemetry-js", |  | ||||||
|   "scripts": { |  | ||||||
|     "lint": "gts check", |  | ||||||
|     "lint:fix": "gts fix", |  | ||||||
|     "clean": "rimraf build/*", |  | ||||||
|     "codecov": "nyc report --reporter=json && codecov -f coverage/*.json -p ../../", |  | ||||||
|     "version:update": "node ../../scripts/version-update.js", |  | ||||||
|     "compile": "npm run version:update && tsc -p .", |  | ||||||
|     "precompile": "tsc --version", |  | ||||||
|     "prepare": "npm run compile", |  | ||||||
|     "tdd": "npm run test -- --watch-extensions ts --watch", |  | ||||||
|     "test": "nyc ts-mocha -p tsconfig.json 'test/**/*.test.ts'" |  | ||||||
|   }, |  | ||||||
|   "keywords": [ |  | ||||||
|     "opentelemetry", |  | ||||||
|     "nodejs", |  | ||||||
|     "tracing", |  | ||||||
|     "profiling", |  | ||||||
|     "stackdriver", |  | ||||||
|     "stackdriver-trace" |  | ||||||
|   ], |  | ||||||
|   "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": { |  | ||||||
|     "@types/mocha": "^5.2.7", |  | ||||||
|     "@types/nock": "^11.1.0", |  | ||||||
|     "@types/node": "^12.6.9", |  | ||||||
|     "@types/sinon": "^7.5.1", |  | ||||||
|     "codecov": "^3.6.1", |  | ||||||
|     "gts": "^1.1.0", |  | ||||||
|     "mocha": "^6.2.0", |  | ||||||
|     "nock": "^11.7.0", |  | ||||||
|     "nyc": "^14.1.1", |  | ||||||
|     "rimraf": "^3.0.0", |  | ||||||
|     "sinon": "^8.0.1", |  | ||||||
|     "ts-mocha": "^6.0.0", |  | ||||||
|     "ts-node": "^8.3.0", |  | ||||||
|     "tslint-consistent-codestyle": "^1.16.0", |  | ||||||
|     "tslint-microsoft-contrib": "^6.2.0", |  | ||||||
|     "typescript": "3.7.2" |  | ||||||
|   }, |  | ||||||
|   "dependencies": { |  | ||||||
|     "@opentelemetry/api": "^0.4.0", |  | ||||||
|     "@opentelemetry/base": "^0.4.0", |  | ||||||
|     "@opentelemetry/core": "^0.4.0", |  | ||||||
|     "@opentelemetry/resources": "^0.4.0", |  | ||||||
|     "@opentelemetry/tracing": "^0.4.0", |  | ||||||
|     "google-auth-library": "^5.7.0", |  | ||||||
|     "googleapis": "^46.0.0" |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  | @ -1,51 +0,0 @@ | ||||||
| /*! |  | ||||||
|  * Copyright 2019, 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 { Logger } from '@opentelemetry/api'; |  | ||||||
| 
 |  | ||||||
| export interface StackdriverExporterOptions { |  | ||||||
|   /** |  | ||||||
|    * Google Cloud Platform project ID where your traces will be stored. |  | ||||||
|    * This is optional and will be inferred from your authentication |  | ||||||
|    * credentials or from the GCP environment when not specified. |  | ||||||
|    */ |  | ||||||
|   projectId?: string; |  | ||||||
|   /** |  | ||||||
|    * Object implementing the logger interface |  | ||||||
|    */ |  | ||||||
|   logger?: Logger; |  | ||||||
|   /** |  | ||||||
|    * Path to a .json, .pem, or .p12 key file. This is optional and |  | ||||||
|    * authentication keys will be inferred from the environment if you |  | ||||||
|    * are running on GCP. |  | ||||||
|    */ |  | ||||||
|   keyFilename?: string; |  | ||||||
|   /** |  | ||||||
|    * Path to a .json, .pem, or .p12 key file. This is optional and |  | ||||||
|    * authentication keys will be inferred from the environment if you |  | ||||||
|    * are running on GCP. |  | ||||||
|    */ |  | ||||||
|   keyFile?: string; |  | ||||||
|   /** |  | ||||||
|    * Object containing client_email and private_key properties |  | ||||||
|    */ |  | ||||||
|   credentials?: Credentials; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export interface Credentials { |  | ||||||
|   client_email?: string; |  | ||||||
|   private_key?: string; |  | ||||||
| } |  | ||||||
|  | @ -1,17 +0,0 @@ | ||||||
| /*! |  | ||||||
|  * Copyright 2019, 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 './external-types'; |  | ||||||
| export * from './trace'; |  | ||||||
|  | @ -1,145 +0,0 @@ | ||||||
| /*! |  | ||||||
|  * Copyright 2019, 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 { ExportResult } from '@opentelemetry/base'; |  | ||||||
| import { NoopLogger } from '@opentelemetry/core'; |  | ||||||
| import { ReadableSpan, SpanExporter } from '@opentelemetry/tracing'; |  | ||||||
| import { Logger } from '@opentelemetry/api'; |  | ||||||
| import { GoogleAuth } from 'google-auth-library'; |  | ||||||
| import { google } from 'googleapis'; |  | ||||||
| import { StackdriverExporterOptions } from './external-types'; |  | ||||||
| import { getReadableSpanTransformer } from './transform'; |  | ||||||
| import { Span, SpansWithCredentials } from './types'; |  | ||||||
| 
 |  | ||||||
| const OT_REQUEST_HEADER = 'x-opentelemetry-outgoing-request'; |  | ||||||
| google.options({ headers: { [OT_REQUEST_HEADER]: 1 } }); |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Format and sends span information to StackDriver Trace. |  | ||||||
|  */ |  | ||||||
| export class StackdriverTraceExporter implements SpanExporter { |  | ||||||
|   private _projectId: string | void | Promise<string | void>; |  | ||||||
|   private readonly _logger: Logger; |  | ||||||
|   private readonly _auth: GoogleAuth; |  | ||||||
| 
 |  | ||||||
|   private static readonly _cloudTrace = google.cloudtrace('v2'); |  | ||||||
| 
 |  | ||||||
|   constructor(options: StackdriverExporterOptions = {}) { |  | ||||||
|     this._logger = options.logger || new NoopLogger(); |  | ||||||
| 
 |  | ||||||
|     this._auth = new GoogleAuth({ |  | ||||||
|       credentials: options.credentials, |  | ||||||
|       keyFile: options.keyFile, |  | ||||||
|       keyFilename: options.keyFilename, |  | ||||||
|       projectId: options.projectId, |  | ||||||
|       scopes: ['https://www.googleapis.com/auth/cloud-platform'], |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     // Start this async process as early as possible. It will be
 |  | ||||||
|     // awaited on the first export because constructors are synchronous
 |  | ||||||
|     this._projectId = this._auth.getProjectId().catch(err => { |  | ||||||
|       this._logger.error(err); |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   /** |  | ||||||
|    * Publishes a list of spans to Stackdriver. |  | ||||||
|    * @param spans The list of spans to transmit to Stackdriver |  | ||||||
|    */ |  | ||||||
|   async export( |  | ||||||
|     spans: ReadableSpan[], |  | ||||||
|     resultCallback: (result: ExportResult) => void |  | ||||||
|   ): Promise<void> { |  | ||||||
|     if (this._projectId instanceof Promise) { |  | ||||||
|       this._projectId = await this._projectId; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (!this._projectId) { |  | ||||||
|       return resultCallback(ExportResult.FAILED_NOT_RETRYABLE); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     this._logger.debug('StackDriver Trace export'); |  | ||||||
|     const authorizedSpans = await this._authorize( |  | ||||||
|       spans.map(getReadableSpanTransformer(this._projectId)) |  | ||||||
|     ); |  | ||||||
| 
 |  | ||||||
|     if (!authorizedSpans) { |  | ||||||
|       return resultCallback(ExportResult.FAILED_NOT_RETRYABLE); |  | ||||||
|     } |  | ||||||
|     this._logger.debug('StackDriver Trace got span authorization'); |  | ||||||
| 
 |  | ||||||
|     try { |  | ||||||
|       await this._batchWriteSpans(authorizedSpans); |  | ||||||
|       resultCallback(ExportResult.SUCCESS); |  | ||||||
|     } catch (err) { |  | ||||||
|       this._logger.error(`Stackdriver Trace failed to export ${err}`); |  | ||||||
|       resultCallback(ExportResult.FAILED_RETRYABLE); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   shutdown(): void {} |  | ||||||
| 
 |  | ||||||
|   /** |  | ||||||
|    * Sends new spans to new or existing traces in the Stackdriver format to the |  | ||||||
|    * service. |  | ||||||
|    * @param spans |  | ||||||
|    */ |  | ||||||
|   private _batchWriteSpans(spans: SpansWithCredentials) { |  | ||||||
|     this._logger.debug('StackDriver Trace batch writing traces'); |  | ||||||
| 
 |  | ||||||
|     return new Promise((resolve, reject) => { |  | ||||||
|       // @todo Consider to use gRPC call (BatchWriteSpansRequest) for sending
 |  | ||||||
|       // data to backend :
 |  | ||||||
|       // https://cloud.google.com/trace/docs/reference/v2/rpc/google.devtools.
 |  | ||||||
|       // cloudtrace.v2#google.devtools.cloudtrace.v2.TraceService
 |  | ||||||
|       StackdriverTraceExporter._cloudTrace.projects.traces.batchWrite( |  | ||||||
|         spans, |  | ||||||
|         (err: Error | null) => { |  | ||||||
|           if (err) { |  | ||||||
|             err.message = `batchWriteSpans error: ${err.message}`; |  | ||||||
|             this._logger.error(err.message); |  | ||||||
|             reject(err); |  | ||||||
|           } else { |  | ||||||
|             const successMsg = 'batchWriteSpans successfully'; |  | ||||||
|             this._logger.debug(successMsg); |  | ||||||
|             resolve(successMsg); |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   /** |  | ||||||
|    * Gets the Google Application Credentials from the environment variables, |  | ||||||
|    * authenticates the client and calls a method to send the spans data. |  | ||||||
|    * @param stackdriverSpans The spans to export |  | ||||||
|    */ |  | ||||||
|   private async _authorize( |  | ||||||
|     spans: Span[] |  | ||||||
|   ): Promise<SpansWithCredentials | null> { |  | ||||||
|     try { |  | ||||||
|       return { |  | ||||||
|         name: `projects/${this._projectId}`, |  | ||||||
|         resource: { spans }, |  | ||||||
|         auth: await this._auth.getClient(), |  | ||||||
|       }; |  | ||||||
|     } catch (err) { |  | ||||||
|       err.message = `authorize error: ${err.message}`; |  | ||||||
|       this._logger.error(err.message); |  | ||||||
|       return null; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  | @ -1,142 +0,0 @@ | ||||||
| /*! |  | ||||||
|  * Copyright 2019, 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 { |  | ||||||
|   hrTimeToTimeStamp, |  | ||||||
|   VERSION as CORE_VERSION, |  | ||||||
| } from '@opentelemetry/core'; |  | ||||||
| import { ReadableSpan } from '@opentelemetry/tracing'; |  | ||||||
| import * as ot from '@opentelemetry/api'; |  | ||||||
| import { |  | ||||||
|   AttributeMap, |  | ||||||
|   Attributes, |  | ||||||
|   AttributeValue, |  | ||||||
|   Link, |  | ||||||
|   LinkType, |  | ||||||
|   Span, |  | ||||||
|   TruncatableString, |  | ||||||
| } from './types'; |  | ||||||
| import { VERSION } from './version'; |  | ||||||
| import { Resource } from '@opentelemetry/resources'; |  | ||||||
| 
 |  | ||||||
| const AGENT_LABEL_KEY = 'g.co/agent'; |  | ||||||
| const AGENT_LABEL_VALUE = `opentelemetry-js [${CORE_VERSION}]; stackdriver-trace-exporter [${VERSION}]`; |  | ||||||
| 
 |  | ||||||
| export function getReadableSpanTransformer( |  | ||||||
|   projectId: string |  | ||||||
| ): (span: ReadableSpan) => Span { |  | ||||||
|   return span => { |  | ||||||
|     const attributes = transformAttributes( |  | ||||||
|       span.attributes, |  | ||||||
|       { |  | ||||||
|         project_id: projectId, |  | ||||||
|         [AGENT_LABEL_KEY]: AGENT_LABEL_VALUE, |  | ||||||
|       }, |  | ||||||
|       span.resource |  | ||||||
|     ); |  | ||||||
| 
 |  | ||||||
|     const out: Span = { |  | ||||||
|       attributes, |  | ||||||
|       displayName: stringToTruncatableString(span.name), |  | ||||||
|       links: { |  | ||||||
|         link: span.links.map(transformLink), |  | ||||||
|       }, |  | ||||||
|       endTime: hrTimeToTimeStamp(span.endTime), |  | ||||||
|       startTime: hrTimeToTimeStamp(span.startTime), |  | ||||||
|       name: `projects/${projectId}/traces/${span.spanContext.traceId}/spans/${span.spanContext.spanId}`, |  | ||||||
|       spanId: span.spanContext.spanId, |  | ||||||
|       sameProcessAsParentSpan: !span.spanContext.isRemote, |  | ||||||
|       status: span.status, |  | ||||||
|       timeEvents: { |  | ||||||
|         timeEvent: span.events.map(e => ({ |  | ||||||
|           time: hrTimeToTimeStamp(e.time), |  | ||||||
|           annotation: { |  | ||||||
|             attributes: transformAttributes(e.attributes), |  | ||||||
|             description: stringToTruncatableString(e.name), |  | ||||||
|           }, |  | ||||||
|         })), |  | ||||||
|       }, |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     if (span.parentSpanId) { |  | ||||||
|       out.parentSpanId = span.parentSpanId; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return out; |  | ||||||
|   }; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function transformLink(link: ot.Link): Link { |  | ||||||
|   return { |  | ||||||
|     attributes: transformAttributes(link.attributes), |  | ||||||
|     spanId: link.context.spanId, |  | ||||||
|     traceId: link.context.traceId, |  | ||||||
|     type: LinkType.UNSPECIFIED, |  | ||||||
|   }; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function transformAttributes( |  | ||||||
|   requestAttributes: ot.Attributes = {}, |  | ||||||
|   serviceAttributes: ot.Attributes = {}, |  | ||||||
|   resource: Resource = Resource.empty() |  | ||||||
| ): Attributes { |  | ||||||
|   const attributes = Object.assign( |  | ||||||
|     {}, |  | ||||||
|     requestAttributes, |  | ||||||
|     serviceAttributes, |  | ||||||
|     resource.labels |  | ||||||
|   ); |  | ||||||
| 
 |  | ||||||
|   const attributeMap = transformAttributeValues(attributes); |  | ||||||
|   return { |  | ||||||
|     attributeMap: attributeMap, |  | ||||||
|     // @todo get dropped attribute count from sdk ReadableSpan
 |  | ||||||
|     droppedAttributesCount: |  | ||||||
|       Object.keys(attributes).length - Object.keys(attributeMap).length, |  | ||||||
|   }; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function transformAttributeValues(attributes: ot.Attributes): AttributeMap { |  | ||||||
|   const out: AttributeMap = {}; |  | ||||||
|   for (const [key, value] of Object.entries(attributes)) { |  | ||||||
|     switch (typeof value) { |  | ||||||
|       case 'number': |  | ||||||
|       case 'boolean': |  | ||||||
|       case 'string': |  | ||||||
|         out[key] = valueToAttributeValue(value); |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   return out; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function stringToTruncatableString(value: string): TruncatableString { |  | ||||||
|   return { value }; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function valueToAttributeValue( |  | ||||||
|   value: string | number | boolean |  | ||||||
| ): AttributeValue { |  | ||||||
|   switch (typeof value) { |  | ||||||
|     case 'number': |  | ||||||
|       // TODO: Consider to change to doubleValue when available in V2 API.
 |  | ||||||
|       return { intValue: String(Math.round(value)) }; |  | ||||||
|     case 'boolean': |  | ||||||
|       return { boolValue: value }; |  | ||||||
|     case 'string': |  | ||||||
|       return { stringValue: stringToTruncatableString(value) }; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  | @ -1,142 +0,0 @@ | ||||||
| /*! |  | ||||||
|  * Copyright 2019, 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 { Compute, JWT, OAuth2Client } from 'google-auth-library'; |  | ||||||
| 
 |  | ||||||
| export interface Span { |  | ||||||
|   name?: string; |  | ||||||
|   spanId?: string; |  | ||||||
|   parentSpanId?: string; |  | ||||||
|   displayName?: TruncatableString; |  | ||||||
|   startTime?: string; |  | ||||||
|   endTime?: string; |  | ||||||
|   attributes?: Attributes; |  | ||||||
|   // This property is currently unused. keeping it here as it is part
 |  | ||||||
|   // of the stack driver trace types and may be used in the future
 |  | ||||||
|   stackTrace?: StackTrace; |  | ||||||
|   timeEvents?: TimeEvents; |  | ||||||
|   links?: Links; |  | ||||||
|   status?: Status; |  | ||||||
|   sameProcessAsParentSpan?: boolean; |  | ||||||
|   childSpanCount?: number; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export interface AttributeMap { |  | ||||||
|   [key: string]: AttributeValue; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export interface Attributes { |  | ||||||
|   attributeMap?: AttributeMap; |  | ||||||
|   droppedAttributesCount?: number; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export interface AttributeValue { |  | ||||||
|   boolValue?: boolean; |  | ||||||
|   intValue?: string; |  | ||||||
|   stringValue?: TruncatableString; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export interface TruncatableString { |  | ||||||
|   value?: string; |  | ||||||
|   truncatedByteCount?: number; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export interface Links { |  | ||||||
|   droppedLinksCount?: number; |  | ||||||
|   link?: Link[]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export interface Link { |  | ||||||
|   attributes?: Attributes; |  | ||||||
|   spanId?: string; |  | ||||||
|   traceId?: string; |  | ||||||
|   type?: LinkType; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export interface StackTrace { |  | ||||||
|   stackFrames?: StackFrames; |  | ||||||
|   stackTraceHashId?: string; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export interface StackFrames { |  | ||||||
|   droppedFramesCount?: number; |  | ||||||
|   frame?: StackFrame[]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export interface StackFrame { |  | ||||||
|   columnNumber?: string; |  | ||||||
|   fileName?: TruncatableString; |  | ||||||
|   functionName?: TruncatableString; |  | ||||||
|   lineNumber?: string; |  | ||||||
|   loadModule?: Module; |  | ||||||
|   originalFunctionName?: TruncatableString; |  | ||||||
|   sourceVersion?: TruncatableString; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export interface Module { |  | ||||||
|   buildId?: TruncatableString; |  | ||||||
|   module?: TruncatableString; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export interface Status { |  | ||||||
|   /** gRPC status code */ |  | ||||||
|   code?: number; |  | ||||||
|   message?: string; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export interface TimeEvents { |  | ||||||
|   droppedAnnotationsCount?: number; |  | ||||||
|   droppedMessageEventsCount?: number; |  | ||||||
|   timeEvent?: TimeEvent[]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export interface TimeEvent { |  | ||||||
|   annotation?: Annotation; |  | ||||||
|   time?: string; |  | ||||||
|   // This property is currently unused. keeping it here as it is part
 |  | ||||||
|   // of the stack driver trace types and may be used in the future
 |  | ||||||
|   messageEvent?: MessageEvent; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export interface Annotation { |  | ||||||
|   attributes?: Attributes; |  | ||||||
|   description?: TruncatableString; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export interface MessageEvent { |  | ||||||
|   id?: string; |  | ||||||
|   type?: Type; |  | ||||||
|   compressedSizeBytes?: string; |  | ||||||
|   uncompressedSizeBytes?: string; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export enum Type { |  | ||||||
|   TYPE_UNSPECIFIED = 0, |  | ||||||
|   SENT = 1, |  | ||||||
|   RECEIVED = 2, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export enum LinkType { |  | ||||||
|   UNSPECIFIED = 0, |  | ||||||
|   CHILD_LINKED_SPAN = 1, |  | ||||||
|   PARENT_LINKED_SPAN = 2, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export interface SpansWithCredentials { |  | ||||||
|   name: string; |  | ||||||
|   resource: { spans: {} }; |  | ||||||
|   auth: JWT | OAuth2Client | Compute; |  | ||||||
| } |  | ||||||
|  | @ -1,18 +0,0 @@ | ||||||
| /*! |  | ||||||
|  * Copyright 2019, 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. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| // this is autogenerated file, see scripts/version-update.js
 |  | ||||||
| export const VERSION = '0.4.0'; |  | ||||||
|  | @ -1,241 +0,0 @@ | ||||||
| /*! |  | ||||||
|  * Copyright 2019, 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 { ExportResult } from '@opentelemetry/base'; |  | ||||||
| import { ConsoleLogger, LogLevel } from '@opentelemetry/core'; |  | ||||||
| import { ReadableSpan } from '@opentelemetry/tracing'; |  | ||||||
| import { Resource } from '@opentelemetry/resources'; |  | ||||||
| import * as types from '@opentelemetry/api'; |  | ||||||
| import * as assert from 'assert'; |  | ||||||
| import * as nock from 'nock'; |  | ||||||
| import * as sinon from 'sinon'; |  | ||||||
| import { StackdriverTraceExporter } from '../src'; |  | ||||||
| import { TraceFlags } from '@opentelemetry/api'; |  | ||||||
| 
 |  | ||||||
| describe('Stackdriver Trace Exporter', () => { |  | ||||||
|   beforeEach(() => { |  | ||||||
|     process.env.GCLOUD_PROJECT = 'not-real'; |  | ||||||
|     nock.disableNetConnect(); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   describe('constructor', () => { |  | ||||||
|     it('should construct an exporter', async () => { |  | ||||||
|       const exporter = new StackdriverTraceExporter({ |  | ||||||
|         credentials: { |  | ||||||
|           client_email: 'noreply@fake.example.com', |  | ||||||
|           private_key: 'this is a key', |  | ||||||
|         }, |  | ||||||
|       }); |  | ||||||
| 
 |  | ||||||
|       assert(exporter); |  | ||||||
|       return (exporter['_projectId'] as Promise<string>).then(id => { |  | ||||||
|         assert.deepStrictEqual(id, 'not-real'); |  | ||||||
|       }); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   describe('export', () => { |  | ||||||
|     let exporter: StackdriverTraceExporter; |  | ||||||
|     let logger: ConsoleLogger; |  | ||||||
|     let batchWrite: sinon.SinonSpy<[any, any], any>; |  | ||||||
|     let debug: sinon.SinonSpy; |  | ||||||
|     let info: sinon.SinonSpy; |  | ||||||
|     let warn: sinon.SinonSpy; |  | ||||||
|     let error: sinon.SinonSpy; |  | ||||||
|     let getClientShouldFail: boolean; |  | ||||||
|     let batchWriteShouldFail: boolean; |  | ||||||
| 
 |  | ||||||
|     beforeEach(() => { |  | ||||||
|       getClientShouldFail = false; |  | ||||||
|       batchWriteShouldFail = false; |  | ||||||
|       logger = new ConsoleLogger(LogLevel.ERROR); |  | ||||||
|       exporter = new StackdriverTraceExporter({ |  | ||||||
|         logger, |  | ||||||
|       }); |  | ||||||
| 
 |  | ||||||
|       batchWrite = sinon.spy( |  | ||||||
|         (spans: any, callback: (err: Error | null) => void): any => { |  | ||||||
|           if (batchWriteShouldFail) { |  | ||||||
|             callback(new Error('fail')); |  | ||||||
|           } else { |  | ||||||
|             callback(null); |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       ); |  | ||||||
| 
 |  | ||||||
|       sinon.replace( |  | ||||||
|         StackdriverTraceExporter['_cloudTrace'].projects.traces, |  | ||||||
|         'batchWrite', |  | ||||||
|         batchWrite as any |  | ||||||
|       ); |  | ||||||
| 
 |  | ||||||
|       sinon.replace(exporter['_auth'], 'getClient', () => { |  | ||||||
|         if (getClientShouldFail) { |  | ||||||
|           throw new Error('fail'); |  | ||||||
|         } |  | ||||||
|         return {} as any; |  | ||||||
|       }); |  | ||||||
| 
 |  | ||||||
|       debug = sinon.spy(); |  | ||||||
|       info = sinon.spy(); |  | ||||||
|       warn = sinon.spy(); |  | ||||||
|       error = sinon.spy(); |  | ||||||
|       sinon.replace(logger, 'debug', debug); |  | ||||||
|       sinon.replace(logger, 'info', info); |  | ||||||
|       sinon.replace(logger, 'warn', warn); |  | ||||||
|       sinon.replace(logger, 'error', error); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     afterEach(() => { |  | ||||||
|       nock.restore(); |  | ||||||
|       sinon.restore(); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     it('should export spans', async () => { |  | ||||||
|       const readableSpan: ReadableSpan = { |  | ||||||
|         attributes: {}, |  | ||||||
|         duration: [32, 800000000], |  | ||||||
|         startTime: [1566156729, 709], |  | ||||||
|         endTime: [1566156731, 709], |  | ||||||
|         ended: true, |  | ||||||
|         events: [], |  | ||||||
|         kind: types.SpanKind.CLIENT, |  | ||||||
|         links: [], |  | ||||||
|         name: 'my-span', |  | ||||||
|         spanContext: { |  | ||||||
|           traceId: 'd4cda95b652f4a1592b449d5929fda1b', |  | ||||||
|           spanId: '6e0c63257de34c92', |  | ||||||
|           traceFlags: TraceFlags.NONE, |  | ||||||
|           isRemote: true, |  | ||||||
|         }, |  | ||||||
|         status: { code: types.CanonicalCode.OK }, |  | ||||||
|         resource: Resource.empty(), |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       const result = await new Promise((resolve, reject) => { |  | ||||||
|         exporter.export([readableSpan], result => { |  | ||||||
|           resolve(result); |  | ||||||
|         }); |  | ||||||
|       }); |  | ||||||
| 
 |  | ||||||
|       assert.deepStrictEqual( |  | ||||||
|         batchWrite.getCall(0).args[0].resource.spans[0].displayName.value, |  | ||||||
|         'my-span' |  | ||||||
|       ); |  | ||||||
| 
 |  | ||||||
|       assert.deepStrictEqual(result, ExportResult.SUCCESS); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     it('should return not retryable if authorization fails', async () => { |  | ||||||
|       const readableSpan: ReadableSpan = { |  | ||||||
|         attributes: {}, |  | ||||||
|         duration: [32, 800000000], |  | ||||||
|         startTime: [1566156729, 709], |  | ||||||
|         endTime: [1566156731, 709], |  | ||||||
|         ended: true, |  | ||||||
|         events: [], |  | ||||||
|         kind: types.SpanKind.CLIENT, |  | ||||||
|         links: [], |  | ||||||
|         name: 'my-span', |  | ||||||
|         spanContext: { |  | ||||||
|           traceId: 'd4cda95b652f4a1592b449d5929fda1b', |  | ||||||
|           spanId: '6e0c63257de34c92', |  | ||||||
|           traceFlags: TraceFlags.NONE, |  | ||||||
|           isRemote: true, |  | ||||||
|         }, |  | ||||||
|         status: { code: types.CanonicalCode.OK }, |  | ||||||
|         resource: Resource.empty(), |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       getClientShouldFail = true; |  | ||||||
| 
 |  | ||||||
|       const result = await new Promise((resolve, reject) => { |  | ||||||
|         exporter.export([readableSpan], result => { |  | ||||||
|           resolve(result); |  | ||||||
|         }); |  | ||||||
|       }); |  | ||||||
| 
 |  | ||||||
|       assert(batchWrite.notCalled); |  | ||||||
|       assert(error.getCall(0).args[0].match(/authorize error: fail/)); |  | ||||||
|       assert.deepStrictEqual(result, ExportResult.FAILED_NOT_RETRYABLE); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     it('should return retryable if span writing fails', async () => { |  | ||||||
|       const readableSpan: ReadableSpan = { |  | ||||||
|         attributes: {}, |  | ||||||
|         duration: [32, 800000000], |  | ||||||
|         startTime: [1566156729, 709], |  | ||||||
|         endTime: [1566156731, 709], |  | ||||||
|         ended: true, |  | ||||||
|         events: [], |  | ||||||
|         kind: types.SpanKind.CLIENT, |  | ||||||
|         links: [], |  | ||||||
|         name: 'my-span', |  | ||||||
|         spanContext: { |  | ||||||
|           traceId: 'd4cda95b652f4a1592b449d5929fda1b', |  | ||||||
|           spanId: '6e0c63257de34c92', |  | ||||||
|           traceFlags: TraceFlags.NONE, |  | ||||||
|           isRemote: true, |  | ||||||
|         }, |  | ||||||
|         status: { code: types.CanonicalCode.OK }, |  | ||||||
|         resource: Resource.empty(), |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       batchWriteShouldFail = true; |  | ||||||
| 
 |  | ||||||
|       const result = await new Promise((resolve, reject) => { |  | ||||||
|         exporter.export([readableSpan], result => { |  | ||||||
|           resolve(result); |  | ||||||
|         }); |  | ||||||
|       }); |  | ||||||
| 
 |  | ||||||
|       assert.deepStrictEqual(result, ExportResult.FAILED_RETRYABLE); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     it('should return not retryable if project id missing', async () => { |  | ||||||
|       const readableSpan: ReadableSpan = { |  | ||||||
|         attributes: {}, |  | ||||||
|         duration: [32, 800000000], |  | ||||||
|         startTime: [1566156729, 709], |  | ||||||
|         endTime: [1566156731, 709], |  | ||||||
|         ended: true, |  | ||||||
|         events: [], |  | ||||||
|         kind: types.SpanKind.CLIENT, |  | ||||||
|         links: [], |  | ||||||
|         name: 'my-span', |  | ||||||
|         spanContext: { |  | ||||||
|           traceId: 'd4cda95b652f4a1592b449d5929fda1b', |  | ||||||
|           spanId: '6e0c63257de34c92', |  | ||||||
|           traceFlags: TraceFlags.NONE, |  | ||||||
|           isRemote: true, |  | ||||||
|         }, |  | ||||||
|         status: { code: types.CanonicalCode.OK }, |  | ||||||
|         resource: Resource.empty(), |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       await exporter['_projectId']; |  | ||||||
|       exporter['_projectId'] = undefined; |  | ||||||
| 
 |  | ||||||
|       const result = await new Promise((resolve, reject) => { |  | ||||||
|         exporter.export([readableSpan], result => { |  | ||||||
|           resolve(result); |  | ||||||
|         }); |  | ||||||
|       }); |  | ||||||
| 
 |  | ||||||
|       assert.deepStrictEqual(result, ExportResult.FAILED_NOT_RETRYABLE); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
|  | @ -1,263 +0,0 @@ | ||||||
| /*! |  | ||||||
|  * Copyright 2019, 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 { VERSION as CORE_VERSION } from '@opentelemetry/core'; |  | ||||||
| import { ReadableSpan } from '@opentelemetry/tracing'; |  | ||||||
| import { Resource } from '@opentelemetry/resources'; |  | ||||||
| import * as types from '@opentelemetry/api'; |  | ||||||
| import * as assert from 'assert'; |  | ||||||
| import { getReadableSpanTransformer } from '../src/transform'; |  | ||||||
| import { LinkType, Span } from '../src/types'; |  | ||||||
| import { VERSION } from '../src/version'; |  | ||||||
| import { TraceFlags } from '@opentelemetry/api'; |  | ||||||
| 
 |  | ||||||
| describe('transform', () => { |  | ||||||
|   let readableSpan: ReadableSpan; |  | ||||||
|   let transformer: (readableSpan: ReadableSpan) => Span; |  | ||||||
|   let spanContext: types.SpanContext; |  | ||||||
| 
 |  | ||||||
|   beforeEach(() => { |  | ||||||
|     spanContext = { |  | ||||||
|       traceId: 'd4cda95b652f4a1592b449d5929fda1b', |  | ||||||
|       spanId: '6e0c63257de34c92', |  | ||||||
|       traceFlags: TraceFlags.NONE, |  | ||||||
|       isRemote: true, |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     transformer = getReadableSpanTransformer('project-id'); |  | ||||||
| 
 |  | ||||||
|     readableSpan = { |  | ||||||
|       attributes: {}, |  | ||||||
|       duration: [32, 800000000], |  | ||||||
|       startTime: [1566156729, 709], |  | ||||||
|       endTime: [1566156731, 709], |  | ||||||
|       ended: true, |  | ||||||
|       events: [], |  | ||||||
|       kind: types.SpanKind.CLIENT, |  | ||||||
|       links: [], |  | ||||||
|       name: 'my-span', |  | ||||||
|       spanContext, |  | ||||||
|       status: { code: types.CanonicalCode.OK }, |  | ||||||
|       resource: new Resource({ |  | ||||||
|         service: 'ui', |  | ||||||
|         version: 1, |  | ||||||
|         cost: 112.12, |  | ||||||
|       }), |  | ||||||
|     }; |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   it('should transform spans', () => { |  | ||||||
|     const result = transformer(readableSpan); |  | ||||||
| 
 |  | ||||||
|     assert.deepStrictEqual(result, { |  | ||||||
|       attributes: { |  | ||||||
|         attributeMap: { |  | ||||||
|           project_id: { stringValue: { value: 'project-id' } }, |  | ||||||
|           'g.co/agent': { |  | ||||||
|             stringValue: { |  | ||||||
|               value: `opentelemetry-js [${CORE_VERSION}]; stackdriver-trace-exporter [${VERSION}]`, |  | ||||||
|             }, |  | ||||||
|           }, |  | ||||||
|           cost: { intValue: '112' }, |  | ||||||
|           service: { stringValue: { value: 'ui' } }, |  | ||||||
|           version: { intValue: '1' }, |  | ||||||
|         }, |  | ||||||
|         droppedAttributesCount: 0, |  | ||||||
|       }, |  | ||||||
|       displayName: { value: 'my-span' }, |  | ||||||
|       links: { link: [] }, |  | ||||||
|       endTime: '2019-08-18T19:32:11.000000709Z', |  | ||||||
|       startTime: '2019-08-18T19:32:09.000000709Z', |  | ||||||
|       name: |  | ||||||
|         'projects/project-id/traces/d4cda95b652f4a1592b449d5929fda1b/spans/6e0c63257de34c92', |  | ||||||
|       spanId: '6e0c63257de34c92', |  | ||||||
|       status: { code: 0 }, |  | ||||||
|       timeEvents: { timeEvent: [] }, |  | ||||||
|       sameProcessAsParentSpan: false, |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   it('should transform spans with parent', () => { |  | ||||||
|     (readableSpan as any).parentSpanId = '3e0c63257de34c92'; |  | ||||||
|     const result = transformer(readableSpan); |  | ||||||
|     assert.deepStrictEqual(result.parentSpanId, '3e0c63257de34c92'); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   it('should transform spans without parent', () => { |  | ||||||
|     const result = transformer(readableSpan); |  | ||||||
|     assert.deepStrictEqual(result.parentSpanId, undefined); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   it('should transform remote spans', () => { |  | ||||||
|     const remote = transformer(readableSpan); |  | ||||||
|     assert.deepStrictEqual(remote.sameProcessAsParentSpan, false); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   it('should transform local spans', () => { |  | ||||||
|     readableSpan.spanContext.isRemote = false; |  | ||||||
|     const local = transformer(readableSpan); |  | ||||||
|     assert.deepStrictEqual(local.sameProcessAsParentSpan, true); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   it('should transform attributes', () => { |  | ||||||
|     readableSpan.attributes.testBool = true; |  | ||||||
|     readableSpan.attributes.testInt = 3; |  | ||||||
|     readableSpan.attributes.testString = 'str'; |  | ||||||
| 
 |  | ||||||
|     const result = transformer(readableSpan); |  | ||||||
| 
 |  | ||||||
|     assert.deepStrictEqual(result.attributes!.attributeMap!.testBool, { |  | ||||||
|       boolValue: true, |  | ||||||
|     }); |  | ||||||
|     assert.deepStrictEqual(result.attributes!.attributeMap!.testInt, { |  | ||||||
|       intValue: '3', |  | ||||||
|     }); |  | ||||||
|     assert.deepStrictEqual(result.attributes!.attributeMap!.testString, { |  | ||||||
|       stringValue: { value: 'str' }, |  | ||||||
|     }); |  | ||||||
|     assert.deepStrictEqual(result.attributes!.droppedAttributesCount, 0); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   it('should drop unknown attribute types', () => { |  | ||||||
|     readableSpan.attributes.testUnknownType = { message: 'dropped' }; |  | ||||||
|     const result = transformer(readableSpan); |  | ||||||
|     assert.deepStrictEqual(result.attributes!.droppedAttributesCount, 1); |  | ||||||
|     assert.deepStrictEqual( |  | ||||||
|       Object.keys(result.attributes!.attributeMap!).length, |  | ||||||
|       5 |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   it('should transform links', () => { |  | ||||||
|     readableSpan.links.push({ |  | ||||||
|       context: { |  | ||||||
|         traceId: 'a4cda95b652f4a1592b449d5929fda1b', |  | ||||||
|         spanId: '3e0c63257de34c92', |  | ||||||
|       }, |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     const result = transformer(readableSpan); |  | ||||||
| 
 |  | ||||||
|     assert.deepStrictEqual(result.links, { |  | ||||||
|       link: [ |  | ||||||
|         { |  | ||||||
|           attributes: { |  | ||||||
|             attributeMap: {}, |  | ||||||
|             droppedAttributesCount: 0, |  | ||||||
|           }, |  | ||||||
|           traceId: 'a4cda95b652f4a1592b449d5929fda1b', |  | ||||||
|           spanId: '3e0c63257de34c92', |  | ||||||
|           type: LinkType.UNSPECIFIED, |  | ||||||
|         }, |  | ||||||
|       ], |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   it('should transform links with attributes', () => { |  | ||||||
|     readableSpan.links.push({ |  | ||||||
|       context: { |  | ||||||
|         traceId: 'a4cda95b652f4a1592b449d5929fda1b', |  | ||||||
|         spanId: '3e0c63257de34c92', |  | ||||||
|       }, |  | ||||||
|       attributes: { |  | ||||||
|         testAttr: 'value', |  | ||||||
|         droppedAttr: {}, |  | ||||||
|       }, |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     const result = transformer(readableSpan); |  | ||||||
| 
 |  | ||||||
|     assert.deepStrictEqual(result.links, { |  | ||||||
|       link: [ |  | ||||||
|         { |  | ||||||
|           attributes: { |  | ||||||
|             attributeMap: { |  | ||||||
|               testAttr: { |  | ||||||
|                 stringValue: { |  | ||||||
|                   value: 'value', |  | ||||||
|                 }, |  | ||||||
|               }, |  | ||||||
|             }, |  | ||||||
|             droppedAttributesCount: 1, |  | ||||||
|           }, |  | ||||||
|           traceId: 'a4cda95b652f4a1592b449d5929fda1b', |  | ||||||
|           spanId: '3e0c63257de34c92', |  | ||||||
|           type: LinkType.UNSPECIFIED, |  | ||||||
|         }, |  | ||||||
|       ], |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   it('should transform events', () => { |  | ||||||
|     readableSpan.events.push({ |  | ||||||
|       name: 'something happened', |  | ||||||
|       time: [1566156729, 809], |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     const result = transformer(readableSpan); |  | ||||||
| 
 |  | ||||||
|     assert.deepStrictEqual(result.timeEvents, { |  | ||||||
|       timeEvent: [ |  | ||||||
|         { |  | ||||||
|           annotation: { |  | ||||||
|             attributes: { |  | ||||||
|               attributeMap: {}, |  | ||||||
|               droppedAttributesCount: 0, |  | ||||||
|             }, |  | ||||||
|             description: { |  | ||||||
|               value: 'something happened', |  | ||||||
|             }, |  | ||||||
|           }, |  | ||||||
|           time: '2019-08-18T19:32:09.000000809Z', |  | ||||||
|         }, |  | ||||||
|       ], |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   it('should transform events with attributes', () => { |  | ||||||
|     readableSpan.events.push({ |  | ||||||
|       name: 'something happened', |  | ||||||
|       attributes: { |  | ||||||
|         error: true, |  | ||||||
|         dropped: {}, |  | ||||||
|       }, |  | ||||||
|       time: [1566156729, 809], |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     const result = transformer(readableSpan); |  | ||||||
| 
 |  | ||||||
|     assert.deepStrictEqual(result.timeEvents, { |  | ||||||
|       timeEvent: [ |  | ||||||
|         { |  | ||||||
|           annotation: { |  | ||||||
|             attributes: { |  | ||||||
|               attributeMap: { |  | ||||||
|                 error: { |  | ||||||
|                   boolValue: true, |  | ||||||
|                 }, |  | ||||||
|               }, |  | ||||||
|               droppedAttributesCount: 1, |  | ||||||
|             }, |  | ||||||
|             description: { |  | ||||||
|               value: 'something happened', |  | ||||||
|             }, |  | ||||||
|           }, |  | ||||||
|           time: '2019-08-18T19:32:09.000000809Z', |  | ||||||
|         }, |  | ||||||
|       ], |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
|  | @ -1,11 +0,0 @@ | ||||||
| { |  | ||||||
|   "extends": "../tsconfig.base", |  | ||||||
|   "compilerOptions": { |  | ||||||
|     "rootDir": ".", |  | ||||||
|     "outDir": "build" |  | ||||||
|   }, |  | ||||||
|   "include": [ |  | ||||||
|     "src/**/*.ts", |  | ||||||
|     "test/**/*.ts" |  | ||||||
|   ] |  | ||||||
| } |  | ||||||
|  | @ -1,4 +0,0 @@ | ||||||
| { |  | ||||||
|   "rulesDirectory": ["node_modules/tslint-microsoft-contrib"], |  | ||||||
|   "extends": ["../../tslint.base.js", "./node_modules/tslint-consistent-codestyle"] |  | ||||||
| } |  | ||||||
		Loading…
	
		Reference in New Issue