diff --git a/common/context.go b/common/context.go
index 7f9294cced677d25c1d985fe1480923df3606bbf..83447401c056ecd374020875dbb69aa47d2fe9eb 100644
--- a/common/context.go
+++ b/common/context.go
@@ -25,6 +25,9 @@ type Context struct {
 	context.Context
 }
 
-func NewContext() *Context {
-	return &Context{Context: context.Background()}
+func NewContext() Context {
+	return NewContextWith(context.Background())
+}
+func NewContextWith(ctx context.Context) Context {
+	return Context{Context: ctx}
 }
diff --git a/filter/filter_impl/tracing_filter.go b/filter/filter_impl/tracing_filter.go
index 5153e28a0959a3829fa872560cb661a08a64447c..3289002e06c2695ce065e534afc7f8d09ba27186 100644
--- a/filter/filter_impl/tracing_filter.go
+++ b/filter/filter_impl/tracing_filter.go
@@ -21,7 +21,9 @@ import (
 	"context"
 
 	"github.com/opentracing/opentracing-go"
+	"github.com/opentracing/opentracing-go/log"
 
+	"github.com/apache/dubbo-go/common"
 	"github.com/apache/dubbo-go/common/extension"
 	"github.com/apache/dubbo-go/filter"
 	"github.com/apache/dubbo-go/protocol"
@@ -31,22 +33,38 @@ const (
 	tracingFilterName = "tracing"
 )
 
+// this should be executed before users set their own Tracer
 func init() {
 	extension.SetFilter(tracingFilterName, NewTracingFilter)
+	opentracing.SetGlobalTracer(opentracing.NoopTracer{})
 }
 
+var (
+	errorKey   = "ErrorMsg"
+	successKey = "Success"
+)
+
 type TracingFilter struct {
 }
 
 func (tf *TracingFilter) Invoke(invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
 
-	// invoker.GetUrl().Context()
-
 	operationName := invoker.GetUrl().ServiceKey() + invocation.MethodName()
+	// withTimeout after we support the timeout between different ends.
+	invCtx, cancel := context.WithCancel(invocation.Context())
+	span, spanCtx := opentracing.StartSpanFromContext(invCtx, operationName)
+	invocation.SetContext(common.NewContextWith(spanCtx))
+	defer func() {
+		span.Finish()
+		cancel()
+	}()
 
-	span, ctx := opentracing.StartSpanFromContext(invocation.Context(), operationName)
-
-	defer span.Finish()
+	result := invoker.Invoke(invocation)
+	span.SetTag(successKey, result.Error() != nil)
+	if result.Error() != nil {
+		span.LogFields(log.String(errorKey, result.Error().Error()))
+	}
+	return result
 }
 
 func (tf *TracingFilter) OnResponse(result protocol.Result, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
diff --git a/protocol/invocation.go b/protocol/invocation.go
index e8da7023b0c0c037d4ff42fbbbdd06fb912d5f4b..e2d03ac5aaf21e4a7568fa4552c5ec2cbbb54d75 100644
--- a/protocol/invocation.go
+++ b/protocol/invocation.go
@@ -32,5 +32,6 @@ type Invocation interface {
 	Attachments() map[string]string
 	AttachmentsByKey(string, string) string
 	Invoker() Invoker
-	Context() *common.Context
+	Context() common.Context
+	SetContext(ctx common.Context)
 }
diff --git a/protocol/invocation/rpcinvocation.go b/protocol/invocation/rpcinvocation.go
index 9912d795ee8ae77c002eb4263e88a68b3c474ee5..0c5b186af07c0d393ef03b18bbb076e7c383a1e0 100644
--- a/protocol/invocation/rpcinvocation.go
+++ b/protocol/invocation/rpcinvocation.go
@@ -41,7 +41,7 @@ type RPCInvocation struct {
 	attachments    map[string]string
 	invoker        protocol.Invoker
 	lock           sync.RWMutex
-	ctx            *common.Context
+	ctx            common.Context
 }
 
 func NewRPCInvocation(methodName string, arguments []interface{}, attachments map[string]string) *RPCInvocation {
@@ -125,11 +125,11 @@ func (r *RPCInvocation) SetCallBack(c interface{}) {
 	r.callBack = c
 }
 
-func (r *RPCInvocation) Context() *common.Context {
+func (r *RPCInvocation) Context() common.Context {
 	return r.ctx
 }
 
-func (r *RPCInvocation) SetContext(ctx *common.Context) {
+func (r *RPCInvocation) SetContext(ctx common.Context) {
 	r.ctx = ctx
 }