Set up basic codes and CI.
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
new file mode 100644
index 0000000..a198b6c
--- /dev/null
+++ b/.github/workflows/ci.yaml
@@ -0,0 +1,29 @@
+name: CI AND IT
+
+on:
+  pull_request:
+  push:
+    branches:
+      - master
+    tags:
+      - 'v*'
+
+
+jobs:
+  CI:
+    runs-on: ubuntu-18.04
+    timeout-minutes: 180
+    strategy:
+      fail-fast: true
+    steps:
+      - uses: actions/checkout@v1
+        with:
+          submodules: true
+      - uses: actions-rs/cargo@v1
+        with:
+          command: build
+          args: --release --all-features
+      - name: 'Install & Test'
+        run: |
+          cargo build
+          cargo test
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..07827cc
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+target/
+.idea/
\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..69a500f
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,5 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "skywalking-core"
+version = "0.1.0"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..007e2b9
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,5 @@
+[workspace]
+
+members = [
+    "tracing-core",
+]
\ No newline at end of file
diff --git a/README.md b/README.md
index ad3629d..205f5e9 100644
--- a/README.md
+++ b/README.md
@@ -8,8 +8,9 @@
 ![CI](https://github.com/apache/skywalking-nginx-lua/workflows/CI/badge.svg?branch=master)
 
 
-[**SkyWalking**](https://github.com/apache/skywalking) Rust Agent provides tracing and metrics capability for Rust App and Library.
-It uses SkyWalking native formats and core concepts.
+[**SkyWalking**](https://github.com/apache/skywalking) Rust Agent provides observability capability for Rust App and Library, 
+including tracing, metrics, topology map for distributed system and alert.
+It uses SkyWalking native formats and core concepts to keep best compatibility and performance.
 
 # License
 Apache 2.0 
\ No newline at end of file
diff --git a/tracing-core/Cargo.toml b/tracing-core/Cargo.toml
new file mode 100644
index 0000000..ca95634
--- /dev/null
+++ b/tracing-core/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "skywalking-core"
+version = "0.1.0"
+authors = ["Apache Software Foundation (ASF)"]
+edition = "2018"
+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
diff --git a/tracing-core/src/context.rs b/tracing-core/src/context.rs
new file mode 100644
index 0000000..17a43c4
--- /dev/null
+++ b/tracing-core/src/context.rs
@@ -0,0 +1,46 @@
+use crate::{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<'a> {
+    /// Fetch the next id for new span
+    fn next_span_id(&mut self) -> i32;
+    fn create_entry_span(&mut self, operation_name: String, parent: Option<&dyn Span>) -> Box<dyn Span>;
+    fn create_exit_span(&mut self, operation_name: String, parent: Option<&dyn Span>) -> Box<dyn Span>;
+    fn create_local_span(&mut self, operation_name: String, parent: Option<&dyn Span>) -> Box<dyn Span>;
+}
+
+pub struct TracingContext {
+    /// Span id sequence. Indicate the number of created spans.
+    next_seq: i32,
+}
+
+impl TracingContext {
+    /// Create a new instance
+    pub fn new() -> Self {
+        TracingContext {
+            next_seq: -1
+        }
+    }
+}
+
+/// Default implementation of Context
+impl<'a> Context<'a> for TracingContext {
+    /// Fetch the next id for new span
+    fn next_span_id(&mut self) -> i32 {
+        self.next_seq = self.next_seq + 1;
+        self.next_seq
+    }
+
+    fn create_entry_span(&mut self, operation_name: String, parent: Option<&dyn Span>) -> Box<dyn Span> {
+        TracingSpan::new_entry_span(operation_name, self, parent)
+    }
+
+    fn create_exit_span(&mut self, operation_name: String, parent: Option<&dyn Span>) -> Box<dyn Span> {
+        TracingSpan::new_exit_span(operation_name,  self, parent)
+    }
+
+    fn create_local_span(&mut self, operation_name: String, parent: Option<&dyn Span>) -> Box<dyn Span> {
+        TracingSpan::new_local_span(operation_name,  self, parent)
+    }
+}
\ No newline at end of file
diff --git a/tracing-core/src/lib.rs b/tracing-core/src/lib.rs
new file mode 100644
index 0000000..4be7dcb
--- /dev/null
+++ b/tracing-core/src/lib.rs
@@ -0,0 +1,7 @@
+pub mod span;
+pub mod context;
+
+pub use span::TracingSpan;
+pub use span::Span;
+pub use context::TracingContext;
+pub use context::Context;
\ No newline at end of file
diff --git a/tracing-core/src/span.rs b/tracing-core/src/span.rs
new file mode 100644
index 0000000..c429e0c
--- /dev/null
+++ b/tracing-core/src/span.rs
@@ -0,0 +1,131 @@
+use std::time::SystemTime;
+
+use crate::Context;
+
+/// Span is one of the tracing concept, representing a time duration.
+/// Typically, it represent a method invocation or a RPC.
+pub trait Span {
+    fn start(&mut self);
+    fn start_with_timestamp(&mut self, timestamp: SystemTime);
+    fn is_entry(&self) -> bool;
+    fn is_exit(&self) -> bool;
+    fn span_id(&self) -> i32;
+}
+
+pub struct TracingSpan {
+    /// The operation name represents the logic process of this span
+    operation_name: String,
+    span_id: i32,
+    paren_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,
+}
+
+impl TracingSpan {
+    /// Create a new entry span
+    pub fn new_entry_span(operation_name: String, context: &mut dyn Context, parent: Option<&dyn Span>) -> Box<dyn Span> {
+        let mut span = TracingSpan::_new(operation_name, context, parent);
+        span.is_entry = true;
+        Box::new(span)
+    }
+
+    /// Create a new exit span
+    pub fn new_exit_span(operation_name: String, context: &mut dyn Context, parent: Option<&dyn Span>) -> Box<dyn Span> {
+        let mut span = TracingSpan::_new(operation_name, context, parent);
+        span.is_exit = true;
+        Box::new(span)
+    }
+
+    /// Create a new local span
+    pub fn new_local_span(operation_name: String, context: &mut dyn Context, parent: Option<&dyn Span>) -> Box<dyn Span> {
+        let span = TracingSpan::_new(operation_name, context, parent);
+        Box::new(span)
+    }
+
+    /// Create a span and set the limited internal values
+    fn _new(operation_name: String, context: &mut dyn Context, parent: Option<&Span>) -> Self {
+        TracingSpan {
+            operation_name: operation_name.clone(),
+            span_id: context.next_span_id(),
+            paren_span_id: match parent {
+                // -1 means no parent span
+                None => { -1 }
+                Some(parent) => { parent.span_id() }
+            },
+            start_time: 0,
+            end_time: 0,
+            is_entry: false,
+            is_exit: false,
+        }
+    }
+}
+
+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 is_entry(&self) -> bool {
+        self.is_entry
+    }
+
+    fn is_exit(&self) -> bool {
+        self.is_exit
+    }
+
+    fn span_id(&self) -> i32 {
+        self.span_id
+    }
+}
+
+#[cfg(test)]
+mod span_tests {
+    use std::time::SystemTime;
+
+    use crate::span::*;
+    use crate::TracingContext;
+
+    #[test]
+    fn test_span_new() {
+        let mut context = TracingContext::new();
+        let mut span = TracingSpan::_new(String::from("op1"), &mut context, None);
+        assert_eq!(span.paren_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(String::from("op2"), &mut context, Some(&span));
+        assert_eq!("op2", span2.operation_name);
+        assert_eq!(span2.paren_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 mut context = TracingContext::new();
+        let mut span = TracingSpan::new_entry_span(String::from("op1"), &mut context, None);
+        assert_eq!(span.is_entry(), true)
+    }
+}
+
+
+