initial commit of skywalking-rust with full-tracing features. (#5)

diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..8993576
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,2 @@
+target/
+e2e/target
\ No newline at end of file
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 2cfeb06..a937273 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -11,19 +11,14 @@
 
 jobs:
   CI:
-    runs-on: ubuntu-18.04
-    timeout-minutes: 180
-    strategy:
-      fail-fast: true
+    runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v1
-        with:
-          submodules: true
-      - uses: actions-rs/cargo@v1
-        with:
-          command: build
-          args: --release --all-features
-      - name: 'Install & Test'
+      - uses: actions/checkout@v2
+      - name: install Rust
         run: |
-          cargo build
-          cargo test
\ No newline at end of file
+          git submodule update --init --recursive
+          rustup toolchain install stable --component clippy --component rustfmt
+      - name: Format
+        run: cargo fmt -- --check
+      - name: clippy
+        run: cargo clippy
diff --git a/.gitignore b/.gitignore
index 07827cc..11469bd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
-target/
-.idea/
\ No newline at end of file
+/target
+/tests/e2e/target
+.idea/
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..69d308e
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "skywalking-data-collect-protocol"]
+	path = skywalking-data-collect-protocol
+	url = https://github.com/apache/skywalking-data-collect-protocol.git
diff --git a/Cargo.lock b/Cargo.lock
index e99ac24..e38a696 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,31 +1,136 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
 [[package]]
-name = "base64"
-version = "0.11.0"
+name = "anyhow"
+version = "1.0.51"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
+checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203"
 
 [[package]]
-name = "c2-chacha"
-version = "0.2.3"
+name = "async-stream"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb"
+checksum = "171374e7e3b2504e0e5236e3b59260560f9fe94bfe9ac39ba5e4e929c5590625"
 dependencies = [
- "ppv-lite86",
+ "async-stream-impl",
+ "futures-core",
 ]
 
 [[package]]
