├── .gitignore ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── .settings.xml ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── RELEASE.md ├── mvnw ├── mvnw.cmd ├── opentracing-api ├── pom.xml └── src │ ├── main │ └── java │ │ └── io │ │ └── opentracing │ │ ├── References.java │ │ ├── Scope.java │ │ ├── ScopeManager.java │ │ ├── Span.java │ │ ├── SpanContext.java │ │ ├── Tracer.java │ │ ├── log │ │ └── Fields.java │ │ ├── propagation │ │ ├── Binary.java │ │ ├── BinaryAdapters.java │ │ ├── BinaryExtract.java │ │ ├── BinaryInject.java │ │ ├── Format.java │ │ ├── TextMap.java │ │ ├── TextMapAdapter.java │ │ ├── TextMapExtract.java │ │ ├── TextMapExtractAdapter.java │ │ ├── TextMapInject.java │ │ └── TextMapInjectAdapter.java │ │ └── tag │ │ ├── AbstractTag.java │ │ ├── BooleanTag.java │ │ ├── IntOrStringTag.java │ │ ├── IntTag.java │ │ ├── StringTag.java │ │ ├── Tag.java │ │ └── Tags.java │ └── test │ └── java │ └── io │ └── opentracing │ ├── AssertionTest.java │ ├── propagation │ ├── BinaryAdaptersTest.java │ ├── BuiltinFormatTest.java │ ├── TextMapExtractAdapterTest.java │ └── TextMapInjectAdapterTest.java │ └── tag │ ├── AbstractTagTest.java │ ├── BooleanTagTest.java │ ├── IntTagTest.java │ └── StringTagTest.java ├── opentracing-mock ├── README.md ├── pom.xml └── src │ ├── main │ └── java │ │ └── io │ │ └── opentracing │ │ └── mock │ │ ├── MockSpan.java │ │ └── MockTracer.java │ └── test │ └── java │ └── io │ └── opentracing │ └── mock │ ├── MockSpanTest.java │ └── MockTracerTest.java ├── opentracing-noop ├── pom.xml └── src │ ├── main │ └── java │ │ └── io │ │ └── opentracing │ │ └── noop │ │ ├── NoopScopeManager.java │ │ ├── NoopSpan.java │ │ ├── NoopSpanBuilder.java │ │ ├── NoopSpanContext.java │ │ ├── NoopTracer.java │ │ └── NoopTracerFactory.java │ └── test │ └── java │ └── io │ └── opentracing │ └── noop │ ├── NoopScopeManagerTest.java │ ├── NoopSpanContextTest.java │ └── NoopTracerTest.java ├── opentracing-testbed ├── README.md ├── pom.xml └── src │ └── test │ └── java │ └── io │ └── opentracing │ └── testbed │ ├── AutoFinishScope.java │ ├── AutoFinishScopeManager.java │ ├── TestUtils.java │ ├── activate_deactivate │ ├── README.md │ ├── RunnableAction.java │ └── ScheduledActionsTest.java │ ├── active_span_replacement │ ├── ActiveSpanReplacementTest.java │ └── README.md │ ├── actor_propagation │ ├── Actor.java │ ├── ActorPropagationTest.java │ └── README.md │ ├── client_server │ ├── Client.java │ ├── Message.java │ ├── README.md │ ├── Server.java │ └── TestClientServerTest.java │ ├── concurrent_common_request_handler │ ├── Client.java │ ├── Context.java │ ├── HandlerTest.java │ ├── README.md │ └── RequestHandler.java │ ├── error_reporting │ ├── ErrorReportingTest.java │ └── README.md │ ├── late_span_finish │ ├── LateSpanFinishTest.java │ └── README.md │ ├── listener_per_request │ ├── Client.java │ ├── ListenerTest.java │ ├── README.md │ └── ResponseListener.java │ ├── multiple_callbacks │ ├── Client.java │ ├── MultipleCallbacksTest.java │ └── README.md │ ├── nested_callbacks │ ├── NestedCallbacksTest.java │ └── README.md │ ├── promise_propagation │ ├── Promise.java │ ├── PromiseContext.java │ ├── PromisePropagationTest.java │ └── README.md │ ├── stateless_common_request_handler │ ├── Client.java │ ├── HandlerTest.java │ ├── README.md │ └── RequestHandler.java │ └── suspend_resume_propagation │ ├── README.md │ ├── SuspendResume.java │ └── SuspendResumePropagationTest.java ├── opentracing-util ├── README.md ├── pom.xml └── src │ ├── main │ └── java │ │ └── io │ │ └── opentracing │ │ └── util │ │ ├── GlobalTracer.java │ │ ├── ThreadLocalScope.java │ │ └── ThreadLocalScopeManager.java │ └── test │ └── java │ └── io │ └── opentracing │ └── util │ ├── GlobalTracerTest.java │ ├── GlobalTracerTestUtil.java │ ├── ThreadLocalScopeManagerTest.java │ └── ThreadLocalScopeTest.java ├── pom.xml ├── src └── etc │ └── header.txt └── travis └── publish.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | #* 3 | *# 4 | .#* 5 | .factorypath 6 | .classpath 7 | .project 8 | .settings/ 9 | target/ 10 | _site/ 11 | .idea 12 | *.iml 13 | *.swp 14 | /opentracing-brave/nbproject/ -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opentracing/opentracing-java/a8557d7c7a56210cbcf6bc518fe24b32923aa66f/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip -------------------------------------------------------------------------------- /.settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 21 | 22 | 23 | sonatype 24 | ${env.SONATYPE_USER} 25 | ${env.SONATYPE_PASSWORD} 26 | 27 | 28 | bintray 29 | ${env.BINTRAY_USER} 30 | ${env.BINTRAY_KEY} 31 | 32 | 33 | jfrog-snapshots 34 | ${env.BINTRAY_USER} 35 | ${env.BINTRAY_KEY} 36 | 37 | 38 | github.com 39 | ${env.GH_USER} 40 | ${env.GH_TOKEN} 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Run `travis lint` when changing this file to avoid breaking the build. 2 | # Default JDK is really old: 1.8.0_31; Trusty's is less old: 1.8.0_51 3 | # https://docs.travis-ci.com/user/ci-environment/#Virtualization-environments 4 | sudo: false 5 | dist: trusty 6 | 7 | cache: 8 | directories: 9 | - $HOME/.m2 10 | 11 | language: java 12 | 13 | jdk: 14 | - oraclejdk8 15 | 16 | addons: 17 | apt: 18 | packages: 19 | - oracle-java8-installer 20 | 21 | before_install: 22 | # allocate commits to CI, not the owner of the deploy key 23 | - git config user.name "opentracingci" 24 | - git config user.email "opentracingci+opentracing@googlegroups.com" 25 | # setup https authentication credentials, used by ./mvnw release:prepare 26 | - git config credential.helper "store --file=.git/credentials" 27 | - echo "https://$GH_TOKEN:@github.com" > .git/credentials 28 | 29 | install: 30 | # Override default travis to use the maven wrapper 31 | - ./mvnw install -DskipTests=true -Dmaven.javadoc.skip=true -B -V 32 | 33 | script: 34 | - ./travis/publish.sh 35 | 36 | # Don't build release tags. This avoids publish conflicts because the version commit exists both on master and the release tag. 37 | # See https://github.com/travis-ci/travis-ci/issues/1532 38 | branches: 39 | except: 40 | - /^[0-9]/ 41 | 42 | after_success: 43 | - mvn jacoco:report coveralls:report 44 | 45 | env: 46 | global: 47 | # Ex. travis encrypt -r org/repo BINTRAY_USER=your_github_account 48 | - secure: "QHoScwXVjj9mTZJuQ59jFvPr7Ri6tVgUyydk8Ba8CYDdgdNfnRzs3PW55g5iuC8Q8DJG6dsNfwWtYCagD8XIZw3bVE4Ic9hJJeOrY7PbaoB9gFb/emRYk83Z91xoYMXtaRCiOsxnXqMeyPd4rAc0mNOL5N00DjGVsDJp7BX4tAz0AL6mF4FNIkuuBIh7EEDpOJPSm4NXjUICaDQ8LETIVN69XvbVyoCu0lA2XIeSkXMq8O3izon4bch+fXe15z3LoWQQlmeK0YlEUZifPlIabIWErHEmjVrMVanIJu8B5SIF58pMhZ3AGL8PRBszDjMS+847LWCvW/VHsL9Le8pYXIxXksKw+DmioxudXV5jugDVy2qKsSIlUkP4MVFPwC4PktbFmn6lnYaN6YXoKj9dnGP5YjtWJdzHHqB9ovVWGq/XwI1m/V4KsMEUkX+PDlUoAa0C5iH1gCRGWfLwPw59wmxaBpsPQgAk1/2ynhNU2Q4TWDc167fZyu2O8to+nAKLX1gyLnsSKjstfWdg8LUGJJSzpNJ9OFJu1lxR/W/RQGy3Yg4nINC+nsBCBis7yRYcWHu1dm42ReFKPpzJgM2f06Hg5IA734NJFYeiHdC5mwdUNvpy/aKb30FljwhRnsczJnH9GKKi3vpTXzf0SU9VJPEuB2MwzUn6ZnI8cNtWE8U=" 49 | # Ex. travis encrypt -r org/repo BINTRAY_KEY=xxx-https://bintray.com/profile/edit-xxx --add 50 | - secure: "PAtbtImeyHnjFR+yPVKggZgXb4oMXchM6YV3+qoYs6LExiqhwRPe4e+gAhfLESHUjiEoixAM77eAuk3Cqpklwtpy3Qwh3ptDtNm1d3VycDbhMVHkeIGaCJlHTitJHwegAHedrqH4qS3sRCG1Ke5Dxs1z1NtuLnIKhoiWKMW9SdNuLt+Wo+uYJnlr2Z78AVrChSsV4CiaJ5jZlFhRHO+cf22Xdx69Z2Imh7/3X+WBXIKqqNewegBlzvtQzZsknhFHmQV8UTJ1lCw6EcGOw5DXqqcRGmkRMsITeGMaUMd21Es2MeIHVsNS6aysLeAF15pbo3C9nhGJ11JWwNaeBVSpK+s8friNEOssJdvn+2W/NKrEHeKcEDwZRqKbOqUeGkwHb4n2nZd3oqc6/0O4Wf3q4bB1Dsh1PpL0tE5oeIbeUT0JMpk+MHIxzHyt5HuPnNqCk09psNbr110DiYNNddJKZOcv/hfxTuao55tbcg7C1tWYYcFxyMN3hE+EOEqhs3e4vOldFZSuF4/3lLYKBPl+Uin8eIUdzNQ01L3iy+FdB1haLS9V+kr72ZYABW0VdAj3Sw2GGsLsv5Xw2p8U3rcJBRm4mzrMSdfdN9YX2pOA/1Ch9rOiercKoy0hg2Q8PkORBJcOKS4uGPAAqrazAkpdih+sDTn7Sq+6sN1UNUR33fw=" 51 | # Ex. travis encrypt -r org/repo GH_TOKEN=XXX-https://github.com/settings/tokens-XXX --add 52 | - secure: "p1Z3Y8cbgEpOrlejqzoR91DGlrdkCjaErDn1EfUj7AdB+B1KtYvy6XGMRfB2YTiHucK/4wFFbxgkchoqDWM/N8h+oCDi0ogJ1BmIFsb4alQJnotrDSrpI4fxAK+e0jlNrLi9PYYEftSVVh71lo6zKIE41wflK+wm90XJtf56cOSDd7q7Xip2qPP5OXcpu49Arce60+jCp2jLa+4pMiqvXQAZTsrkXdMDiPYgRfNqjT5qJ+fTNF/soIH0Vdy3yEbwrx/CwRSxumZ3ntyXZ7bxiUIMjRIhwO50nigBNJzHJqYaeguEKhfugWk+iSqxaZf9LVbSfG3c/IsvCFzna8BjSs9SV9DUe8a7x7OcvU3wlnSd4bPCvv4QDLsLfbbxhNbYg3asvRHUAOXxudA5LoLK+eZwD74efr/CHyU1uTPMwgNHUxPeLHFQJRYjq1+NTQFkp/Dc+DC8oYRv/Tf1eSHgg5d3j84eU/cClSsACf9Lt3GLziDmJCkctPA22CkrWULKSn/DrvsJqYfoBpof4AM1QBPIB2MuKuk1nHJ+vhBnfeP4bKFsMjZWZrRcWw9zt2zl7NVJFh/W4wMHiq75ZF+Z7msYKCB22e7buMTnDqNBapO6PEXmk6972Q00QmI+rFMYGEpRDgbxZixMVRcPL+89EWhAZplfbI+YiOoSZQEFPNU=" 53 | # Ex. travis encrypt -r org/repo SONATYPE_USER=your_sonatype_account 54 | - secure: "oE16AjpS/aabLRNkQN6SmyfYJwCwBqYOvqyhPPZCYDYfZpBtJHugUXdds9GYc6BXfgPKF3QJQ727dPqXrmbh9UPkSyE1LYv1De/HbGsPmwBn+S2fg1Id2BrV3qVPg7aYaO8EX0zIxfh5BxY0woC4Lj9Wl5EbTYf00h/JhCaKr1ZYR9/gzG8Ngyexr+FLlKFCKhka+3iEcwCz8feyxcPCsgGo3TiNI42Q9cLGpqGAuStQcwUZe2296qQd1Zn9khZYpP5bm7+mOCI62xXI+PEIES+ss/kB8b9pfUiHgfxtKS6gs4I3oDEelJw3fjrHdsgMs6YfLTPp9yKMMqSIzcp4dmqOf5zxadCKQ+eETervLJEngZAwzuAvdeh8/9Az8eN96FDfKWrf8tkbkdzY9Ajqk5qra4vx87ChQ/u6Am9OV6dqwIBU4i7sBUa55jXQns8gE2nT+R0xAM57Arolr768QriPAiUlom8AmeUryUWj1S8JC+jjNhw0v9wFk2JEkrY1WBrCStnCYAPZ3CP5uoNGsQS42t0Cd05TtjHjnJE8EHfHHFiWSF1+ov7GkAQQXqH473T1Be7HPJo9EQ5PRsea5li2AtTU80dBuCaeqBnE6Tm1kuiVDrDo3kO/+C5fjF065z1Xvl42pcJhlYH/uNItQbGiFfcBP6hT3szVIDeSElc=" 55 | # Ex. travis encrypt -r org/repo SONATYPE_PASSWORD=your_sonatype_password 56 | - secure: "jWfEmREf5VjjJwvlAA+11a8DYQa4ZZzhfUOkUObO0do1fG+aQtMKndesa0h8xETGggySEc5nn0e7THJ5EjBlppNtH7LqK1bfgTF4PlkMwHOkhGjLaoxCpT0HVyAaWUEZdD8uGwiY+NkLc3AC06fhB3MjpMbM82tOWXOpWLxnLpLgqP9L1DM/9uWiD36T3k6vkVABHGoGmQPgyXiTL6NHhNLVlI44L++ddXHGxrCEOs4oFhP7MXtR5T+51Bdalpj6eko4nP4/mve+5KMH8mzays04YX0F2TxtCXmgqLAeHE5AWm/A++85bJqnIwyApdT0A1NQR2GAJN6FyeA/zTCslbIMt2sqg0auXikCRbkwhom56E6KDbnyXoE9VfViMmaTT9FF/d3vIV29BiCitfbVmUMXcsFQEljhPigbva3ayHHdOsBbI2KTvH+rbzPHv6Jqp0TQJlE9qU2qTVS2bWHPyOltbyx2KiSJUwx5zqsC20J7lnPgqWCYXEVzyS2wwzFm752bxIRGAeghgVVdTnPST1Lu7Z/LQ3Vt827juk1qAU9HzVPu+OmJS6os0EIzAWZoC9KksYvslv0mUlmc5IbEDqdqK5MA/bw72Vv8KOlVbJPQ5XC26utF/44Gn35nx8OI/yg1Qkdoj/iISnk4b/oCOLr9l39xsTZUj7HhrnlLbbM=" 57 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changes by Version 2 | 3 | ## v0.33.0 (2019-05-06) 4 | 5 | * Deprecated members removed: 6 | - `ScopeManager.active()` 7 | - `ScopeManager.activate(Span, boolean)` 8 | - `Scope.span()` 9 | - `SpanBuilder.startActive()` 10 | - `Tracer.startManual()` 11 | - `AutoFinishScopeManager` 12 | 13 | ## v0.32.0 (2019-03-20) 14 | 15 | * Trace Identifiers added to `SpanContext`. 16 | * Finishing `Span` upon Scope close is deprecated overall. 17 | * `ScopeManager.active()` is deprecated. 18 | * `SpanBuilder.startActive()` is deprecated. 19 | * `AutoFinishScopeManager` is deprecated. 20 | * Added a new `Binary` format on top of `ByteBuffer`. 21 | * Added generic typed `setTag()`/`withTag()` versions. 22 | * Split Inject and Extract builtin interfaces. 23 | * `Tracer` implements `Closable`. 24 | * Added `GlobalTracer.registerIfAbsent()`. 25 | 26 | ## v0.31.0 (2018-01-12) 27 | * `BaseSpan` and `ActiveSpan` are simplified into a single `Span` class. 28 | * `Scope` replaces `ActiveSpan`, removing `Continuations`. 29 | * `ScopeManager` replaces `ActiveSpanSource`. 30 | * `Tracer.activeSpan()` returns the current value of `Tracer.scopeManager().active().span()` as a convenience. 31 | * `startManual()` deprecated in favor of `start()` 32 | * new examples directory 33 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to OpenTracing 2 | 3 | If you would like to contribute code you can do so through GitHub by forking the repository and sending a pull request (on a branch other than `master` or `gh-pages`). 4 | 5 | 6 | ## License 7 | 8 | By contributing your code, you agree to license your contribution under the terms of the APLv2: https://github.com/opentracing/opentracing-java/blob/master/LICENSE 9 | 10 | All files are released with the Apache 2.0 license. 11 | 12 | If you are adding a new file it should have a header like below. This can be automatically added by running `./mvnw com.mycila:license-maven-plugin:format`. 13 | 14 | ``` 15 | /** 16 | * Copyright 2016-2020 The OpenTracing Authors 17 | * 18 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 19 | * in compliance with the License. You may obtain a copy of the License at 20 | * 21 | * http://www.apache.org/licenses/LICENSE-2.0 22 | * 23 | * Unless required by applicable law or agreed to in writing, software distributed under the License 24 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 25 | * or implied. See the License for the specific language governing permissions and limitations under 26 | * the License. 27 | */ 28 | ``` 29 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | # OpenTracing Release Process 2 | 3 | This repo uses semantic versions. Please keep this in mind when choosing version numbers. 4 | 5 | 1. **Alert others you are releasing** 6 | 7 | There should be no commits made to master while the release is in progress (about 10 minutes). Before you start 8 | a release, alert others on [gitter](https://gitter.im/opentracing/public) so that they don't accidentally merge 9 | anything. If they do, and the build fails because of that, you'll have to recreate the release tag described below. 10 | 11 | 1. **Update Change Log** 12 | 13 | Update CHANGELOG.md with a list changes since the last release. Each entry must include the release number, 14 | date and a bulleted list of changes where each change is summarized in a single sentence. 15 | 16 | 1. **Push a git tag** 17 | 18 | The tag should be of the format `release-N.M.L`, ex `git tag release-3.7.1; git push origin release-3.7.1`. 19 | 20 | 1. **Wait for Travis CI** 21 | 22 | This part is controlled by [`travis/publish.sh`](travis/publish.sh). It creates a bunch of new commits, bumps 23 | the version, publishes artifacts, and syncs to Maven Central. 24 | 25 | ## Release candidates 26 | 27 | Repository supports releasing release candidates from branches `v.N.M.L`. The version schema 28 | for release candidates is `N.M.L-RCH`, where `H` denotes a release candidate version. 29 | 30 | To release the first release candidate switch to a branch `v.3.7.1`/`HEAD` and push a tag `release-3.7.1-RC1`. 31 | 32 | ## Credentials 33 | 34 | Credentials of various kind are needed for the release process to work. If you notice something 35 | failing due to unauthorized, re-encrypt them using instructions at the bottom of the `.travis.yml` 36 | 37 | Ex You'll see comments like this: 38 | ```yaml 39 | env: 40 | global: 41 | # Ex. travis encrypt -r org/repo BINTRAY_USER=your_github_account 42 | - secure: "VeTO... 43 | ``` 44 | 45 | To re-encrypt, you literally run the commands with relevant values and replace the "secure" key with the output: 46 | 47 | ```bash 48 | $ travis encrypt BINTRAY_USER=adrianmole 49 | Please add the following to your .travis.yml file: 50 | 51 | secure: "mQnECL+dXc5l9wCYl/wUz+AaYFGt/1G31NAZcTLf2RbhKo8mUenc4hZNjHCEv+4ZvfYLd/NoTNMhTCxmtBMz1q4CahPKLWCZLoRD1ExeXwRymJPIhxZUPzx9yHPHc5dmgrSYOCJLJKJmHiOl9/bJi123456=" 52 | ``` 53 | 54 | ## Troubleshooting 55 | 56 | Release automation doesn't tend to fail. When it does, it is usually.. 57 | * The build failed due to a unit test failure 58 | * Someone pushed a tag with incorrect syntax 59 | * The configured credentials are incorrect 60 | 61 | ### Troubleshooting invalid credentials 62 | 63 | If you receive a '401 unauthorized' failure from jCenter or Bintray, it is 64 | likely `BINTRAY_USER` or `BINTRAY_KEY` entries are invalid, or possibly the user 65 | associated with them does not have rights to upload. 66 | 67 | The least destructive test is to try to publish a snapshot manually. By passing 68 | the values Travis would use, you can kick off a snapshot from your laptop. This 69 | is a good way to validate that your unencrypted credentials are authorized. 70 | 71 | Here's an example of a snapshot deploy with specified credentials. 72 | ```bash 73 | $ BINTRAY_USER=adrianmole BINTRAY_KEY=ed6f20bde9123bbb2312b221 TRAVIS_PULL_REQUEST=false TRAVIS_TAG= TRAVIS_BRANCH=master travis/publish.sh 74 | ``` 75 | 76 | ## First release of the year 77 | 78 | The license plugin verifies license headers of files include a copyright notice indicating the years a file was affected. 79 | This information is taken from git history. There's a once-a-year problem with files that include version numbers (pom.xml). 80 | When a release tag is made, it increments version numbers, then commits them to git. On the first release of the year, 81 | further commands will fail due to the version increments invalidating the copyright statement. The way to sort this out is 82 | the following: 83 | 84 | Before you do the first release of the year, move the SNAPSHOT version back and forth from whatever the current is. 85 | In-between, re-apply the licenses. 86 | ```bash 87 | $ ./mvnw versions:set -DnewVersion=1.3.3-SNAPSHOT -DgenerateBackupPoms=false 88 | $ ./mvnw com.mycila:license-maven-plugin:format 89 | $ ./mvnw versions:set -DnewVersion=1.3.2-SNAPSHOT -DgenerateBackupPoms=false 90 | $ git commit -am"Adjusts copyright headers for this year" 91 | ``` 92 | 93 | -------------------------------------------------------------------------------- /opentracing-api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 4.0.0 19 | 20 | 21 | io.opentracing 22 | parent 23 | 0.33.1-SNAPSHOT 24 | 25 | 26 | opentracing-api 27 | OpenTracing API 28 | OpenTracing Java API 29 | 30 | 31 | ${project.basedir}/.. 32 | 1.6 33 | java16 34 | 35 | 36 | 37 | 38 | 39 | maven-jar-plugin 40 | 41 | 42 | 43 | io.opentracing.api 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /opentracing-api/src/main/java/io/opentracing/References.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing; 15 | 16 | /** 17 | * References is essentially a namespace for the official OpenTracing reference types. 18 | * 19 | * References are used by Tracer.buildSpan() to describe the relationships between Spans. 20 | * 21 | * @see Tracer.SpanBuilder#addReference(String, SpanContext) 22 | */ 23 | public final class References { 24 | private References(){} 25 | 26 | /** 27 | * See http://opentracing.io/spec/#causal-span-references for more information about CHILD_OF references 28 | */ 29 | public static final String CHILD_OF = "child_of"; 30 | 31 | /** 32 | * See http://opentracing.io/spec/#causal-span-references for more information about FOLLOWS_FROM references 33 | */ 34 | public static final String FOLLOWS_FROM = "follows_from"; 35 | } 36 | -------------------------------------------------------------------------------- /opentracing-api/src/main/java/io/opentracing/Scope.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing; 15 | 16 | import java.io.Closeable; 17 | 18 | /** 19 | * A {@link Scope} formalizes the activation and deactivation of a {@link Span}, usually from a CPU standpoint. 20 | * 21 | *

