Finish the basic structure of nginx.conf
diff --git a/examples/nginx.conf b/examples/nginx.conf
index 8540267..84feefc 100644
--- a/examples/nginx.conf
+++ b/examples/nginx.conf
@@ -33,6 +33,9 @@
     server {
         listen 8080;
 
+        # This is for local dev only, please do not add this in any production env.
+        lua_code_cache off;
+
         location /ingress {
             default_type text/html;
             rewrite_by_lua_block {
@@ -50,19 +53,46 @@
                 end
 
                 local contextCarrier = {}
-                local exitSpan = tracingContext:createExitSpan("exit_op", nil, "127.0.0.1", contextCarrier)
+                contextCarrier["sw6"] = ngx.req.get_headers()["sw6"]
+                local entrySpan = tracingContext:createEntrySpan(ngx.var.uri, nil, contextCarrier)
+                entrySpan:start(ngx.now())
+                
+                contextCarrier = {}
+                -- Use the same URI to represent incoming and forwarding requests
+                -- Change it if you need.
+                local upstreamUri = ngx.var.uri
+                -- This variable represents the upstream logic address
+                -- Please set them as service logic name or DNS name
+                local upstreamServerName = "upstream_ip:port"
+                local exitSpan = tracingContext:createExitSpan(upstreamUri, entrySpan, upstreamServerName, contextCarrier)
+                entrySpan:start(ngx.now())
+                
                 for name, value in pairs(contextCarrier) do
                     ngx.req.set_header(name, value)
                 end
 
                 -- Push the data in the context
+                ngx.ctx.tracingContext = tracingContext
+                ngx.ctx.entrySpan = entrySpan
                 ngx.ctx.exitSpan = exitSpan
             }
 
             proxy_pass http://127.0.0.1:8080/backend;
 
             body_filter_by_lua_block {
-                ngx.log(ngx.ERR, 'span exist? ' .. ngx.ctx.exitSpan.span_id)
+                -- Finish the exit span when received the first response package from upstream
+                if ngx.ctx.exitSpan ~= nil then
+                    ngx.ctx.exitSpan:finish()
+                    ngx.ctx.exitSpan = nil
+                end
+            }
+
+            log_by_lua_block {
+                if ngx.ctx.entrySpan ~= nil then
+                    ngx.ctx.entrySpan:finish()
+                    local status, segment = ngx.ctx.tracingContext:drainAfterFinished()
+                    ngx.log(ngx.ERR, 'span exist? ' .. segment.spans[1].start_time)
+                end
             }
         }
 
diff --git a/lib/skywalking/segment.lua b/lib/skywalking/segment.lua
new file mode 100644
index 0000000..3b64229
--- /dev/null
+++ b/lib/skywalking/segment.lua
@@ -0,0 +1,36 @@
+-- 
+-- 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.
+-- 
+
+-- Segment represents a finished tracing context
+-- Including all information to send to the SkyWalking OAP server.
+
+local Segment = {
+    trace_id,
+    segment_id,
+    service_inst_id,
+    spans,
+}
+
+function Segment:new()
+    local o = {}
+    setmetatable(o, self)
+    self.__index = self
+
+    return o
+end
+
+return Segment
\ No newline at end of file
diff --git a/lib/skywalking/span.lua b/lib/skywalking/span.lua
index 9f66ec2..deffd50 100644
--- a/lib/skywalking/span.lua
+++ b/lib/skywalking/span.lua
@@ -163,12 +163,39 @@
 end
 
 ---- All belowing are instance methods
-function Span:finish()
+
+-- Set start time explicitly
+function Span:start(startTime)
     if self.is_noop then
         return self
     end
 
-    self.end_time = Util.timestamp()
+    self.start_time = startTime
+
+    return self
+end
+
+function Span:finishWithDuration(duration)
+    if self.is_noop then
+        return self
+    end
+
+    self:finish(self.start_time + duration)
+    
+    return self
+end
+
+-- @param endTime, optional.
+function Span:finish(endTime)
+    if self.is_noop then
+        return self
+    end
+
+    if endTime == nil then
+        self.end_time = Util.timestamp()
+    else
+        self.end_time = endTime
+    end
     self.owner.internal:finishSpan(self)
 
     return self
diff --git a/lib/skywalking/span_test.lua b/lib/skywalking/span_test.lua
index fea35a1..d005d44 100644
--- a/lib/skywalking/span_test.lua
+++ b/lib/skywalking/span_test.lua
@@ -104,6 +104,18 @@
         lu.assertEquals(span1.parent_span_id, -1)
         lu.assertEquals(span1.span_id, 0)
     end
+
+    function TestSpan:testProperties()
+        local context = TC:new(1)
+
+        local span1 = Span:new("operation_name", context, nil)
+        span1:start(1234567)
+        lu.assertEquals(span1.start_time, 1234567)
+        span1:finish(2222222)
+        lu.assertEquals(span1.end_time, 2222222)
+        span1:finishWithDuration(123)
+        lu.assertEquals(span1.end_time, 1234690)
+    end
 -- end TestSpan
 
 
diff --git a/lib/skywalking/tracing_context.lua b/lib/skywalking/tracing_context.lua
index c4dcc3d..52ff9b8 100644
--- a/lib/skywalking/tracing_context.lua
+++ b/lib/skywalking/tracing_context.lua
@@ -17,6 +17,7 @@
 
 local Util = require('util')
 local Span = require('span')
+local Segment = require('segment')
 
 local TracingContext = {
     trace_id,
@@ -97,14 +98,23 @@
 -- Notice, it is different with Java agent, a finished context is still able to recreate new span, and be checked as finished again.
 -- This gives the end user more flexibility. Unless it is a real reasonable case, don't call #drainAfterFinished multiple times.
 -- 
--- Return (boolean isSegmentFinished, list SpanList). 
--- SpanList has value only when the isSegmentFinished is true
+-- Return (boolean isSegmentFinished, Segment segment). 
+-- Segment has value only when the isSegmentFinished is true
 -- if isSegmentFinished == false, SpanList = nil
 function TracingContext:drainAfterFinished()
+    if self.is_noop then
+        return true, Segment:new()
+    end
+
     if self.internal.active_count ~= 0 then
         return false, nil
     else
-        return true, self.internal.finished_spans
+        local segment = Segment:new()
+        segment.trace_id = self.trace_id
+        segment.segment_id = self.segment_id
+        segment.service_inst_id = self.service_inst_id
+        segment.spans = self.internal.finished_spans
+        return true, segment
     end
 end
 
@@ -158,7 +168,7 @@
     -- span id starts at 0, to fit LUA, we need to plus one.
     self.active_spans[span.span_id + 1] = nil
     self.active_count = self.active_count - 1
-    table.insert(self.finished_spans, span)
+    self.finished_spans[#self.finished_spans + 1] = span
 
     return self.owner
 end
diff --git a/lib/skywalking/tracing_context_test.lua b/lib/skywalking/tracing_context_test.lua
index d665850..50f127f 100644
--- a/lib/skywalking/tracing_context_test.lua
+++ b/lib/skywalking/tracing_context_test.lua
@@ -66,9 +66,9 @@
         lu.assertEquals(#(activeSpans), 0)
         lu.assertEquals(#(finishedSpans), 2)
 
-        local isSegmentFinished, spanList = context:drainAfterFinished()
-        lu.assertEquals(span2, spanList[1])
-        lu.assertEquals(span1, spanList[2])
+        local isSegmentFinished, segment = context:drainAfterFinished()
+        lu.assertEquals(span2, segment.spans[1])
+        lu.assertEquals(span1, segment.spans[2])
     end
 
     function TestTracingContext:testNewNoOP()