-name = "cfg-if"
-version = "0.1.10"
+name = "async-stream-impl"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
+checksum = "648ed8c8d2ce5409ccd57453d9d1b214b342a0d69376a6feda1fd6cae3299308"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "async-trait"
+version = "0.1.52"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
+
+[[package]]
+name = "base64"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bytes"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "either"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
+
+[[package]]
+name = "fixedbitset"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "futures-channel"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888"
+dependencies = [
+ "futures-core",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d"
+
+[[package]]
+name = "futures-sink"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11"
+
+[[package]]
+name = "futures-task"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99"
+
+[[package]]
+name = "futures-util"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481"
+dependencies = [
+ "autocfg",
+ "futures-core",
+ "futures-task",
+ "pin-project-lite",
+ "pin-utils",
+]
 
 [[package]]
 name = "getrandom"
-version = "0.1.14"
+version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
+checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
 dependencies = [
  "cfg-if",
  "libc",
@@ -33,6 +138,153 @@
 ]
 
 [[package]]
+name = "h2"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f072413d126e57991455e0a922b31e4c8ba7c2ffbebf6b78b4f8521397d65cd"
+dependencies = [
+ "bytes",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "http",
+ "indexmap",
+ "slab",
+ "tokio",
+ "tokio-util",
+ "tracing",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
+
+[[package]]
+name = "heck"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "http"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "http-body"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6"
+dependencies = [
+ "bytes",
+ "http",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "httparse"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503"
+
+[[package]]
+name = "httpdate"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
+
+[[package]]
+name = "hyper"
+version = "0.14.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "socket2",
+ "tokio",
+ "tower-service",
+ "tracing",
+ "want",
+]
+
+[[package]]
+name = "hyper-timeout"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
+dependencies = [
+ "hyper",
+ "pin-project-lite",
+ "tokio",
+ "tokio-io-timeout",
+]
+
+[[package]]
+name = "indexmap"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+]
+
+[[package]]
+name = "instant"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "itertools"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "0.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
+
+[[package]]
 name = "lazy_static"
 version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -40,23 +292,241 @@
 
 [[package]]
 name = "libc"
-version = "0.2.67"
+version = "0.2.112"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018"
+checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
+
+[[package]]
+name = "lock_api"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
+dependencies = [
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "memchr"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
+
+[[package]]
+name = "mio"
+version = "0.7.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc"
+dependencies = [
+ "libc",
+ "log",
+ "miow",
+ "ntapi",
+ "winapi",
+]
+
+[[package]]
+name = "miow"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "multimap"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
+
+[[package]]
+name = "ntapi"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
+
+[[package]]
+name = "parking_lot"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
+dependencies = [
+ "instant",
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
+dependencies = [
+ "cfg-if",
+ "instant",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "winapi",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
+
+[[package]]
+name = "petgraph"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7"
+dependencies = [
+ "fixedbitset",
+ "indexmap",
+]
+
+[[package]]
+name = "pin-project"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
 
 [[package]]
 name = "ppv-lite86"
-version = "0.2.6"
+version = "0.2.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
+checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "prost"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de5e2533f59d08fcf364fd374ebda0692a70bd6d7e66ef97f306f45c6c5d8020"
+dependencies = [
+ "bytes",
+ "prost-derive",
+]
+
+[[package]]
+name = "prost-build"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "355f634b43cdd80724ee7848f95770e7e70eefa6dcf14fea676216573b8fd603"
+dependencies = [
+ "bytes",
+ "heck",
+ "itertools",
+ "log",
+ "multimap",
+ "petgraph",
+ "prost",
+ "prost-types",
+ "tempfile",
+ "which",
+]
+
+[[package]]
+name = "prost-derive"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "600d2f334aa05acb02a755e217ef1ab6dea4d51b58b7846588b747edec04efba"
+dependencies = [
+ "anyhow",
+ "itertools",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "prost-types"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "603bbd6394701d13f3f25aada59c7de9d35a6a5887cfc156181234a44002771b"
+dependencies = [
+ "bytes",
+ "prost",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
+dependencies = [
+ "proc-macro2",
+]
 
 [[package]]
 name = "rand"
-version = "0.7.3"
+version = "0.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
+checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
 dependencies = [
- "getrandom",
  "libc",
  "rand_chacha",
  "rand_core",
@@ -65,43 +535,390 @@
 
 [[package]]
 name = "rand_chacha"
-version = "0.2.1"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
 dependencies = [
- "c2-chacha",
+ "ppv-lite86",
  "rand_core",
 ]
 
 [[package]]
 name = "rand_core"
-version = "0.5.1"
+version = "0.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
 dependencies = [
  "getrandom",
 ]
 
 [[package]]
 name = "rand_hc"
-version = "0.2.0"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
+checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
 dependencies = [
  "rand_core",
 ]
 
 [[package]]
-name = "skywalking-core"
-version = "0.1.0"
+name = "redox_syscall"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
 dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "remove_dir_all"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "serde"
+version = "1.0.132"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b9875c23cf305cd1fd7eb77234cbb705f21ea6a72c637a5c6db5fe4b8e7f008"
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "skywalking_rust"
+version = "0.0.1"
+dependencies = [
+ "async-stream",
  "base64",
- "lazy_static",
+ "bytes",
+ "prost",
+ "prost-derive",
+ "tokio",
+ "tonic",
+ "tonic-build",
+ "uuid",
+]
+
+[[package]]
+name = "slab"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
+
+[[package]]
+name = "smallvec"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
+
+[[package]]
+name = "socket2"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.82"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "tempfile"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
+dependencies = [
+ "cfg-if",
+ "libc",
  "rand",
+ "redox_syscall",
+ "remove_dir_all",
+ "winapi",
+]
+
+[[package]]
+name = "tokio"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838"
+dependencies = [
+ "bytes",
+ "libc",
+ "memchr",
+ "mio",
+ "num_cpus",
+ "once_cell",
+ "parking_lot",
+ "pin-project-lite",
+ "signal-hook-registry",
+ "tokio-macros",
+ "winapi",
+]
+
+[[package]]
+name = "tokio-io-timeout"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90c49f106be240de154571dd31fbe48acb10ba6c6dd6f6517ad603abffa42de9"
+dependencies = [
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tokio-stream"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.6.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "log",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tonic"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "796c5e1cd49905e65dd8e700d4cb1dffcbfdb4fc9d017de08c1a537afd83627c"
+dependencies = [
+ "async-stream",
+ "async-trait",
+ "base64",
+ "bytes",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "hyper-timeout",
+ "percent-encoding",
+ "pin-project",
+ "prost",
+ "prost-derive",
+ "tokio",
+ "tokio-stream",
+ "tokio-util",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+ "tracing-futures",
+]
+
+[[package]]
+name = "tonic-build"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12b52d07035516c2b74337d2ac7746075e7dcae7643816c1b12c5ff8a7484c08"
+dependencies = [
+ "proc-macro2",
+ "prost-build",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tower"
+version = "0.4.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5651b5f6860a99bd1adb59dbfe1db8beb433e73709d9032b413a77e2fb7c066a"
+dependencies = [
+ "futures-core",
+ "futures-util",
+ "indexmap",
+ "pin-project",
+ "pin-project-lite",
+ "rand",
+ "slab",
+ "tokio",
+ "tokio-stream",
+ "tokio-util",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "tower-layer"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62"
+
+[[package]]
+name = "tower-service"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
+
+[[package]]
+name = "tracing"
+version = "0.1.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105"
+dependencies = [
+ "cfg-if",
+ "log",
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4"
+dependencies = [
+ "lazy_static",
+]
+
+[[package]]
+name = "tracing-futures"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
+dependencies = [
+ "pin-project",
+ "tracing",
+]
+
+[[package]]
+name = "try-lock"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
+
+[[package]]
+name = "uuid"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
+dependencies = [
+ "getrandom",
+ "serde",
+]
+
+[[package]]
+name = "want"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
+dependencies = [
+ "log",
+ "try-lock",
 ]
 
 [[package]]
 name = "wasi"
-version = "0.9.0+wasi-snapshot-preview1"
+version = "0.10.2+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
+
+[[package]]
+name = "which"
+version = "4.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea187a8ef279bc014ec368c27a920da2024d2a711109bfbe3440585d5cf27ad9"
+dependencies = [
+ "either",
+ "lazy_static",
+ "libc",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/Cargo.toml b/Cargo.toml
index 629476f..f1634bc 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,8 +13,25 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-[workspace]
+[package]
+name = "skywalking_rust"
+version = "0.0.1"
+authors = ["Rei Shimizu (Shikugawa@gmail.com)"]
+edition = "2018"
 
-members = [
-    "core",
-]
\ No newline at end of file
+[dependencies]
+tonic = "0.5.2"
+bytes = "1.1.0"
+prost = "0.8.0"
+prost-derive = "0.8.0"
+uuid = { version = "0.8", features = ["serde", "v4"] }
+base64 = "0.13.0"
+tokio = { version = "1", features = ["full"] }
+async-stream = "0.3.2"
+
+[build-dependencies]
+tonic-build = "0.5.2"
+
+[[example]]
+name = "simple_trace_report"
+path = "examples/simple_trace_report.rs"
diff --git a/README.md b/README.md
index f9ca49d..ac106cd 100644
--- a/README.md
+++ b/README.md
@@ -30,60 +30,43 @@
 TracingContext is the context of the tracing process. Span should only be created through context, and be archived into the
 context after the span finished.
 
-## Injectable
-Injectable is used(optional) when the exit span creates. This Injectable received the notification from tracing context,
-including the key and value for tracing context across process propagation. Typically, Injectable implementation would 
-manipulate the RPC header/metadata to make the key/value sent to the server side.
-
-## Extractable
-Extractable is used(optional) when the entry span creates. The Extractable fetches the value of the given key from the propagated
-context. Typically, Extractable implementation would read the RPC header/metadata, which sent from the client side. 
-
-# APIs
-## High-Level APIs
-High level APIs are targeting convenient usages. These APIs use the ThreadLocal to propagate the context, so users could
-create span at any moment, and the context will finish automatically once the first created span of this thread stopped.
+# Example
 
 ```rust
-ContextManager::tracing_entry("op1", Some(&injector), |mut span| {
-    // Use span freely in this closure
-    // Span's start/end time is set automatically with this closure start/end(s).
-    span.tag(Tag::new(String::from("tag1"), String::from("value1")));
+use skywalking_rust::context::trace_context::TracingContext;
+use skywalking_rust::reporter::grpc::Reporter;
+use tokio;
 
-    ContextManager::tracing_exit("op2", "127.0.0.1:8080", Some(&extractor), |mut span| {
-        span.set_component_id(33);
-    });
-
-    ContextManager::tracing_local("op3", |mut span| {});
-});
-```
-
-## Low-Level Core APIs
-Tracing core APIs are 100% manual control tracing APIs. Users could use them to trace any process by following SkyWalking
-core concepts.
-
-Low Level APIs request users to create and hold the context and span by the codes manually.
-
-```rust
-let mut context = TracingContext::new(reporter.service_instance_id()).unwrap();
-let span1 = context.create_entry_span("op1", None, Some(&dyn injector));
-{
-    assert_eq!(span1.span_id(), 0);
-    let mut span2 = context.create_local_span("op2", Some(&span1));
-    span2.tag(Tag::new(String::from("tag1"), String::from("value1")));
+async fn handle_request(reporter: ContextReporter) {
+    let mut ctx = TracingContext::default("svc", "ins");
     {
-        assert_eq!(span2.span_id(), 1);
-        let mut span3 = context.create_exit_span("op3", Some(&span2), "127.0.0.1:8080", Some(&dyn extractor));
-        assert_eq!(span3.span_id(), 2);
+        // Generate an Entry Span when a request
+        // is received. An Entry Span is generated only once per context.
+        let span = ctx.create_entry_span("operation1").unwrap();
 
-        context.finish_span(span3);
+        // Something...
+
+        {
+            // Generates an Exit Span when executing an RPC.
+            let span2 = ctx.create_exit_span("operation2").unwrap();
+            
+            // Something...
+
+            ctx.finalize_span(span2);
+        }
+
+        ctx.finalize_span(span);
     }
-    context.finish_span(span2);
+    reporter.send(context).await;
 }
-context.finish_span(span1);
 
-reporter.report_trace(context);
+#[tokio::main]
+async fn main() {
+    let tx = Reporter::start("http://0.0.0.0:11800".to_string()).await;
+
+    // Start server...
+}
 ```
 
 # License
-Apache 2.0 
\ No newline at end of file
+Apache 2.0
diff --git a/core/src/lib.rs b/build.rs
similarity index 71%
copy from core/src/lib.rs
copy to build.rs
index f94e272..157d3d4 100644
--- a/core/src/lib.rs
+++ b/build.rs
@@ -5,13 +5,19 @@
 // (the "License"); you may not use this file except in compliance with
 // the License.  You may obtain a copy of the License at
 //
-// http://www.apache.org/licenses/LICENSE-2.0
+//     http://www.apache.org/licenses/LICENSE-2.0
 //
 // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+//
 
-pub mod skywalking;
-
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+    tonic_build::configure().compile(
+        &["./skywalking-data-collect-protocol/language-agent/Tracing.proto"],
+        &["./skywalking-data-collect-protocol"],
+    )?;
+    Ok(())
+}
diff --git a/core/Cargo.toml b/core/Cargo.toml
deleted file mode 100644
index c187379..0000000
--- a/core/Cargo.toml
+++ /dev/null
@@ -1,27 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-# http:#www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-[package]
-name = "skywalking-core"
-version = "0.1.0"
-authors = ["Apache Software Foundation (ASF)"]
-edition = "2018"
-description = "SkyWalking tracing core APIs. Provide the way to build SkyWalking native format traces/spans and propagated context."
-license = "Apache 2.0"
-
-[dependencies]
-rand = "0.7.3"
-base64 = "0.11.0"
-lazy_static = "1.4.0"
\ No newline at end of file
diff --git a/core/src/skywalking/agent/context_manager.rs b/core/src/skywalking/agent/context_manager.rs
deleted file mode 100644
index 5c5df7f..0000000
--- a/core/src/skywalking/agent/context_manager.rs
+++ /dev/null
@@ -1,265 +0,0 @@
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to You under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License.  You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-use std::borrow::{Borrow, BorrowMut};
-use std::cell::RefCell;
-use std::rc::Rc;
-
-use lazy_static::lazy_static;
-
-use crate::skywalking::agent::reporter::Reporter;
-use crate::skywalking::core::{Context, ContextListener, Extractable, Injectable, Span, TracingContext};
-use crate::skywalking::core::span::TracingSpan;
-
-/// Thread Local tracing context. Host the context and propagate it in each thread if needed.
-thread_local!( static CTX: RefCell<CurrentTracingContext> = RefCell::new(CurrentTracingContext::new()));
-/// Global reporter
-/// Status: WIP
-lazy_static! {
-    static ref SKYWALKING_REPORTER : Reporter = {
-        Reporter::new()
-    };
-}
-
-pub struct ContextManager {}
-
-impl ContextManager {
-    /// Run a closure under an entry span observing.
-    /// Span is automatically created, started and ended around the closure f.
-    pub fn tracing_entry<F>(operation_name: &str, extractor: Option<&dyn Extractable>, f: F)
-        where F: FnOnce(&mut Box<dyn Span>) {
-        CTX.with(|context| {
-            let span;
-            {
-                // Borrow mut ref has to end in this specific scope, as the context is nested used in f<F>
-                let mut mut_context = context.borrow_mut();
-                let parent_span_id = mut_context.parent_span_id();
-                span = mut_context.create_entry_span(operation_name, parent_span_id, extractor);
-            }
-            match span {
-                None => {}
-                Some(mut s) => {
-                    s.start();
-                    f(s.borrow_mut());
-                    s.end();
-
-                    let is_first_span = s.span_id() == 0;
-                    let mut mut_context = context.borrow_mut();
-                    mut_context.finish_span(s);
-
-                    if is_first_span {
-                        mut_context.finish();
-                    }
-                }
-            };
-        });
-    }
-
-    /// Run a closure under an exit span observing.
-    /// Span is automatically created, started and ended around the closure f.
-    pub fn tracing_exit<F>(operation_name: &str, peer: &str, injector: Option<&dyn Injectable>, f: F)
-        where F: FnOnce(&mut Box<dyn Span>) {
-        CTX.with(|context| {
-            let span;
-            {
-                // Borrow mut ref has to end in this specific scope, as the context is nested used in f<F>
-                let mut mut_context = context.borrow_mut();
-                let parent_span_id = mut_context.parent_span_id();
-                span = mut_context.create_exit_span(operation_name, parent_span_id, peer, injector);
-            }
-            match span {
-                None => {}
-                Some(mut s) => {
-                    s.start();
-                    f(s.borrow_mut());
-                    s.end();
-
-                    let is_first_span = s.span_id() == 0;
-
-                    let mut mut_context = context.borrow_mut();
-                    mut_context.finish_span(s);
-
-                    if is_first_span {
-                        mut_context.finish();
-                    }
-                }
-            };
-        });
-    }
-
-    /// Run a closure under a local span observing.
-    /// Span is automatically created, started and ended around the closure f.
-    pub fn tracing_local<F>(operation_name: &str, f: F)
-        where F: FnOnce(&mut Box<dyn Span>) {
-        CTX.with(|context| {
-            let span;
-            {
-                // Borrow mut ref has to end in this specific scope, as the context is nested used in f<F>
-                let mut mut_context = context.borrow_mut();
-                let parent_span_id = mut_context.parent_span_id();
-                span = mut_context.create_local(operation_name, parent_span_id);
-            }
-            match span {
-                None => {}
-                Some(mut s) => {
-                    s.start();
-                    f(s.borrow_mut());
-                    s.end();
-
-                    let is_first_span = s.span_id() == 0;
-
-                    let mut mut_context = context.borrow_mut();
-                    mut_context.finish_span(s);
-
-                    if is_first_span {
-                        mut_context.finish();
-                    }
-                }
-            };
-        });
-    }
-}
-
-struct CurrentTracingContext {
-    option: Option<Box<WorkingContext>>,
-}
-
-struct WorkingContext {
-    context: Box<TracingContext>,
-    span_stack: Vec<i32>,
-}
-
-impl CurrentTracingContext {
-    /// Create the tracing context in the thread local at the first time.
-    fn new() -> Self {
-        CurrentTracingContext {
-            option: match TracingContext::new(SKYWALKING_REPORTER.service_instance_id()) {
-                Some(tx) => {
-                    Some(Box::new(WorkingContext {
-                        context: Box::new(tx),
-                        span_stack: Vec::new(),
-                    }))
-                }
-                None => { None }
-            },
-        }
-    }
-
-    /// Delegate to the tracing core entry span creation method, if current context is valid.
-    fn create_entry_span(&mut self, operation_name: &str, parent_span_id: Option<i32>, extractor: Option<&dyn Extractable>) -> Option<Box<dyn Span>> {
-        match self.option.borrow_mut() {
-            None => { None }
-            Some(wx) => {
-                let span = wx.context.create_entry_span(operation_name, parent_span_id, extractor);
-                wx.span_stack.push(span.span_id());
-                Some(span)
-            }
-        }
-    }
-
-    /// Delegate to the tracing core exit span creation method, if current context is valid.
-    fn create_exit_span(&mut self, operation_name: &str, parent_span_id: Option<i32>, peer: &str, injector: Option<&dyn Injectable>) -> Option<Box<dyn Span>> {
-        match self.option.borrow_mut() {
-            None => { None }
-            Some(wx) => {
-                let span = wx.context.create_exit_span(operation_name, parent_span_id, peer, injector);
-                wx.span_stack.push(span.span_id());
-                Some(span)
-            }
-        }
-    }
-
-    /// Delegate to the tracing core local span creation method, if current context is valid.
-    fn create_local(&mut self, operation_name: &str, parent_span_id: Option<i32>) -> Option<Box<dyn Span>> {
-        match self.option.borrow_mut() {
-            None => { None }
-            Some(wx) => {
-                let span = wx.context.create_local_span(operation_name, parent_span_id);
-                wx.span_stack.push(span.span_id());
-                Some(span)
-            }
-        }
-    }
-
-    /// Delegate to the tracing core span finish method, if current context is valid.
-    fn finish_span(&mut self, span: Box<dyn Span>) {
-        match self.option.borrow_mut() {
-            None => {}
-            Some(wx) => {
-                wx.context.finish_span(span);
-                wx.span_stack.pop();
-            }
-        };
-    }
-
-    /// Fetch the parent span id, to be used in next new span.
-    /// The span id(s) are saved in the span_stack by following as same the stack-style as span creation sequence.
-    fn parent_span_id(&self) -> Option<i32> {
-        match self.option.borrow() {
-            None => { None }
-            Some(wx) => {
-                match wx.span_stack.last() {
-                    None => { None }
-                    Some(span_id) => { Some(span_id.clone()) }
-                }
-            }
-        }
-    }
-
-    /// Finish the current tracing context, including
-    /// 1. Clear up the context
-    /// 2. Transfer the context to profobuf format and pass to reporter.
-    fn finish(&mut self) {
-        match self.option.borrow_mut() {
-            None => {}
-            Some(wx) => {
-                let tracingContext = &wx.context;
-
-                wx.span_stack.clear();
-
-                // TODO: Transfer tracingContext to protobuf
-            }
-        }
-        self.option = None;
-    }
-}
-
-
-#[cfg(test)]
-mod context_tests {
-    use crate::skywalking::agent::context_manager::*;
-    use crate::skywalking::core::{ContextListener, Tag, TracingContext};
-
-    #[test]
-    fn test_context_manager() {
-        ContextManager::tracing_entry("op1", None, |mut span| {
-            span.tag(Tag::new(String::from("tag1"), String::from("value1")));
-
-            ContextManager::tracing_exit("op2", "127.0.0.1:8080", None, |mut span| {
-                span.set_component_id(33);
-            });
-
-            ContextManager::tracing_local("op3", |mut span| {});
-        });
-    }
-
-    struct MockReporter {}
-
-    impl ContextListener for MockReporter {
-        fn service_instance_id(&self) -> Option<i32> {
-            Some(1)
-        }
-
-        fn report_trace(&self, finished_context: Box<TracingContext>) {}
-    }
-}
diff --git a/core/src/skywalking/agent/reporter.rs b/core/src/skywalking/agent/reporter.rs
deleted file mode 100644
index cf26f3f..0000000
--- a/core/src/skywalking/agent/reporter.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements.  See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to You under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License.  You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-use crate::skywalking::core::{ContextListener, TracingContext};
-
-pub struct Reporter {}
-
-impl ContextListener for Reporter {
-    fn service_instance_id(&self) -> Option<i32> {
-        Some(1)
-    }
-
-    fn report_trace(&self, finished_context: Box<TracingContext>) {
-        unimplemented!()
-    }
-}
-
-impl Reporter {
-    pub fn new() -> Self {
-        Reporter {}
-    }
-}
\ No newline at end of file
diff --git a/core/src/skywalking/core/context.rs b/core/src/skywalking/core/context.rs
deleted file mode 100644
index a9465b3..0000000
--- a/core/src/skywalking/core/context.rs
+++ /dev/null
@@ -1,238 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements.  See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to You under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License.  You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-use base64::{decode, encode};
-
-use crate::skywalking::agent::reporter::Reporter;
-use crate::skywalking::core::{ID, Span};
-use crate::skywalking::core::context_carrier::{Extractable, Injectable};
-use crate::skywalking::core::id::IDGenerator;
-use crate::skywalking::core::segment_ref::SegmentRef;
-use crate::skywalking::core::span::TracingSpan;
-
-/// Context represents the context of a tracing process.
-/// All new span belonging to this tracing context should be created through this context.
-pub trait Context {
-    /// Create an entry span belonging this context
-    fn create_entry_span(&mut self, operation_name: &str, parent_span_id: Option<i32>, extractor: Option<&dyn Extractable>) -> Box<dyn Span>;
-    /// Create an exit span belonging this context
-    fn create_exit_span(&mut self, operation_name: &str, parent_span_id: Option<i32>, peer: &str, injector: Option<&dyn Injectable>) -> Box<dyn Span>;
-    /// Create an local span belonging this context
-    fn create_local_span(&mut self, operation_name: &str, parent_span_id: Option<i32>) -> Box<dyn Span>;
-    /// Finish the given span. The span is only being accept if it belongs to this context.
-    /// Return err if the span was created by another context.
-    fn finish_span(&mut self, span: Box<dyn Span>);
-}
-
-pub struct TracingContext {
-    /// Span id sequence. Indicate the number of created spans.
-    next_seq: i32,
-
-    primary_trace_id: ID,
-    segment_id: ID,
-    self_generated_id: bool,
-    entry_endpoint_name: Option<String>,
-    first_ref: Option<SegmentRef>,
-    service_instance_id: i32,
-
-    finished_spans: Vec<Box<dyn Span>>,
-}
-
-impl TracingContext {
-    /// Create a new instance
-    pub fn new(service_instance_id: Option<i32>) -> Option<TracingContext> {
-        match service_instance_id {
-            None => { None }
-            Some(id) => {
-                Some(TracingContext {
-                    next_seq: -1,
-                    primary_trace_id: IDGenerator::new_id(id),
-                    segment_id: IDGenerator::new_id(id),
-                    self_generated_id: true,
-                    entry_endpoint_name: None,
-                    first_ref: None,
-                    service_instance_id: id,
-                    finished_spans: Vec::new(),
-                }
-                )
-            }
-        }
-    }
-
-    pub fn service_instance_id(&self) -> i32 {
-        self.service_instance_id
-    }
-
-    pub fn first_ref(&self) -> &Option<SegmentRef> {
-        &self.first_ref
-    }
-
-    pub fn entry_endpoint_name(&self) -> &Option<String> {
-        &self.entry_endpoint_name
-    }
-
-    pub fn trace_id(&self) -> ID {
-        self.primary_trace_id.clone()
-    }
-
-    pub fn segment_id(&self) -> ID {
-        self.segment_id.clone()
-    }
-
-    /// Fetch the next id for new span
-    fn next_span_id(&mut self) -> i32 {
-        self.next_seq = self.next_seq + 1;
-        self.next_seq
-    }
-}
-
-/// Default implementation of Context
-impl Context for TracingContext {
-    fn create_entry_span(&mut self, operation_name: &str, parent_span_id: Option<i32>, extractor: Option<&dyn Extractable>) -> Box<dyn Span> {
-        let mut entry_span = TracingSpan::new_entry_span(operation_name, self.next_span_id(), match parent_span_id {
-            None => { -1 }
-            Some(s) => { s }
-        });
-
-        if extractor.is_some() {
-            match SegmentRef::from_text(extractor.unwrap().extract("sw6".to_string())) {
-                Some(reference) => {
-                    if self.self_generated_id {
-                        self.self_generated_id = false;
-                        self.primary_trace_id = reference.get_trace_id();
-                    }
-                    if self.first_ref.is_none() {
-                        self.first_ref = Some(reference.clone());
-                        self.entry_endpoint_name = Some(String::from(operation_name))
-                    }
-                    entry_span._add_ref(reference);
-                }
-                _ => {}
-            }
-        }
-        Box::new(entry_span)
-    }
-
-    fn create_exit_span(&mut self, operation_name: &str, parent_span_id: Option<i32>, peer: &str, injector: Option<&dyn Injectable>) -> Box<dyn Span> {
-        let exit_span = TracingSpan::new_exit_span(operation_name, self.next_span_id(), match parent_span_id {
-            None => { -1 }
-            Some(s) => { s }
-        }, peer);
-
-        if injector.is_some() {
-            injector.unwrap().inject(String::from("sw6"), SegmentRef::for_across_process(self, &exit_span, &peer).serialize());
-        }
-
-        Box::new(exit_span)
-    }
-
-    fn create_local_span(&mut self, operation_name: &str, parent_span_id: Option<i32>) -> Box<dyn Span> {
-        Box::new(TracingSpan::new_local_span(operation_name, self.next_span_id(), match parent_span_id {
-            None => { -1 }
-            Some(s) => { s }
-        }))
-    }
-
-    fn finish_span(&mut self, mut span: Box<dyn Span>) {
-        if !span.is_ended() {
-            span.end();
-        }
-        self.finished_spans.push(span);
-    }
-}
-
-#[cfg(test)]
-mod context_tests {
-    use std::sync::mpsc;
-    use std::sync::mpsc::{Receiver, Sender};
-
-    use crate::skywalking::core::{Context, ContextListener, Extractable, ID, Injectable, Tag, TracingContext};
-
-    #[test]
-    fn test_context_stack() {
-        let reporter = MockReporter::new();
-        let mut context = TracingContext::new(reporter.service_instance_id()).unwrap();
-        let span1 = context.create_entry_span("op1", None, Some(&MockerHeader {}));
-        {
-            assert_eq!(span1.span_id(), 0);
-            let mut span2 = context.create_local_span("op2", Some(span1.span_id()));
-            span2.tag(Tag::new(String::from("tag1"), String::from("value1")));
-            {
-                assert_eq!(span2.span_id(), 1);
-                let span3 = context.create_exit_span("op3", Some(span2.span_id()), "127.0.0.1:8080", Some(&HeaderCarrier {}));
-                assert_eq!(span3.span_id(), 2);
-
-                context.finish_span(span3);
-            }
-            context.finish_span(span2);
-        }
-        context.finish_span(span1);
-
-        reporter.report_trace(Box::new(context));
-        // context has moved into reporter. Can't be used again.
-
-        let received_context = reporter.recv.recv().unwrap();
-        assert_eq!(received_context.primary_trace_id == ID::new(3, 4, 5), true);
-        assert_eq!(received_context.finished_spans.len(), 3);
-    }
-
-    #[test]
-    fn test_no_context() {
-        let context = TracingContext::new(None);
-        assert_eq!(context.is_none(), true);
-    }
-
-    struct MockReporter {
-        sender: Box<Sender<Box<TracingContext>>>,
-        recv: Box<Receiver<Box<TracingContext>>>,
-    }
-
-    impl MockReporter {
-        fn new() -> Self {
-            let (tx, rx) = mpsc::channel();
-            MockReporter {
-                sender: Box::new(tx),
-                recv: Box::new(rx),
-            }
-        }
-    }
-
-    impl ContextListener for MockReporter {
-        fn service_instance_id(&self) -> Option<i32> {
-            Some(1)
-        }
-
-        fn report_trace(&self, finished_context: Box<TracingContext>) {
-            self.sender.send(finished_context);
-        }
-    }
-
-    struct MockerHeader {}
-
-    impl Extractable for MockerHeader {
-        fn extract(&self, key: String) -> &str {
-            "1-My40LjU=-MS4yLjM=-4-1-1-IzEyNy4wLjAuMTo4MDgw-Iy9wb3J0YWw=-MTIz"
-        }
-    }
-
-    struct HeaderCarrier {}
-
-    impl Injectable for HeaderCarrier {
-        fn inject(&self, key: String, value: String) {
-            assert_eq!(key, "sw6");
-            assert_eq!(value.len() > 0, true);
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/src/skywalking/core/context_carrier.rs b/core/src/skywalking/core/context_carrier.rs
deleted file mode 100644
index 3ab607d..0000000
--- a/core/src/skywalking/core/context_carrier.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements.  See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to You under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License.  You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-/// The Injectable implementation supports inject the give key/value for further propagation,
-/// Such as putting a key/value into the HTTP header.
-pub trait Injectable {
-    /// Inject the given key/value into the implementation.
-    /// The way of injection is determined by the implementation, no panic! should happens even injection fails.
-    fn inject(&self, key: String, value: String);
-}
-
-/// The Extractable implementations extract propagated context out the implementation.
-/// Such as fetching the key/value from the HTTP header.
-pub trait Extractable {
-    /// Fetch the value by the given key.
-    fn extract(&self, key: String) -> &str;
-}
\ No newline at end of file
diff --git a/core/src/skywalking/core/context_listener.rs b/core/src/skywalking/core/context_listener.rs
deleted file mode 100644
index 9cb5842..0000000
--- a/core/src/skywalking/core/context_listener.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements.  See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to You under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License.  You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-use crate::skywalking::core::TracingContext;
-
-///Report bridge defines the traits for the skywalking-report
-
-/// Register implementation communicate with the SkyWalking OAP backend.
-/// It does metadata register, traces report, and runtime status report or interaction.
-pub trait ContextListener {
-    /// Return the registered service id
-    /// If haven't registered successfully, return None.
-    fn service_instance_id(&self) -> Option<i32>;
-
-    /// Move the finished and inactive context to the reporter.
-    /// The reporter should use async way to transport the data to the backend through HTTP, gRPC or SkyWalking forwarder.
-    fn report_trace(&self, finished_context: Box<TracingContext>);
-}
diff --git a/core/src/skywalking/core/id.rs b/core/src/skywalking/core/id.rs
deleted file mode 100644
index 384963a..0000000
--- a/core/src/skywalking/core/id.rs
+++ /dev/null
@@ -1,116 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements.  See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to You under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License.  You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-use std::hash::Hash;
-use std::time::SystemTime;
-
-use rand::RngCore;
-
-pub struct IDGenerator {}
-
-impl IDGenerator {
-    /// ID generated by 3 parts
-    /// 1. Registered service instance id
-    /// 2. thread local level random u64
-    /// 3. Timestamp in ms
-    pub fn new_id(instance_id: i32) -> ID {
-        ID::new(
-            instance_id as i64,
-            rand::thread_rng().next_u64() as i64,
-            SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).ok().unwrap().as_millis() as i64,
-        )
-    }
-}
-
-/// ID is used for trace id and segment id.
-/// It is combined by 3 i64 numbers, and could be formatted as `part1.part2.part3` string.
-#[derive(Clone, Hash)]
-pub struct ID {
-    part1: i64,
-    part2: i64,
-    part3: i64,
-}
-
-impl ID {
-    pub fn new(part1: i64, part2: i64, part3: i64) -> Self {
-        ID {
-            part1,
-            part2,
-            part3,
-        }
-    }
-
-    /// Convert the literal string text back to ID object.
-    /// Return Option::None if the text is not combined by 3 dot split i64 parts
-    pub fn from(id_text: String) -> Result<Self, String> {
-        let strings: Vec<&str> = id_text.split(".").collect();
-        if strings.len() == 3 {
-            let part1 = strings[0].parse::<i64>();
-            if part1.is_err() { return Err("part 1 is not a i64".to_string()); }
-            let part2 = strings[1].parse::<i64>();
-            if part2.is_err() { return Err("part 2 is not a i64".to_string()); }
-            let part3 = strings[2].parse::<i64>();
-            if part3.is_err() { return Err("part 3 is not a i64".to_string()); }
-            Ok(ID::new(part1.unwrap(), part2.unwrap(), part3.unwrap()))
-        } else {
-            Err("The ID is not combined by 3 parts.".to_string())
-        }
-    }
-}
-
-impl PartialEq for ID {
-    fn eq(&self, other: &Self) -> bool {
-        self.part1 == other.part1 && self.part2 == other.part2 && self.part3 == other.part3
-    }
-}
-
-impl ToString for ID {
-    fn to_string(&self) -> String {
-        format!("{}.{}.{}", self.part1, self.part2, self.part3)
-    }
-}
-
-
-#[cfg(test)]
-mod id_tests {
-    use crate::skywalking::core::ID;
-    use crate::skywalking::core::id::IDGenerator;
-
-    #[test]
-    fn test_id_generator() {
-        let id = IDGenerator::new_id(1);
-        assert_eq!(id.part1, 1);
-    }
-
-    #[test]
-    fn test_id_new() {
-        let id1 = ID::new(1, 2, 3);
-        let id2 = ID::new(1, 2, 3);
-        let id3 = ID::new(1, 2, 4);
-
-        assert_eq!(id1.eq(&id2), true);
-        assert_eq!(id1.ne(&id3), true);
-        assert_eq!(id1.to_string(), "1.2.3");
-
-        let id4 = ID::from(String::from("1.2.3")).unwrap();
-        assert_eq!(id4.eq(&id1), true);
-
-        let id5_none = ID::from(String::from("1.2"));
-        assert_ne!(id5_none.err().unwrap().len(), 0);
-
-        let id6_illegal = ID::from(String::from("1.2.a"));
-        assert_ne!(id6_illegal.err().unwrap().len(), 0);
-    }
-}
\ No newline at end of file
diff --git a/core/src/skywalking/core/log.rs b/core/src/skywalking/core/log.rs
deleted file mode 100644
index e0b81f1..0000000
--- a/core/src/skywalking/core/log.rs
+++ /dev/null
@@ -1,65 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements.  See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to You under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License.  You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-/// Log represents an event happened during the span duration.
-/// It is much heavier than tag. Usually this is only used in the error case to log the detailed error message.
-/// Log Entity is a creation once object. Can't be change once it is created.
-pub struct LogEvent {
-    timestamp: i64,
-    /// Any extra fields to describe the event.
-    fields: Box<[EventField]>,
-}
-
-pub struct EventField {
-    name: String,
-    value: String,
-}
-
-impl LogEvent {
-    pub fn new(timestamp: i64, fields: Box<[EventField]>) -> Self {
-        LogEvent {
-            timestamp,
-            fields,
-        }
-    }
-}
-
-impl EventField {
-    pub fn new(name: String, value: String) -> Self {
-        EventField {
-            name,
-            value,
-        }
-    }
-}
-
-#[cfg(test)]
-mod log_tests {
-    use crate::skywalking::core::log::{EventField, LogEvent};
-
-    #[test]
-    fn test_log_new() {
-        let fields = [
-            { EventField::new(String::from("event1"), String::from("event description")) },
-            { EventField::new(String::from("event2"), String::from("event description")) },
-        ];
-        let event = LogEvent::new(123, Box::new(fields));
-        assert_eq!(event.timestamp, 123);
-        assert_eq!(event.fields.len(), 2);
-        assert_eq!(event.fields[0].name, "event1");
-        assert_eq!(event.fields[1].value, "event description");
-    }
-}
-
diff --git a/core/src/skywalking/core/mod.rs b/core/src/skywalking/core/mod.rs
deleted file mode 100644
index 7715556..0000000
--- a/core/src/skywalking/core/mod.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements.  See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to You under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License.  You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-pub use context::Context;
-pub use context::TracingContext;
-pub use context_carrier::Extractable;
-pub use context_carrier::Injectable;
-pub use context_listener::ContextListener;
-pub use id::ID;
-pub use log::EventField;
-pub use log::LogEvent;
-pub use span::Span;
-pub use tag::Tag;
-
-pub mod span;
-pub mod context;
-pub mod tag;
-pub mod id;
-pub mod context_listener;
-pub mod log;
-pub mod context_carrier;
-pub mod segment_ref;
\ No newline at end of file
diff --git a/core/src/skywalking/core/segment_ref.rs b/core/src/skywalking/core/segment_ref.rs
deleted file mode 100644
index 421da20..0000000
--- a/core/src/skywalking/core/segment_ref.rs
+++ /dev/null
@@ -1,248 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements.  See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to You under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License.  You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-use std::os::raw::c_long;
-
-use crate::skywalking::core::{ID, Span, TracingContext};
-use crate::skywalking::core::segment_ref::SegmentRefType::CROSS_PROCESS;
-
-#[derive(Clone, Hash)]
-pub struct SegmentRef {
-    ref_type: SegmentRefType,
-    trace_id: ID,
-    segment_id: ID,
-    span_id: i32,
-    parent_service_instance_id: i32,
-    entry_service_instance_id: i32,
-    network_address: Option<String>,
-    network_address_id: i32,
-    entry_endpoint: Option<String>,
-    entry_endpoint_id: i32,
-    parent_endpoint: Option<String>,
-    parent_endpoint_id: i32,
-}
-
-#[derive(Clone, Hash)]
-enum SegmentRefType {
-    CROSS_PROCESS,
-    CROSS_THREAD,
-}
-
-impl SegmentRef {
-    pub fn from_text(value: &str) -> Option<Self> {
-        let strings: Vec<&str> = value.split("-").collect();
-        if strings.len() == 9 {
-            // Ignore string[0].
-            let trace_id = match SegmentRef::string_to_id(strings[1]) {
-                Some(id) => { id }
-                _ => { return None; }
-            };
-            let segment_id = match SegmentRef::string_to_id(strings[2]) {
-                Some(id) => { id }
-                _ => { return None; }
-            };
-            let span_id = match strings[3].parse::<i32>() {
-                Ok(id) => { id }
-                _ => { return None; }
-            };
-            let parent_service_instance_id = match strings[4].parse::<i32>() {
-                Ok(id) => { id }
-                _ => { return None; }
-            };
-            let entry_service_instance_id = match strings[5].parse::<i32>() {
-                Ok(id) => { id }
-                _ => { return None; }
-            };
-
-            let (network_address, network_address_id) = match SegmentRef::decode_base64_to_string_or_id(strings[6]) {
-                Some(decoded) => { decoded }
-                _ => { return None; }
-            };
-            let (entry_endpoint, entry_endpoint_id) = match SegmentRef::decode_base64_to_string_or_id(strings[7]) {
-                Some(decoded) => { decoded }
-                _ => { return None; }
-            };
-            let (parent_endpoint, parent_endpoint_id) = match SegmentRef::decode_base64_to_string_or_id(strings[8]) {
-                Some(decoded) => { decoded }
-                _ => { return None; }
-            };
-
-            Some(SegmentRef {
-                ref_type: CROSS_PROCESS,
-                trace_id,
-                segment_id,
-                span_id,
-                parent_service_instance_id,
-                entry_service_instance_id,
-                network_address,
-                network_address_id,
-                entry_endpoint,
-                entry_endpoint_id,
-                parent_endpoint,
-                parent_endpoint_id,
-            })
-        } else {
-            None
-        }
-    }
-
-    pub fn for_across_process(context: &TracingContext, exit_span: &dyn Span, peer: &str) -> Self {
-        // -1 represent the object doesn't exist.
-        let inexistence = -1;
-        let (entry_endpoint, entry_endpoint_id) = match context.first_ref() {
-            None => {
-                match context.entry_endpoint_name() {
-                    None => { (None, inexistence) }
-                    Some(endpoint) => { (Some(endpoint.clone()), 0) }
-                }
-            }
-            Some(reference) => {
-                match &reference.entry_endpoint {
-                    None => { (None, reference.entry_endpoint_id) }
-                    Some(endpoint) => { (Some(endpoint.clone()), 0) }
-                }
-            }
-        };
-        let (parent_endpoint, parent_endpoint_id) = match context.entry_endpoint_name() {
-            None => { (None, inexistence) }
-            Some(endpoint) => { (Some(endpoint.clone()), 0) }
-        };
-
-        SegmentRef {
-            ref_type: CROSS_PROCESS,
-            trace_id: context.trace_id(),
-            segment_id: context.segment_id(),
-            span_id: exit_span.span_id(),
-            network_address: Some(String::from(peer.clone())),
-            // No network address register, the id always be 0
-            network_address_id: 0,
-            entry_service_instance_id: {
-                match context.first_ref() {
-                    None => { context.service_instance_id() }
-                    Some(reference) => { reference.entry_service_instance_id }
-                }
-            },
-            parent_service_instance_id: context.service_instance_id(),
-            entry_endpoint,
-            entry_endpoint_id,
-            parent_endpoint,
-            parent_endpoint_id,
-        }
-    }
-
-    pub fn serialize(&self) -> String {
-        let parts: Vec<String> = vec![
-            "1".to_string(),
-            base64::encode(self.trace_id.to_string().as_bytes()),
-            base64::encode(self.segment_id.to_string().as_bytes()),
-            self.span_id.to_string(),
-            self.parent_service_instance_id.to_string(),
-            self.entry_service_instance_id.to_string(),
-            SegmentRef::string_or_id_to_encode_base64(&self.network_address, self.network_address_id),
-            SegmentRef::string_or_id_to_encode_base64(&self.entry_endpoint, self.entry_endpoint_id),
-            SegmentRef::string_or_id_to_encode_base64(&self.parent_endpoint, self.parent_endpoint_id),
-        ];
-        parts.join("-")
-    }
-
-    pub fn get_trace_id(&self) -> ID {
-        self.trace_id.clone()
-    }
-
-    fn string_to_id(text: &str) -> Option<ID> {
-        match base64::decode(text) {
-            Ok(value) => {
-                match String::from_utf8(value) {
-                    Ok(str) => {
-                        match ID::from(str) {
-                            Ok(id) => { Some(id) }
-                            _ => None
-                        }
-                    }
-                    _ => { None }
-                }
-            }
-            _ => { None }
-        }
-    }
-
-    fn decode_base64_to_string_or_id(text: &str) -> Option<(Option<String>, i32)> {
-        match base64::decode(text) {
-            Ok(value) => {
-                match String::from_utf8(value) {
-                    Ok(str) => {
-                        if str.starts_with("#") {
-                            let network: Vec<&str> = str.split("#").collect();
-                            (Some((Some(network[1].to_string()), 0)))
-                        } else {
-                            match str.parse::<i32>() {
-                                Ok(id) => { Some((None, id)) }
-                                _ => { None }
-                            }
-                        }
-                    }
-                    _ => { None }
-                }
-            }
-            _ => { None }
-        }
-    }
-
-    fn string_or_id_to_encode_base64(text: &Option<String>, id: i32) -> String {
-        base64::encode(match text {
-            None => { id.to_string() }
-            Some(t) => {
-                let mut network = "#".to_string();
-                network.push_str(&t);
-                network
-            }
-        }.as_bytes())
-    }
-}
-
-#[cfg(test)]
-mod segment_ref_tests {
-    use crate::skywalking::core::ID;
-    use crate::skywalking::core::segment_ref::SegmentRef;
-
-    #[test]
-    fn test_deserialize_context_carrier() {
-        let carrier = SegmentRef::from_text("1-My40LjU=-MS4yLjM=-4-1-1-IzEyNy4wLjAuMTo4MDgw-Iy9wb3J0YWw=-MTIz").unwrap();
-        assert_eq!(carrier.trace_id == ID::new(3, 4, 5), true);
-        assert_eq!(carrier.segment_id == ID::new(1, 2, 3), true);
-        assert_eq!(carrier.span_id, 4);
-        assert_eq!(carrier.entry_service_instance_id, 1);
-        assert_eq!(carrier.parent_service_instance_id, 1);
-        assert_eq!(carrier.network_address, Some("127.0.0.1:8080".to_string()));
-        assert_eq!(carrier.entry_endpoint, Some("/portal".to_string()));
-        assert_eq!(carrier.parent_endpoint_id, 123);
-    }
-
-    #[test]
-    fn test_serialize_ref() {
-        let carrier = SegmentRef::from_text("1-My40LjU=-MS4yLjM=-4-1-1-IzEyNy4wLjAuMTo4MDgw-Iy9wb3J0YWw=-MTIz").unwrap();
-        assert_eq!(carrier.trace_id == ID::new(3, 4, 5), true);
-        assert_eq!(carrier.segment_id == ID::new(1, 2, 3), true);
-        assert_eq!(carrier.span_id, 4);
-        assert_eq!(carrier.entry_service_instance_id, 1);
-        assert_eq!(carrier.parent_service_instance_id, 1);
-        assert_eq!(carrier.network_address, Some("127.0.0.1:8080".to_string()));
-        assert_eq!(carrier.entry_endpoint, Some("/portal".to_string()));
-        assert_eq!(carrier.parent_endpoint_id, 123);
-
-        let carrier_text = carrier.serialize();
-        assert_eq!(carrier_text, "1-My40LjU=-MS4yLjM=-4-1-1-IzEyNy4wLjAuMTo4MDgw-Iy9wb3J0YWw=-MTIz");
-    }
-}
diff --git a/core/src/skywalking/core/span.rs b/core/src/skywalking/core/span.rs
deleted file mode 100644
index 9842dea..0000000
--- a/core/src/skywalking/core/span.rs
+++ /dev/null
@@ -1,264 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements.  See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to You under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License.  You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-use std::time::SystemTime;
-
-use crate::skywalking::core::log::LogEvent;
-use crate::skywalking::core::segment_ref::SegmentRef;
-use crate::skywalking::core::Tag;
-
-/// Span is one of the tracing concept, representing a time duration.
-///Span is an important and common concept in distributed tracing system. Learn Span from Google Dapper Paper.
-/// For better performance, we extend the span into 3 kinds.
-///
-/// 1. EntrySpan EntrySpan represents a service provider, also the endpoint of server side. As an APM system, we are targeting the application servers. So almost all the services and MQ-consumer are EntrySpan(s).
-/// 2. LocalSpan LocalSpan represents a normal Java method, which does not relate to remote service, neither a MQ producer/consumer nor a service(e.g. HTTP service) provider/consumer.
-/// 3. ExitSpan ExitSpan represents a client of service or MQ-producer, as named as LeafSpan at early age of SkyWalking. e.g. accessing DB by JDBC, reading Redis/Memcached are cataloged an ExitSpan.
-pub trait Span {
-    /// Start the span with the current system time
-    fn start(&mut self);
-    /// Start the span by using given time point.
-    fn start_with_timestamp(&mut self, timestamp: SystemTime);
-    /// Add a new tag to the span
-    fn tag(&mut self, tag: Tag);
-    /// Add a log event to the span
-    fn log(&mut self, log: LogEvent);
-    /// Indicate error occurred during the span execution.
-    fn error_occurred(&mut self);
-    /// Set the component id represented by this span.
-    /// Component id is pre-definition in the SkyWalking OAP backend component-libraries.yml file.
-    /// Read [Component library settings](https://github.com/apache/skywalking/blob/master/docs/en/guides/Component-library-settings.md) documentation for more details
-    fn set_component_id(&mut self, component_id: i32);
-    /// End the span with the current system time.
-    /// End just means sealing the end time, still need to call Context::finish_span to officially finish span and archive it for further reporting.
-    fn end(&mut self);
-    /// End the span by using given time point.
-    /// End just means sealing the end time, still need to call Context::finish_span to officially finish span and archive it for further reporting.
-    fn end_with_timestamp(&mut self, timestamp: SystemTime);
-
-
-    /// All following are status reading methods.
-
-    /// Return true if the span has been set end time
-    fn is_ended(&self) -> bool;
-    /// Return true if the span is an entry span
-    fn is_entry(&self) -> bool;
-    /// Return true if the span is an exit span
-    fn is_exit(&self) -> bool;
-    /// Return span id.
-    fn span_id(&self) -> i32;
-    /// Return the replicated existing tags.
-    fn tags(&self) -> Vec<Tag>;
-}
-
-pub struct TracingSpan {
-    /// The operation name represents the logic process of this span
-    operation_name: String,
-    span_id: i32,
-    parent_span_id: i32,
-    /// The timestamp of the span start time
-    start_time: u64,
-    /// The timestamp of the span end time
-    end_time: u64,
-    /// As an entry span
-    is_entry: bool,
-    /// As an exit span
-    is_exit: bool,
-    /// The peer network address when as an RPC related span.
-    /// Typically used in exit span, representing the target server address.
-    peer: Option<String>,
-    /// Tag this span in error status.
-    error_occurred: bool,
-    /// Component id is defined in the main repo to represent the library kind.
-    component_id: Option<i32>,
-    tags: Vec<Tag>,
-    logs: Vec<LogEvent>,
-    refs: Vec<SegmentRef>,
-}
-
-/// Tracing Span is only created inside TracingContext.
-impl TracingSpan {
-    /// Create a new entry span
-    pub fn new_entry_span(operation_name: &str, span_id: i32, parent_span_id: i32) -> TracingSpan {
-        let mut span = TracingSpan::_new(operation_name, span_id, parent_span_id);
-        span.is_entry = true;
-        span
-    }
-
-    /// Create a new exit span
-    pub fn new_exit_span(operation_name: &str, span_id: i32, parent_span_id: i32, peer: &str) -> TracingSpan {
-        let mut span = TracingSpan::_new(operation_name, span_id, parent_span_id);
-        span.is_exit = true;
-        span.peer = Some(String::from(peer));
-        span
-    }
-
-    /// Create a new local span
-    pub fn new_local_span(operation_name: &str, span_id: i32, parent_span_id: i32) -> TracingSpan {
-        let span = TracingSpan::_new(operation_name, span_id, parent_span_id);
-        span
-    }
-
-    /// Create a span
-    fn _new(operation_name: &str, span_id: i32, parent_span_id: i32) -> Self {
-        TracingSpan {
-            operation_name: String::from(operation_name),
-            span_id,
-            parent_span_id,
-            start_time: 0,
-            end_time: 0,
-            is_entry: false,
-            is_exit: false,
-            peer: None,
-            error_occurred: false,
-            component_id: None,
-            tags: Vec::new(),
-            logs: Vec::new(),
-            refs: Vec::new(),
-        }
-    }
-
-    pub fn _add_ref(&mut self, reference: SegmentRef) {
-        self.refs.push(reference);
-    }
-}
-
-impl Span for TracingSpan {
-    fn start(&mut self) {
-        self.start_time = match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
-            Ok(n) => { n.as_millis() }
-            Err(_) => self.start_time as u128,
-        } as u64;
-    }
-
-    fn start_with_timestamp(&mut self, timestamp: SystemTime) {
-        self.start_time = match timestamp.duration_since(SystemTime::UNIX_EPOCH) {
-            Ok(n) => { n.as_millis() }
-            Err(_) => self.start_time as u128,
-        } as u64;
-    }
-
-    fn tag(&mut self, tag: Tag) {
-        self.tags.push(tag);
-    }
-
-    fn log(&mut self, log: LogEvent) {
-        self.logs.push(log);
-    }
-
-    fn error_occurred(&mut self) {
-        self.error_occurred = true;
-    }
-
-    fn set_component_id(&mut self, component_id: i32) {
-        self.component_id = Some(component_id);
-    }
-
-    fn end(&mut self) {
-        self.end_time = match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
-            Ok(n) => { n.as_millis() }
-            Err(_) => self.start_time as u128,
-        } as u64;
-    }
-
-    fn end_with_timestamp(&mut self, timestamp: SystemTime) {
-        self.end_time = match timestamp.duration_since(SystemTime::UNIX_EPOCH) {
-            Ok(n) => { n.as_millis() }
-            Err(_) => self.start_time as u128,
-        } as u64;
-    }
-
-    fn is_ended(&self) -> bool {
-        self.end_time != 0
-    }
-
-    fn is_entry(&self) -> bool {
-        self.is_entry
-    }
-
-    fn is_exit(&self) -> bool {
-        self.is_exit
-    }
-
-    fn span_id(&self) -> i32 {
-        self.span_id
-    }
-
-    fn tags(&self) -> Vec<Tag> {
-        let mut tags = Vec::new();
-        for t in &self.tags {
-            tags.push(t.clone());
-        };
-        tags
-    }
-}
-
-#[cfg(test)]
-mod span_tests {
-    use std::time::SystemTime;
-
-    use crate::skywalking::core::log::{EventField, LogEvent};
-    use crate::skywalking::core::span::*;
-    use crate::skywalking::core::Tag;
-
-    #[test]
-    fn test_span_new() {
-        let mut span = TracingSpan::_new("op1", 0, -1);
-        assert_eq!(span.parent_span_id, -1);
-        assert_eq!(span.span_id, 0);
-        assert_eq!(span.start_time, 0);
-        span.start();
-        assert_ne!(span.start_time, 0);
-
-        let mut span2 = TracingSpan::_new("op2", 1, 0);
-        assert_eq!("op2", span2.operation_name);
-        assert_eq!(span2.parent_span_id, 0);
-        assert_eq!(span2.span_id, 1);
-        span2.start_with_timestamp(SystemTime::now());
-        assert_ne!(span2.start_time, 0);
-    }
-
-    #[test]
-    fn test_new_entry_span() {
-        let span = TracingSpan::new_entry_span("op1", 0, 1);
-        assert_eq!(span.is_entry(), true)
-    }
-
-    #[test]
-    fn test_span_with_tags() {
-        let mut span = TracingSpan::new_entry_span("op1", 0, 1);
-        span.tag(Tag::new(String::from("tag1"), String::from("value1")));
-        span.tag(Tag::new(String::from("tag2"), String::from("value2")));
-
-        let tags = span.tags();
-        assert_eq!(tags.len(), 2);
-        assert_eq!(tags.get(0).unwrap().key(), "tag1")
-    }
-
-    #[test]
-    fn test_span_with_logs() {
-        let mut span = TracingSpan::_new("op1", 0, -1);
-
-        span.log(LogEvent::new(123, Box::new([
-            { EventField::new(String::from("event1"), String::from("event description")) },
-            { EventField::new(String::from("event2"), String::from("event description")) },
-        ])));
-
-        assert_eq!(span.logs.len(), 1);
-    }
-}
-
-
-
diff --git a/core/src/skywalking/core/tag.rs b/core/src/skywalking/core/tag.rs
deleted file mode 100644
index 80bbad9..0000000
--- a/core/src/skywalking/core/tag.rs
+++ /dev/null
@@ -1,55 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements.  See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to You under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License.  You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-/// Tag is a key value pair to represent an supplementary instruction for the span.
-/// Common and most widely used tags could be found here,
-/// https://github.com/apache/skywalking/blob/master/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java.
-#[derive(Clone, Hash)]
-pub struct Tag {
-    key: String,
-    value: String,
-}
-
-impl Tag {
-    pub fn new(key: String, value: String) -> Self {
-        Tag {
-            key,
-            value,
-        }
-    }
-
-    pub fn key(&self) -> String {
-        self.key.clone()
-    }
-
-    pub fn value(&self) -> String {
-        self.value.clone()
-    }
-}
-
-#[cfg(test)]
-mod tag_tests {
-    use crate::skywalking::core::Tag;
-
-    #[test]
-    fn test_tag_new() {
-        let tag = Tag::new(String::from("tag_key"), String::from("tag_value"));
-        assert_eq!(tag.key, "tag_key");
-        assert_eq!(tag.value, "tag_value");
-        let tag_clone = tag.clone();
-        assert_eq!(tag_clone.key, "tag_key");
-        assert_eq!(tag_clone.value, "tag_value");
-    }
-}
\ No newline at end of file
diff --git a/core/src/skywalking/mod.rs b/core/src/skywalking/mod.rs
deleted file mode 100644
index 08730c9..0000000
--- a/core/src/skywalking/mod.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements.  See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to You under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License.  You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-pub mod core;
-pub mod agent;
diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml
new file mode 100644
index 0000000..579fc58
--- /dev/null
+++ b/docker-compose.dev.yml
@@ -0,0 +1,65 @@
+version: "3.7"
+services:
+  # Skywalking components.
+  elasticsearch:
+    image: elasticsearch:7.9.2
+    restart: always
+    ports:
+      - 9200:9200
+    healthcheck:
+      test: ["CMD-SHELL", "curl --silent --fail localhost:9200/_cluster/health || exit 1"]
+      interval: 30s
+      timeout: 10s
+      retries: 3
+      start_period: 40s
+    environment:
+      discovery.type: single-node
+    expose:
+      - "9200"
+    ulimits:
+      memlock:
+        soft: -1
+        hard: -1
+  consul:
+    image: docker.io/bitnami/consul:1-debian-10
+    ports:
+      - '8300:8300'
+      - '8301:8301'
+      - '8301:8301/udp'
+      - '8500:8500'
+      - '8600:8600'
+      - '8600:8600/udp'
+  oap:
+    image: apache/skywalking-oap-server:8.6.0-es7
+    depends_on:
+      - elasticsearch
+    links:
+      - elasticsearch
+    ports:
+      - 11800:11800
+      - 12800:12800
+    environment:
+      SW_STORAGE: elasticsearch7
+      SW_STORAGE_ES_CLUSTER_NODES: elasticsearch:9200
+    restart: always
+    healthcheck:
+      test: ["CMD-SHELL", "/skywalking/bin/swctl"]
+      interval: 30s
+      timeout: 10s
+      retries: 3
+      start_period: 40s
+    depends_on:
+      - consul
+      - elasticsearch
+  ui:
+    image: apache/skywalking-ui:8.6.0
+    depends_on:
+      - oap
+    links:
+      - oap
+    ports:
+      - 8080:8080
+    environment:
+      SW_OAP_ADDRESS: oap:12800
+    depends_on:
+      - oap
\ No newline at end of file
diff --git a/docker-compose.e2e.yml b/docker-compose.e2e.yml
new file mode 100644
index 0000000..3c28ead
--- /dev/null
+++ b/docker-compose.e2e.yml
@@ -0,0 +1,30 @@
+version: "3.7"
+services:
+  collector:
+    build:
+      context: .
+      dockerfile: ./tests/e2e/docker/Dockerfile.tool
+    ports:
+      - 19876:19876
+      - 12800:12800
+
+  consumer:
+    build:
+      context: .
+      dockerfile: ./tests/e2e/docker/Dockerfile
+    expose: 
+      - 8082
+    command: cargo run -- --mode consumer
+    depends_on:
+      - collector
+
+  producer:
+    build:
+      context: .
+      dockerfile: ./tests/e2e/docker/Dockerfile
+    ports:
+      - 8081:8081
+    command: cargo run -- --mode producer
+    depends_on:
+      - collector
+      - consumer
\ No newline at end of file
diff --git a/examples/simple_trace_report.rs b/examples/simple_trace_report.rs
new file mode 100644
index 0000000..6848475
--- /dev/null
+++ b/examples/simple_trace_report.rs
@@ -0,0 +1,16 @@
+use skywalking_rust::context::system_time::UnixTimeStampFetcher;
+use skywalking_rust::context::trace_context::TracingContext;
+use skywalking_rust::reporter::grpc::Reporter;
+use std::sync::Arc;
+use tokio;
+
+#[tokio::main]
+async fn main() {
+    let tx = Reporter::start("http://0.0.0.0:11800".to_string()).await;
+    let mut context = TracingContext::default_internal("service", "instance");
+    {
+        let span = context.create_entry_span("op1").unwrap();
+        context.finalize_span(span);
+    }
+    let _ = tx.send(context).await;
+}
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..a8774cb
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,2 @@
+PyYAML==5.4
+apache-skywalking==0.5.0
diff --git a/skywalking-data-collect-protocol b/skywalking-data-collect-protocol
new file mode 160000
index 0000000..fbbe955
--- /dev/null
+++ b/skywalking-data-collect-protocol
@@ -0,0 +1 @@
+Subproject commit fbbe955545fd2c942ca59cd05720a084d010bb8a
diff --git a/core/src/lib.rs b/src/common/mod.rs
similarity index 88%
copy from core/src/lib.rs
copy to src/common/mod.rs
index f94e272..cd8c341 100644
--- a/core/src/lib.rs
+++ b/src/common/mod.rs
@@ -5,13 +5,14 @@
 // (the "License"); you may not use this file except in compliance with
 // the License.  You may obtain a copy of the License at
 //
-// http://www.apache.org/licenses/LICENSE-2.0
+//     http://www.apache.org/licenses/LICENSE-2.0
 //
 // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+//
 
-pub mod skywalking;
-
+pub mod random_generator;
+pub mod time;
diff --git a/core/src/lib.rs b/src/common/random_generator.rs
similarity index 77%
copy from core/src/lib.rs
copy to src/common/random_generator.rs
index f94e272..6c64f5b 100644
--- a/core/src/lib.rs
+++ b/src/common/random_generator.rs
@@ -5,13 +5,21 @@
 // (the "License"); you may not use this file except in compliance with
 // the License.  You may obtain a copy of the License at
 //
-// http://www.apache.org/licenses/LICENSE-2.0
+//     http://www.apache.org/licenses/LICENSE-2.0
 //
 // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+//
 
-pub mod skywalking;
+use uuid::Uuid;
 
+pub struct RandomGenerator;
+
+impl RandomGenerator {
+    pub fn generate() -> String {
+        Uuid::new_v4().as_u128().to_string()
+    }
+}
diff --git a/core/src/lib.rs b/src/common/time.rs
similarity index 81%
copy from core/src/lib.rs
copy to src/common/time.rs
index f94e272..8c28600 100644
--- a/core/src/lib.rs
+++ b/src/common/time.rs
@@ -5,13 +5,16 @@
 // (the "License"); you may not use this file except in compliance with
 // the License.  You may obtain a copy of the License at
 //
-// http://www.apache.org/licenses/LICENSE-2.0
+//     http://www.apache.org/licenses/LICENSE-2.0
 //
 // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+//
 
-pub mod skywalking;
-
+pub trait TimeFetcher {
+    // Get current UNIX timestamp with sec resolution.
+    fn get(&self) -> i64;
+}
diff --git a/core/src/lib.rs b/src/context/mod.rs
similarity index 85%
copy from core/src/lib.rs
copy to src/context/mod.rs
index f94e272..3e9e727 100644
--- a/core/src/lib.rs
+++ b/src/context/mod.rs
@@ -5,13 +5,15 @@
 // (the "License"); you may not use this file except in compliance with
 // the License.  You may obtain a copy of the License at
 //
-// http://www.apache.org/licenses/LICENSE-2.0
+//     http://www.apache.org/licenses/LICENSE-2.0
 //
 // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+//
 
-pub mod skywalking;
-
+pub mod propagation;
+pub mod system_time;
+pub mod trace_context;
diff --git a/src/context/propagation/context.rs b/src/context/propagation/context.rs
new file mode 100644
index 0000000..c72f3aa
--- /dev/null
+++ b/src/context/propagation/context.rs
@@ -0,0 +1,73 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+pub static SKYWALKING_HTTP_CONTEXT_HEADER_KEY: &str = "sw8";
+
+pub struct PropagationContext {
+    /// It defines whether next span should be trace or not.
+    /// In SkyWalking, If `do_sample == true`, the span should be reported to
+    /// OAP server and can be analyzed.
+    pub do_sample: bool,
+
+    /// It defines trace ID that previous span has. It expresses unique value of entire trace.
+    pub parent_trace_id: String,
+
+    /// It defines segment ID that previos span has. It expresses unique value of entire trace.
+    pub parent_trace_segment_id: String,
+
+    /// It defines parent span's span ID.
+    pub parent_span_id: i32,
+
+    /// Service name of service parent belongs.
+    pub parent_service: String,
+
+    /// Instance name of service parent belongs.
+    pub parent_service_instance: String,
+
+    /// An endpoint name that parent requested to.
+    pub destination_endpoint: String,
+
+    /// An address that parent requested to. It can be authority or network address.
+    pub destination_address: String,
+}
+
+/// PropagationContext carries the context which include trace infomation.
+/// In general, this context will be used if you create new TraceContext after received
+/// decoded context that should be packed in `sw8` header.
+impl PropagationContext {
+    #[allow(clippy::too_many_arguments)]
+    pub fn new(
+        do_sample: bool,
+        parent_trace_id: String,
+        parent_trace_segment_id: String,
+        parent_span_id: i32,
+        parent_service: String,
+        parent_service_instance: String,
+        destination_endpoint: String,
+        destination_address: String,
+    ) -> PropagationContext {
+        PropagationContext {
+            do_sample,
+            parent_trace_id,
+            parent_trace_segment_id,
+            parent_span_id,
+            parent_service,
+            parent_service_instance,
+            destination_endpoint,
+            destination_address,
+        }
+    }
+}
diff --git a/src/context/propagation/decoder.rs b/src/context/propagation/decoder.rs
new file mode 100644
index 0000000..155af43
--- /dev/null
+++ b/src/context/propagation/decoder.rs
@@ -0,0 +1,77 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+use crate::context::propagation::context::PropagationContext;
+use base64::decode;
+
+/// Decode context value packed in `sw8` header.
+pub fn decode_propagation(header_value: &str) -> Result<PropagationContext, &str> {
+    let pieces: Vec<&str> = header_value.split('-').collect();
+
+    if pieces.len() != 8 {
+        return Err("failed to parse propagation context: it must have 8 properties.");
+    }
+
+    let do_sample = try_parse_sample_status(pieces[0])?;
+    let parent_trace_id = b64_encoded_into_string(pieces[1])?;
+    let parent_trace_segment_id = b64_encoded_into_string(pieces[2])?;
+    let parent_span_id: i32 = try_parse_parent_span_id(pieces[3])?;
+    let parent_service = b64_encoded_into_string(pieces[4])?;
+    let parent_service_instance = b64_encoded_into_string(pieces[5])?;
+    let destination_endpoint = b64_encoded_into_string(pieces[6])?;
+    let destination_address = b64_encoded_into_string(pieces[7])?;
+
+    let context = PropagationContext::new(
+        do_sample,
+        parent_trace_id,
+        parent_trace_segment_id,
+        parent_span_id,
+        parent_service,
+        parent_service_instance,
+        destination_endpoint,
+        destination_address,
+    );
+
+    Ok(context)
+}
+
+fn try_parse_parent_span_id(id: &str) -> Result<i32, &str> {
+    if let Ok(result) = id.parse::<i32>() {
+        Ok(result)
+    } else {
+        Err("failed to parse span id from parent.")
+    }
+}
+
+fn try_parse_sample_status(status: &str) -> Result<bool, &str> {
+    if status == "0" {
+        Ok(false)
+    } else if status == "1" {
+        Ok(true)
+    } else {
+        Err("failed to parse sample status.")
+    }
+}
+
+fn b64_encoded_into_string(enc: &str) -> Result<String, &str> {
+    if let Ok(result) = decode(enc) {
+        if let Ok(decoded_str) = String::from_utf8(result) {
+            return Ok(decoded_str);
+        }
+    }
+
+    Err("failed to decode value.")
+}
diff --git a/src/context/propagation/encoder.rs b/src/context/propagation/encoder.rs
new file mode 100644
index 0000000..937e5f7
--- /dev/null
+++ b/src/context/propagation/encoder.rs
@@ -0,0 +1,34 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+use crate::context::trace_context::TracingContext;
+use base64::encode;
+
+/// Encode TracingContext to carry current trace info to the destination of RPC call.
+/// In general, the output of this function will be packed in `sw8` header in HTTP call.
+pub fn encode_propagation(context: &TracingContext, endpoint: &str, address: &str) -> String {
+    let mut res = String::new();
+
+    res += "1-";
+    res += format!("{}-", encode(context.trace_id.to_string())).as_str();
+    res += format!("{}-", encode(context.trace_segment_id.to_string())).as_str();
+    res += format!("{}-", context.next_span_id.to_string()).as_str();
+    res += format!("{}-", encode(context.service.as_str())).as_str();
+    res += format!("{}-", encode(context.service_instance.as_str())).as_str();
+    res += format!("{}-", encode(endpoint)).as_str();
+    res += &encode(address);
+    res
+}
diff --git a/core/src/lib.rs b/src/context/propagation/mod.rs
similarity index 87%
copy from core/src/lib.rs
copy to src/context/propagation/mod.rs
index f94e272..6c522f3 100644
--- a/core/src/lib.rs
+++ b/src/context/propagation/mod.rs
@@ -5,13 +5,15 @@
 // (the "License"); you may not use this file except in compliance with
 // the License.  You may obtain a copy of the License at
 //
-// http://www.apache.org/licenses/LICENSE-2.0
+//     http://www.apache.org/licenses/LICENSE-2.0
 //
 // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+//
 
-pub mod skywalking;
-
+pub mod context;
+pub mod decoder;
+pub mod encoder;
diff --git a/core/src/lib.rs b/src/context/system_time.rs
similarity index 65%
copy from core/src/lib.rs
copy to src/context/system_time.rs
index f94e272..69f2423 100644
--- a/core/src/lib.rs
+++ b/src/context/system_time.rs
@@ -5,13 +5,26 @@
 // (the "License"); you may not use this file except in compliance with
 // the License.  You may obtain a copy of the License at
 //
-// http://www.apache.org/licenses/LICENSE-2.0
+//     http://www.apache.org/licenses/LICENSE-2.0
 //
 // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+//
 
-pub mod skywalking;
+use crate::common::time::TimeFetcher;
+use std::time::{SystemTime, UNIX_EPOCH};
 
+#[derive(Default)]
+pub struct UnixTimeStampFetcher {}
+
+impl TimeFetcher for UnixTimeStampFetcher {
+    fn get(&self) -> i64 {
+        SystemTime::now()
+            .duration_since(UNIX_EPOCH)
+            .unwrap()
+            .as_secs() as i64
+    }
+}
diff --git a/src/context/trace_context.rs b/src/context/trace_context.rs
new file mode 100644
index 0000000..ee34b73
--- /dev/null
+++ b/src/context/trace_context.rs
@@ -0,0 +1,355 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+use crate::common::random_generator::RandomGenerator;
+use crate::common::time::TimeFetcher;
+use crate::context::propagation::context::PropagationContext;
+use crate::skywalking_proto::v3::{
+    KeyStringValuePair, Log, RefType, SegmentObject, SegmentReference, SpanLayer, SpanObject,
+    SpanType,
+};
+use std::sync::Arc;
+
+use super::system_time::UnixTimeStampFetcher;
+
+/// Span is a concept that represents trace information for a single RPC.
+/// The Rust SDK supports Entry Span to represent inbound to a service
+/// and Exit Span to represent outbound from a service.
+///
+/// # Example
+///
+/// ```
+/// async fn handle_request() {
+///     let mut ctx = TracingContext::default("svc", "ins");
+///     {
+///         // Generate an Entry Span when a request
+///         // is received. An Entry Span is generated only once per context.
+///         let span = ctx.create_entry_span("operation1").unwrap();
+///         
+///         // Something...
+///         
+///         {
+///             // Generates an Exit Span when executing an RPC.
+///             let span2 = ctx.create_exit_span("operation2").unwrap();
+///             
+///             // Something...
+///
+///             ctx.finalize_span(span2);
+///         }
+///
+///         ctx.finalize_span(span);
+///     }
+/// }
+/// ```
+pub struct Span {
+    span_internal: SpanObject,
+    time_fetcher: Arc<dyn TimeFetcher + Sync + Send>,
+}
+
+static SKYWALKING_RUST_COMPONENT_ID: i32 = 11000;
+
+impl Span {
+    pub fn new(
+        parent_span_id: i32,
+        operation_name: String,
+        remote_peer: String,
+        span_type: SpanType,
+        span_layer: SpanLayer,
+        skip_analysis: bool,
+        time_fetcher: Arc<dyn TimeFetcher + Sync + Send>,
+    ) -> Self {
+        let span_internal = SpanObject {
+            span_id: parent_span_id + 1,
+            parent_span_id,
+            start_time: time_fetcher.get(),
+            end_time: 0, // not set
+            refs: Vec::<SegmentReference>::new(),
+            operation_name,
+            peer: remote_peer,
+            span_type: span_type as i32,
+            span_layer: span_layer as i32,
+            component_id: SKYWALKING_RUST_COMPONENT_ID,
+            is_error: false,
+            tags: Vec::<KeyStringValuePair>::new(),
+            logs: Vec::<Log>::new(),
+            skip_analysis,
+        };
+
+        Span {
+            span_internal,
+            time_fetcher,
+        }
+    }
+
+    /// Close span. It only registers end time to the span.
+    pub fn close(&mut self) {
+        self.span_internal.end_time = self.time_fetcher.get();
+    }
+
+    pub fn span_object(&self) -> &SpanObject {
+        &self.span_internal
+    }
+
+    /// Add logs to the span.
+    pub fn add_log(&mut self, message: Vec<(&str, &str)>) {
+        let log = Log {
+            time: self.time_fetcher.get(),
+            data: message
+                .into_iter()
+                .map(|v| {
+                    let (key, value) = v;
+                    KeyStringValuePair {
+                        key: key.to_string(),
+                        value: value.to_string(),
+                    }
+                })
+                .collect(),
+        };
+        self.span_internal.logs.push(log);
+    }
+
+    /// Add tag to the span.
+    pub fn add_tag(&mut self, tag: (&str, &str)) {
+        let (key, value) = tag;
+        self.span_internal.tags.push(KeyStringValuePair {
+            key: key.to_string(),
+            value: value.to_string(),
+        });
+    }
+
+    fn add_segment_reference(&mut self, segment_reference: SegmentReference) {
+        self.span_internal.refs.push(segment_reference);
+    }
+}
+
+pub struct TracingContext {
+    pub trace_id: String,
+    pub trace_segment_id: String,
+    pub service: String,
+    pub service_instance: String,
+    pub next_span_id: i32,
+    pub spans: Vec<Box<Span>>,
+    time_fetcher: Arc<dyn TimeFetcher + Sync + Send>,
+    segment_link: Option<PropagationContext>,
+}
+
+impl TracingContext {
+    /// Generate a new trace context. Typically called when no context has
+    /// been propagated and a new trace is to be started.
+    pub fn default(service_name: &str, instance_name: &str) -> Self {
+        let unix_time_fetcher = UnixTimeStampFetcher {};
+        TracingContext::default_internal(Arc::new(unix_time_fetcher), service_name, instance_name)
+    }
+
+    pub fn default_internal(
+        time_fetcher: Arc<dyn TimeFetcher + Sync + Send>,
+        service_name: &str,
+        instance_name: &str,
+    ) -> Self {
+        TracingContext {
+            trace_id: RandomGenerator::generate(),
+            trace_segment_id: RandomGenerator::generate(),
+            service: String::from(service_name),
+            service_instance: String::from(instance_name),
+            next_span_id: 0,
+            time_fetcher,
+            spans: Vec::new(),
+            segment_link: None,
+        }
+    }
+
+    /// Generate a new trace context using the propagated context.
+    /// They should be propagated on `sw8` header in HTTP request with encoded form.
+    /// You can retrieve decoded context with `skywalking_rust::context::propagation::encoder::encode_propagation`
+    pub fn from_propagation_context(
+        service_name: &str,
+        instance_name: &str,
+        context: PropagationContext,
+    ) -> Self {
+        let unix_time_fetcher = UnixTimeStampFetcher {};
+        TracingContext::from_propagation_context_internal(
+            Arc::new(unix_time_fetcher),
+            service_name,
+            instance_name,
+            context,
+        )
+    }
+
+    pub fn from_propagation_context_internal(
+        time_fetcher: Arc<dyn TimeFetcher + Sync + Send>,
+        service_name: &str,
+        instance_name: &str,
+        context: PropagationContext,
+    ) -> Self {
+        TracingContext {
+            trace_id: context.parent_trace_id.clone(),
+            trace_segment_id: RandomGenerator::generate(),
+            service: service_name.to_string(),
+            service_instance: instance_name.to_string(),
+            next_span_id: 0,
+            time_fetcher,
+            spans: Vec::new(),
+            segment_link: Some(context),
+        }
+    }
+
+    /// A wrapper of create entry span, which close generated span automatically.
+    /// Note that, we may use async operation in closure. But that is not unstable feature in 2021/12.
+    /// https://github.com/rust-lang/rust/issues/62290
+    /// So we should create and close spans manually in general.
+    pub fn entry<F: FnMut(&Span)>(
+        &mut self,
+        operation_name: &str,
+        mut process_fn: F,
+    ) -> Result<(), &str> {
+        match self.create_entry_span(operation_name) {
+            Ok(mut span) => {
+                process_fn(span.as_ref());
+                span.close();
+                Ok(())
+            }
+            Err(message) => Err(message),
+        }
+    }
+
+    /// Create a new entry span, which is an initiator of collection of spans.
+    /// This should be called by invocation of the function which is triggered by
+    /// external service.
+    pub fn create_entry_span(&mut self, operation_name: &str) -> Result<Box<Span>, &'static str> {
+        if self.next_span_id >= 1 {
+            return Err("entry span have already exist.");
+        }
+
+        let mut span = Box::new(Span::new(
+            self.next_span_id,
+            operation_name.to_string(),
+            String::default(),
+            SpanType::Entry,
+            SpanLayer::Http,
+            false,
+            self.time_fetcher.clone(),
+        ));
+
+        if self.segment_link.is_some() {
+            span.add_segment_reference(SegmentReference {
+                ref_type: RefType::CrossProcess as i32,
+                trace_id: self.trace_id.clone(),
+                parent_trace_segment_id: self
+                    .segment_link
+                    .as_ref()
+                    .unwrap()
+                    .parent_trace_segment_id
+                    .clone(),
+                parent_span_id: self.segment_link.as_ref().unwrap().parent_span_id,
+                parent_service: self.segment_link.as_ref().unwrap().parent_service.clone(),
+                parent_service_instance: self
+                    .segment_link
+                    .as_ref()
+                    .unwrap()
+                    .parent_service_instance
+                    .clone(),
+                parent_endpoint: self
+                    .segment_link
+                    .as_ref()
+                    .unwrap()
+                    .destination_endpoint
+                    .clone(),
+                network_address_used_at_peer: self
+                    .segment_link
+                    .as_ref()
+                    .unwrap()
+                    .destination_address
+                    .clone(),
+            });
+        }
+        self.next_span_id += 1;
+        Ok(span)
+    }
+
+    /// A wrapper of create exit span, which close generated span automatically.
+    /// Note that, we may use async operation in closure. But that is not unstable feature in 2021/12.
+    /// https://github.com/rust-lang/rust/issues/62290
+    /// So we should create and close spans manually in general.
+    pub fn exit<F: FnMut(&Span)>(
+        &mut self,
+        operation_name: &str,
+        remote_peer: &str,
+        mut process_fn: F,
+    ) -> Result<(), &str> {
+        match self.create_exit_span(operation_name, remote_peer) {
+            Ok(mut span) => {
+                process_fn(span.as_ref());
+                span.close();
+                Ok(())
+            }
+            Err(message) => Err(message),
+        }
+    }
+
+    /// Create a new exit span, which will be created when tracing context will generate
+    /// new span for function invocation.
+    /// Currently, this SDK supports RPC call. So we must set `remote_peer`.
+    pub fn create_exit_span(
+        &mut self,
+        operation_name: &str,
+        remote_peer: &str,
+    ) -> Result<Box<Span>, &'static str> {
+        if self.next_span_id == 0 {
+            return Err("entry span must be existed.");
+        }
+
+        let span = Box::new(Span::new(
+            self.next_span_id,
+            operation_name.to_string(),
+            remote_peer.to_string(),
+            SpanType::Exit,
+            SpanLayer::Http,
+            false,
+            self.time_fetcher.clone(),
+        ));
+        self.next_span_id += 1;
+        Ok(span)
+    }
+
+    /// Close span. We can't use closed span after finalize called.
+    pub fn finalize_span(&mut self, mut span: Box<Span>) {
+        span.close();
+        self.spans.push(span);
+    }
+
+    pub fn finalize_span_for_test(&self, span: &mut Box<Span>) {
+        span.close();
+    }
+
+    /// It converts tracing context into segment object.
+    /// This conversion should be done before sending segments into OAP.
+    pub fn convert_segment_object(&self) -> SegmentObject {
+        let mut objects = Vec::<SpanObject>::new();
+
+        for span in self.spans.iter() {
+            objects.push(span.span_internal.clone());
+        }
+
+        SegmentObject {
+            trace_id: self.trace_id.to_string(),
+            trace_segment_id: self.trace_segment_id.to_string(),
+            spans: objects,
+            service: self.service.clone(),
+            service_instance: self.service_instance.clone(),
+            is_size_limited: false,
+        }
+    }
+}
diff --git a/core/src/skywalking/agent/mod.rs b/src/lib.rs
similarity index 79%
rename from core/src/skywalking/agent/mod.rs
rename to src/lib.rs
index 7cf36a6..0793220 100644
--- a/core/src/skywalking/agent/mod.rs
+++ b/src/lib.rs
@@ -5,16 +5,21 @@
 // (the "License"); you may not use this file except in compliance with
 // the License.  You may obtain a copy of the License at
 //
-// http://www.apache.org/licenses/LICENSE-2.0
+//     http://www.apache.org/licenses/LICENSE-2.0
 //
 // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+//
 
-pub use context_manager::ContextManager;
+pub mod skywalking_proto {
+    pub mod v3 {
+        tonic::include_proto!("skywalking.v3");
+    }
+}
 
-pub mod context_manager;
+pub mod common;
+pub mod context;
 pub mod reporter;
-
diff --git a/src/reporter/grpc.rs b/src/reporter/grpc.rs
new file mode 100644
index 0000000..43f9664
--- /dev/null
+++ b/src/reporter/grpc.rs
@@ -0,0 +1,70 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+use crate::context::trace_context::TracingContext;
+use crate::skywalking_proto::v3::trace_segment_report_service_client::TraceSegmentReportServiceClient;
+use crate::skywalking_proto::v3::SegmentObject;
+use tokio::sync::mpsc;
+use tonic::transport::Channel;
+
+pub type ReporterClient = TraceSegmentReportServiceClient<Channel>;
+
+async fn flush(client: &mut ReporterClient, context: SegmentObject) -> Result<(), tonic::Status> {
+    let stream = async_stream::stream! {
+        yield context;
+    };
+    match client.collect(stream).await {
+        Ok(_) => Ok(()),
+        Err(e) => Err(e),
+    }
+}
+
+pub struct Reporter {}
+
+static CHANNEL_BUF_SIZE: usize = 1024;
+
+pub type ContextReporter = mpsc::Sender<TracingContext>;
+
+impl Reporter {
+    /// Open gRPC client stream to send collected trace context.
+    /// This function generates a new async task which watch to arrive new trace context.
+    /// We can send collected context to push into sender.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use tokio;
+    ///
+    /// #[tokio::main]
+    /// async fn main {
+    ///     let tx = Reporter::start("localhost:12800");
+    ///     tx.send(context).await;
+    /// }
+    /// ```
+    pub async fn start(address: &str) -> ContextReporter {
+        let (tx, mut rx): (mpsc::Sender<TracingContext>, mpsc::Receiver<TracingContext>) =
+            mpsc::channel(CHANNEL_BUF_SIZE);
+        let mut reporter = ReporterClient::connect(address.to_string()).await.unwrap();
+        tokio::spawn(async move {
+            while let Some(message) = rx.recv().await {
+                flush(&mut reporter, message.convert_segment_object())
+                    .await
+                    .unwrap();
+            }
+        });
+        tx
+    }
+}
diff --git a/core/src/lib.rs b/src/reporter/mod.rs
similarity index 91%
rename from core/src/lib.rs
rename to src/reporter/mod.rs
index f94e272..3a196cf 100644
--- a/core/src/lib.rs
+++ b/src/reporter/mod.rs
@@ -5,13 +5,13 @@
 // (the "License"); you may not use this file except in compliance with
 // the License.  You may obtain a copy of the License at
 //
-// http://www.apache.org/licenses/LICENSE-2.0
+//     http://www.apache.org/licenses/LICENSE-2.0
 //
 // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+//
 
-pub mod skywalking;
-
+pub mod grpc;
diff --git a/tests/e2e/Cargo.lock b/tests/e2e/Cargo.lock
new file mode 100644
index 0000000..197c8a4
--- /dev/null
+++ b/tests/e2e/Cargo.lock
@@ -0,0 +1,1050 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "ansi_term"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.51"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203"
+
+[[package]]
+name = "async-stream"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "171374e7e3b2504e0e5236e3b59260560f9fe94bfe9ac39ba5e4e929c5590625"
+dependencies = [
+ "async-stream-impl",
+ "futures-core",
+]
+
+[[package]]
+name = "async-stream-impl"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "648ed8c8d2ce5409ccd57453d9d1b214b342a0d69376a6feda1fd6cae3299308"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "async-trait"
+version = "0.1.52"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
+
+[[package]]
+name = "base64"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bytes"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "clap"
+version = "2.34.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
+dependencies = [
+ "ansi_term",
+ "atty",
+ "bitflags",
+ "strsim",
+ "textwrap",
+ "unicode-width",
+ "vec_map",
+]
+
+[[package]]
+name = "e2e"
+version = "0.1.0"
+dependencies = [
+ "hyper",
+ "skywalking_rust",
+ "structopt",
+ "tokio",
+]
+
+[[package]]
+name = "either"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
+
+[[package]]
+name = "fixedbitset"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "futures-channel"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888"
+dependencies = [
+ "futures-core",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d"
+
+[[package]]
+name = "futures-sink"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11"
+
+[[package]]
+name = "futures-task"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99"
+
+[[package]]
+name = "futures-util"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481"
+dependencies = [
+ "autocfg",
+ "futures-core",
+ "futures-task",
+ "pin-project-lite",
+ "pin-utils",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "h2"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f072413d126e57991455e0a922b31e4c8ba7c2ffbebf6b78b4f8521397d65cd"
+dependencies = [
+ "bytes",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "http",
+ "indexmap",
+ "slab",
+ "tokio",
+ "tokio-util",
+ "tracing",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
+
+[[package]]
+name = "heck"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "http"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "http-body"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6"
+dependencies = [
+ "bytes",
+ "http",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "httparse"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503"
+
+[[package]]
+name = "httpdate"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
+
+[[package]]
+name = "hyper"
+version = "0.14.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "socket2",
+ "tokio",
+ "tower-service",
+ "tracing",
+ "want",
+]
+
+[[package]]
+name = "hyper-timeout"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
+dependencies = [
+ "hyper",
+ "pin-project-lite",
+ "tokio",
+ "tokio-io-timeout",
+]
+
+[[package]]
+name = "indexmap"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+]
+
+[[package]]
+name = "instant"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "itertools"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "0.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.112"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
+
+[[package]]
+name = "lock_api"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
+dependencies = [
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "memchr"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
+
+[[package]]
+name = "mio"
+version = "0.7.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc"
+dependencies = [
+ "libc",
+ "log",
+ "miow",
+ "ntapi",
+ "winapi",
+]
+
+[[package]]
+name = "miow"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "multimap"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
+
+[[package]]
+name = "ntapi"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
+
+[[package]]
+name = "parking_lot"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
+dependencies = [
+ "instant",
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
+dependencies = [
+ "cfg-if",
+ "instant",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "winapi",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
+
+[[package]]
+name = "petgraph"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7"
+dependencies = [
+ "fixedbitset",
+ "indexmap",
+]
+
+[[package]]
+name = "pin-project"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba"
+
+[[package]]
+name = "proc-macro-error"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "prost"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de5e2533f59d08fcf364fd374ebda0692a70bd6d7e66ef97f306f45c6c5d8020"
+dependencies = [
+ "bytes",
+ "prost-derive",
+]
+
+[[package]]
+name = "prost-build"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "355f634b43cdd80724ee7848f95770e7e70eefa6dcf14fea676216573b8fd603"
+dependencies = [
+ "bytes",
+ "heck",
+ "itertools",
+ "log",
+ "multimap",
+ "petgraph",
+ "prost",
+ "prost-types",
+ "tempfile",
+ "which",
+]
+
+[[package]]
+name = "prost-derive"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "600d2f334aa05acb02a755e217ef1ab6dea4d51b58b7846588b747edec04efba"
+dependencies = [
+ "anyhow",
+ "itertools",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "prost-types"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "603bbd6394701d13f3f25aada59c7de9d35a6a5887cfc156181234a44002771b"
+dependencies = [
+ "bytes",
+ "prost",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+ "rand_hc",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "remove_dir_all"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "serde"
+version = "1.0.132"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b9875c23cf305cd1fd7eb77234cbb705f21ea6a72c637a5c6db5fe4b8e7f008"
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "skywalking_rust"
+version = "0.0.1"
+dependencies = [
+ "async-stream",
+ "base64",
+ "bytes",
+ "prost",
+ "prost-derive",
+ "tokio",
+ "tonic",
+ "tonic-build",
+ "uuid",
+]
+
+[[package]]
+name = "slab"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
+
+[[package]]
+name = "smallvec"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
+
+[[package]]
+name = "socket2"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "strsim"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+
+[[package]]
+name = "structopt"
+version = "0.3.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c"
+dependencies = [
+ "clap",
+ "lazy_static",
+ "structopt-derive",
+]
+
+[[package]]
+name = "structopt-derive"
+version = "0.4.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
+dependencies = [
+ "heck",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.82"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "tempfile"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "rand",
+ "redox_syscall",
+ "remove_dir_all",
+ "winapi",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
+name = "tokio"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838"
+dependencies = [
+ "bytes",
+ "libc",
+ "memchr",
+ "mio",
+ "num_cpus",
+ "once_cell",
+ "parking_lot",
+ "pin-project-lite",
+ "signal-hook-registry",
+ "tokio-macros",
+ "winapi",
+]
+
+[[package]]
+name = "tokio-io-timeout"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90c49f106be240de154571dd31fbe48acb10ba6c6dd6f6517ad603abffa42de9"
+dependencies = [
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tokio-stream"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.6.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "log",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tonic"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "796c5e1cd49905e65dd8e700d4cb1dffcbfdb4fc9d017de08c1a537afd83627c"
+dependencies = [
+ "async-stream",
+ "async-trait",
+ "base64",
+ "bytes",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "hyper-timeout",
+ "percent-encoding",
+ "pin-project",
+ "prost",
+ "prost-derive",
+ "tokio",
+ "tokio-stream",
+ "tokio-util",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+ "tracing-futures",
+]
+
+[[package]]
+name = "tonic-build"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12b52d07035516c2b74337d2ac7746075e7dcae7643816c1b12c5ff8a7484c08"
+dependencies = [
+ "proc-macro2",
+ "prost-build",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tower"
+version = "0.4.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5651b5f6860a99bd1adb59dbfe1db8beb433e73709d9032b413a77e2fb7c066a"
+dependencies = [
+ "futures-core",
+ "futures-util",
+ "indexmap",
+ "pin-project",
+ "pin-project-lite",
+ "rand",
+ "slab",
+ "tokio",
+ "tokio-stream",
+ "tokio-util",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "tower-layer"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62"
+
+[[package]]
+name = "tower-service"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
+
+[[package]]
+name = "tracing"
+version = "0.1.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105"
+dependencies = [
+ "cfg-if",
+ "log",
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4"
+dependencies = [
+ "lazy_static",
+]
+
+[[package]]
+name = "tracing-futures"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
+dependencies = [
+ "pin-project",
+ "tracing",
+]
+
+[[package]]
+name = "try-lock"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
+
+[[package]]
+name = "uuid"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
+dependencies = [
+ "getrandom",
+ "serde",
+]
+
+[[package]]
+name = "vec_map"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
+
+[[package]]
+name = "version_check"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
+
+[[package]]
+name = "want"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
+dependencies = [
+ "log",
+ "try-lock",
+]
+
+[[package]]
+name = "wasi"
+version = "0.10.2+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
+
+[[package]]
+name = "which"
+version = "4.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea187a8ef279bc014ec368c27a920da2024d2a711109bfbe3440585d5cf27ad9"
+dependencies = [
+ "either",
+ "lazy_static",
+ "libc",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/tests/e2e/Cargo.toml b/tests/e2e/Cargo.toml
new file mode 100644
index 0000000..6a5cf5b
--- /dev/null
+++ b/tests/e2e/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "e2e"
+version = "0.1.0"
+authors = ["Shikugawa <Shikugawa@gmail.com>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+skywalking_rust = { path = "../../" }
+hyper = { version = "0.14", features = ["full"] }
+tokio = { version = "1", features = ["full"] }
+structopt = "0.3"
diff --git a/tests/e2e/data/expected_context.yaml b/tests/e2e/data/expected_context.yaml
new file mode 100644
index 0000000..79f78b5
--- /dev/null
+++ b/tests/e2e/data/expected_context.yaml
@@ -0,0 +1,56 @@
+segmentItems:
+- segmentSize: 1
+  segments:
+  - segmentId: not null
+    spans:
+    - componentId: 11000
+      endTime: gt 0
+      isError: false
+      operationId: 0
+      operationName: /pong
+      parentSpanId: 1
+      peer: consumer:8082
+      skipAnalysis: false
+      spanId: 2
+      spanLayer: Http
+      spanType: Exit
+      startTime: gt 0
+    - componentId: 11000
+      endTime: gt 0
+      isError: false
+      operationId: 0
+      operationName: /ping
+      parentSpanId: 0
+      peer: ''
+      skipAnalysis: false
+      spanId: 1
+      spanLayer: Http
+      spanType: Entry
+      startTime: gt 0
+  serviceName: producer
+- segmentSize: 1
+  segments:
+  - segmentId: not null
+    spans:
+    - componentId: 11000
+      endTime: gt 0
+      isError: false
+      operationId: 0
+      operationName: /pong
+      parentSpanId: 0
+      peer: ''
+      refs:
+      - networkAddress: consumer:8082
+        parentEndpoint: /pong
+        parentService: producer
+        parentServiceInstance: node_0
+        parentSpanId: 2
+        parentTraceSegmentId: not null
+        refType: CrossProcess
+        traceId: not null
+      skipAnalysis: false
+      spanId: 1
+      spanLayer: Http
+      spanType: Entry
+      startTime: gt 0
+  serviceName: consumer
\ No newline at end of file
diff --git a/tests/e2e/docker/Dockerfile b/tests/e2e/docker/Dockerfile
new file mode 100644
index 0000000..2ec7258
--- /dev/null
+++ b/tests/e2e/docker/Dockerfile
@@ -0,0 +1,5 @@
+FROM rust:1.50.0
+RUN apt update && apt install -y protobuf-compiler
+RUN rustup component add rustfmt
+COPY . /tmp
+WORKDIR tmp/tests/e2e
diff --git a/tests/e2e/docker/Dockerfile.tool b/tests/e2e/docker/Dockerfile.tool
new file mode 100644
index 0000000..74ef01c
--- /dev/null
+++ b/tests/e2e/docker/Dockerfile.tool
@@ -0,0 +1,15 @@
+FROM openjdk:8
+WORKDIR /tests
+ARG COMMIT_HASH=8db606f3470cce75c1b013ae498ac93b862b75b7
+ADD https://github.com/apache/skywalking-agent-test-tool/archive/${COMMIT_HASH}.tar.gz .
+RUN tar -xf ${COMMIT_HASH}.tar.gz --strip 1
+RUN rm ${COMMIT_HASH}.tar.gz
+RUN ./mvnw -B -DskipTests package
+
+FROM openjdk:8
+EXPOSE 19876 12800
+WORKDIR /tests
+COPY --from=0 /tests/dist/skywalking-mock-collector.tar.gz /tests
+RUN tar -xf skywalking-mock-collector.tar.gz --strip 1
+RUN chmod +x bin/collector-startup.sh
+ENTRYPOINT bin/collector-startup.sh
diff --git a/tests/e2e/run_e2e.py b/tests/e2e/run_e2e.py
new file mode 100644
index 0000000..cd2e1c9
--- /dev/null
+++ b/tests/e2e/run_e2e.py
@@ -0,0 +1,61 @@
+import os
+import sys
+import time
+from difflib import Differ
+from os.path import dirname
+
+import argparse
+import yaml
+import requests
+import time
+
+try:
+  from yaml import CSafeLoader as Loader
+except ImportError:
+  from yaml import SafeLoader as Loader
+
+def validate(expected_file_name):
+  with open(expected_file_name) as expected_data_file:
+    expected_data = os.linesep.join(expected_data_file.readlines())
+
+    response = requests.post(url='http://0.0.0.0:12800/dataValidate', data=expected_data)
+
+    if response.status_code != 200:
+      res = requests.get('http://0.0.0.0:12800/receiveData')
+      actual_data = yaml.dump(yaml.load(res.content, Loader=Loader))
+
+      differ = Differ()
+      diff_list = list(differ.compare(
+        actual_data.splitlines(keepends=True),
+        yaml.dump(yaml.load(expected_data, Loader=Loader)).splitlines(keepends=True)
+      ))
+
+      print('diff list: ')
+      sys.stdout.writelines(diff_list)
+
+    return response
+
+if __name__ == "__main__":
+  parser = argparse.ArgumentParser()
+  parser.add_argument('--expected_file', help='File name which includes expected reported value')
+  parser.add_argument('--max_retry_times', help='Max retry times', type=int)
+  parser.add_argument('--target_path', help='Specify target path')
+  
+  args = parser.parse_args()
+
+  retry_times = 0
+  while True:
+    if retry_times > args.max_retry_times:
+      raise RuntimeError("Max retry times exceeded")
+
+    try:
+      requests.get('http://0.0.0.0:8081{0}'.format(args.target_path), timeout=5)
+    except Exception as e:
+      print(e)
+      retry_times += 1
+      time.sleep(2)
+      continue
+
+    res = validate(args.expected_file)
+    assert res.status_code == 200
+    break
diff --git a/tests/e2e/src/main.rs b/tests/e2e/src/main.rs
new file mode 100644
index 0000000..cc9f76c
--- /dev/null
+++ b/tests/e2e/src/main.rs
@@ -0,0 +1,135 @@
+use hyper::client::HttpConnector;
+use hyper::service::{make_service_fn, service_fn};
+use hyper::{Body, Client, Method, Request, Response, Server, StatusCode};
+use skywalking_rust::context::propagation::context::SKYWALKING_HTTP_CONTEXT_HEADER_KEY;
+use skywalking_rust::context::propagation::decoder::decode_propagation;
+use skywalking_rust::context::propagation::encoder::encode_propagation;
+use skywalking_rust::context::trace_context::TracingContext;
+use skywalking_rust::reporter::grpc::Reporter;
+use std::convert::Infallible;
+use std::net::SocketAddr;
+use structopt::StructOpt;
+use tokio::sync::mpsc;
+
+static NOT_FOUND_MSG: &str = "not found";
+
+async fn handle_ping(
+    _req: Request<Body>,
+    client: Client<HttpConnector>,
+    tx: mpsc::Sender<TracingContext>,
+) -> Result<Response<Body>, Infallible> {
+    let mut context = TracingContext::default("producer", "node_0");
+    let span = context.create_entry_span("/ping").unwrap();
+    {
+        let span2 = context.create_exit_span("/pong", "consumer:8082").unwrap();
+        let header = encode_propagation(&context, "/pong", "consumer:8082");
+        let req = Request::builder()
+            .method(Method::GET)
+            .header(SKYWALKING_HTTP_CONTEXT_HEADER_KEY, header)
+            .uri("http://consumer:8082/pong")
+            .body(Body::from(""))
+            .unwrap();
+
+        client.request(req).await.unwrap();
+        context.finalize_span(span2);
+    }
+    context.finalize_span(span);
+    let _ = tx.send(context).await;
+    Ok(Response::new(Body::from("hoge")))
+}
+
+async fn producer_response(
+    _req: Request<Body>,
+    client: Client<HttpConnector>,
+    tx: mpsc::Sender<TracingContext>,
+) -> Result<Response<Body>, Infallible> {
+    match (_req.method(), _req.uri().path()) {
+        (&Method::GET, "/ping") => handle_ping(_req, client, tx).await,
+        _ => Ok(Response::builder()
+            .status(StatusCode::NOT_FOUND)
+            .body(Body::from(NOT_FOUND_MSG))
+            .unwrap()),
+    }
+}
+
+async fn run_producer_service(host: [u8; 4], tx: mpsc::Sender<TracingContext>) {
+    let client = Client::new();
+    let make_svc = make_service_fn(|_| {
+        let tx = tx.clone();
+        let client = client.clone();
+
+        async {
+            Ok::<_, Infallible>(service_fn(move |req| {
+                producer_response(req, client.to_owned(), tx.to_owned())
+            }))
+        }
+    });
+    let addr = SocketAddr::from((host, 8081));
+    let server = Server::bind(&addr).serve(make_svc);
+
+    if let Err(e) = server.await {
+        eprintln!("server error: {}", e);
+    }
+}
+
+async fn handle_pong(
+    _req: Request<Body>,
+    tx: mpsc::Sender<TracingContext>,
+) -> Result<Response<Body>, Infallible> {
+    let ctx = decode_propagation(
+        &_req.headers()[SKYWALKING_HTTP_CONTEXT_HEADER_KEY]
+            .to_str()
+            .unwrap(),
+    )
+    .unwrap();
+    let mut context = TracingContext::from_propagation_context("consumer", "node_0", ctx);
+    let span = context.create_entry_span("/pong").unwrap();
+    context.finalize_span(span);
+    let _ = tx.send(context).await;
+    Ok(Response::new(Body::from("hoge")))
+}
+
+async fn consumer_response(
+    _req: Request<Body>,
+    tx: mpsc::Sender<TracingContext>,
+) -> Result<Response<Body>, Infallible> {
+    match (_req.method(), _req.uri().path()) {
+        (&Method::GET, "/pong") => handle_pong(_req, tx).await,
+        _ => Ok(Response::builder()
+            .status(StatusCode::NOT_FOUND)
+            .body(Body::from(NOT_FOUND_MSG))
+            .unwrap()),
+    }
+}
+
+async fn run_consumer_service(host: [u8; 4], tx: mpsc::Sender<TracingContext>) {
+    let make_svc = make_service_fn(|_| {
+        let tx = tx.clone();
+        async { Ok::<_, Infallible>(service_fn(move |req| consumer_response(req, tx.to_owned()))) }
+    });
+    let addr = SocketAddr::from((host, 8082));
+    let server = Server::bind(&addr).serve(make_svc);
+
+    if let Err(e) = server.await {
+        eprintln!("server error: {}", e);
+    }
+}
+
+#[derive(StructOpt)]
+#[structopt(name = "basic")]
+struct Opt {
+    #[structopt(short, long)]
+    mode: String,
+}
+
+#[tokio::main]
+async fn main() {
+    let opt = Opt::from_args();
+    let tx = Reporter::start("http://collector:19876").await;
+
+    if opt.mode == "consumer" {
+        run_consumer_service([0, 0, 0, 0], tx).await;
+    } else if opt.mode == "producer" {
+        run_producer_service([0, 0, 0, 0], tx).await;
+    }
+}
diff --git a/tests/propagation.rs b/tests/propagation.rs
new file mode 100644
index 0000000..99ad4fb
--- /dev/null
+++ b/tests/propagation.rs
@@ -0,0 +1,81 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#![allow(unused_imports)]
+use skywalking_rust::common::time::TimeFetcher;
+use skywalking_rust::context::propagation::context::PropagationContext;
+use skywalking_rust::context::propagation::decoder::decode_propagation;
+use skywalking_rust::context::propagation::encoder::encode_propagation;
+use skywalking_rust::context::trace_context::TracingContext;
+use std::sync::Arc;
+
+struct MockTimeFetcher {}
+
+impl TimeFetcher for MockTimeFetcher {
+    fn get(&self) -> i64 {
+        100
+    }
+}
+
+#[test]
+fn basic() {
+    let data = "1-MQ==-NQ==-3-bWVzaA==-aW5zdGFuY2U=-L2FwaS92MS9oZWFsdGg=-ZXhhbXBsZS5jb206ODA4MA==";
+    let res = decode_propagation(data).unwrap();
+
+    assert_eq!(res.do_sample, true);
+    assert_eq!(res.parent_trace_id, "1");
+    assert_eq!(res.parent_trace_segment_id, "5");
+    assert_eq!(res.parent_span_id, 3);
+    assert_eq!(res.parent_service, "mesh");
+    assert_eq!(res.parent_service_instance, "instance");
+    assert_eq!(res.destination_endpoint, "/api/v1/health");
+    assert_eq!(res.destination_address, "example.com:8080");
+}
+
+#[test]
+fn less_field() {
+    let data = "1-MQ==-NQ==-3-bWVzaA==-aW5zdGFuY2U=-L2FwaS92MS9oZWFsdGg=";
+    let res = decode_propagation(data);
+
+    assert_eq!(res.is_err(), true);
+}
+
+#[test]
+fn more_field() {
+    let data = "1-MQ==-NQ==-3-bWVzaA==-aW5zdGFuY2U=-L2FwaS92MS9oZWFsdGg=-ZXhhbXBsZS5jb206ODA4MA==-hogehoge";
+    let res = decode_propagation(data);
+
+    assert_eq!(res.is_err(), true);
+}
+
+#[test]
+fn invalid_sample() {
+    let data = "3-MQ==-NQ==-3-bWVzaA==-aW5zdGFuY2U=-L2FwaS92MS9oZWFsdGg=-ZXhhbXBsZS5jb206ODA4MA==";
+    let res = decode_propagation(data);
+
+    assert_eq!(res.is_err(), true);
+}
+
+#[test]
+fn basic_encode() {
+    let time_fetcher = MockTimeFetcher {};
+    let tc = TracingContext::default_internal(Arc::new(time_fetcher), "mesh", "instance");
+    let res = encode_propagation(&tc, "/api/v1/health", "example.com:8080");
+    let res2 = decode_propagation(&res).unwrap();
+    assert_eq!(true, res2.do_sample);
+    assert_eq!("/api/v1/health", res2.destination_endpoint);
+    assert_eq!("example.com:8080", res2.destination_address)
+}
diff --git a/tests/trace_context.rs b/tests/trace_context.rs
new file mode 100644
index 0000000..eea0d0a
--- /dev/null
+++ b/tests/trace_context.rs
@@ -0,0 +1,224 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#![allow(unused_imports)]
+
+pub mod skywalking_proto {
+    pub mod v3 {
+        tonic::include_proto!("skywalking.v3");
+    }
+}
+
+use prost::Message;
+use skywalking_proto::v3::{
+    KeyStringValuePair, Log, RefType, SegmentObject, SegmentReference, SpanLayer, SpanObject,
+    SpanType,
+};
+use skywalking_rust::common::time::TimeFetcher;
+use skywalking_rust::context::propagation::context::PropagationContext;
+use skywalking_rust::context::propagation::decoder::decode_propagation;
+use skywalking_rust::context::propagation::encoder::encode_propagation;
+use skywalking_rust::context::trace_context::TracingContext;
+use std::{cell::Ref, sync::Arc};
+
+/// Serialize from A should equal Serialize from B
+#[allow(dead_code)]
+pub fn check_serialize_equivalent<M, N>(msg_a: &M, msg_b: &N)
+where
+    M: Message + Default + PartialEq,
+    N: Message + Default + PartialEq,
+{
+    let mut buf_a = Vec::new();
+    msg_a.encode(&mut buf_a).unwrap();
+    let mut buf_b = Vec::new();
+    msg_b.encode(&mut buf_b).unwrap();
+    assert_eq!(buf_a, buf_b);
+}
+
+struct MockTimeFetcher {}
+
+impl TimeFetcher for MockTimeFetcher {
+    fn get(&self) -> i64 {
+        100
+    }
+}
+
+#[test]
+fn create_span() {
+    let time_fetcher = MockTimeFetcher {};
+    let mut context =
+        TracingContext::default_internal(Arc::new(time_fetcher), "service", "instance");
+    assert_eq!(context.service, "service");
+    assert_eq!(context.service_instance, "instance");
+
+    {
+        let mut span1 = context.create_entry_span("op1").unwrap();
+        let mut logs = Vec::<(&str, &str)>::new();
+        logs.push(("hoge", "fuga"));
+        logs.push(("hoge2", "fuga2"));
+        let expected_log_message = logs
+            .to_owned()
+            .into_iter()
+            .map(|v| {
+                let (key, value) = v;
+                KeyStringValuePair {
+                    key: key.to_string(),
+                    value: value.to_string(),
+                }
+            })
+            .collect();
+        let mut expected_log = Vec::<Log>::new();
+        expected_log.push(Log {
+            time: 100,
+            data: expected_log_message,
+        });
+        span1.add_log(logs);
+
+        let mut tags = Vec::<(&str, &str)>::new();
+        tags.push(("hoge", "fuga"));
+        let expected_tags = tags
+            .to_owned()
+            .into_iter()
+            .map(|v| {
+                let (key, value) = v;
+                KeyStringValuePair {
+                    key: key.to_string(),
+                    value: value.to_string(),
+                }
+            })
+            .collect();
+        span1.add_tag(tags[0].clone());
+
+        let span1_expected = SpanObject {
+            span_id: 1,
+            parent_span_id: 0,
+            start_time: 100,
+            end_time: 100,
+            refs: Vec::<SegmentReference>::new(),
+            operation_name: "op1".to_string(),
+            peer: String::default(),
+            span_type: SpanType::Entry as i32,
+            span_layer: SpanLayer::Http as i32,
+            component_id: 11000,
+            is_error: false,
+            tags: expected_tags,
+            logs: expected_log,
+            skip_analysis: false,
+        };
+        context.finalize_span_for_test(&mut span1);
+        check_serialize_equivalent(span1.span_object(), &span1_expected);
+    }
+
+    {
+        let span2 = context.create_entry_span("op2");
+        assert_eq!(span2.is_err(), true);
+    }
+
+    {
+        let mut span3 = context.create_exit_span("op3", "example.com/test").unwrap();
+        let span3_expected = SpanObject {
+            span_id: 2,
+            parent_span_id: 1,
+            start_time: 100,
+            end_time: 100,
+            refs: Vec::<SegmentReference>::new(),
+            operation_name: "op3".to_string(),
+            peer: "example.com/test".to_string(),
+            span_type: SpanType::Exit as i32,
+            span_layer: SpanLayer::Http as i32,
+            component_id: 11000,
+            is_error: false,
+            tags: Vec::<KeyStringValuePair>::new(),
+            logs: Vec::<Log>::new(),
+            skip_analysis: false,
+        };
+        context.finalize_span_for_test(&mut span3);
+        check_serialize_equivalent(span3.span_object(), &span3_expected);
+    }
+
+    let segment = context.convert_segment_object();
+    assert_eq!(segment.trace_id.len() != 0, true);
+    assert_eq!(segment.trace_segment_id.len() != 0, true);
+    assert_eq!(segment.service, "service");
+    assert_eq!(segment.service_instance, "instance");
+    assert_eq!(segment.is_size_limited, false);
+}
+
+#[test]
+fn create_span_from_context() {
+    let data = "1-MQ==-NQ==-3-bWVzaA==-aW5zdGFuY2U=-L2FwaS92MS9oZWFsdGg=-ZXhhbXBsZS5jb206ODA4MA==";
+    let prop = decode_propagation(data).unwrap();
+    let time_fetcher = MockTimeFetcher {};
+    let context = TracingContext::from_propagation_context_internal(
+        Arc::new(time_fetcher),
+        "service2",
+        "instance2",
+        prop,
+    );
+
+    let segment = context.convert_segment_object();
+    assert_eq!(segment.trace_id.len() != 0, true);
+    assert_eq!(segment.trace_segment_id.len() != 0, true);
+    assert_eq!(segment.service, "service2");
+    assert_eq!(segment.service_instance, "instance2");
+    assert_eq!(segment.is_size_limited, false);
+}
+
+#[test]
+fn crossprocess_test() {
+    let time_fetcher1 = MockTimeFetcher {};
+    let mut context1 =
+        TracingContext::default_internal(Arc::new(time_fetcher1), "service", "instance");
+    assert_eq!(context1.service, "service");
+    assert_eq!(context1.service_instance, "instance");
+
+    let mut span1 = context1.create_entry_span("op1").unwrap();
+    context1.finalize_span_for_test(&mut span1);
+
+    let mut span2 = context1.create_exit_span("op2", "remote_peer").unwrap();
+    context1.finalize_span_for_test(&mut span2);
+
+    let enc_prop = encode_propagation(&context1, "endpoint", "address");
+    let dec_prop = decode_propagation(&enc_prop).unwrap();
+
+    let time_fetcher2 = MockTimeFetcher {};
+    let mut context2 = TracingContext::from_propagation_context_internal(
+        Arc::new(time_fetcher2),
+        "service2",
+        "instance2",
+        dec_prop,
+    );
+
+    let mut span3 = context2.create_entry_span("op2").unwrap();
+    context2.finalize_span_for_test(&mut span3);
+
+    assert_eq!(span3.span_object().span_id, 1);
+    assert_eq!(span3.span_object().parent_span_id, 0);
+    assert_eq!(span3.span_object().refs.len(), 1);
+
+    let expected_ref = SegmentReference {
+        ref_type: RefType::CrossProcess as i32,
+        trace_id: context2.trace_id,
+        parent_trace_segment_id: context1.trace_segment_id,
+        parent_span_id: context1.next_span_id,
+        parent_service: context1.service,
+        parent_service_instance: context1.service_instance,
+        parent_endpoint: "endpoint".to_string(),
+        network_address_used_at_peer: "address".to_string(),
+    };
+
+    check_serialize_equivalent(&expected_ref, &span3.span_object().refs[0]);
+}