Add a new dependency for random. ID provided for trace and segment.
diff --git a/Cargo.lock b/Cargo.lock
index 69a500f..afa77c2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,5 +1,93 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
 [[package]]
+name = "c2-chacha"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb"
+dependencies = [
+ "ppv-lite86",
+]
+
+[[package]]
+name = "cfg-if"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
+
+[[package]]
+name = "getrandom"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.67"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
+
+[[package]]
+name = "rand"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
+dependencies = [
+ "getrandom",
+ "libc",
+ "rand_chacha",
+ "rand_core",
+ "rand_hc",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853"
+dependencies = [
+ "c2-chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
 name = "skywalking-core"
 version = "0.1.0"
+dependencies = [
+ "rand",
+]
+
+[[package]]
+name = "wasi"
+version = "0.9.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
diff --git a/tracing-core/Cargo.toml b/tracing-core/Cargo.toml
index ca95634..8010bb8 100644
--- a/tracing-core/Cargo.toml
+++ b/tracing-core/Cargo.toml
@@ -6,4 +6,5 @@
 description = "SkyWalking Rust Agent provides observability capability for Rust App and Library, including tracing, metrics, topology map for distributed system and alert."
 license = "Apache 2.0"
 
-[dependencies]
\ No newline at end of file
+[dependencies]
+rand = "0.7.3"
\ No newline at end of file
diff --git a/tracing-core/src/id.rs b/tracing-core/src/id.rs
new file mode 100644
index 0000000..b7b81a2
--- /dev/null
+++ b/tracing-core/src/id.rs
@@ -0,0 +1,102 @@
+use std::hash::Hash;
+use std::thread;
+use std::time::SystemTime;
+
+use rand::{Rng, 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) -> Option<Self> {
+        let strings: Vec<&str> = id_text.split(".").collect();
+        if strings.len() == 3 {
+            let part1 = strings[0].parse::<i64>();
+            if part1.is_err() { return None; }
+            let part2 = strings[1].parse::<i64>();
+            if part2.is_err() { return None; }
+            let part3 = strings[2].parse::<i64>();
+            if part3.is_err() { return None; }
+            Some(ID::new(part1.unwrap(), part2.unwrap(), part3.unwrap()))
+        } else {
+            None
+        }
+    }
+}
+
+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::ID;
+    use crate::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_eq!(id5_none == None, true);
+
+        let id6_illegal = ID::from(String::from("1.2.a"));
+        assert_eq!(id6_illegal == None, true);
+    }
+}
\ No newline at end of file
diff --git a/tracing-core/src/lib.rs b/tracing-core/src/lib.rs
index 71be014..be6a9ef 100644
--- a/tracing-core/src/lib.rs
+++ b/tracing-core/src/lib.rs
@@ -1,9 +1,12 @@
+pub use context::Context;
+pub use context::TracingContext;
+pub use id::ID;
+pub use span::Span;
+pub use span::TracingSpan;
+pub use tag::Tag;
+
 pub mod span;
 pub mod context;
 pub mod tag;
+pub mod id;
 
-pub use context::TracingContext;
-pub use context::Context;
-pub use span::TracingSpan;
-pub use span::Span;
-pub use tag::Tag;
\ No newline at end of file
diff --git a/tracing-core/src/span.rs b/tracing-core/src/span.rs
index a69135c..623783e 100644
--- a/tracing-core/src/span.rs
+++ b/tracing-core/src/span.rs
@@ -176,8 +176,8 @@
     fn test_span_with_tags() {
         let context = TracingContext::new();
         let mut span = TracingSpan::new_entry_span(String::from("op1"), 0, 1);
-        span.tag(Tag::New(String::from("tag1"), String::from("value1")));
-        span.tag(Tag::New(String::from("tag2"), String::from("value2")));
+        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);
diff --git a/tracing-core/src/tag.rs b/tracing-core/src/tag.rs
index d51c96b..112aebb 100644
--- a/tracing-core/src/tag.rs
+++ b/tracing-core/src/tag.rs
@@ -1,11 +1,11 @@
-#[derive(Clone)]
+#[derive(Clone, Hash)]
 pub struct Tag {
     key: String,
     value: String,
 }
 
 impl Tag {
-    pub fn New(key: String, value: String) -> Self {
+    pub fn new(key: String, value: String) -> Self {
         Tag {
             key,
             value,
@@ -27,7 +27,7 @@
 
     #[test]
     fn test_tag_new() {
-        let tag = Tag::New(String::from("tag_key"), String::from("tag_value"));
+        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();