22 | * Many times a {@link Span} will be extant (in that {@link Span#finish()} has not been called) despite being in a 23 | * non-runnable state from a CPU/scheduler standpoint. For instance, a {@link Span} representing the client side of an 24 | * RPC will be unfinished but blocked on IO while the RPC is still outstanding. A {@link Scope} defines when a given 25 | * {@link Span} is scheduled and on the path. 26 | */ 27 | public interface Scope extends Closeable { 28 | /** 29 | * Mark the end of the active period for the current context (usually a thread) 30 | * and {@link Scope}, updating {@link ScopeManager#active()} and {@link ScopeManager#activeSpan()} 31 | * in the process. 32 | * 33 | *

34 | * NOTE: Calling {@link #close} more than once on a single {@link Scope} instance leads to undefined 35 | * behavior. 36 | */ 37 | @Override 38 | void close(); 39 | } 40 | -------------------------------------------------------------------------------- /opentracing-api/src/main/java/io/opentracing/ScopeManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing; 15 | 16 | import io.opentracing.Tracer.SpanBuilder; 17 | 18 | /** 19 | * The {@link ScopeManager} interface abstracts both the activation of {@link Span} instances via 20 | * {@link ScopeManager#activate(Span)} and access to an active {@link Span} 21 | * via {@link ScopeManager#activeSpan()}. 22 | * 23 | * @see Scope 24 | * @see Tracer#scopeManager() 25 | */ 26 | public interface ScopeManager { 27 | 28 | /** 29 | * Set the specified {@link Span} as the active instance for the current 30 | * context (usually a thread). 31 | * 32 | *

33 | * The returned {@link Scope} represents the active state for the span. 34 | * Once its active period is due, {@link Scope#close()} ought to be called. 35 | * To ease this operation, {@link Scope} supports try-with-resources. 36 | * Observe the span will not be automatically finished when {@link Scope#close()} 37 | * is called. 38 | * 39 | *

40 | * The corresponding {@link Span} can be accessed at any time through {@link #activeSpan()}. 41 | * 42 | *

43 | * Usage: 44 | *


45 |      *     Span span = tracer.buildSpan("...").start();
46 |      *     try (Scope scope = tracer.scopeManager().activate(span)) {
47 |      *         span.setTag("...", "...");
48 |      *         ...
49 |      *     } catch (Exception e) {
50 |      *         span.log(...);
51 |      *     } finally {
52 |      *         // Optionally finish the Span if the operation it represents
53 |      *         // is logically completed at this point.
54 |      *         span.finish();
55 |      *     }
56 |      * 
57 | * 58 | * @param span the {@link Span} that should become the {@link #activeSpan()} 59 | * @return a {@link Scope} instance to control the end of the active period for the {@link Span}. It is a 60 | * programming error to neglect to call {@link Scope#close()} on the returned instance. 61 | */ 62 | Scope activate(Span span); 63 | 64 | /** 65 | * Return the currently active {@link Span}. 66 | * 67 | *

68 | * Because both {@link #active()} and {@link #activeSpan()} reference the current 69 | * active state, they both will be either null or non-null. 70 | * 71 | * @return the {@link Span active span}, or null if none could be found. 72 | */ 73 | Span activeSpan(); 74 | } 75 | -------------------------------------------------------------------------------- /opentracing-api/src/main/java/io/opentracing/SpanContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing; 15 | 16 | import java.util.Map; 17 | 18 | /** 19 | * SpanContext represents Span state that must propagate to descendant Spans and across process boundaries. 20 | * 21 | * SpanContext is logically divided into two pieces: (1) the user-level "Baggage" that propagates across Span 22 | * boundaries and (2) any Tracer-implementation-specific fields that are needed to identify or otherwise contextualize 23 | * the associated Span instance (e.g., a <trace_id, span_id, sampled> tuple). 24 | * 25 | * @see Span#setBaggageItem(String, String) 26 | * @see Span#getBaggageItem(String) 27 | */ 28 | public interface SpanContext { 29 | /** 30 | * Return the ID of the trace. 31 | * 32 | * Should be globally unique. Every span in a trace shares this ID. 33 | * 34 | * An empty String will be returned if the tracer does not support this functionality 35 | * (this is the case for no-op tracers, for example). null is an invalid return value. 36 | * 37 | * @return the trace ID for this context. 38 | */ 39 | String toTraceId(); 40 | 41 | /** 42 | * Return the ID of the associated Span. 43 | * 44 | * Should be unique within a trace. Each span within a trace contains a different ID. 45 | * 46 | * An empty String will be returned if the tracer does not support this functionality 47 | * (this is the case for no-op tracers, for example). null is an invalid return value. 48 | * 49 | * @return the Span ID for this context. 50 | */ 51 | String toSpanId(); 52 | 53 | /** 54 | * @return all zero or more baggage items propagating along with the associated Span 55 | * 56 | * @see Span#setBaggageItem(String, String) 57 | * @see Span#getBaggageItem(String) 58 | */ 59 | Iterable> baggageItems(); 60 | } 61 | -------------------------------------------------------------------------------- /opentracing-api/src/main/java/io/opentracing/log/Fields.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.log; 15 | 16 | /** 17 | * The following log fields are recommended for instrumentors who are trying to capture more 18 | * information about a logged event. Tracers may expose additional features based on these 19 | * standardized data points. 20 | * 21 | * @see https://github.com/opentracing/specification/blob/master/semantic_conventions.md 22 | */ 23 | public class Fields { 24 | private Fields() { 25 | } 26 | 27 | /** 28 | * The type or "kind" of an error (only for event="error" logs). E.g., "Exception", "OSError" 29 | */ 30 | public static final String ERROR_KIND = "error.kind"; 31 | 32 | /** 33 | * The actual Throwable/Exception/Error object instance itself. E.g., A java.lang.UnsupportedOperationException instance 34 | */ 35 | public static final String ERROR_OBJECT = "error.object"; 36 | 37 | /** 38 | * A stable identifier for some notable moment in the lifetime of a Span. For instance, a mutex 39 | * lock acquisition or release or the sorts of lifetime events in a browser page load described 40 | * in the Performance.timing specification. E.g., from Zipkin, "cs", "sr", "ss", or "cr". Or, 41 | * more generally, "initialized" or "timed out". For errors, "error" 42 | */ 43 | public static final String EVENT = "event"; 44 | 45 | /** 46 | * A concise, human-readable, one-line message explaining the event. E.g., "Could not connect 47 | * to backend", "Cache invalidation succeeded" 48 | */ 49 | public static final String MESSAGE = "message"; 50 | 51 | /** 52 | * A stack trace in platform-conventional format; may or may not pertain to an error. 53 | */ 54 | public static final String STACK = "stack"; 55 | } 56 | -------------------------------------------------------------------------------- /opentracing-api/src/main/java/io/opentracing/propagation/Binary.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.propagation; 15 | 16 | import io.opentracing.SpanContext; 17 | import java.nio.ByteBuffer; 18 | 19 | /** 20 | * Binary is an interface defining the required operations for a binary carrier for 21 | * Tracer.inject() and Tracer.extract(). Binary can be defined either as inbound (extraction) 22 | * or outbound (injection). 23 | * 24 | * When Binary is defined as inbound, extractionBuffer() will be called to retrieve the ByteBuffer 25 | * containing the data used for SpanContext extraction. 26 | * 27 | * When Binary is defined as outbound, setInjectBufferLength() will be called in order to hint 28 | * the required buffer length to inject the SpanContext, and injectionBuffer() will be called 29 | * afterwards to retrieve the actual ByteBuffer used for the SpanContext injection. 30 | * 31 | * @see Format.Builtin#BINARY 32 | * @see io.opentracing.Tracer#inject(SpanContext, Format, Object) 33 | * @see io.opentracing.Tracer#extract(Format, Object) 34 | */ 35 | public interface Binary extends BinaryInject, BinaryExtract { 36 | } 37 | -------------------------------------------------------------------------------- /opentracing-api/src/main/java/io/opentracing/propagation/BinaryAdapters.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.propagation; 15 | 16 | import java.nio.ByteBuffer; 17 | 18 | public final class BinaryAdapters { 19 | 20 | private BinaryAdapters() {} 21 | 22 | /** 23 | * Creates an inbound Binary instance used for extraction with the 24 | * specified ByteBuffer as input. 25 | * 26 | * @param buffer The ByteBuffer used as input. 27 | * 28 | * @return The new {@link Binary} carrier used for extraction. 29 | */ 30 | public static BinaryExtract extractionCarrier(ByteBuffer buffer) { 31 | if (buffer == null) { 32 | throw new NullPointerException(); 33 | } 34 | 35 | return new BinaryExtractAdapter(buffer); 36 | } 37 | 38 | /** 39 | * Creates an outbound {@link Binary} instance used for injection with the 40 | * specified ByteBuffer as output. ByteBuffer.limit() will be set to the value 41 | * of the requested length at {@link BinaryInject#injectionBuffer} time, and 42 | * AssertionError will be thrown if the requested length is larger than 43 | * the remaining length of ByteBuffer. 44 | * 45 | * @param buffer The ByteBuffer used as input. 46 | * 47 | * @return The new Binary carrier used for injection. 48 | */ 49 | public static BinaryInject injectionCarrier(ByteBuffer buffer) { 50 | return new BinaryInjectAdapter(buffer); 51 | } 52 | 53 | static class BinaryExtractAdapter implements BinaryExtract { 54 | ByteBuffer buffer; 55 | 56 | public BinaryExtractAdapter(ByteBuffer buffer) { 57 | this.buffer = buffer; 58 | } 59 | 60 | @Override 61 | public ByteBuffer extractionBuffer() { 62 | return buffer; 63 | } 64 | } 65 | 66 | static class BinaryInjectAdapter implements BinaryInject { 67 | ByteBuffer buffer; 68 | 69 | public BinaryInjectAdapter(ByteBuffer buffer) { 70 | this.buffer = buffer; 71 | } 72 | 73 | @Override 74 | public ByteBuffer injectionBuffer(int length) { 75 | if (length < 1) { 76 | throw new IllegalArgumentException("length needs to be larger than 0"); 77 | } 78 | if (length > buffer.remaining()) { 79 | throw new AssertionError("length is larger than the backing ByteBuffer remaining length"); 80 | } 81 | 82 | buffer.limit(buffer.position() + length); 83 | return buffer; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /opentracing-api/src/main/java/io/opentracing/propagation/BinaryExtract.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.propagation; 15 | 16 | import io.opentracing.SpanContext; 17 | import io.opentracing.Tracer; 18 | import java.nio.ByteBuffer; 19 | 20 | /** 21 | * {@link BinaryExtract} is an interface defining the required operations for a binary carrier for 22 | * {@link Tracer#extract} only. {@link BinaryExtract} is defined as inbound (extraction). 23 | * 24 | * When called with {@link Tracer#extract}, {@link #extractionBuffer} will be called to retrieve the {@link ByteBuffer} 25 | * containing the data used for {@link SpanContext} extraction. 26 | * 27 | * @see Format.Builtin#BINARY 28 | * @see io.opentracing.Tracer#extract(Format, Object) 29 | */ 30 | public interface BinaryExtract { 31 | 32 | /** 33 | * Gets the buffer containing the data used for {@link SpanContext} extraction. 34 | * 35 | * It is an error to call this method when Binary is used 36 | * for {@link SpanContext} injection. 37 | * 38 | * @return The buffer used for {@link SpanContext} extraction. 39 | */ 40 | ByteBuffer extractionBuffer(); 41 | } 42 | -------------------------------------------------------------------------------- /opentracing-api/src/main/java/io/opentracing/propagation/BinaryInject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.propagation; 15 | 16 | import io.opentracing.SpanContext; 17 | import io.opentracing.Tracer; 18 | import java.nio.ByteBuffer; 19 | 20 | /** 21 | * {@link BinaryInject} is an interface defining the required operations for a binary carrier for 22 | * {@link Tracer#inject} only. {@link BinaryInject} is defined as outbound (injection). 23 | * 24 | * When called with {@link Tracer#inject}, {@link #injectionBuffer} will be called 25 | * to retrieve the actual {@link ByteBuffer} used for the {@link SpanContext} injection. 26 | * 27 | * @see Format.Builtin#BINARY 28 | * @see io.opentracing.Tracer#inject(SpanContext, Format, Object) 29 | */ 30 | public interface BinaryInject { 31 | /** 32 | * Gets the buffer used to store data as part of {@link SpanContext} injection. 33 | * 34 | * The lenght parameter hints the buffer length required for 35 | * {@link SpanContext} injection. The user may use this to allocate a new 36 | * ByteBuffer or resize an existing one. 37 | * 38 | * It is an error to call this method when Binary is used 39 | * for {@link SpanContext} extraction. 40 | * 41 | * @param length The buffer length required for {@link SpanContext} injection. 42 | * It needs to be larger than zero. 43 | * 44 | * @return The buffer used for {@link SpanContext} injection. 45 | */ 46 | ByteBuffer injectionBuffer(int length); 47 | } 48 | -------------------------------------------------------------------------------- /opentracing-api/src/main/java/io/opentracing/propagation/Format.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.propagation; 15 | 16 | import io.opentracing.SpanContext; 17 | import io.opentracing.Tracer; 18 | 19 | /** 20 | * Format instances control the behavior of Tracer.inject and Tracer.extract (and also constrain the type of the 21 | * carrier parameter to same). 22 | * 23 | * Most OpenTracing users will only reference the Format.Builtin constants. For example: 24 | * 25 | *


 26 |  * Tracer tracer = ...
 27 |  * io.opentracing.propagation.TextMap httpCarrier = new AnHttpHeaderCarrier(httpRequest);
 28 |  * SpanContext spanCtx = tracer.extract(Format.Builtin.HTTP_HEADERS, httpCarrier);
 29 |  * 
30 | * 31 | * @see Tracer#inject(SpanContext, Format, Object) 32 | * @see Tracer#extract(Format, Object) 33 | */ 34 | public interface Format { 35 | final class Builtin implements Format { 36 | private final String name; 37 | 38 | private Builtin(String name) { 39 | this.name = name; 40 | } 41 | 42 | /** 43 | * The TEXT_MAP format allows for arbitrary String->String map encoding of SpanContext state for 44 | * Tracer.inject and Tracer.extract. 45 | * 46 | * Unlike HTTP_HEADERS, the builtin TEXT_MAP format expresses no constraints on keys or values. 47 | * 48 | * @see io.opentracing.Tracer#inject(SpanContext, Format, Object) 49 | * @see io.opentracing.Tracer#extract(Format, Object) 50 | * @see Format 51 | * @see Builtin#HTTP_HEADERS 52 | */ 53 | public final static Format TEXT_MAP = new Builtin("TEXT_MAP"); 54 | 55 | /** 56 | * Like {@link Builtin#TEXT_MAP} but specific for calling {@link Tracer#inject} with. 57 | * 58 | * @see io.opentracing.Tracer#inject(SpanContext, Format, Object) 59 | * @see Format 60 | */ 61 | public final static Format TEXT_MAP_INJECT = new Builtin("TEXT_MAP_INJECT"); 62 | 63 | /** 64 | * Like {@link Builtin#TEXT_MAP} but specific for calling {@link Tracer#extract} with. 65 | * 66 | * @see io.opentracing.Tracer#extract(Format, Object) 67 | * @see Format 68 | */ 69 | public final static Format TEXT_MAP_EXTRACT = new Builtin("TEXT_MAP_EXTRACT"); 70 | 71 | /** 72 | * The HTTP_HEADERS format allows for HTTP-header-compatible String->String map encoding of SpanContext state 73 | * for Tracer.inject and Tracer.extract. 74 | * 75 | * I.e., keys written to the TextMap MUST be suitable for HTTP header keys (which are poorly defined but 76 | * certainly restricted); and similarly for values (i.e., URL-escaped and "not too long"). 77 | * 78 | * @see io.opentracing.Tracer#inject(SpanContext, Format, Object) 79 | * @see io.opentracing.Tracer#extract(Format, Object) 80 | * @see Format 81 | * @see Builtin#TEXT_MAP 82 | */ 83 | public final static Format HTTP_HEADERS = new Builtin("HTTP_HEADERS"); 84 | 85 | /** 86 | * The BINARY format allows for unconstrained binary encoding of SpanContext state for Tracer.inject and 87 | * Tracer.extract. 88 | * 89 | * @see io.opentracing.Tracer#inject(SpanContext, Format, Object) 90 | * @see io.opentracing.Tracer#extract(Format, Object) 91 | * @see Format 92 | */ 93 | public final static Format BINARY = new Builtin("BINARY"); 94 | 95 | /** 96 | * Like {@link Builtin#BINARY} but specific for calling {@link Tracer#inject} with. 97 | * 98 | * @see io.opentracing.Tracer#inject(SpanContext, Format, Object) 99 | * @see Format 100 | */ 101 | public final static Format BINARY_INJECT = new Builtin("BINARY_INJECT"); 102 | 103 | /** 104 | * Like {@link Builtin#BINARY} but specific for calling {@link Tracer#extract} with. 105 | * 106 | * @see io.opentracing.Tracer#extract(Format, Object) 107 | * @see Format 108 | */ 109 | public final static Format BINARY_EXTRACT = new Builtin("BINARY_EXTRACT"); 110 | 111 | /** 112 | * @return Short name for built-in formats as they tend to show up in exception messages. 113 | */ 114 | @Override 115 | public String toString() { 116 | return Builtin.class.getSimpleName() + "." + name; 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /opentracing-api/src/main/java/io/opentracing/propagation/TextMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.propagation; 15 | 16 | import io.opentracing.SpanContext; 17 | import java.util.Iterator; 18 | 19 | import java.util.Map; 20 | 21 | /** 22 | * TextMap is a built-in carrier for Tracer.inject() and Tracer.extract(). TextMap implementations allows Tracers to 23 | * read and write key:value String pairs from arbitrary underlying sources of data. 24 | * 25 | * @see io.opentracing.Tracer#inject(SpanContext, Format, Object) 26 | * @see io.opentracing.Tracer#extract(Format, Object) 27 | */ 28 | public interface TextMap extends TextMapInject, TextMapExtract { 29 | } 30 | -------------------------------------------------------------------------------- /opentracing-api/src/main/java/io/opentracing/propagation/TextMapAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.propagation; 15 | 16 | import io.opentracing.SpanContext; 17 | import io.opentracing.Tracer; 18 | import java.util.Map; 19 | 20 | /** 21 | * A {@link TextMap} carrier for use with {@link Tracer#inject} and {@link Tracer#extract}. 22 | * 23 | * @see Tracer#inject(SpanContext, Format, Object) 24 | * @see Tracer#extract(Format, Object) 25 | */ 26 | public class TextMapAdapter extends TextMapExtractAdapter implements TextMap { 27 | public TextMapAdapter(Map map) { 28 | super(map); 29 | } 30 | 31 | @Override 32 | public void put(String key, String value) { 33 | map.put(key, value); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /opentracing-api/src/main/java/io/opentracing/propagation/TextMapExtract.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.propagation; 15 | 16 | import io.opentracing.SpanContext; 17 | import io.opentracing.Tracer; 18 | import java.util.Iterator; 19 | import java.util.Map; 20 | 21 | /** 22 | * {@link TextMapExtract} is a built-in carrier for {@link Tracer#extract} only. 23 | * {@link TextMapExtract} implementations allows Tracers to write key:value String 24 | * pairs to arbitrary underlying sources of data. 25 | * 26 | * @see io.opentracing.Tracer#extract(Format, Object) 27 | */ 28 | public interface TextMapExtract extends Iterable> { 29 | /** 30 | * Gets an iterator over arbitrary key:value pairs from the TextMapReader. 31 | * 32 | * @return entries in the TextMap backing store; note that for some Formats, the iterator may include entries that 33 | * were never injected by a Tracer implementation (e.g., unrelated HTTP headers) 34 | * 35 | * @see io.opentracing.Tracer#extract(Format, Object) 36 | * @see Format.Builtin#TEXT_MAP 37 | * @see Format.Builtin#HTTP_HEADERS 38 | */ 39 | Iterator> iterator(); 40 | } 41 | -------------------------------------------------------------------------------- /opentracing-api/src/main/java/io/opentracing/propagation/TextMapExtractAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.propagation; 15 | 16 | import io.opentracing.Tracer; 17 | import java.util.Iterator; 18 | 19 | import java.util.Map; 20 | 21 | /** 22 | * A TextMap carrier for use with Tracer.extract() ONLY (it has no mutating methods). 23 | * 24 | * Note that the TextMap interface can be made to wrap around arbitrary data types (not just Map<String, String> 25 | * as illustrated here). 26 | * 27 | * @see Tracer#extract(Format, Object) 28 | */ 29 | public class TextMapExtractAdapter implements TextMapExtract { 30 | protected final Map map; 31 | 32 | public TextMapExtractAdapter(final Map map) { 33 | this.map = map; 34 | } 35 | 36 | @Override 37 | public Iterator> iterator() { 38 | return map.entrySet().iterator(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /opentracing-api/src/main/java/io/opentracing/propagation/TextMapInject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.propagation; 15 | 16 | import io.opentracing.SpanContext; 17 | import io.opentracing.Tracer; 18 | 19 | /** 20 | * {@link TextMapInject} is a built-in carrier for {@link Tracer#inject} only. 21 | * {@link TextMapInject} implementations allows Tracers to read key:value String 22 | * pairs from arbitrary underlying sources of data. 23 | * 24 | * @see io.opentracing.Tracer#inject(SpanContext, Format, Object) 25 | */ 26 | public interface TextMapInject { 27 | 28 | /** 29 | * Puts a key:value pair into the TextMapWriter's backing store. 30 | * 31 | * @param key a String, possibly with constraints dictated by the particular Format this TextMap is paired with 32 | * @param value a String, possibly with constraints dictated by the particular Format this TextMap is paired with 33 | * 34 | * @see io.opentracing.Tracer#inject(io.opentracing.SpanContext, Format, Object) 35 | * @see Format.Builtin#TEXT_MAP 36 | * @see Format.Builtin#HTTP_HEADERS 37 | */ 38 | void put(String key, String value); 39 | } 40 | -------------------------------------------------------------------------------- /opentracing-api/src/main/java/io/opentracing/propagation/TextMapInjectAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.propagation; 15 | 16 | import io.opentracing.SpanContext; 17 | import io.opentracing.Tracer; 18 | import java.util.Iterator; 19 | 20 | import java.util.Map; 21 | 22 | /** 23 | * A TextMap carrier for use with Tracer.inject() ONLY (it has no read methods). 24 | * 25 | * Note that the TextMap interface can be made to wrap around arbitrary data types (not just Map<String, String> 26 | * as illustrated here). 27 | * 28 | * @see Tracer#inject(SpanContext, Format, Object) 29 | */ 30 | public class TextMapInjectAdapter implements TextMapInject { 31 | protected final Map map; 32 | 33 | public TextMapInjectAdapter(final Map map) { 34 | this.map = map; 35 | } 36 | 37 | @Override 38 | public void put(String key, String value) { 39 | this.map.put(key, value); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /opentracing-api/src/main/java/io/opentracing/tag/AbstractTag.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.tag; 15 | 16 | import io.opentracing.Span; 17 | 18 | public abstract class AbstractTag implements Tag { 19 | protected final String key; 20 | 21 | public AbstractTag(String tagKey) { 22 | this.key = tagKey; 23 | } 24 | 25 | @Override 26 | public String getKey() { 27 | return key; 28 | } 29 | 30 | @Override 31 | public abstract void set(Span span, T tagValue); 32 | } 33 | -------------------------------------------------------------------------------- /opentracing-api/src/main/java/io/opentracing/tag/BooleanTag.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.tag; 15 | 16 | import io.opentracing.Span; 17 | 18 | public class BooleanTag extends AbstractTag { 19 | public BooleanTag(String key) { 20 | super(key); 21 | } 22 | 23 | @Override 24 | public void set(Span span, Boolean tagValue) { 25 | span.setTag(super.key, tagValue); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /opentracing-api/src/main/java/io/opentracing/tag/IntOrStringTag.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.tag; 15 | 16 | import io.opentracing.Span; 17 | 18 | public class IntOrStringTag extends IntTag { 19 | public IntOrStringTag(String key) { 20 | super(key); 21 | } 22 | 23 | public void set(Span span, String tagValue) { 24 | span.setTag(super.key, tagValue); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /opentracing-api/src/main/java/io/opentracing/tag/IntTag.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.tag; 15 | 16 | import io.opentracing.Span; 17 | 18 | public class IntTag extends AbstractTag { 19 | public IntTag(String key) { 20 | super(key); 21 | } 22 | 23 | @Override 24 | public void set(Span span, Integer tagValue) { 25 | span.setTag(super.key, tagValue); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /opentracing-api/src/main/java/io/opentracing/tag/StringTag.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.tag; 15 | 16 | import io.opentracing.Span; 17 | 18 | public class StringTag extends AbstractTag { 19 | public StringTag(String key) { 20 | super(key); 21 | } 22 | 23 | @Override 24 | public void set(Span span, String tagValue) { 25 | span.setTag(super.key, tagValue); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /opentracing-api/src/main/java/io/opentracing/tag/Tag.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.tag; 15 | 16 | import io.opentracing.Span; 17 | 18 | public interface Tag { 19 | String getKey(); 20 | void set(Span span, T value); 21 | } 22 | -------------------------------------------------------------------------------- /opentracing-api/src/test/java/io/opentracing/AssertionTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing; 15 | 16 | import org.junit.Test; 17 | 18 | public final class AssertionTest { 19 | 20 | @Test 21 | public void test_assertions_enabled() { 22 | boolean asserted = false; 23 | try { 24 | assert false; 25 | } catch (AssertionError error) { 26 | asserted = true; 27 | } 28 | if (!asserted) { 29 | throw new AssertionError("assertions are not enabled"); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /opentracing-api/src/test/java/io/opentracing/propagation/BinaryAdaptersTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.propagation; 15 | 16 | import java.nio.ByteBuffer; 17 | import org.junit.Test; 18 | 19 | import static org.junit.Assert.assertArrayEquals; 20 | import static org.junit.Assert.assertEquals; 21 | import static org.junit.Assert.assertNotNull; 22 | 23 | public class BinaryAdaptersTest { 24 | 25 | @Test 26 | public void testExtractBinary() { 27 | ByteBuffer buff = ByteBuffer.wrap(new byte[0]); 28 | BinaryExtract binary = BinaryAdapters.extractionCarrier(buff); 29 | assertEquals(buff, binary.extractionBuffer()); 30 | } 31 | 32 | @Test(expected = NullPointerException.class) 33 | public void testExtractBinaryNull() { 34 | BinaryAdapters.extractionCarrier(null); 35 | } 36 | 37 | @Test 38 | public void testInjectBinary() { 39 | ByteBuffer buffer = ByteBuffer.allocate(1); 40 | BinaryInject binary = BinaryAdapters.injectionCarrier(buffer); 41 | assertEquals(buffer, binary.injectionBuffer(1)); 42 | assertEquals(0, buffer.position()); 43 | } 44 | 45 | @Test(expected = IllegalArgumentException.class) 46 | public void testInjectBinaryInvalidLength() { 47 | BinaryInject binary = BinaryAdapters.injectionCarrier(ByteBuffer.allocate(1)); 48 | binary.injectionBuffer(0); 49 | } 50 | 51 | @Test(expected = AssertionError.class) 52 | public void testInjectBinaryLargerLength() { 53 | BinaryInject binary = BinaryAdapters.injectionCarrier(ByteBuffer.allocate(1)); 54 | binary.injectionBuffer(2); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /opentracing-api/src/test/java/io/opentracing/propagation/BuiltinFormatTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.propagation; 15 | 16 | import org.junit.Test; 17 | 18 | import static org.junit.Assert.assertEquals; 19 | 20 | public class BuiltinFormatTest { 21 | 22 | @Test 23 | public void test_HTTP_HEADERS_toString() { 24 | assertEquals("Builtin.HTTP_HEADERS", Format.Builtin.HTTP_HEADERS.toString()); 25 | } 26 | 27 | @Test 28 | public void test_TEXT_MAP_toString() { 29 | assertEquals("Builtin.TEXT_MAP", Format.Builtin.TEXT_MAP.toString()); 30 | assertEquals("Builtin.TEXT_MAP_INJECT", Format.Builtin.TEXT_MAP_INJECT.toString()); 31 | assertEquals("Builtin.TEXT_MAP_EXTRACT", Format.Builtin.TEXT_MAP_EXTRACT.toString()); 32 | } 33 | 34 | @Test 35 | public void test_BINARY_toString() { 36 | assertEquals("Builtin.BINARY", Format.Builtin.BINARY.toString()); 37 | assertEquals("Builtin.BINARY_INJECT", Format.Builtin.BINARY_INJECT.toString()); 38 | assertEquals("Builtin.BINARY_EXTRACT", Format.Builtin.BINARY_EXTRACT.toString()); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /opentracing-api/src/test/java/io/opentracing/propagation/TextMapExtractAdapterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.propagation; 15 | 16 | import static org.junit.Assert.assertEquals; 17 | import static org.junit.Assert.assertFalse; 18 | import static org.junit.Assert.assertTrue; 19 | 20 | import java.util.Iterator; 21 | import java.util.LinkedHashMap; 22 | import java.util.Map; 23 | import java.util.Map.Entry; 24 | import org.junit.Test; 25 | 26 | /** 27 | * @author Pavol Loffay 28 | */ 29 | public class TextMapExtractAdapterTest { 30 | 31 | @Test 32 | public void testIterator() { 33 | Map headers = new LinkedHashMap(); 34 | headers.put("foo", "bar"); 35 | TextMapExtractAdapter extractAdapter = new TextMapExtractAdapter(headers); 36 | 37 | Iterator> iterator = extractAdapter.iterator(); 38 | assertTrue(iterator.hasNext()); 39 | assertEquals("bar", iterator.next().getValue()); 40 | assertFalse(iterator.hasNext()); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /opentracing-api/src/test/java/io/opentracing/propagation/TextMapInjectAdapterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.propagation; 15 | 16 | import static org.junit.Assert.assertEquals; 17 | 18 | import java.util.LinkedHashMap; 19 | import java.util.Map; 20 | import org.junit.Test; 21 | 22 | /** 23 | * @author Pavol Loffay 24 | */ 25 | public class TextMapInjectAdapterTest { 26 | 27 | @Test 28 | public void testPut() { 29 | Map headers = new LinkedHashMap(); 30 | TextMapInjectAdapter injectAdapter = new TextMapInjectAdapter(headers); 31 | injectAdapter.put("foo", "bar"); 32 | 33 | assertEquals("bar", headers.get("foo")); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /opentracing-api/src/test/java/io/opentracing/tag/AbstractTagTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.tag; 15 | 16 | import static org.junit.Assert.assertEquals; 17 | import static org.mockito.Mockito.mock; 18 | import static org.mockito.Mockito.verify; 19 | 20 | import io.opentracing.Span; 21 | import org.junit.Test; 22 | 23 | /** 24 | * @author Pavol Loffay 25 | */ 26 | public class AbstractTagTest { 27 | 28 | @Test 29 | public void testGetKey() { 30 | String key = "bar"; 31 | StringTag tag = new StringTag(key); 32 | assertEquals(key, tag.getKey()); 33 | } 34 | 35 | @Test 36 | public void testSetTagOnSpan() { 37 | String value = "foo"; 38 | String key = "bar"; 39 | 40 | Span activeSpan = mock(Span.class); 41 | StringTag tag = new StringTag(key); 42 | tag.set(activeSpan, value); 43 | 44 | verify(activeSpan).setTag(key, value); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /opentracing-api/src/test/java/io/opentracing/tag/BooleanTagTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.tag; 15 | 16 | import io.opentracing.Span; 17 | import org.junit.Test; 18 | 19 | import static org.mockito.Mockito.mock; 20 | import static org.mockito.Mockito.verify; 21 | 22 | public class BooleanTagTest { 23 | @Test 24 | public void testSetBoolean() { 25 | Boolean value = true; 26 | String key = "expected.key"; 27 | Span span = mock(Span.class); 28 | 29 | BooleanTag tag = new BooleanTag(key); 30 | tag.set(span, value); 31 | 32 | verify(span).setTag(key, value); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /opentracing-api/src/test/java/io/opentracing/tag/IntTagTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.tag; 15 | 16 | import io.opentracing.Span; 17 | import org.junit.Test; 18 | 19 | import static org.mockito.Mockito.mock; 20 | import static org.mockito.Mockito.verify; 21 | 22 | public class IntTagTest { 23 | @Test 24 | public void testSetInt() { 25 | Integer value = 7; 26 | String key = "expected.key"; 27 | Span span = mock(Span.class); 28 | 29 | IntTag tag = new IntTag(key); 30 | tag.set(span, value); 31 | 32 | verify(span).setTag(key, value); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /opentracing-api/src/test/java/io/opentracing/tag/StringTagTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.tag; 15 | 16 | import static org.mockito.Mockito.mock; 17 | import static org.mockito.Mockito.verify; 18 | 19 | import io.opentracing.Span; 20 | import org.junit.Test; 21 | 22 | public class StringTagTest { 23 | 24 | @Test 25 | public void testSetString() { 26 | String value = "expected.value"; 27 | String key = "expected.key"; 28 | 29 | Span span = mock(Span.class); 30 | StringTag tag = new StringTag(key); 31 | tag.set(span, value); 32 | 33 | verify(span).setTag(key, value); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /opentracing-mock/README.md: -------------------------------------------------------------------------------- 1 | # OpenTracing-Java Mock Tracer 2 | 3 | The `opentracing-mock` artifact (and `io.opentracing.mock.MockTracer` in particular) make it easy to unittest the semantics of OpenTracing instrumentation. 4 | 5 | ## Example Usage 6 | 7 | Imagine the following (admittedly unrealistic) OpenTracing-instrumented application code: 8 | 9 | ```java 10 | public void handlePurchase(User user, Item item, Tracer tracer) { 11 | try (Scope scope = tracer.buildSpan("handlePurchase").startActive()) { 12 | scope.span().setTag("username", user.getUsername()); 13 | } 14 | } 15 | ``` 16 | 17 | Using `MockTracer`, one could write a unittest for the above instrumentation like so: 18 | 19 | ```java 20 | @Test 21 | public void testHandlePurchaseTracing() { 22 | // Initialize the MockTracer and call handlePurchase(). 23 | MockTracer tracer = new MockTracer(); 24 | foo.handlePurchase(..., ..., tracer); 25 | 26 | // Verify that the instrumentation generates the expected Span data. 27 | List finishedSpans = tracer.finishedSpans(); 28 | assertEquals(1, finishedSpans.size()); 29 | MockSpan finishedSpan = finishedSpans.get(0); 30 | assertEquals("handlePurchase", finishedSpan.operationName()); 31 | Map tags = finishedSpan.tags(); 32 | assertEquals(1, tags.size()); 33 | assertEquals("mockUsername", tags.get("username")); 34 | } 35 | ``` 36 | -------------------------------------------------------------------------------- /opentracing-mock/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 4.0.0 19 | 20 | 21 | io.opentracing 22 | parent 23 | 0.33.1-SNAPSHOT 24 | 25 | 26 | opentracing-mock 27 | OpenTracing-mock 28 | OpenTracing Mock Tracer 29 | 30 | 31 | ${project.basedir}/.. 32 | 33 | 34 | 35 | 36 | ${project.groupId} 37 | opentracing-api 38 | 39 | 40 | io.opentracing 41 | opentracing-noop 42 | 43 | 44 | io.opentracing 45 | opentracing-util 46 | 47 | 48 | 49 | 50 | 51 | 52 | maven-jar-plugin 53 | 54 | 55 | 56 | io.opentracing.mock 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /opentracing-mock/src/test/java/io/opentracing/mock/MockSpanTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.mock; 15 | 16 | import org.junit.Assert; 17 | import org.junit.Test; 18 | 19 | import io.opentracing.Span; 20 | 21 | /** 22 | * @author Pavol Loffay 23 | */ 24 | public class MockSpanTest { 25 | 26 | @Test 27 | public void testSetOperationNameAfterFinish() { 28 | MockTracer tracer = new MockTracer(); 29 | Span span = tracer.buildSpan("foo").start(); 30 | span.finish(); 31 | 32 | try { 33 | span.setOperationName("bar"); 34 | Assert.fail(); 35 | } catch (RuntimeException ex) { 36 | } 37 | Assert.assertEquals(1, tracer.finishedSpans().get(0).generatedErrors().size()); 38 | } 39 | 40 | @Test 41 | public void testSetTagAfterFinish() { 42 | MockTracer tracer = new MockTracer(); 43 | Span span = tracer.buildSpan("foo").start(); 44 | span.finish(); 45 | 46 | try { 47 | span.setTag("bar", "foo"); 48 | Assert.fail(); 49 | } catch (RuntimeException ex) { 50 | } 51 | Assert.assertEquals(1, tracer.finishedSpans().get(0).generatedErrors().size()); 52 | } 53 | 54 | @Test 55 | public void testAddLogAfterFinish() { 56 | MockTracer tracer = new MockTracer(); 57 | Span span = tracer.buildSpan("foo").start(); 58 | span.finish(); 59 | 60 | try { 61 | span.log("bar"); 62 | Assert.fail(); 63 | } catch (RuntimeException ex) { 64 | } 65 | Assert.assertEquals(1, tracer.finishedSpans().get(0).generatedErrors().size()); 66 | } 67 | 68 | @Test 69 | public void testAddBaggageAfterFinish() { 70 | MockTracer tracer = new MockTracer(); 71 | Span span = tracer.buildSpan("foo").start(); 72 | span.finish(); 73 | 74 | try { 75 | span.setBaggageItem("foo", "bar"); 76 | Assert.fail(); 77 | } catch (RuntimeException ex) { 78 | } 79 | Assert.assertEquals(1, tracer.finishedSpans().get(0).generatedErrors().size()); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /opentracing-noop/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 4.0.0 19 | 20 | 21 | io.opentracing 22 | parent 23 | 0.33.1-SNAPSHOT 24 | 25 | 26 | opentracing-noop 27 | OpenTracing-noop 28 | OpenTracing NoOp 29 | 30 | 31 | ${project.basedir}/.. 32 | 1.6 33 | 34 | 35 | 36 | 37 | ${project.groupId} 38 | opentracing-api 39 | 40 | 41 | 42 | 43 | 44 | 45 | maven-jar-plugin 46 | 47 | 48 | 49 | io.opentracing.noop 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /opentracing-noop/src/main/java/io/opentracing/noop/NoopScopeManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.noop; 15 | 16 | import io.opentracing.Scope; 17 | import io.opentracing.ScopeManager; 18 | import io.opentracing.Span; 19 | 20 | public interface NoopScopeManager extends ScopeManager { 21 | NoopScopeManager INSTANCE = new NoopScopeManagerImpl(); 22 | 23 | interface NoopScope extends Scope { 24 | NoopScope INSTANCE = new NoopScopeManagerImpl.NoopScopeImpl(); 25 | } 26 | } 27 | 28 | /** 29 | * A noop (i.e., cheap-as-possible) implementation of an ScopeManager. 30 | */ 31 | class NoopScopeManagerImpl implements NoopScopeManager { 32 | 33 | @Override 34 | public Scope activate(Span span) { 35 | return NoopScope.INSTANCE; 36 | } 37 | 38 | @Override 39 | public Span activeSpan() { 40 | return NoopSpan.INSTANCE; 41 | } 42 | 43 | static class NoopScopeImpl implements NoopScopeManager.NoopScope { 44 | @Override 45 | public void close() {} 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /opentracing-noop/src/main/java/io/opentracing/noop/NoopSpan.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.noop; 15 | 16 | import io.opentracing.Span; 17 | import io.opentracing.SpanContext; 18 | import io.opentracing.tag.Tag; 19 | 20 | import java.util.Map; 21 | 22 | public interface NoopSpan extends Span { 23 | static final NoopSpan INSTANCE = new NoopSpanImpl(); 24 | } 25 | 26 | final class NoopSpanImpl implements NoopSpan { 27 | 28 | @Override 29 | public SpanContext context() { return NoopSpanContextImpl.INSTANCE; } 30 | 31 | @Override 32 | public void finish() {} 33 | 34 | @Override 35 | public void finish(long finishMicros) {} 36 | 37 | @Override 38 | public NoopSpan setTag(String key, String value) { return this; } 39 | 40 | @Override 41 | public NoopSpan setTag(String key, boolean value) { return this; } 42 | 43 | @Override 44 | public NoopSpan setTag(String key, Number value) { return this; } 45 | 46 | @Override 47 | public NoopSpan setTag(Tag tag, T value) { return this; } 48 | 49 | @Override 50 | public NoopSpan log(Map fields) { return this; } 51 | 52 | @Override 53 | public NoopSpan log(long timestampMicroseconds, Map fields) { return this; } 54 | 55 | @Override 56 | public NoopSpan log(String event) { return this; } 57 | 58 | @Override 59 | public NoopSpan log(long timestampMicroseconds, String event) { return this; } 60 | 61 | @Override 62 | public NoopSpan setBaggageItem(String key, String value) { return this; } 63 | 64 | @Override 65 | public String getBaggageItem(String key) { return null; } 66 | 67 | @Override 68 | public NoopSpan setOperationName(String operationName) { return this; } 69 | 70 | @Override 71 | public String toString() { return NoopSpan.class.getSimpleName(); } 72 | } 73 | 74 | -------------------------------------------------------------------------------- /opentracing-noop/src/main/java/io/opentracing/noop/NoopSpanBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.noop; 15 | 16 | import io.opentracing.Scope; 17 | import io.opentracing.Span; 18 | import io.opentracing.SpanContext; 19 | import io.opentracing.Tracer; 20 | import io.opentracing.tag.Tag; 21 | 22 | public interface NoopSpanBuilder extends Tracer.SpanBuilder { 23 | NoopSpanBuilder INSTANCE = new NoopSpanBuilderImpl(); 24 | } 25 | 26 | final class NoopSpanBuilderImpl implements NoopSpanBuilder { 27 | 28 | @Override 29 | public Tracer.SpanBuilder addReference(String refType, SpanContext referenced) { 30 | return this; 31 | } 32 | 33 | @Override 34 | public Tracer.SpanBuilder asChildOf(SpanContext parent) { 35 | return this; 36 | } 37 | 38 | @Override 39 | public Tracer.SpanBuilder ignoreActiveSpan() { return this; } 40 | 41 | @Override 42 | public Tracer.SpanBuilder asChildOf(Span parent) { 43 | return this; 44 | } 45 | 46 | @Override 47 | public Tracer.SpanBuilder withTag(String key, String value) { 48 | return this; 49 | } 50 | 51 | @Override 52 | public Tracer.SpanBuilder withTag(String key, boolean value) { 53 | return this; 54 | } 55 | 56 | @Override 57 | public Tracer.SpanBuilder withTag(String key, Number value) { 58 | return this; 59 | } 60 | 61 | @Override 62 | public Tracer.SpanBuilder withTag(Tag key, T value) { 63 | return this; 64 | } 65 | 66 | @Override 67 | public Tracer.SpanBuilder withStartTimestamp(long microseconds) { 68 | return this; 69 | } 70 | 71 | @Override 72 | public Span start() { 73 | return NoopSpanImpl.INSTANCE; 74 | } 75 | 76 | @Override 77 | public String toString() { return NoopSpanBuilder.class.getSimpleName(); } 78 | } 79 | -------------------------------------------------------------------------------- /opentracing-noop/src/main/java/io/opentracing/noop/NoopSpanContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.noop; 15 | 16 | import io.opentracing.SpanContext; 17 | 18 | import java.util.Collections; 19 | import java.util.Map; 20 | 21 | 22 | public interface NoopSpanContext extends SpanContext { 23 | } 24 | 25 | final class NoopSpanContextImpl implements NoopSpanContext { 26 | static final NoopSpanContextImpl INSTANCE = new NoopSpanContextImpl(); 27 | 28 | @Override 29 | public String toTraceId() { 30 | return ""; 31 | } 32 | 33 | @Override 34 | public String toSpanId() { 35 | return ""; 36 | } 37 | 38 | @Override 39 | public Iterable> baggageItems() { 40 | return Collections.emptyList(); 41 | } 42 | 43 | @Override 44 | public String toString() { return NoopSpanContext.class.getSimpleName(); } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /opentracing-noop/src/main/java/io/opentracing/noop/NoopTracer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.noop; 15 | 16 | import io.opentracing.ScopeManager; 17 | import io.opentracing.Scope; 18 | import io.opentracing.Span; 19 | import io.opentracing.SpanContext; 20 | import io.opentracing.Tracer; 21 | import io.opentracing.propagation.Format; 22 | 23 | public interface NoopTracer extends Tracer { 24 | } 25 | 26 | final class NoopTracerImpl implements NoopTracer { 27 | final static NoopTracer INSTANCE = new NoopTracerImpl(); 28 | 29 | @Override 30 | public ScopeManager scopeManager() { 31 | return NoopScopeManager.INSTANCE; 32 | } 33 | 34 | @Override 35 | public Span activeSpan() { 36 | return NoopSpanImpl.INSTANCE; 37 | } 38 | 39 | @Override 40 | public Scope activateSpan(Span span) { 41 | return NoopScopeManager.NoopScope.INSTANCE; 42 | } 43 | 44 | @Override 45 | public SpanBuilder buildSpan(String operationName) { return NoopSpanBuilderImpl.INSTANCE; } 46 | 47 | @Override 48 | public void inject(SpanContext spanContext, Format format, C carrier) {} 49 | 50 | @Override 51 | public SpanContext extract(Format format, C carrier) { return NoopSpanContextImpl.INSTANCE; } 52 | 53 | @Override 54 | public void close() {} 55 | 56 | @Override 57 | public String toString() { return NoopTracer.class.getSimpleName(); } 58 | } 59 | 60 | -------------------------------------------------------------------------------- /opentracing-noop/src/main/java/io/opentracing/noop/NoopTracerFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.noop; 15 | 16 | public final class NoopTracerFactory { 17 | 18 | public static NoopTracer create() { 19 | return NoopTracerImpl.INSTANCE; 20 | } 21 | 22 | private NoopTracerFactory() {} 23 | } 24 | 25 | -------------------------------------------------------------------------------- /opentracing-noop/src/test/java/io/opentracing/noop/NoopScopeManagerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.noop; 15 | 16 | import static org.junit.Assert.*; 17 | 18 | import org.junit.Test; 19 | 20 | import io.opentracing.Scope; 21 | 22 | public class NoopScopeManagerTest { 23 | 24 | @Test 25 | public void activeValueToleratesUseTest() { 26 | try{ 27 | final Scope active = NoopScopeManager.INSTANCE.activate(NoopSpanImpl.INSTANCE); 28 | assertNotNull(active); 29 | active.close(); 30 | } catch (final NullPointerException e) { 31 | fail("NoopScopeManagerImpl.active() should return a usable scope"); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /opentracing-noop/src/test/java/io/opentracing/noop/NoopSpanContextTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.noop; 15 | 16 | import static org.junit.Assert.*; 17 | 18 | import org.junit.Test; 19 | 20 | import io.opentracing.SpanContext; 21 | 22 | public class NoopSpanContextTest { 23 | 24 | @Test 25 | public void traceIdentifierTest() { 26 | SpanContext ctx = NoopSpanContextImpl.INSTANCE; 27 | assertEquals("", ctx.toTraceId()); 28 | } 29 | 30 | @Test 31 | public void spanIdentifierTest() { 32 | SpanContext ctx = NoopSpanContextImpl.INSTANCE; 33 | assertEquals("", ctx.toSpanId()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /opentracing-noop/src/test/java/io/opentracing/noop/NoopTracerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.noop; 15 | 16 | import static org.junit.Assert.*; 17 | 18 | import org.junit.Test; 19 | 20 | import io.opentracing.Span; 21 | import io.opentracing.tag.Tags; 22 | 23 | public class NoopTracerTest { 24 | 25 | @Test 26 | public void activeSpanValueToleratesUseTest() { 27 | try { 28 | final Span activeSpan = NoopTracerImpl.INSTANCE.activeSpan(); 29 | assertNotNull(activeSpan); 30 | Tags.ERROR.set(activeSpan, true); 31 | } catch (final NullPointerException e) { 32 | fail("NoopTracer.activeSpan() should return a usable span"); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /opentracing-testbed/README.md: -------------------------------------------------------------------------------- 1 | # OpenTracing-Java testbed 2 | 3 | Goal of these examples is to 4 | - test API changes 5 | - use for regression testing 6 | - show common instrumentation patterns 7 | 8 | List of patterns: 9 | 10 | - [activate_deactivate](src/test/java/io/opentracing/testbed/activate_deactivate) - actions are executed by scheduler. 11 | It shows continuation as a solution to finish span when last action is completed. 12 | - [active_span_replacement](src/test/java/io/opentracing/testbed/active_span_replacement) - start an isolated task and query for its result in another task/thread 13 | - [actor_propagation](src/test/java/io/opentracing/testbed/actor_propagation) - tracing for blocking and non-blocking actor based tracing 14 | - [client_server](src/test/java/io/opentracing/testbed/client_server) - typical client-server example 15 | - [concurrent_common_request_handler](src/test/java/io/opentracing/testbed/concurrent_common_request_handler) - one request handler for concurrent requests 16 | - [error_reporting](src/test/java/io/opentracing/testbed/error_reporting) - a few common cases of error reporting 17 | - [late_span_finish](src/test/java/io/opentracing/testbed/late_span_finish) - late parent span finish 18 | - [listener_per_request](src/test/java/io/opentracing/testbed/listener_per_request) - one listener per request 19 | - [multiple_callbacks](src/test/java/io/opentracing/testbed/multiple_callbacks) - many callbacks spawned at the same time 20 | - [nested_callbacks](src/test/java/io/opentracing/testbed/nested_callbacks) - one callback at the time, defined in a pipeline fashion 21 | - [promise_propagation](src/test/java/io/opentracing/testbed/promise_propagation) - tracing patterns for promises with callbacks 22 | - [suspend_resume_propagation](src/test/java/io/opentracing/testbed/suspend_resume_propagation) - tracing pattern for interleaving of spans 23 | - [stateless_common_request_handler](src/test/java/io/opentracing/testbed/stateless_common_request_handler) - one stateless request handler for requests 24 | -------------------------------------------------------------------------------- /opentracing-testbed/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 4.0.0 19 | 20 | 21 | io.opentracing 22 | parent 23 | 0.33.1-SNAPSHOT 24 | 25 | 26 | opentracing-testbed 27 | OpenTracing-testbed 28 | OpenTracing Testbed 29 | 30 | 31 | ${project.basedir}/.. 32 | 33 | 34 | 35 | 36 | io.opentracing 37 | opentracing-util 38 | test 39 | 40 | 41 | 42 | io.opentracing 43 | opentracing-mock 44 | test 45 | 46 | 47 | 48 | org.awaitility 49 | awaitility 50 | ${awaitility.version} 51 | test 52 | 53 | 54 | 55 | ch.qos.logback 56 | logback-classic 57 | ${logback.version} 58 | test 59 | 60 | 61 | 62 | 63 | 64 | 65 | org.apache.maven.plugins 66 | maven-deploy-plugin 67 | ${maven-deploy-plugin.version} 68 | 69 | true 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/AutoFinishScope.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | 15 | package io.opentracing.testbed; 16 | 17 | import io.opentracing.Scope; 18 | import io.opentracing.Span; 19 | 20 | import java.util.concurrent.atomic.AtomicInteger; 21 | 22 | /** 23 | * The operation mode of this class contrasts with the 0.32 24 | * deprecation of auto finishing {@link Span}s upon {@link Scope#close()}. 25 | 26 | * {@link AutoFinishScope} is a {@link Scope} implementation that uses ref-counting 27 | * to automatically finish the wrapped {@link Span}. 28 | * 29 | * @see AutoFinishScopeManager 30 | */ 31 | public class AutoFinishScope implements Scope { 32 | final AutoFinishScopeManager manager; 33 | final AtomicInteger refCount; 34 | private final Span wrapped; 35 | private final AutoFinishScope toRestore; 36 | 37 | AutoFinishScope(AutoFinishScopeManager manager, AtomicInteger refCount, Span wrapped) { 38 | this.manager = manager; 39 | this.refCount = refCount; 40 | this.wrapped = wrapped; 41 | this.toRestore = manager.tlsScope.get(); 42 | manager.tlsScope.set(this); 43 | } 44 | 45 | public class Continuation { 46 | public Continuation() { 47 | refCount.incrementAndGet(); 48 | } 49 | 50 | public AutoFinishScope activate() { 51 | return new AutoFinishScope(manager, refCount, wrapped); 52 | } 53 | } 54 | 55 | public Continuation capture() { 56 | return new Continuation(); 57 | } 58 | 59 | @Override 60 | public void close() { 61 | if (manager.tlsScope.get() != this) { 62 | return; 63 | } 64 | 65 | if (refCount.decrementAndGet() == 0) { 66 | wrapped.finish(); 67 | } 68 | 69 | manager.tlsScope.set(toRestore); 70 | } 71 | 72 | public Span span() { 73 | return wrapped; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/AutoFinishScopeManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed; 15 | 16 | import io.opentracing.ScopeManager; 17 | import io.opentracing.Span; 18 | 19 | import java.util.concurrent.atomic.AtomicInteger; 20 | 21 | /** 22 | * The operation mode of this class contrasts with the 0.32 23 | * deprecation of auto finishing {@link Span}s upon {@link Scope#close()}. 24 | * See https://github.com/opentracing/opentracing-java/issues/291 25 | * 26 | * A {@link ScopeManager} implementation that uses ref-counting to automatically finish {@link Span}s. 27 | * 28 | * @see AutoFinishScope 29 | */ 30 | public class AutoFinishScopeManager implements ScopeManager { 31 | final ThreadLocal tlsScope = new ThreadLocal(); 32 | 33 | @Override 34 | public AutoFinishScope activate(Span span) { 35 | return new AutoFinishScope(this, new AtomicInteger(1), span); 36 | } 37 | 38 | @Override 39 | public Span activeSpan() { 40 | AutoFinishScope scope = tlsScope.get(); 41 | return scope == null ? null : scope.span(); 42 | } 43 | 44 | public AutoFinishScope active() { 45 | return tlsScope.get(); 46 | } 47 | 48 | public AutoFinishScope.Continuation captureScope() { 49 | AutoFinishScope scope = tlsScope.get(); 50 | return scope == null ? null : scope.capture(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/TestUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed; 15 | 16 | import io.opentracing.mock.MockSpan; 17 | import io.opentracing.mock.MockTracer; 18 | import io.opentracing.tag.AbstractTag; 19 | 20 | import java.util.ArrayList; 21 | import java.util.Collections; 22 | import java.util.Comparator; 23 | import java.util.List; 24 | import java.util.Random; 25 | import java.util.concurrent.Callable; 26 | import java.util.concurrent.TimeUnit; 27 | 28 | import static org.junit.Assert.assertEquals; 29 | 30 | public class TestUtils { 31 | 32 | public static Callable finishedSpansSize(final MockTracer tracer) { 33 | return new Callable() { 34 | @Override 35 | public Integer call() throws Exception { 36 | return tracer.finishedSpans().size(); 37 | } 38 | }; 39 | } 40 | 41 | public static List getByTag(List spans, AbstractTag key, Object value) { 42 | List found = new ArrayList<>(spans.size()); 43 | for (MockSpan span : spans) { 44 | if (span.tags().get(key.getKey()).equals(value)) { 45 | found.add(span); 46 | } 47 | } 48 | return found; 49 | } 50 | 51 | public static MockSpan getOneByTag(List spans, AbstractTag key, Object value) { 52 | List found = getByTag(spans, key, value); 53 | if (found.size() > 1) { 54 | throw new IllegalArgumentException("there is more than one span with tag '" 55 | + key.getKey() + "' and value '" + value + "'"); 56 | } 57 | if (found.isEmpty()) { 58 | return null; 59 | } else { 60 | return found.get(0); 61 | } 62 | } 63 | 64 | public static void sleep() { 65 | try { 66 | TimeUnit.MILLISECONDS.sleep(new Random().nextInt(2000)); 67 | } catch (InterruptedException e) { 68 | e.printStackTrace(); 69 | Thread.currentThread().interrupt(); 70 | } 71 | } 72 | 73 | public static void sleep(long milliseconds) { 74 | try { 75 | TimeUnit.MILLISECONDS.sleep(milliseconds); 76 | } catch (InterruptedException e) { 77 | e.printStackTrace(); 78 | Thread.currentThread().interrupt(); 79 | } 80 | } 81 | 82 | public static void sortByStartMicros(List spans) { 83 | Collections.sort(spans, new Comparator() { 84 | @Override 85 | public int compare(MockSpan o1, MockSpan o2) { 86 | return Long.compare(o1.startMicros(), o2.startMicros()); 87 | } 88 | }); 89 | } 90 | 91 | public static void assertSameTrace(List spans) { 92 | for (int i = 0; i < spans.size() - 1; i++) { 93 | assertEquals(true, spans.get(spans.size() - 1).finishMicros() >= spans.get(i).finishMicros()); 94 | assertEquals(spans.get(spans.size() - 1).context().traceId(), spans.get(i).context().traceId()); 95 | assertEquals(spans.get(spans.size() - 1).context().spanId(), spans.get(i).parentId()); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/activate_deactivate/README.md: -------------------------------------------------------------------------------- 1 | # Activate-deactivate example. 2 | 3 | This example shows the usage of the `Continuation` concept (now part of the `AutoFinishScopeManager`/`AutoScope.capture()`), as means to finish a `Span` till **all** its related subtasks have been executed. This example is similar to the **Multiple callbacks example**, but slightly more complex, and more aimed at trying out the usage of `Continuation`s. 4 | 5 | `RunnableAction` is a class implementing `Runnable`, and represents a subtask/callback that is scheduled to run at random time in the future, increasing the reference count of the passed `Scope`/`Span`. The `ScheduledActionsTest` includes both a test case with a single subtask, and another with two of them. 6 | 7 | ```java 8 | return new Thread(new Runnable() { 9 | @Override 10 | public void run() { 11 | Span span = tracer.buildSpan("parent").start(); 12 | try (Scope scope = tracer.activateSpan(span)) { 13 | Runnable action = new RunnableAction((AutoFinishScope)scope); 14 | Runnable action2 = new RunnableAction((AutoFinishScope)scope); 15 | 16 | Random random = new Random(); 17 | 18 | // Actions are executed at some time and most likely are running in parallel 19 | service.schedule(action, random.nextInt(1000) + 100, TimeUnit.MILLISECONDS); 20 | service.schedule(action2, random.nextInt(1000) + 100, TimeUnit.MILLISECONDS); 21 | 22 | } 23 | } 24 | }); 25 | ``` 26 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/activate_deactivate/RunnableAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.activate_deactivate; 15 | 16 | import io.opentracing.testbed.AutoFinishScope; 17 | import io.opentracing.testbed.AutoFinishScope.Continuation; 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | import java.util.concurrent.ThreadLocalRandom; 22 | import java.util.concurrent.TimeUnit; 23 | 24 | /** 25 | * Runnable Action. Scheduler submit it for execution. 26 | */ 27 | public class RunnableAction implements Runnable { 28 | 29 | private static final Logger logger = LoggerFactory.getLogger(RunnableAction.class); 30 | 31 | private final Continuation continuation; 32 | 33 | RunnableAction(AutoFinishScope scope) { 34 | continuation = scope.capture(); 35 | logger.info("Action created"); 36 | } 37 | 38 | /** 39 | * Can be used continuation.activate().deactivate() chain only. It is splitted for testing 40 | * purposes (span should not be finished before deactivate() called here). 41 | */ 42 | @Override 43 | public void run() { 44 | logger.info("Action started"); 45 | AutoFinishScope scope = continuation.activate(); 46 | 47 | try { 48 | TimeUnit.SECONDS.sleep(1); // without sleep first action can finish before second is started 49 | } catch (InterruptedException e) { 50 | e.printStackTrace(); 51 | } 52 | 53 | // set random tag starting with 'test_tag_' to test that finished span has all of them 54 | scope.span().setTag("test_tag_" + ThreadLocalRandom.current().nextInt(), "random"); 55 | 56 | scope.close(); 57 | logger.info("Action finished"); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/activate_deactivate/ScheduledActionsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.activate_deactivate; 15 | 16 | import io.opentracing.Scope; 17 | import io.opentracing.Span; 18 | import io.opentracing.mock.MockSpan; 19 | import io.opentracing.mock.MockTracer; 20 | import io.opentracing.mock.MockTracer.Propagator; 21 | import org.junit.Test; 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | 25 | import java.util.List; 26 | import java.util.Random; 27 | import java.util.concurrent.Executors; 28 | import java.util.concurrent.ScheduledExecutorService; 29 | import java.util.concurrent.TimeUnit; 30 | 31 | import io.opentracing.testbed.AutoFinishScope; 32 | import io.opentracing.testbed.AutoFinishScopeManager; 33 | 34 | import static io.opentracing.testbed.TestUtils.finishedSpansSize; 35 | import static org.awaitility.Awaitility.await; 36 | import static org.hamcrest.core.IsEqual.equalTo; 37 | import static org.junit.Assert.assertEquals; 38 | 39 | public class ScheduledActionsTest { 40 | 41 | private static final Logger logger = LoggerFactory.getLogger(ScheduledActionsTest.class); 42 | 43 | private final MockTracer tracer = new MockTracer(new AutoFinishScopeManager(), 44 | Propagator.TEXT_MAP); 45 | private final ScheduledExecutorService service = Executors.newScheduledThreadPool(10); 46 | 47 | @Test 48 | public void test_one_scheduled_action() throws Exception { 49 | Thread entryThread = entryThread(); 50 | entryThread.start(); 51 | 52 | await().atMost(15, TimeUnit.SECONDS).until(finishedSpansSize(tracer), equalTo(1)); 53 | 54 | List finished = tracer.finishedSpans(); 55 | assertEquals(1, finished.size()); 56 | 57 | assertEquals(1, getTestTagsCount(finished.get(0))); 58 | } 59 | 60 | @Test 61 | public void test_two_scheduled_actions() throws Exception { 62 | Thread entryThread = entryThreadWithTwoActions(); 63 | entryThread.start(); 64 | entryThread.join(10_000); 65 | // Entry thread is completed but Actions are still running (or even not started) 66 | 67 | await().atMost(15, TimeUnit.SECONDS).until(finishedSpansSize(tracer), equalTo(1)); 68 | 69 | List finished = tracer.finishedSpans(); 70 | assertEquals(1, finished.size()); 71 | 72 | // Check that two actions finished and each added to span own tag ('test_tag_{random}') 73 | assertEquals(2, getTestTagsCount(finished.get(0))); 74 | } 75 | 76 | private int getTestTagsCount(MockSpan mockSpan) { 77 | int tagCounter = 0; 78 | for (String tagKey : mockSpan.tags().keySet()) { 79 | if (tagKey.startsWith("test_tag_")) { 80 | tagCounter++; 81 | } 82 | } 83 | return tagCounter; 84 | } 85 | 86 | /** 87 | * Thread will be completed before action completed. 88 | */ 89 | private Thread entryThread() { 90 | return new Thread(new Runnable() { 91 | @Override 92 | public void run() { 93 | logger.info("Entry thread started"); 94 | Span span = tracer.buildSpan("parent").start(); 95 | try (Scope scope = tracer.activateSpan(span)) { 96 | Runnable action = new RunnableAction((AutoFinishScope)scope); 97 | 98 | // Action is executed at some time and we are not able to check status 99 | service.schedule(action, 500, TimeUnit.MILLISECONDS); 100 | } 101 | logger.info("Entry thread finished"); 102 | } 103 | }); 104 | } 105 | 106 | /** 107 | * Thread will be completed before action completed. 108 | */ 109 | private Thread entryThreadWithTwoActions() { 110 | return new Thread(new Runnable() { 111 | @Override 112 | public void run() { 113 | logger.info("Entry thread 2x started"); 114 | Span span = tracer.buildSpan("parent").start(); 115 | try (Scope scope = tracer.activateSpan(span)) { 116 | Runnable action = new RunnableAction((AutoFinishScope)scope); 117 | Runnable action2 = new RunnableAction((AutoFinishScope)scope); 118 | 119 | Random random = new Random(); 120 | 121 | // Actions are executed at some time and most likely are running in parallel 122 | service.schedule(action, random.nextInt(1000) + 100, TimeUnit.MILLISECONDS); 123 | service.schedule(action2, random.nextInt(1000) + 100, TimeUnit.MILLISECONDS); 124 | 125 | } 126 | logger.info("Entry thread 2x finished"); 127 | } 128 | }); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/active_span_replacement/ActiveSpanReplacementTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.active_span_replacement; 15 | 16 | import io.opentracing.Scope; 17 | import io.opentracing.Span; 18 | import io.opentracing.mock.MockSpan; 19 | import io.opentracing.mock.MockTracer; 20 | import io.opentracing.mock.MockTracer.Propagator; 21 | import io.opentracing.util.ThreadLocalScopeManager; 22 | import org.junit.Test; 23 | 24 | import java.util.List; 25 | import java.util.concurrent.ExecutorService; 26 | import java.util.concurrent.Executors; 27 | import java.util.concurrent.TimeUnit; 28 | 29 | import static io.opentracing.testbed.TestUtils.finishedSpansSize; 30 | import static io.opentracing.testbed.TestUtils.sleep; 31 | import static org.awaitility.Awaitility.await; 32 | import static org.hamcrest.core.IsEqual.equalTo; 33 | import static org.junit.Assert.assertEquals; 34 | import static org.junit.Assert.assertNotEquals; 35 | import static org.junit.Assert.assertNull; 36 | 37 | public class ActiveSpanReplacementTest { 38 | 39 | private final MockTracer tracer = new MockTracer(new ThreadLocalScopeManager(), 40 | Propagator.TEXT_MAP); 41 | 42 | private final ExecutorService executor = Executors.newCachedThreadPool(); 43 | 44 | @Test 45 | public void test() throws Exception { 46 | // Start an isolated task and query for its result in another task/thread 47 | Span span = tracer.buildSpan("initial").start(); 48 | try (Scope scope = tracer.scopeManager().activate(span)) { 49 | // Explicitly pass a Span to be finished once a late calculation is done. 50 | submitAnotherTask(span); 51 | } 52 | 53 | await().atMost(15, TimeUnit.SECONDS).until(finishedSpansSize(tracer), equalTo(3)); 54 | 55 | List spans = tracer.finishedSpans(); 56 | assertEquals(3, spans.size()); 57 | assertEquals("initial", spans.get(0).operationName()); // Isolated task 58 | assertEquals("subtask", spans.get(1).operationName()); 59 | assertEquals("task", spans.get(2).operationName()); 60 | 61 | // task/subtask are part of the same trace, and subtask is a child of task 62 | assertEquals(spans.get(1).context().traceId(), spans.get(2).context().traceId()); 63 | assertEquals(spans.get(2).context().spanId(), spans.get(1).parentId()); 64 | 65 | // initial task is not related in any way to those two tasks 66 | assertNotEquals(spans.get(0).context().traceId(), spans.get(1).context().traceId()); 67 | assertEquals(0, spans.get(0).parentId()); 68 | 69 | assertNull(tracer.scopeManager().activeSpan()); 70 | } 71 | 72 | private void submitAnotherTask(final Span initialSpan) { 73 | 74 | executor.submit(new Runnable() { 75 | @Override 76 | public void run() { 77 | // Create a new Span for this task 78 | Span taskSpan = tracer.buildSpan("task").start(); 79 | try (Scope scope = tracer.scopeManager().activate(taskSpan)) { 80 | 81 | // Simulate work strictly related to the initial Span 82 | // and finish it. 83 | try (Scope initialScope = tracer.scopeManager().activate(initialSpan)) { 84 | sleep(50); 85 | } finally { 86 | initialSpan.finish(); 87 | } 88 | 89 | // Restore the span for this task and create a subspan 90 | Span subTaskSpan = tracer.buildSpan("subtask").start(); 91 | try (Scope subTaskScope = tracer.scopeManager().activate(subTaskSpan)) { 92 | } finally { 93 | subTaskSpan.finish(); 94 | } 95 | } finally { 96 | taskSpan.finish(); 97 | } 98 | } 99 | }); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/active_span_replacement/README.md: -------------------------------------------------------------------------------- 1 | # Active Span replacement example. 2 | 3 | This example shows a `Span` being created and then passed to an asynchronous task, which will temporary activate it to finish its processing, and further restore the previously active `Span`. 4 | 5 | ```java 6 | // Create a new Span for this task 7 | Span taskSpan = tracer.buildSpan("task").start(); 8 | try (Scope scope = tracer.scopeManager().activate(taskSpan)) { 9 | 10 | // Simulate work strictly related to the initial Span 11 | // and finish it. 12 | try (Scope initialScope = tracer.scopeManager().activate(initialSpan)) { 13 | } finally { 14 | initialSpan.finish(); 15 | } 16 | 17 | // Continue doing tasks under taskSpan 18 | } finally { 19 | taskSpan.finish(); 20 | } 21 | ``` 22 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/actor_propagation/Actor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.actor_propagation; 15 | 16 | import io.opentracing.References; 17 | import io.opentracing.Scope; 18 | import io.opentracing.Span; 19 | import io.opentracing.mock.MockTracer; 20 | import io.opentracing.tag.Tags; 21 | import java.util.concurrent.Callable; 22 | import java.util.concurrent.ExecutorService; 23 | import java.util.concurrent.Executors; 24 | import java.util.concurrent.Future; 25 | import java.util.concurrent.Phaser; 26 | 27 | /** @author tylerbenson */ 28 | public class Actor implements AutoCloseable { 29 | private final ExecutorService executor; 30 | private final MockTracer tracer; 31 | private final Phaser phaser; 32 | 33 | public Actor(MockTracer tracer, Phaser phaser) { 34 | // Passed along here for testing. Normally should be referenced via GlobalTracer.get(). 35 | this.tracer = tracer; 36 | 37 | this.phaser = phaser; 38 | executor = Executors.newFixedThreadPool(2); 39 | } 40 | 41 | @Override 42 | public void close() { 43 | executor.shutdown(); 44 | } 45 | 46 | public void tell(final String message) { 47 | final Span parent = tracer.scopeManager().activeSpan(); 48 | phaser.register(); 49 | executor.submit( 50 | new Runnable() { 51 | @Override 52 | public void run() { 53 | Span child = tracer 54 | .buildSpan("received") 55 | .addReference(References.FOLLOWS_FROM, parent.context()) 56 | .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER) 57 | .start(); 58 | try (Scope scope = tracer.activateSpan(child)) { 59 | phaser.arriveAndAwaitAdvance(); // child tracer started 60 | child.log("received " + message); 61 | phaser.arriveAndAwaitAdvance(); // assert size 62 | } finally { 63 | child.finish(); 64 | } 65 | 66 | phaser.arriveAndAwaitAdvance(); // child tracer finished 67 | phaser.arriveAndAwaitAdvance(); // assert size 68 | } 69 | }); 70 | } 71 | 72 | public Future ask(final String message) { 73 | final Span parent = tracer.scopeManager().activeSpan(); 74 | phaser.register(); 75 | Future future = 76 | executor.submit( 77 | new Callable() { 78 | @Override 79 | public String call() throws Exception { 80 | Span span = tracer 81 | .buildSpan("received") 82 | .addReference(References.FOLLOWS_FROM, parent.context()) 83 | .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER) 84 | .start(); 85 | try { 86 | phaser.arriveAndAwaitAdvance(); // child tracer started 87 | phaser.arriveAndAwaitAdvance(); // assert size 88 | return "received " + message; 89 | } finally { 90 | span.finish(); 91 | 92 | phaser.arriveAndAwaitAdvance(); // child tracer finished 93 | phaser.arriveAndAwaitAdvance(); // assert size 94 | } 95 | } 96 | }); 97 | return future; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/actor_propagation/ActorPropagationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.actor_propagation; 15 | 16 | import io.opentracing.Scope; 17 | import io.opentracing.Span; 18 | import io.opentracing.mock.MockSpan; 19 | import io.opentracing.mock.MockTracer; 20 | import io.opentracing.mock.MockTracer.Propagator; 21 | import io.opentracing.tag.Tags; 22 | import io.opentracing.util.ThreadLocalScopeManager; 23 | import org.junit.Before; 24 | import org.junit.Test; 25 | 26 | import java.util.List; 27 | import java.util.concurrent.ExecutionException; 28 | import java.util.concurrent.Future; 29 | import java.util.concurrent.Phaser; 30 | 31 | import static io.opentracing.testbed.TestUtils.getByTag; 32 | import static io.opentracing.testbed.TestUtils.getOneByTag; 33 | import static org.assertj.core.api.Assertions.assertThat; 34 | 35 | /** 36 | * These tests are intended to simulate the kind of async models that are common in java async 37 | * frameworks. 38 | * 39 | * For improved readability, ignore the phaser lines as those are there to ensure deterministic 40 | * execution for the tests without sleeps. 41 | * 42 | * @author tylerbenson 43 | */ 44 | public class ActorPropagationTest { 45 | 46 | private final MockTracer tracer = 47 | new MockTracer(new ThreadLocalScopeManager(), Propagator.TEXT_MAP); 48 | private Phaser phaser; 49 | 50 | @Before 51 | public void before() { 52 | phaser = new Phaser(); 53 | } 54 | 55 | @Test 56 | public void testActorTell() { 57 | try (Actor actor = new Actor(tracer, phaser)) { 58 | phaser.register(); 59 | Span parent = tracer 60 | .buildSpan("actorTell") 61 | .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_PRODUCER) 62 | .withTag(Tags.COMPONENT.getKey(), "example-actor") 63 | .start(); 64 | try (Scope scope = tracer.activateSpan(parent)) { 65 | actor.tell("my message 1"); 66 | actor.tell("my message 2"); 67 | } finally { 68 | parent.finish(); 69 | } 70 | phaser.arriveAndAwaitAdvance(); // child tracer started 71 | assertThat(tracer.finishedSpans().size()).isEqualTo(1); // Parent should be reported 72 | phaser.arriveAndAwaitAdvance(); // continue... 73 | 74 | phaser.arriveAndAwaitAdvance(); // child tracer finished 75 | assertThat(tracer.finishedSpans().size()).isEqualTo(3); 76 | assertThat(getByTag(tracer.finishedSpans(), Tags.SPAN_KIND, Tags.SPAN_KIND_CONSUMER)) 77 | .hasSize(2); 78 | phaser.arriveAndDeregister(); // continue... 79 | 80 | List finished = tracer.finishedSpans(); 81 | 82 | assertThat(finished.size()).isEqualTo(3); 83 | assertThat(finished.get(0).context().traceId()) 84 | .isEqualTo(finished.get(1).context().traceId()); 85 | assertThat(getByTag(finished, Tags.SPAN_KIND, Tags.SPAN_KIND_CONSUMER)).hasSize(2); 86 | assertThat(getOneByTag(finished, Tags.SPAN_KIND, Tags.SPAN_KIND_PRODUCER)).isNotNull(); 87 | assertThat(tracer.scopeManager().activeSpan()).isNull(); 88 | } 89 | } 90 | 91 | @Test 92 | public void testActorAsk() throws ExecutionException, InterruptedException { 93 | try (Actor actor = new Actor(tracer, phaser)) { 94 | phaser.register(); 95 | Future future1; 96 | Future future2; 97 | Span span = tracer 98 | .buildSpan("actorAsk") 99 | .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_PRODUCER) 100 | .withTag(Tags.COMPONENT.getKey(), "example-actor") 101 | .start(); 102 | try (Scope scope = tracer.activateSpan(span)) { 103 | future1 = actor.ask("my message 1"); 104 | future2 = actor.ask("my message 2"); 105 | } finally { 106 | span.finish(); 107 | } 108 | phaser.arriveAndAwaitAdvance(); // child tracer started 109 | assertThat(tracer.finishedSpans().size()).isEqualTo(1); 110 | phaser.arriveAndAwaitAdvance(); // continue... 111 | 112 | phaser.arriveAndAwaitAdvance(); // child tracer finished 113 | assertThat(tracer.finishedSpans().size()).isEqualTo(3); 114 | assertThat(getByTag(tracer.finishedSpans(), Tags.SPAN_KIND, Tags.SPAN_KIND_CONSUMER)) 115 | .hasSize(2); 116 | phaser.arriveAndDeregister(); // continue... 117 | 118 | List finished = tracer.finishedSpans(); 119 | 120 | String message1 = future1.get(); // This really should be a non-blocking callback... 121 | String message2 = future2.get(); // This really should be a non-blocking callback... 122 | assertThat(message1).isEqualTo("received my message 1"); 123 | assertThat(message2).isEqualTo("received my message 2"); 124 | assertThat(finished.size()).isEqualTo(3); 125 | assertThat(finished.get(0).context().traceId()) 126 | .isEqualTo(finished.get(1).context().traceId()); 127 | assertThat(getByTag(finished, Tags.SPAN_KIND, Tags.SPAN_KIND_CONSUMER)).hasSize(2); 128 | assertThat(getOneByTag(finished, Tags.SPAN_KIND, Tags.SPAN_KIND_PRODUCER)).isNotNull(); 129 | assertThat(tracer.scopeManager().activeSpan()).isNull(); 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/actor_propagation/README.md: -------------------------------------------------------------------------------- 1 | # Actor propagation example. 2 | 3 | This example shows `Span` usage with `Scala` frameworks using the `Actor` paradigm (such as the **Akka** framework), with both `tell` (fire and forget) and `ask` (asynchronous, but returning a result) message passing ways. 4 | 5 | `Actor` mimics the API offered by such frameworks, and `java.util.concurrent.Phaser` is used to synchronize the steps of the example. 6 | 7 | ```java 8 | public void tell(final String message) { 9 | final Span parent = tracer.scopeManager().activeSpan(); 10 | executor.submit( 11 | new Runnable() { 12 | @Override 13 | public void run() { 14 | Span child = tracer 15 | .buildSpan("received") 16 | .addReference(References.FOLLOWS_FROM, parent.context()) 17 | .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER) 18 | .start(); 19 | try (Scope scope = tracer.activateSpan(child)) { 20 | child.log("received " + message); 21 | } finally { 22 | child.finish(); 23 | } 24 | } 25 | }); 26 | ``` 27 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/client_server/Client.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.client_server; 15 | 16 | import io.opentracing.Scope; 17 | import io.opentracing.Span; 18 | import io.opentracing.Tracer; 19 | import io.opentracing.propagation.Format.Builtin; 20 | import io.opentracing.propagation.TextMapInjectAdapter; 21 | import io.opentracing.tag.Tags; 22 | 23 | import java.util.concurrent.ArrayBlockingQueue; 24 | 25 | public class Client { 26 | 27 | private final ArrayBlockingQueue queue; 28 | private final Tracer tracer; 29 | 30 | public Client(ArrayBlockingQueue queue, Tracer tracer) { 31 | this.queue = queue; 32 | this.tracer = tracer; 33 | } 34 | 35 | public void send() throws InterruptedException { 36 | Message message = new Message(); 37 | 38 | Span span = tracer.buildSpan("send") 39 | .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT) 40 | .withTag(Tags.COMPONENT.getKey(), "example-client") 41 | .start(); 42 | try (Scope scope = tracer.activateSpan(span)) { 43 | tracer.inject(span.context(), Builtin.TEXT_MAP_INJECT, new TextMapInjectAdapter(message)); 44 | queue.put(message); 45 | } finally { 46 | span.finish(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/client_server/Message.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.client_server; 15 | 16 | import java.util.HashMap; 17 | 18 | public class Message extends HashMap { 19 | 20 | } 21 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/client_server/README.md: -------------------------------------------------------------------------------- 1 | # Client-Server example. 2 | 3 | This example shows a `Span` created by a `Client`, which will send a `Message`/`SpanContext` to a `Server`, which will in turn extract such context and use it as parent of a new (server-side) `Span`. 4 | 5 | `Client.send()` is used to send messages and inject the `SpanContext` using the `TEXT_MAP` format, and `Server.process()` will process received messages and will extract the context used as parent. 6 | 7 | ```java 8 | public void send() throws InterruptedException { 9 | Message message = new Message(); 10 | 11 | Span span = tracer.buildSpan("send") 12 | .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT) 13 | .withTag(Tags.COMPONENT.getKey(), "example-client") 14 | .start(); 15 | try (Scope scope = tracer.activateSpan(span)) { 16 | tracer.inject(span.context(), Builtin.TEXT_MAP, new TextMapInjectAdapter(message)); 17 | queue.put(message); 18 | } finally { 19 | span.finish(); 20 | } 21 | } 22 | ``` 23 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/client_server/Server.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.client_server; 15 | 16 | import io.opentracing.Scope; 17 | import io.opentracing.Span; 18 | import io.opentracing.SpanContext; 19 | import io.opentracing.Tracer; 20 | import io.opentracing.propagation.Format.Builtin; 21 | import io.opentracing.propagation.TextMapExtractAdapter; 22 | import io.opentracing.tag.Tags; 23 | 24 | import java.util.concurrent.ArrayBlockingQueue; 25 | 26 | public class Server extends Thread { 27 | 28 | private final ArrayBlockingQueue queue; 29 | private final Tracer tracer; 30 | 31 | public Server(ArrayBlockingQueue queue, Tracer tracer) { 32 | this.queue = queue; 33 | this.tracer = tracer; 34 | } 35 | 36 | private void process(Message message) { 37 | SpanContext context = tracer.extract(Builtin.TEXT_MAP_EXTRACT, new TextMapExtractAdapter(message)); 38 | Span span = tracer.buildSpan("receive") 39 | .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER) 40 | .withTag(Tags.COMPONENT.getKey(), "example-server") 41 | .asChildOf(context) 42 | .start(); 43 | 44 | try (Scope scope = tracer.activateSpan(span)) { 45 | } finally { 46 | span.finish(); 47 | } 48 | } 49 | 50 | @Override 51 | public void run() { 52 | while (!Thread.currentThread().isInterrupted()) { 53 | 54 | try { 55 | process(queue.take()); 56 | } catch (InterruptedException e) { 57 | Thread.currentThread().interrupt(); 58 | return; 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/client_server/TestClientServerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.client_server; 15 | 16 | import io.opentracing.mock.MockSpan; 17 | import io.opentracing.mock.MockTracer; 18 | import io.opentracing.mock.MockTracer.Propagator; 19 | import io.opentracing.tag.Tags; 20 | import io.opentracing.util.ThreadLocalScopeManager; 21 | import org.junit.After; 22 | import org.junit.Before; 23 | import org.junit.Test; 24 | 25 | import java.util.List; 26 | import java.util.concurrent.ArrayBlockingQueue; 27 | import java.util.concurrent.TimeUnit; 28 | 29 | import static io.opentracing.testbed.TestUtils.finishedSpansSize; 30 | import static io.opentracing.testbed.TestUtils.getOneByTag; 31 | import static org.awaitility.Awaitility.await; 32 | import static org.hamcrest.core.IsEqual.equalTo; 33 | import static org.junit.Assert.assertEquals; 34 | import static org.junit.Assert.assertNotNull; 35 | import static org.junit.Assert.assertNull; 36 | 37 | public class TestClientServerTest { 38 | 39 | private final MockTracer tracer = new MockTracer(new ThreadLocalScopeManager(), 40 | Propagator.TEXT_MAP); 41 | private final ArrayBlockingQueue queue = new ArrayBlockingQueue<>(10); 42 | private Server server; 43 | 44 | @Before 45 | public void before() { 46 | server = new Server(queue, tracer); 47 | server.start(); 48 | } 49 | 50 | @After 51 | public void after() throws InterruptedException { 52 | server.interrupt(); 53 | server.join(5_000L); 54 | } 55 | 56 | @Test 57 | public void test() throws Exception { 58 | Client client = new Client(queue, tracer); 59 | client.send(); 60 | 61 | await().atMost(15, TimeUnit.SECONDS).until(finishedSpansSize(tracer), equalTo(2)); 62 | 63 | List finished = tracer.finishedSpans(); 64 | assertEquals(2, finished.size()); 65 | assertEquals(finished.get(0).context().traceId(), finished.get(1).context().traceId()); 66 | assertNotNull(getOneByTag(finished, Tags.SPAN_KIND, Tags.SPAN_KIND_CLIENT)); 67 | assertNotNull(getOneByTag(finished, Tags.SPAN_KIND, Tags.SPAN_KIND_SERVER)); 68 | assertNull(tracer.scopeManager().activeSpan()); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/concurrent_common_request_handler/Client.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.concurrent_common_request_handler; 15 | 16 | import io.opentracing.testbed.TestUtils; 17 | import org.slf4j.Logger; 18 | import org.slf4j.LoggerFactory; 19 | 20 | import java.util.concurrent.Callable; 21 | import java.util.concurrent.ExecutorService; 22 | import java.util.concurrent.Executors; 23 | import java.util.concurrent.Future; 24 | 25 | public class Client { 26 | 27 | private static final Logger logger = LoggerFactory.getLogger(Client.class); 28 | 29 | private final ExecutorService executor = Executors.newCachedThreadPool(); 30 | 31 | private final RequestHandler requestHandler; 32 | 33 | 34 | public Client(RequestHandler requestHandler) { 35 | this.requestHandler = requestHandler; 36 | } 37 | 38 | 39 | public Future send(final Object message) { 40 | 41 | final Context context = new Context(); 42 | return executor.submit(new Callable() { 43 | @Override 44 | public String call() throws Exception { 45 | logger.info("send {}", message); 46 | TestUtils.sleep(); 47 | executor.submit(new Runnable() { 48 | @Override 49 | public void run() { 50 | TestUtils.sleep(); 51 | requestHandler.beforeRequest(message, context); 52 | } 53 | }).get(); 54 | 55 | executor.submit(new Runnable() { 56 | @Override 57 | public void run() { 58 | TestUtils.sleep(); 59 | requestHandler.afterResponse(message, context); 60 | } 61 | }).get(); 62 | 63 | return message + ":response"; 64 | } 65 | }); 66 | 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/concurrent_common_request_handler/Context.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.concurrent_common_request_handler; 15 | 16 | import java.util.HashMap; 17 | 18 | public class Context extends HashMap { 19 | 20 | } 21 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/concurrent_common_request_handler/README.md: -------------------------------------------------------------------------------- 1 | # Concurrent common Request Handler example. 2 | 3 | This example shows a `Span` used with `RequestHandler`, which is used as a middleware (as in web frameworks) to concurrently manage a new `Span` per operation through its `beforeRequest()`/`afterResponse()` methods. 4 | 5 | Since its methods are not guaranteed to be run in the same thread, activation of such `Span`s is not done. 6 | 7 | ```java 8 | public void beforeRequest(Object request, Context context) { 9 | // we cannot use active span because we don't know in which thread it is executed 10 | // and we cannot therefore activate span. thread can come from common thread pool. 11 | SpanBuilder spanBuilder = tracer.buildSpan(OPERATION_NAME) 12 | .ignoreActiveSpan() 13 | .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT); 14 | 15 | if (parentContext != null) { 16 | spanBuilder.asChildOf(parentContext); 17 | } 18 | 19 | context.put("span", spanBuilder.start()); 20 | } 21 | 22 | public void afterResponse(Object response, Context context) { 23 | Object spanObject = context.get("span"); 24 | if (spanObject instanceof Span) { 25 | Span span = (Span) spanObject; 26 | span.finish(); 27 | } 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/concurrent_common_request_handler/RequestHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.concurrent_common_request_handler; 15 | 16 | import io.opentracing.Span; 17 | import io.opentracing.SpanContext; 18 | import io.opentracing.Tracer; 19 | import io.opentracing.Tracer.SpanBuilder; 20 | import io.opentracing.tag.Tags; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | /** 25 | * One instance per Client. Executed concurrently for all requests of one client. 'beforeRequest' 26 | * and 'afterResponse' are executed in different threads for one 'send' 27 | */ 28 | public class RequestHandler { 29 | 30 | private static final Logger logger = LoggerFactory.getLogger(RequestHandler.class); 31 | 32 | static final String OPERATION_NAME = "send"; 33 | 34 | private final Tracer tracer; 35 | 36 | private final SpanContext parentContext; 37 | 38 | public RequestHandler(Tracer tracer) { 39 | this(tracer, null); 40 | } 41 | 42 | public RequestHandler(Tracer tracer, SpanContext parentContext) { 43 | this.tracer = tracer; 44 | this.parentContext = parentContext; 45 | } 46 | 47 | public void beforeRequest(Object request, Context context) { 48 | logger.info("before send {}", request); 49 | 50 | // we cannot use active span because we don't know in which thread it is executed 51 | // and we cannot therefore activate span. thread can come from common thread pool. 52 | SpanBuilder spanBuilder = tracer.buildSpan(OPERATION_NAME) 53 | .ignoreActiveSpan() 54 | .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT); 55 | 56 | if (parentContext != null) { 57 | spanBuilder.asChildOf(parentContext); 58 | } 59 | 60 | context.put("span", spanBuilder.start()); 61 | } 62 | 63 | public void afterResponse(Object response, Context context) { 64 | logger.info("after response {}", response); 65 | 66 | Object spanObject = context.get("span"); 67 | if (spanObject instanceof Span) { 68 | Span span = (Span) spanObject; 69 | span.finish(); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/error_reporting/README.md: -------------------------------------------------------------------------------- 1 | # Error Reporting example. 2 | 3 | This example shows a few common error reporting cases, mostly interacting with `Scope` and `Span` propagation. In such cases, at the very least `opentracing.tags.Tag.ERROR` must be set in the `Span`: 4 | 5 | ```java 6 | Span span = tracer.buildSpan("one").start(); 7 | executor.submit(new Runnable() { 8 | @Override 9 | public void run() { 10 | try (Scope scope = tracer.activateSpan(span)) { 11 | throw new RuntimeException("Invalid state"); 12 | } catch (Exception exc) { 13 | Tags.ERROR.set(span, true); 14 | } finally { 15 | span.finish(); 16 | } 17 | } 18 | }); 19 | ``` 20 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/late_span_finish/LateSpanFinishTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.late_span_finish; 15 | 16 | import io.opentracing.Scope; 17 | import io.opentracing.Span; 18 | import io.opentracing.mock.MockSpan; 19 | import io.opentracing.mock.MockTracer; 20 | import io.opentracing.mock.MockTracer.Propagator; 21 | import io.opentracing.util.ThreadLocalScopeManager; 22 | import org.junit.Test; 23 | 24 | import java.util.List; 25 | import java.util.concurrent.ExecutorService; 26 | import java.util.concurrent.Executors; 27 | import java.util.concurrent.TimeUnit; 28 | 29 | import static io.opentracing.testbed.TestUtils.assertSameTrace; 30 | import static io.opentracing.testbed.TestUtils.sleep; 31 | import static org.junit.Assert.assertEquals; 32 | import static org.junit.Assert.assertNull; 33 | 34 | public class LateSpanFinishTest { 35 | 36 | private final MockTracer tracer = new MockTracer(new ThreadLocalScopeManager(), 37 | Propagator.TEXT_MAP); 38 | private final ExecutorService executor = Executors.newCachedThreadPool(); 39 | 40 | @Test 41 | public void test() throws Exception { 42 | // Create a Span manually and use it as parent of a pair of subtasks 43 | Span parentSpan = tracer.buildSpan("parent").start(); 44 | submitTasks(parentSpan); 45 | 46 | // Wait for the threadpool to be done first, instead of polling/waiting 47 | executor.shutdown(); 48 | executor.awaitTermination(15, TimeUnit.SECONDS); 49 | 50 | // Late-finish the parent Span now 51 | parentSpan.finish(); 52 | 53 | List spans = tracer.finishedSpans(); 54 | assertEquals(3, spans.size()); 55 | assertEquals("task1", spans.get(0).operationName()); 56 | assertEquals("task2", spans.get(1).operationName()); 57 | assertEquals("parent", spans.get(2).operationName()); 58 | 59 | assertSameTrace(spans); 60 | 61 | assertNull(tracer.scopeManager().activeSpan()); 62 | } 63 | 64 | 65 | /** 66 | * Fire away a few subtasks, passing a parent Span whose lifetime 67 | * is not tied at-all to the children 68 | */ 69 | private void submitTasks(final Span parentSpan) { 70 | 71 | executor.submit(new Runnable() { 72 | @Override 73 | public void run() { 74 | /* Alternative to calling activate() is to pass it manually to asChildOf() for each created Span. */ 75 | try (Scope scope = tracer.scopeManager().activate(parentSpan)) { 76 | Span childSpan = tracer.buildSpan("task1").start(); 77 | try (Scope childScope = tracer.scopeManager().activate(childSpan)) { 78 | sleep(55); 79 | } finally { 80 | childSpan.finish(); 81 | } 82 | } 83 | } 84 | }); 85 | 86 | executor.submit(new Runnable() { 87 | @Override 88 | public void run() { 89 | try (Scope scope = tracer.scopeManager().activate(parentSpan)) { 90 | Span childSpan = tracer.buildSpan("task2").start(); 91 | try (Scope childScope = tracer.scopeManager().activate(childSpan)) { 92 | sleep(85); 93 | } finally { 94 | childSpan.finish(); 95 | } 96 | } 97 | } 98 | }); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/late_span_finish/README.md: -------------------------------------------------------------------------------- 1 | # Late Span finish example. 2 | 3 | This example shows a `Span` for a top-level operation, with independent, unknown lifetime, acting as parent of a few asynchronous subtasks (which must re-activate it but not finish it). 4 | 5 | ```java 6 | // Inside the function submitting the subtasks. 7 | executor.submit(new Runnable() { 8 | @Override 9 | public void run() { 10 | try (Scope scope = tracer.scopeManager().activate(parentSpan)) { 11 | } 12 | } 13 | }); 14 | ``` 15 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/listener_per_request/Client.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.listener_per_request; 15 | 16 | import io.opentracing.Span; 17 | import io.opentracing.Tracer; 18 | import io.opentracing.tag.Tags; 19 | 20 | import java.util.concurrent.Callable; 21 | import java.util.concurrent.ExecutorService; 22 | import java.util.concurrent.Executors; 23 | import java.util.concurrent.Future; 24 | 25 | public class Client { 26 | 27 | private final ExecutorService executor = Executors.newCachedThreadPool(); 28 | private final Tracer tracer; 29 | 30 | public Client(Tracer tracer) { 31 | this.tracer = tracer; 32 | } 33 | 34 | 35 | /** 36 | * Async execution 37 | */ 38 | private Future execute(final Object message, final ResponseListener responseListener) { 39 | return executor.submit(new Callable() { 40 | @Override 41 | public Object call() throws Exception { 42 | // send via wire and get response 43 | Object response = message + ":response"; 44 | responseListener.onResponse(response); 45 | return response; 46 | } 47 | }); 48 | } 49 | 50 | public Future send(final Object message) { 51 | Span span = tracer.buildSpan("send"). 52 | withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT) 53 | .start(); 54 | return execute(message, new ResponseListener(span)); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/listener_per_request/ListenerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.listener_per_request; 15 | 16 | import io.opentracing.mock.MockSpan; 17 | import io.opentracing.mock.MockTracer; 18 | import io.opentracing.mock.MockTracer.Propagator; 19 | import io.opentracing.tag.Tags; 20 | import io.opentracing.util.ThreadLocalScopeManager; 21 | import org.junit.Test; 22 | 23 | import java.util.List; 24 | 25 | import static io.opentracing.testbed.TestUtils.getOneByTag; 26 | import static org.junit.Assert.assertEquals; 27 | import static org.junit.Assert.assertNotNull; 28 | import static org.junit.Assert.assertNull; 29 | 30 | /** 31 | * Each request has own instance of ResponseListener 32 | */ 33 | public class ListenerTest { 34 | 35 | private final MockTracer tracer = new MockTracer(new ThreadLocalScopeManager(), 36 | Propagator.TEXT_MAP); 37 | 38 | @Test 39 | public void test() throws Exception { 40 | Client client = new Client(tracer); 41 | Object response = client.send("message").get(); 42 | assertEquals("message:response", response); 43 | 44 | List finished = tracer.finishedSpans(); 45 | assertEquals(1, finished.size()); 46 | assertNotNull(getOneByTag(finished, Tags.SPAN_KIND, Tags.SPAN_KIND_CLIENT)); 47 | assertNull(tracer.scopeManager().activeSpan()); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/listener_per_request/README.md: -------------------------------------------------------------------------------- 1 | # Listener Response example. 2 | 3 | This example shows a `Span` created upon a message being sent to a `Client`, and its handling along a related, **not shared** `ResponseListener` object with a `onResponse(Object response)` method to finish it. 4 | 5 | ```java 6 | public Future send(final Object message) { 7 | Span span = tracer.buildSpan("send"). 8 | withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT) 9 | .startManual(); 10 | return execute(message, new ResponseListener(span)); 11 | } 12 | 13 | private Future execute(final Object message, final ResponseListener responseListener) { 14 | return executor.submit(new Callable() { 15 | @Override 16 | public Object call() throws Exception { 17 | // send via wire and get response 18 | Object response = message + ":response"; 19 | responseListener.onResponse(response); 20 | return response; 21 | } 22 | }); 23 | } 24 | ``` 25 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/listener_per_request/ResponseListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.listener_per_request; 15 | 16 | import io.opentracing.Span; 17 | 18 | /** 19 | * Response listener per request. Executed in a thread different from 'send' thread 20 | */ 21 | public class ResponseListener { 22 | 23 | private final Span span; 24 | 25 | public ResponseListener(Span span) { 26 | this.span = span; 27 | } 28 | 29 | /** 30 | * executed when response is received from server. Any thread. 31 | */ 32 | public void onResponse(Object response) { 33 | span.finish(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/multiple_callbacks/Client.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.multiple_callbacks; 15 | 16 | import io.opentracing.Scope; 17 | import io.opentracing.Span; 18 | import io.opentracing.Tracer; 19 | import io.opentracing.testbed.AutoFinishScope; 20 | import io.opentracing.testbed.AutoFinishScope.Continuation; 21 | import io.opentracing.testbed.AutoFinishScopeManager; 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | 25 | import java.util.concurrent.Callable; 26 | import java.util.concurrent.ExecutorService; 27 | import java.util.concurrent.Executors; 28 | import java.util.concurrent.Future; 29 | 30 | import static io.opentracing.testbed.TestUtils.sleep; 31 | 32 | public class Client { 33 | 34 | private static final Logger logger = LoggerFactory.getLogger(Client.class); 35 | 36 | private final ExecutorService executor = Executors.newCachedThreadPool(); 37 | private final Tracer tracer; 38 | 39 | public Client(Tracer tracer) { 40 | this.tracer = tracer; 41 | } 42 | 43 | public Future send(final Object message, final long milliseconds) { 44 | final Continuation cont = ((AutoFinishScopeManager)tracer.scopeManager()).captureScope(); 45 | 46 | return executor.submit(new Callable() { 47 | @Override 48 | public Object call() throws Exception { 49 | logger.info("Child thread with message '{}' started", message); 50 | 51 | try (Scope parentScope = cont.activate()) { 52 | 53 | Span span = tracer.buildSpan("subtask").start(); 54 | try (Scope subtaskScope = tracer.activateSpan(span)) { 55 | // Simulate work. 56 | sleep(milliseconds); 57 | } 58 | } 59 | 60 | logger.info("Child thread with message '{}' finished", message); 61 | return message + "::response"; 62 | } 63 | }); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/multiple_callbacks/MultipleCallbacksTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.multiple_callbacks; 15 | 16 | import io.opentracing.Scope; 17 | import io.opentracing.Span; 18 | import io.opentracing.mock.MockSpan; 19 | import io.opentracing.mock.MockTracer; 20 | import io.opentracing.mock.MockTracer.Propagator; 21 | import io.opentracing.testbed.AutoFinishScopeManager; 22 | import org.junit.Test; 23 | 24 | import java.util.List; 25 | import java.util.concurrent.TimeUnit; 26 | 27 | 28 | import static io.opentracing.testbed.TestUtils.finishedSpansSize; 29 | import static org.awaitility.Awaitility.await; 30 | import static org.hamcrest.core.IsEqual.equalTo; 31 | import static org.junit.Assert.assertEquals; 32 | import static org.junit.Assert.assertNull; 33 | 34 | public class MultipleCallbacksTest { 35 | 36 | private final MockTracer tracer = new MockTracer(new AutoFinishScopeManager(), 37 | Propagator.TEXT_MAP); 38 | 39 | @Test 40 | public void test() throws Exception { 41 | Client client = new Client(tracer); 42 | Span span = tracer.buildSpan("parent").start(); 43 | try (Scope scope = tracer.activateSpan(span)) { 44 | client.send("task1", 300); 45 | client.send("task2", 200); 46 | client.send("task3", 100); 47 | } 48 | 49 | await().atMost(15, TimeUnit.SECONDS).until(finishedSpansSize(tracer), equalTo(4)); 50 | 51 | List spans = tracer.finishedSpans(); 52 | assertEquals(4, spans.size()); 53 | assertEquals("parent", spans.get(3).operationName()); 54 | 55 | MockSpan parentSpan = spans.get(3); 56 | for (int i = 0; i < 3; i++) { 57 | assertEquals(true, parentSpan.finishMicros() >= spans.get(i).finishMicros()); 58 | assertEquals(parentSpan.context().traceId(), spans.get(i).context().traceId()); 59 | assertEquals(parentSpan.context().spanId(), spans.get(i).parentId()); 60 | } 61 | 62 | assertNull(tracer.scopeManager().activeSpan()); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/multiple_callbacks/README.md: -------------------------------------------------------------------------------- 1 | # Multiple callbacks example. 2 | 3 | This example shows a `Span` created for a top-level operation, covering a set of asynchronous operations (representing callbacks), and have this `Span` finished when **all** of them have been executed. 4 | 5 | `Client.send()` is used to create a new asynchronous operation (callback), and in turn every operation both restores the active `Span`, and creates a child `Span` (useful for measuring the performance of each callback). `AutoFinishScopeManager` is used so the related callbacks can be referenced, and properly finish the main `Span` when all pending work is done. 6 | 7 | ```java 8 | // Client.send() 9 | final Continuation cont = ((AutoFinishScopeManager)tracer.scopeManager()).captureScope(); 10 | 11 | return executor.submit(new Callable() { 12 | @Override 13 | public Object call() throws Exception { 14 | logger.info("Child thread with message '{}' started", message); 15 | 16 | try (Scope parentScope = cont.activate()) { 17 | 18 | Span span = tracer.buildSpan("subtask").start(); 19 | try (Scope subtaskScope = tracer.activateSpan(span)) { 20 | ... 21 | 22 | ``` 23 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/nested_callbacks/NestedCallbacksTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.nested_callbacks; 15 | 16 | import io.opentracing.Scope; 17 | import io.opentracing.Span; 18 | import io.opentracing.mock.MockSpan; 19 | import io.opentracing.mock.MockTracer; 20 | import io.opentracing.mock.MockTracer.Propagator; 21 | import io.opentracing.util.ThreadLocalScopeManager; 22 | import org.junit.Test; 23 | 24 | import java.util.List; 25 | import java.util.Map; 26 | import java.util.concurrent.ExecutorService; 27 | import java.util.concurrent.Executors; 28 | import java.util.concurrent.TimeUnit; 29 | 30 | import static io.opentracing.testbed.TestUtils.finishedSpansSize; 31 | import static org.awaitility.Awaitility.await; 32 | import static org.hamcrest.core.IsEqual.equalTo; 33 | import static org.junit.Assert.assertEquals; 34 | import static org.junit.Assert.assertNull; 35 | 36 | public class NestedCallbacksTest { 37 | 38 | private final MockTracer tracer = new MockTracer(new ThreadLocalScopeManager(), 39 | Propagator.TEXT_MAP); 40 | private final ExecutorService executor = Executors.newCachedThreadPool(); 41 | 42 | @Test 43 | public void test() throws Exception { 44 | 45 | Span span = tracer.buildSpan("one").start(); 46 | submitCallbacks(span); 47 | 48 | await().atMost(15, TimeUnit.SECONDS).until(finishedSpansSize(tracer), equalTo(1)); 49 | 50 | List spans = tracer.finishedSpans(); 51 | assertEquals(1, spans.size()); 52 | assertEquals("one", spans.get(0).operationName()); 53 | 54 | Map tags = spans.get(0).tags(); 55 | assertEquals(3, tags.size()); 56 | for (int i = 1; i <= 3; i++) { 57 | assertEquals(Integer.toString(i), tags.get("key" + i)); 58 | } 59 | 60 | assertNull(tracer.scopeManager().activeSpan()); 61 | } 62 | 63 | private void submitCallbacks(final Span span) { 64 | 65 | executor.submit(new Runnable() { 66 | @Override 67 | public void run() { 68 | try (Scope scope = tracer.scopeManager().activate(span)) { 69 | span.setTag("key1", "1"); 70 | 71 | executor.submit(new Runnable() { 72 | @Override 73 | public void run() { 74 | try (Scope scope = tracer.scopeManager().activate(span)) { 75 | span.setTag("key2", "2"); 76 | 77 | executor.submit(new Runnable() { 78 | @Override 79 | public void run() { 80 | try (Scope scope = tracer.scopeManager().activate(span)) { 81 | span.setTag("key3", "3"); 82 | } finally { 83 | span.finish(); 84 | } 85 | } 86 | }); 87 | } 88 | } 89 | }); 90 | } 91 | } 92 | }); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/nested_callbacks/README.md: -------------------------------------------------------------------------------- 1 | # Nested callbacks example. 2 | 3 | This example shows a `Span` for a top-level operation, and how it can be manually passed down on a list of nested callbacks (always one at a time), re-activated on each one, and finished **only** when the last one executes. 4 | 5 | ```java 6 | try (Scope scope = tracer.scopeManager().activate(span)) { 7 | span.setTag("key1", "1"); 8 | 9 | executor.submit(new Runnable() { 10 | @Override 11 | public void run() { 12 | try (Scope scope = tracer.scopeManager().activate(span)) { 13 | span.setTag("key2", "2"); 14 | ... 15 | 16 | ``` 17 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/promise_propagation/Promise.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.promise_propagation; 15 | 16 | import io.opentracing.References; 17 | import io.opentracing.Scope; 18 | import io.opentracing.Span; 19 | import io.opentracing.mock.MockTracer; 20 | import io.opentracing.tag.Tags; 21 | import java.util.Collection; 22 | import java.util.LinkedList; 23 | 24 | /** @author tylerbenson */ 25 | public class Promise { 26 | private final PromiseContext context; 27 | private final MockTracer tracer; 28 | private final Span parentSpan; 29 | 30 | private final Collection> successCallbacks = new LinkedList<>(); 31 | private final Collection errorCallbacks = new LinkedList<>(); 32 | 33 | public Promise(PromiseContext context, MockTracer tracer) { 34 | this.context = context; 35 | 36 | // Passed along here for testing. Normally should be referenced via GlobalTracer.get(). 37 | this.tracer = tracer; 38 | parentSpan = tracer.scopeManager().activeSpan(); 39 | } 40 | 41 | public void onSuccess(SuccessCallback successCallback) { 42 | successCallbacks.add(successCallback); 43 | } 44 | 45 | public void onError(ErrorCallback errorCallback) { 46 | errorCallbacks.add(errorCallback); 47 | } 48 | 49 | public void success(final T result) { 50 | for (final SuccessCallback callback : successCallbacks) { 51 | context.submit( 52 | new Runnable() { 53 | @Override 54 | public void run() { 55 | Span childSpan = tracer 56 | .buildSpan("success") 57 | .addReference(References.FOLLOWS_FROM, parentSpan.context()) 58 | .withTag(Tags.COMPONENT.getKey(), "success") 59 | .start(); 60 | try (Scope childScope = tracer.activateSpan(childSpan)) { 61 | callback.accept(result); 62 | } finally { 63 | childSpan.finish(); 64 | } 65 | context.getPhaser().arriveAndAwaitAdvance(); // trace reported 66 | } 67 | }); 68 | } 69 | } 70 | 71 | public void error(final Throwable error) { 72 | for (final ErrorCallback callback : errorCallbacks) { 73 | context.submit( 74 | new Runnable() { 75 | @Override 76 | public void run() { 77 | Span childSpan = tracer 78 | .buildSpan("error") 79 | .addReference(References.FOLLOWS_FROM, parentSpan.context()) 80 | .withTag(Tags.COMPONENT.getKey(), "error") 81 | .start(); 82 | try (Scope childScope = tracer.activateSpan(childSpan)) { 83 | callback.accept(error); 84 | } finally { 85 | childSpan.finish(); 86 | } 87 | context.getPhaser().arriveAndAwaitAdvance(); // trace reported 88 | } 89 | }); 90 | } 91 | } 92 | 93 | public interface SuccessCallback { 94 | /** @param t the result of the promise */ 95 | void accept(T t); 96 | } 97 | 98 | public interface ErrorCallback { 99 | /** @param t the error result of the promise */ 100 | void accept(Throwable t); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/promise_propagation/PromiseContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.promise_propagation; 15 | 16 | import java.util.concurrent.ExecutorService; 17 | import java.util.concurrent.Executors; 18 | import java.util.concurrent.Phaser; 19 | 20 | /** @author tylerbenson */ 21 | public class PromiseContext implements AutoCloseable { 22 | 23 | private final Phaser phaser; 24 | private final ExecutorService executor; 25 | 26 | public PromiseContext(Phaser phaser, int concurrency) { 27 | this.phaser = phaser; 28 | executor = Executors.newFixedThreadPool(concurrency); 29 | } 30 | 31 | @Override 32 | public void close() { 33 | executor.shutdown(); 34 | } 35 | 36 | public void submit(Runnable runnable) { 37 | phaser.register(); // register the work to be done on the executor 38 | executor.submit(runnable); 39 | } 40 | 41 | public Phaser getPhaser() { 42 | return phaser; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/promise_propagation/PromisePropagationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.promise_propagation; 15 | 16 | import io.opentracing.Scope; 17 | import io.opentracing.Span; 18 | import io.opentracing.mock.MockSpan; 19 | import io.opentracing.mock.MockTracer; 20 | import io.opentracing.mock.MockTracer.Propagator; 21 | import io.opentracing.tag.Tags; 22 | import io.opentracing.util.ThreadLocalScopeManager; 23 | import java.util.List; 24 | import java.util.concurrent.Phaser; 25 | import java.util.concurrent.atomic.AtomicReference; 26 | import org.junit.Before; 27 | import org.junit.Test; 28 | 29 | import static io.opentracing.testbed.TestUtils.getByTag; 30 | import static io.opentracing.testbed.TestUtils.getOneByTag; 31 | import static org.assertj.core.api.Assertions.assertThat; 32 | 33 | /** 34 | * These tests are intended to simulate the kind of async models that are common in java async 35 | * frameworks. 36 | * 37 | * For improved readability, ignore the phaser lines as those are there to ensure deterministic 38 | * execution for the tests without sleeps. 39 | * 40 | * @author tylerbenson 41 | */ 42 | public class PromisePropagationTest { 43 | 44 | private final MockTracer tracer = 45 | new MockTracer(new ThreadLocalScopeManager(), Propagator.TEXT_MAP); 46 | private Phaser phaser; 47 | 48 | @Before 49 | public void before() { 50 | phaser = new Phaser(); 51 | } 52 | 53 | @Test 54 | public void testPromiseCallback() { 55 | phaser.register(); // register test thread 56 | final AtomicReference successResult1 = new AtomicReference<>(); 57 | final AtomicReference successResult2 = new AtomicReference<>(); 58 | final AtomicReference errorResult = new AtomicReference<>(); 59 | try (PromiseContext context = new PromiseContext(phaser, 3)) { 60 | Span parentSpan = tracer 61 | .buildSpan("promises") 62 | .withTag(Tags.COMPONENT.getKey(), "example-promises") 63 | .start(); 64 | try (Scope parentScope = tracer.activateSpan(parentSpan)) { 65 | Promise successPromise = new Promise<>(context, tracer); 66 | 67 | successPromise.onSuccess( 68 | new Promise.SuccessCallback() { 69 | @Override 70 | public void accept(String s) { 71 | tracer.activeSpan().log("Promised 1 " + s); 72 | successResult1.set(s); 73 | phaser.arriveAndAwaitAdvance(); // result set 74 | } 75 | }); 76 | successPromise.onSuccess( 77 | new Promise.SuccessCallback() { 78 | @Override 79 | public void accept(String s) { 80 | tracer.activeSpan().log("Promised 2 " + s); 81 | successResult2.set(s); 82 | phaser.arriveAndAwaitAdvance(); // result set 83 | } 84 | }); 85 | 86 | Promise errorPromise = new Promise(context, tracer); 87 | 88 | errorPromise.onError( 89 | new Promise.ErrorCallback() { 90 | @Override 91 | public void accept(Throwable t) { 92 | errorResult.set(t); 93 | phaser.arriveAndAwaitAdvance(); // result set 94 | } 95 | }); 96 | assertThat(tracer.finishedSpans().size()).isEqualTo(0); 97 | successPromise.success("success!"); 98 | errorPromise.error(new Exception("some error.")); 99 | } finally { 100 | parentSpan.finish(); 101 | } 102 | 103 | phaser.arriveAndAwaitAdvance(); // wait for results to be set 104 | assertThat(successResult1.get()).isEqualTo("success!"); 105 | assertThat(successResult2.get()).isEqualTo("success!"); 106 | assertThat(errorResult.get()).hasMessage("some error."); 107 | 108 | phaser.arriveAndAwaitAdvance(); // wait for traces to be reported 109 | List finished = tracer.finishedSpans(); 110 | assertThat(finished.size()).isEqualTo(4); 111 | assertThat(getOneByTag(finished, Tags.COMPONENT, "example-promises")).isNotNull(); 112 | assertThat(getOneByTag(finished, Tags.COMPONENT, "example-promises").parentId()).isEqualTo(0); 113 | long parentId = getOneByTag(finished, Tags.COMPONENT, "example-promises").context().spanId(); 114 | assertThat(getByTag(finished, Tags.COMPONENT, "success")).hasSize(2); 115 | for (MockSpan span : getByTag(finished, Tags.COMPONENT, "success")) { 116 | assertThat(span.parentId()).isEqualTo(parentId); 117 | } 118 | assertThat(getOneByTag(finished, Tags.COMPONENT, "error")).isNotNull(); 119 | assertThat(getOneByTag(finished, Tags.COMPONENT, "error").parentId()).isEqualTo(parentId); 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/promise_propagation/README.md: -------------------------------------------------------------------------------- 1 | # Promise propagation example. 2 | 3 | This example shows `Span` usage with `Promise` objects, such as the ones in **Akka** and other asynchronous frameworks: objects representing the result of a concurrent operation that can have multiple callbacks for success/error, along a way to manually set the final result (a writable `Future`, that is). 4 | 5 | A top-level `Span` is created for the main work, and later passed to the `Promise` object, to be used as reference for the newly created `Span`s in each callback. Since those callbacks are scheduled through a executor and will possibly run at different times, possibly in parallel, the `FOLLOWS_FROM` reference is used instead of the usual `CHILD_OF`, to document the top-level `Span` doesn't depend on the finish time of its children. 6 | 7 | ```java 8 | // Promise.success() 9 | public void success(final T result) { 10 | for (final SuccessCallback callback : successCallbacks) { 11 | context.submit( 12 | new Runnable() { 13 | @Override 14 | public void run() { 15 | Span childSpan = tracer 16 | .buildSpan("success") 17 | .addReference(References.FOLLOWS_FROM, parentSpan.context()) 18 | .withTag(Tags.COMPONENT.getKey(), "success") 19 | .start(); 20 | try (Scope childScope = tracer.activateSpan(childSpan)) { 21 | callback.accept(result); 22 | } finally { 23 | childSpan.finish(); 24 | } 25 | ... 26 | } 27 | }); 28 | } 29 | } 30 | ``` 31 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/stateless_common_request_handler/Client.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.stateless_common_request_handler; 15 | 16 | import io.opentracing.testbed.TestUtils; 17 | import org.slf4j.Logger; 18 | import org.slf4j.LoggerFactory; 19 | 20 | import java.util.concurrent.Callable; 21 | import java.util.concurrent.ExecutorService; 22 | import java.util.concurrent.Executors; 23 | import java.util.concurrent.Future; 24 | 25 | public class Client { 26 | 27 | private static final Logger logger = LoggerFactory.getLogger(Client.class); 28 | 29 | private final ExecutorService executor = Executors.newCachedThreadPool(); 30 | 31 | private final RequestHandler requestHandler; 32 | 33 | public Client(RequestHandler requestHandler) { 34 | this.requestHandler = requestHandler; 35 | } 36 | 37 | public Future send(final Object message) { 38 | 39 | return executor.submit(new Callable() { 40 | @Override 41 | public String call() throws Exception { 42 | logger.info("send {}", message); 43 | TestUtils.sleep(); 44 | requestHandler.beforeRequest(message); 45 | 46 | TestUtils.sleep(); 47 | requestHandler.afterResponse(message); 48 | 49 | return message + ":response"; 50 | } 51 | }); 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/stateless_common_request_handler/HandlerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.stateless_common_request_handler; 15 | 16 | import io.opentracing.mock.MockSpan; 17 | import io.opentracing.mock.MockTracer; 18 | import io.opentracing.mock.MockTracer.Propagator; 19 | import io.opentracing.util.ThreadLocalScopeManager; 20 | import org.junit.Before; 21 | import org.junit.Test; 22 | 23 | import java.util.List; 24 | import java.util.concurrent.Future; 25 | import java.util.concurrent.TimeUnit; 26 | 27 | import static org.junit.Assert.assertEquals; 28 | 29 | /** 30 | * There is only one instance of 'RequestHandler' per 'Client'. Methods of 'RequestHandler' are 31 | * executed in the same thread (beforeRequest() and its resulting afterRequest(), that is). 32 | */ 33 | public class HandlerTest { 34 | 35 | private final MockTracer tracer = new MockTracer(new ThreadLocalScopeManager(), 36 | Propagator.TEXT_MAP); 37 | private final Client client = new Client(new RequestHandler(tracer)); 38 | 39 | @Before 40 | public void before() { 41 | tracer.reset(); 42 | } 43 | 44 | @Test 45 | public void test_requests() throws Exception { 46 | Future responseFuture = client.send("message"); 47 | Future responseFuture2 = client.send("message2"); 48 | Future responseFuture3 = client.send("message3"); 49 | 50 | assertEquals("message3:response", responseFuture3.get(5, TimeUnit.SECONDS)); 51 | assertEquals("message2:response", responseFuture2.get(5, TimeUnit.SECONDS)); 52 | assertEquals("message:response", responseFuture.get(5, TimeUnit.SECONDS)); 53 | 54 | List finished = tracer.finishedSpans(); 55 | assertEquals(3, finished.size()); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/stateless_common_request_handler/README.md: -------------------------------------------------------------------------------- 1 | # Stateless common Request Handler example. 2 | 3 | This example shows a `Span` used with `RequestHandler`, which is used as common, *stateless* middleware (as in web frameworks) to manage a new `Span` per operation through its `beforeRequest()`/`afterResponse()` methods. As these methods do not expose any object storing state, a thread-local field in `RequestHandler` itself is used to contain the `Scope` related to `Span` activation. 4 | 5 | ```java 6 | public void beforeRequest(Object request) { 7 | logger.info("before send {}", request); 8 | 9 | Span span = tracer.buildSpan(OPERATION_NAME).start(); 10 | tlsScope.set(tracer.activateSpan(span)); 11 | } 12 | 13 | public void afterResponse(Object response) { 14 | logger.info("after response {}", response); 15 | 16 | // Finish the Span 17 | tracer.scopeManager().activeSpan().finish(); 18 | 19 | // Deactivate the Span 20 | tlsScope.get().close(); 21 | } 22 | ``` 23 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/stateless_common_request_handler/RequestHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.stateless_common_request_handler; 15 | 16 | import io.opentracing.Scope; 17 | import io.opentracing.Span; 18 | import io.opentracing.Tracer; 19 | import org.slf4j.Logger; 20 | import org.slf4j.LoggerFactory; 21 | 22 | /** 23 | * One instance per Client. 'beforeRequest' and 'afterResponse' 24 | * are executed in the same thread for one 'send', 25 | * but as these methods do not expose any object storing state, 26 | * a thread-local field in 'RequestHandler' itself is used 27 | * to contain the Scope related to Span activation. 28 | */ 29 | public class RequestHandler { 30 | 31 | private static final Logger logger = LoggerFactory.getLogger(RequestHandler.class); 32 | 33 | static final String OPERATION_NAME = "send"; 34 | 35 | private final Tracer tracer; 36 | 37 | private final ThreadLocal tlsScope = new ThreadLocal(); 38 | 39 | public RequestHandler(Tracer tracer) { 40 | this.tracer = tracer; 41 | } 42 | 43 | public void beforeRequest(Object request) { 44 | logger.info("before send {}", request); 45 | 46 | Span span = tracer.buildSpan(OPERATION_NAME).start(); 47 | tlsScope.set(tracer.activateSpan(span)); 48 | } 49 | 50 | public void afterResponse(Object response) { 51 | logger.info("after response {}", response); 52 | 53 | // Finish the Span 54 | tracer.scopeManager().activeSpan().finish(); 55 | 56 | // Deactivate the Span 57 | tlsScope.get().close(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/suspend_resume_propagation/README.md: -------------------------------------------------------------------------------- 1 | # Suspend-resume example. 2 | 3 | This example shows `Span` usage with the suspend-resume model found in asynchronous frameworks, where each step is reported and finally signaled as done. 4 | 5 | `SuspendResume` is used as the class reporting progress (at which point the captured `Span` is activated) and signaling the operation success (at which point the `Span` is finished). 6 | 7 | ```java 8 | // SuspendResume 9 | public void doPart(String name) { 10 | try (Scope scope = tracer.scopeManager().activate(span)) { 11 | scope.span().log("part: " + name); 12 | } 13 | } 14 | 15 | public void done() { 16 | span.finish(); 17 | } 18 | ``` 19 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/suspend_resume_propagation/SuspendResume.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.suspend_resume_propagation; 15 | 16 | import io.opentracing.Scope; 17 | import io.opentracing.Span; 18 | import io.opentracing.mock.MockTracer; 19 | import io.opentracing.tag.Tags; 20 | 21 | /** @author tylerbenson */ 22 | public class SuspendResume { 23 | 24 | private final int id; 25 | private final MockTracer tracer; 26 | private Span span; 27 | 28 | public SuspendResume(int id, MockTracer tracer) { 29 | this.id = id; 30 | 31 | // Passed along here for testing. Normally should be referenced via GlobalTracer.get(). 32 | this.tracer = tracer; 33 | 34 | Span span = tracer 35 | .buildSpan("job " + id) 36 | .withTag(Tags.COMPONENT.getKey(), "suspend-resume") 37 | .start(); 38 | try (Scope scope = tracer.scopeManager().activate(span)) { 39 | this.span = span; 40 | } 41 | } 42 | 43 | public void doPart(String name) { 44 | try (Scope scope = tracer.scopeManager().activate(span)) { 45 | span.log("part: " + name); 46 | } 47 | } 48 | 49 | public void done() { 50 | span.finish(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /opentracing-testbed/src/test/java/io/opentracing/testbed/suspend_resume_propagation/SuspendResumePropagationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.testbed.suspend_resume_propagation; 15 | 16 | import io.opentracing.mock.MockSpan; 17 | import io.opentracing.mock.MockTracer; 18 | import io.opentracing.mock.MockTracer.Propagator; 19 | import io.opentracing.util.ThreadLocalScopeManager; 20 | import org.junit.Before; 21 | import org.junit.Test; 22 | 23 | import java.util.List; 24 | import java.util.concurrent.Phaser; 25 | 26 | import static org.assertj.core.api.Assertions.assertThat; 27 | 28 | /** 29 | * These tests are intended to simulate the kind of async models that are common in java async 30 | * frameworks. 31 | * 32 | * For improved readability, ignore the phaser lines as those are there to ensure deterministic 33 | * execution for the tests without sleeps. 34 | * 35 | * @author tylerbenson 36 | */ 37 | public class SuspendResumePropagationTest { 38 | 39 | private final MockTracer tracer = 40 | new MockTracer(new ThreadLocalScopeManager(), Propagator.TEXT_MAP); 41 | private Phaser phaser; 42 | 43 | @Before 44 | public void before() { 45 | phaser = new Phaser(); 46 | } 47 | 48 | @Test 49 | public void testContinuationInterleaving() { 50 | SuspendResume job1 = new SuspendResume(1, tracer); 51 | SuspendResume job2 = new SuspendResume(2, tracer); 52 | 53 | // Pretend that the framework is controlling actual execution here. 54 | job1.doPart("some work for 1"); 55 | job2.doPart("some work for 2"); 56 | job1.doPart("other work for 1"); 57 | job2.doPart("other work for 2"); 58 | job2.doPart("more work for 2"); 59 | job1.doPart("more work for 1"); 60 | 61 | job1.done(); 62 | job2.done(); 63 | 64 | List finished = tracer.finishedSpans(); 65 | assertThat(finished.size()).isEqualTo(2); 66 | 67 | assertThat(finished.get(0).operationName()).isEqualTo("job 1"); 68 | assertThat(finished.get(1).operationName()).isEqualTo("job 2"); 69 | 70 | assertThat(finished.get(0).parentId()).isEqualTo(0); 71 | assertThat(finished.get(1).parentId()).isEqualTo(0); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /opentracing-util/README.md: -------------------------------------------------------------------------------- 1 | # OpenTracing-Java utilities 2 | 3 | The `opentracing-util` artifact contains utility classes that are not part of the OpenTracing API 4 | but can provide useful features to OpenTracing users. 5 | 6 | ## GlobalTracer 7 | 8 | The `io.opentracing.util.GlobalTracer` has a static `Tracer` reference that can be 9 | used throughout an application or from independent instrumentation libraries. 10 | 11 | It defines the following methods: 12 | - `GlobalTracer.get()` : Returns the constant global tracer. 13 | All methods are forwarded to the currently configured tracer. 14 | Until a tracer is explicitly registered, the `NoopTracer` will be used. 15 | - `GlobalTracer.register(Tracer)` : Register a `Tracer` to become the global tracer. 16 | Registration is a one-time operation, attempting to call it more often will result in a runtime exception. 17 | Every application intending to use the global tracer is responsible for registering it during its initialization. 18 | - `GlobalTracer.isRegistered` : Identify whether a `Tracer` has previously been registered. 19 | This check is useful in scenarios where more than one component may be responsible 20 | for registering a tracer. For example, when using a Java Agent, it will need to determine 21 | if the application has already registered a tracer, and if not attempt to resolve and 22 | register one itself. 23 | 24 | ### Using the GlobalTracer 25 | 26 | **Application intialization** 27 | 28 | Initialize a new tracer from the application configuration and let it to become the GlobalTracer for the application: 29 | 30 | ```java 31 | Tracer configuredTracer = applicationConfiguration.buildConfiguredTracer(); 32 | GlobalTracer.register(configuredTracer); 33 | ``` 34 | 35 | **Tracing some block of code** 36 | 37 | Once initialized, all application code can instrument tracing by starting new spans like: 38 | 39 | ```java 40 | try (Scope scope = GlobalTracer.get().buildSpan("someOperation").startActive()) { 41 | // ... Traced block of code ... 42 | } 43 | ``` 44 | 45 | If no GlobalTracer is configured, this code will not throw any exceptions. Tracing is simply delegated to the NoopTracer instead. 46 | -------------------------------------------------------------------------------- /opentracing-util/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 4.0.0 19 | 20 | 21 | io.opentracing 22 | parent 23 | 0.33.1-SNAPSHOT 24 | 25 | 26 | opentracing-util 27 | OpenTracing-util 28 | OpenTracing utilities 29 | 30 | 31 | ${project.basedir}/.. 32 | 1.6 33 | 34 | 35 | 36 | 37 | ${project.groupId} 38 | opentracing-api 39 | 40 | 41 | ${project.groupId} 42 | opentracing-noop 43 | 44 | 45 | 46 | 47 | 48 | 49 | maven-jar-plugin 50 | 51 | 52 | 53 | test-jar 54 | 55 | 56 | 57 | **/*TestUtil.* 58 | 59 | 60 | 61 | io.opentracing.util.tests 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | io.opentracing.util 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /opentracing-util/src/main/java/io/opentracing/util/ThreadLocalScope.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.util; 15 | 16 | import io.opentracing.Scope; 17 | import io.opentracing.ScopeManager; 18 | import io.opentracing.Span; 19 | 20 | /** 21 | * {@link ThreadLocalScope} is a simple {@link Scope} implementation that relies on Java's 22 | * thread-local storage primitive. 23 | * 24 | * @see ScopeManager 25 | */ 26 | public class ThreadLocalScope implements Scope { 27 | private final ThreadLocalScopeManager scopeManager; 28 | private final Span wrapped; 29 | private final ThreadLocalScope toRestore; 30 | 31 | ThreadLocalScope(ThreadLocalScopeManager scopeManager, Span wrapped) { 32 | this.scopeManager = scopeManager; 33 | this.wrapped = wrapped; 34 | this.toRestore = scopeManager.tlsScope.get(); 35 | scopeManager.tlsScope.set(this); 36 | } 37 | 38 | @Override 39 | public void close() { 40 | if (scopeManager.tlsScope.get() != this) { 41 | // This shouldn't happen if users call methods in the expected order. Bail out. 42 | return; 43 | } 44 | 45 | scopeManager.tlsScope.set(toRestore); 46 | } 47 | 48 | Span span() { 49 | return wrapped; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /opentracing-util/src/main/java/io/opentracing/util/ThreadLocalScopeManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.util; 15 | 16 | import io.opentracing.Scope; 17 | import io.opentracing.ScopeManager; 18 | import io.opentracing.Span; 19 | 20 | /** 21 | * A simple {@link ScopeManager} implementation built on top of Java's thread-local storage primitive. 22 | * 23 | * @see ThreadLocalScope 24 | */ 25 | public class ThreadLocalScopeManager implements ScopeManager { 26 | final ThreadLocal tlsScope = new ThreadLocal(); 27 | 28 | @Override 29 | public Scope activate(Span span) { 30 | return new ThreadLocalScope(this, span); 31 | } 32 | 33 | @Override 34 | public Span activeSpan() { 35 | ThreadLocalScope scope = tlsScope.get(); 36 | return scope == null ? null : scope.span(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /opentracing-util/src/test/java/io/opentracing/util/GlobalTracerTestUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.util; 15 | 16 | import io.opentracing.Tracer; 17 | import io.opentracing.noop.NoopTracerFactory; 18 | 19 | import java.lang.reflect.Field; 20 | 21 | /** 22 | * Utility class for manipulating the {@link GlobalTracer} when testing. 23 | *

24 | * The {@linkplain GlobalTracer} has register-once semantics, but for testing purposes it is useful to 25 | * manipulate the globaltracer to guarantee certain preconditions. 26 | *

27 | * The {@code GlobalTracerTestUtil} can be included in your own code by adding the following dependency: 28 | *


29 |  *     <dependency>
30 |  *         <groupId>io.opentracing</groupId>
31 |  *         <artifactId>opentracing-util</artifactId>
32 |  *         <version>version</version>
33 |  *         <type>test-jar</type>
34 |  *         <scope>test</scope>
35 |  *      </dependency>
36 |  * 
37 | */ 38 | public class GlobalTracerTestUtil { 39 | 40 | private GlobalTracerTestUtil() { 41 | throw new UnsupportedOperationException("Cannot instantiate static test utility class."); 42 | } 43 | 44 | /** 45 | * Resets the {@link GlobalTracer} to its initial, unregistered state. 46 | */ 47 | public static void resetGlobalTracer() { 48 | setGlobalTracerUnconditionally(NoopTracerFactory.create()); 49 | 50 | try { 51 | Field isRegisteredField = GlobalTracer.class.getDeclaredField("isRegistered"); 52 | isRegisteredField.setAccessible(true); 53 | isRegisteredField.set(null, false); 54 | isRegisteredField.setAccessible(false); 55 | } catch (Exception e) { 56 | throw new IllegalStateException("Error reflecting GlobalTracer.tracer: " + e.getMessage(), e); 57 | } 58 | } 59 | 60 | /** 61 | * Unconditionally sets the {@link GlobalTracer} to the specified {@link Tracer tracer} instance. 62 | * 63 | * @param tracer The tracer to become the GlobalTracer's delegate. 64 | */ 65 | public static void setGlobalTracerUnconditionally(Tracer tracer) { 66 | try { 67 | Field globalTracerField = GlobalTracer.class.getDeclaredField("tracer"); 68 | globalTracerField.setAccessible(true); 69 | globalTracerField.set(null, tracer); 70 | globalTracerField.setAccessible(false); 71 | 72 | Field isRegisteredField = GlobalTracer.class.getDeclaredField("isRegistered"); 73 | isRegisteredField.setAccessible(true); 74 | isRegisteredField.set(null, true); 75 | isRegisteredField.setAccessible(false); 76 | } catch (Exception e) { 77 | throw new IllegalStateException("Error reflecting GlobalTracer.tracer: " + e.getMessage(), e); 78 | } 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /opentracing-util/src/test/java/io/opentracing/util/ThreadLocalScopeManagerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.util; 15 | 16 | import io.opentracing.Scope; 17 | import io.opentracing.Span; 18 | import org.junit.Before; 19 | import org.junit.Test; 20 | 21 | import static org.junit.Assert.*; 22 | import static org.mockito.Mockito.mock; 23 | import static org.mockito.Mockito.never; 24 | import static org.mockito.Mockito.verify; 25 | 26 | public class ThreadLocalScopeManagerTest { 27 | private ThreadLocalScopeManager source; 28 | 29 | @Before 30 | public void before() throws Exception { 31 | source = new ThreadLocalScopeManager(); 32 | } 33 | 34 | @Test 35 | public void missingActiveSpan() throws Exception { 36 | Span missingSpan = source.activeSpan(); 37 | assertNull(missingSpan); 38 | } 39 | 40 | @Test 41 | public void defaultActivateSpan() throws Exception { 42 | Span span = mock(Span.class); 43 | 44 | Scope scope = source.activate(span); 45 | try { 46 | assertNotNull(scope); 47 | 48 | Span otherSpan = source.activeSpan(); 49 | assertEquals(otherSpan, span); 50 | } finally { 51 | scope.close(); 52 | } 53 | 54 | // Make sure the Span is not finished. 55 | verify(span, never()).finish(); 56 | 57 | // And now Scope/Span are gone: 58 | Span missingSpan = source.activeSpan(); 59 | assertNull(missingSpan); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /opentracing-util/src/test/java/io/opentracing/util/ThreadLocalScopeTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2020 The OpenTracing Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package io.opentracing.util; 15 | 16 | import static org.junit.Assert.assertEquals; 17 | import static org.junit.Assert.assertNotNull; 18 | import static org.junit.Assert.assertNull; 19 | import static org.mockito.Mockito.mock; 20 | import static org.mockito.Mockito.times; 21 | import static org.mockito.Mockito.verify; 22 | 23 | import io.opentracing.Scope; 24 | import io.opentracing.Span; 25 | import org.junit.Before; 26 | import org.junit.Test; 27 | 28 | public class ThreadLocalScopeTest { 29 | private ThreadLocalScopeManager scopeManager; 30 | 31 | @Before 32 | public void before() throws Exception { 33 | scopeManager = new ThreadLocalScopeManager(); 34 | } 35 | 36 | @Test 37 | public void implicitSpanStack() throws Exception { 38 | Span backgroundSpan = mock(Span.class); 39 | Span foregroundSpan = mock(Span.class); 40 | 41 | Scope backgroundActive = scopeManager.activate(backgroundSpan); 42 | try { 43 | assertNotNull(backgroundActive); 44 | assertEquals(scopeManager.activeSpan(), backgroundSpan); 45 | 46 | // Activate a new Scope on top of the background one. 47 | Scope foregroundActive = scopeManager.activate(foregroundSpan); 48 | try { 49 | assertNotNull(foregroundActive); 50 | assertEquals(scopeManager.activeSpan(), foregroundSpan); 51 | } finally { 52 | foregroundActive.close(); 53 | } 54 | 55 | // And now the backgroundActive should be reinstated. 56 | assertEquals(scopeManager.activeSpan(), backgroundSpan); 57 | } finally { 58 | backgroundActive.close(); 59 | } 60 | 61 | // The background and foreground Spans should NOT be finished. 62 | verify(backgroundSpan, times(0)).finish(); 63 | verify(foregroundSpan, times(0)).finish(); 64 | 65 | // And now nothing is active. 66 | assertNull(scopeManager.activeSpan()); 67 | } 68 | 69 | @Test 70 | public void testDeactivateWhenDifferentSpanIsActive() { 71 | Span span = mock(Span.class); 72 | 73 | Scope active = scopeManager.activate(span); 74 | scopeManager.activate(mock(Span.class)); 75 | active.close(); 76 | 77 | verify(span, times(0)).finish(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/etc/header.txt: -------------------------------------------------------------------------------- 1 | Copyright ${license.git.copyrightYears} The OpenTracing Authors 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 4 | in compliance with the License. You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software distributed under the License 9 | is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 10 | or implied. See the License for the specific language governing permissions and limitations under 11 | the License. 12 | --------------------------------------------------------------------------------