Repository: pinpoint-apm/pinpoint-c-agent (language: python)

Issue:
[BUG] No call chain when python application call MySql
## Bug

> what is it ?

 No call chain when python application call MySql

> how to reproduce 

1. call Mysql
2. check Pinpoint Web

![1711530110](https://github.com/pinpoint-apm/pinpoint-c-agent/assets/72844069/f47d73aa-5a12-49b2-b4f3-91fd79192c51)


![1711529667](https://github.com/pinpoint-apm/pinpoint-c-agent/assets/72844069/a753cf55-f39b-47ec-afea-81ff1ac6bbcc)
  
> expected result:


![1711528190](https://github.com/pinpoint-apm/pinpoint-c-agent/assets/72844069/9ad6ff8b-e687-49eb-a626-6d7d3d85e4bc)

remove unique id at agent
**Is your feature request related to a problem? Please describe.**

There is no need to store unique-id at agent side, try to move to collector-agent side.

**Describe the solution you'd like**

pass connect_time to agent, then agent uses it as start_time in TID.

![image](https://github.com/pinpoint-apm/pinpoint-c-agent/assets/27064129/2aad86cb-39f2-43bf-a246-ae0d93abf732)



**Additional context**
- https://github.com/pinpoint-apm/pinpoint-c-agent/issues/570
[Task] support windows python
## Background

pinpointpy , does not working on windows. That's a pity ! 

## Solutions

- remove unique id at agent
- try build-wheels on windows 

## Tasks

> steps

- [x] #581
- [x] #569
- [x] CI
- [x]  cibuildwheel release



## PRs



Discussion / hints:


This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.
This issue was closed because it has been stalled for 5 days with no activity.
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.
This issue was closed because it has been stalled for 5 days with no activity.

Fix patch:
diff --git a/.clang-format b/.clang-format
deleted file mode 100644
index b66517444..000000000
--- a/.clang-format
+++ /dev/null
@@ -1,15 +0,0 @@
----
-Language:        Cpp
-AccessModifierOffset: -2
-ColumnLimit: 100
-DerivePointerAlignment: false
-PointerAlignment: Left
-SortIncludes: false
-TypenameMacros: ['STACK_OF']
-
----
-Language: Proto
-ColumnLimit: 100
-SpacesInContainerLiterals: false
-AllowShortFunctionsOnASingleLine: false
-ReflowComments: false
\ No newline at end of file
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index efa31fa16..83c2da584 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -41,6 +41,7 @@
         "formulahendry.vscode-mysql",
         "ms-python.autopep8",
         "streetsidesoftware.code-spell-checker",
-        "jeff-hykin.better-dockerfile-syntax"
+        "jeff-hykin.better-dockerfile-syntax",
+        "cschlosser.doxdocgen"
     ]
 }
\ No newline at end of file
diff --git a/.github/workflows/build-wheels.yml b/.github/workflows/build-wheels.yml
index d79ad4f06..fa3e9f292 100644
--- a/.github/workflows/build-wheels.yml
+++ b/.github/workflows/build-wheels.yml
@@ -1,6 +1,6 @@
 name: build-wheels
 
-on: 
+on:
   workflow_dispatch:
     inputs:
       release-testpypi:
@@ -16,72 +16,69 @@ on:
 
 jobs:
   build_wheels_pypitest:
-    name: Build wheels on ${{ matrix.os }}
+    name: Build test wheels on ${{ matrix.os }}
     runs-on: ${{ matrix.os }}
     if: ${{ inputs.release-testpypi }}
     strategy:
       matrix:
-        os: [ubuntu-20.04, macos-latest]
+        os: [ubuntu-latest, windows-latest, macos-13, macos-14]
 
     steps:
       - uses: actions/checkout@v4
 
-      # Used to host cibuildwheel
+      - name: rename file
+        run: |
+          cp setup_pypi_test.py setup.py
+
       - uses: actions/setup-python@v3
 
-      - name: set test version
-        run: |
-          rm setup.py
-          ln -s setup_pypi_test.py setup.py
+      - name: Set up QEMU
+        if: runner.os == 'Linux'
+        uses: docker/setup-qemu-action@v3
+        with:
+          platforms: all
 
-      # - name: Set up QEMU
-      #   if: runner.os == 'Linux'
-      #   uses: docker/setup-qemu-action@v3
-      #   with:
-      #     platforms: all
+      - name: Release dist
+        if: runner.os == 'Linux'
+        run: |
+          pip install build
+          python -m build -s --outdir wheelhouse
 
       - name: Install cibuildwheel
-        run: python -m pip install cibuildwheel==2.16.0
-
-      # - name: Build wheels
-      #   uses: pypa/cibuildwheel@v2.16.0
-      #   env:
-      #     # configure cibuildwheel to build native archs ('auto'), and some
-      #     # emulated ones
-      #     CIBW_ARCHS_LINUX: auto aarch64 ppc64le s390x
+        run: python -m pip install cibuildwheel
 
       - name: Build wheels
         run: python -m cibuildwheel --output-dir wheelhouse
-        # to supply options, put them in 'env', like:
         env:
-          CIBW_ARCHS_MACOS: "x86_64 arm64"
-          # CIBW_ARCHS_LINUX: "auto aarch64"
+          CIBW_ARCHS_LINUX: auto aarch64
+          CIBW_ARCHS_WINDOWS: ARM64 AMD64 x86
+          CIBW_ARCHS_MACOS: auto x86_64 arm64
 
       - uses: actions/upload-artifact@v3
         with:
           name: pypi_test
-          path: ./wheelhouse/*.whl
+          path: ./wheelhouse/*
 
   publish-pypitest:
     needs: build_wheels_pypitest
     runs-on: ubuntu-latest
     steps:
       - uses: actions/download-artifact@v3
-        with: 
+        with:
           name: pypi_test
           path: ./wheelhouse/
 
       - name: show all artifact
         run: |
           ls -R ./wheelhouse/
-  
+
       - name: Publish package to pypitest
         uses: pypa/gh-action-pypi-publish@release/v1
         with:
           user: __token__
           password: ${{ secrets.EELIUTEST }}
-          packages_dir: ./wheelhouse/  
-          repository_url: https://test.pypi.org/legacy/          
+          packages_dir: ./wheelhouse/
+          repository_url: https://test.pypi.org/legacy/
 
   build_wheels:
     name: Build wheels on ${{ matrix.os }}
@@ -89,58 +86,60 @@ jobs:
     if: ${{ inputs.release }}
     strategy:
       matrix:
-        os: [ubuntu-20.04, macos-latest]
+        os: [ubuntu-latest, windows-latest, macos-13, macos-14]
 
     steps:
       - uses: actions/checkout@v4
 
-      # Used to host cibuildwheel
+      - name: rename file
+        run: |
+          cp setup_pypi_test.py setup.py
+
       - uses: actions/setup-python@v3
 
-      # - name: Set up QEMU
-      #   if: runner.os == 'Linux'
-      #   uses: docker/setup-qemu-action@v3
-      #   with:
-      #     platforms: all
+      - name: Set up QEMU
+        if: runner.os == 'Linux'
+        uses: docker/setup-qemu-action@v3
+        with:
+          platforms: all
 
-      - name: Install cibuildwheel
-        run: python -m pip install cibuildwheel==2.16.0
+      - name: Release dist
+        if: runner.os == 'Linux'
+        run: |
+          pip install build
+          python -m build -s --outdir wheelhouse
 
-      # - name: Build wheels
-      #   uses: pypa/cibuildwheel@v2.16.0
-      #   env:
-      #     # configure cibuildwheel to build native archs ('auto'), and some
-      #     # emulated ones
-      #     CIBW_ARCHS_LINUX: auto aarch64 ppc64le s390x
+      - name: Install cibuildwheel
+        run: python -m pip install cibuildwheel
 
       - name: Build wheels
         run: python -m cibuildwheel --output-dir wheelhouse
-        # to supply options, put them in 'env', like:
         env:
-          CIBW_ARCHS_MACOS: "x86_64 arm64"
-          # CIBW_ARCHS_LINUX: "auto aarch64"
+          CIBW_ARCHS_LINUX: auto aarch64
+          CIBW_ARCHS_WINDOWS: ARM64 AMD64 x86
+          CIBW_ARCHS_MACOS: auto x86_64 arm64
 
       - uses: actions/upload-artifact@v3
         with:
           name: pypi
-          path: ./wheelhouse/*.whl          
+          path: ./wheelhouse/*
 
   publish:
     needs: build_wheels
     runs-on: ubuntu-latest
     steps:
       - uses: actions/download-artifact@v3
-        with: 
+        with:
           name: pypi
           path: ./wheelhouse/
 
       - name: show all artifact
         run: |
           ls -R ./wheelhouse/
-  
+
       - name: Publish package to pypitest
         uses: pypa/gh-action-pypi-publish@release/v1
         with:
           user: __token__
           password: ${{ secrets.PINPOINTPY }}
-          packages_dir: ./wheelhouse/       
+          packages_dir: ./wheelhouse/
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 25279e0b4..dafe2a2d0 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -43,7 +43,7 @@ jobs:
 
     # Initializes the CodeQL tools for scanning.
     - name: Initialize CodeQL
-      uses: github/codeql-action/init@v1
+      uses: github/codeql-action/init@v2
       with:
         languages: ${{ matrix.language }}
         # If you wish to specify custom queries, you can do so here or in a config file.
@@ -54,7 +54,7 @@ jobs:
     # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
     # If this step fails, then you should remove it and run the build manually (see below)
     - name: Autobuild
-      uses: github/codeql-action/autobuild@v1
+      uses: github/codeql-action/autobuild@v2
 
     # ℹ️ Command-line programs to run using the OS shell.
     # 📚 https://git.io/JvXDl
@@ -68,4 +68,4 @@ jobs:
     #   make release
 
     - name: Perform CodeQL Analysis
-      uses: github/codeql-action/analyze@v1
+      uses: github/codeql-action/analyze@v2
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index ea71424ab..2aebdf21f 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -1,6 +1,6 @@
 name: CI
 
-on: [pull_request, workflow_dispatch]
+on: [pull_request, workflow_dispatch,push]
 
 jobs:
   cpp:
@@ -25,6 +25,26 @@ jobs:
       - name: Codecovage
         uses: codecov/codecov-action@v1
 
+  cpp-windows:
+    runs-on: [windows-latest]
+    steps:
+      - uses: actions/checkout@v2
+      # - name: actions-setup-cmake
+      #   uses: jwlawson/actions-setup-cmake@v1.14
+      #   with:
+      #     cmake-version: 'latest'
+
+      - name: powershell allow...
+        shell: cmd
+        run: powershell -Command "Set-ExecutionPolicy RemoteSigned -Scope CurrentUser"
+
+      - name: Build agent
+        run: |
+          cd common
+          cmake --no-warn-unused-cli -DWITH_TEST_CASE=1 -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -S. -B./build -G "Visual Studio 17 2022" -T host=x86 -A win32
+          cmake --build build --target ALL_BUILD --config debug --
+          ./build/bin/Debug/TestCommon.exe
+
   memory-leak:
     runs-on: ubuntu-latest
     steps:
@@ -74,7 +94,7 @@ jobs:
     strategy:
       matrix:
         # php-versions: ["7.0", "7.1", "7.2", "7.3", "7.4", "8.0"]
-        php-versions: ["7.4","8.0"]
+        php-versions: ["7.4", "8.0"]
     steps:
       - uses: actions/checkout@v2
       - uses: shivammathur/setup-php@v2
@@ -95,12 +115,12 @@ jobs:
           # composer install
           # cp tests/think .
           # php think unit -v
-          
+
   Python:
     strategy:
       matrix:
         os: [ubuntu-latest, macos-latest]
-        python-version: ["3.8","3.9","3.10","3.11"]
+        python-version: ["3.8", "3.9", "3.10", "3.11"]
     runs-on: ${{ matrix.os }}
     steps:
       - uses: actions/checkout@v2
@@ -119,14 +139,14 @@ jobs:
     steps:
       - uses: actions/checkout@v2
         with:
-          submodules: 'true'
+          submodules: "true"
       - name: update docker compose
         run: |
           wget "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-x86_64"
           chmod +x docker-compose-linux-x86_64
           ./docker-compose-linux-x86_64 version
-      # - name: build python-plugins
         # run: docker-compose  -f "testapps/compose.yaml" build python-plugins
+      # - name: build python-plugins
       - name: start test environment
         run: ./docker-compose-linux-x86_64 -f "testapps/compose.yaml" up python-plugins --exit-code-from python-plugins
       - name: Stop containers
@@ -146,13 +166,13 @@ jobs:
       - name: Checkout code
         uses: actions/checkout@v2
         with:
-          submodules: 'true'
+          submodules: "true"
 
       - name: Setup protoc
         uses: arduino/setup-protoc@v2.1.0
-      
+
       - run: |
           go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
           go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
           export PATH="$PATH:$(go env GOPATH)/bin"
-          cd collector-agent && make && go test ./... -v
\ No newline at end of file
+          cd collector-agent && make && go test ./... -v
diff --git a/.github/workflows/publish-build-env.yml b/.github/workflows/publish-build-env.yml
index f01d4f2a5..e61257c64 100644
--- a/.github/workflows/publish-build-env.yml
+++ b/.github/workflows/publish-build-env.yml
@@ -2,7 +2,6 @@ name: publish-build-env
 
 on: 
   release:
-    types: [workflow_dispatch]
   workflow_dispatch:
 
 
diff --git a/.gitignore b/.gitignore
index 5570f8bbb..91c98fdf0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -73,6 +73,7 @@ compile_commands.json
 testapps/PHP/composer-setup.php
 testapps/PHP/composer.phar
 wheelhouse/
-.clangd
 collector-agent/pinpoint-grpc-idl/
 *.so
+.clangd
+.vs
\ No newline at end of file
diff --git a/DOC/PY/Readme.md b/DOC/PY/Readme.md
index e0eb20681..a36c4c6d2 100644
--- a/DOC/PY/Readme.md
+++ b/DOC/PY/Readme.md
@@ -4,16 +4,15 @@
 
 > Requirement
 
-Dependency| Version| More
----|----|---
-python |3+ | (async must 3.7.1+)
-*inux|  | `windows` is on the way
-collector-agent| [installed ?](../collector-agent/readme.md)
+| Dependency      | Version                                     | More                |
+| --------------- | ------------------------------------------- | ------------------- |
+| python          | 3+                                          | (async must 3.7.1+) |
+| collector-agent | [installed ?](../collector-agent/readme.md) |
 
 ### Installation
 
 ```shell
-$ pip install pinpointPy==1.1.0
+$ pip install pinpointPy
 ```
 
 ### How to Use
@@ -68,7 +67,7 @@ middleware = [
     Middleware(ContextMiddleware),
     Middleware(PinPointMiddleWare)
 ]
-set_agent("cd.dev.test.py", "cd.dev.test.py", 'tcp:dev-collector:10000')
+set_agent("cd.dev.test.py", "cd.dev.test.py",0, 'tcp:dev-collector:10000')
 use_starlette_context()
 ## patch for synchronous libraries, such as requests,myql-connector-python ...
 # support lists https://github.com/pinpoint-apm/pinpoint-c-agent/tree/dev/plugins/PY/pinpointPy/libs
@@ -121,15 +120,15 @@ Todo....
 
 ### Case: flask/test_mysql
 
--|TPR(ms)|RPS(#/sec)
-----|-----|----
-pinpointPy|4.487|445.73|
--|4.498 |444.69
--|4.526 |441.88
-pure|4.440|450.44
--|4.479|446.51
--|4.425|451.96
-Result|+0.05ms|-1%
+| -          | TPR(ms) | RPS(#/sec) |
+| ---------- | ------- | ---------- |
+| pinpointPy | 4.487   | 445.73     |
+| -          | 4.498   | 444.69     |
+| -          | 4.526   | 441.88     |
+| pure       | 4.440   | 450.44     |
+| -          | 4.479   | 446.51     |
+| -          | 4.425   | 451.96     |
+| Result     | +0.05ms | -1%        |
 
 > TPR: time per request         
 > RPS: requests per second
diff --git a/MANIFEST.in b/MANIFEST.in
index a39f9303f..a49493abb 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,4 +1,4 @@
-#include *.txt README.md NOTICE LICENSE  MANIFEST.in
-#recursive-include common *.cmake *.h *.txt *.in *.cc *.c *.cpp *.h *.inl
-#recursive-include src/PY *.c *.h
-#recursive-include plugins/PY/ *.py
\ No newline at end of file
+include *.txt README.md NOTICE LICENSE  MANIFEST.in
+recursive-include common *.cmake *.h *.txt *.in *.c *.cpp *.h *.inl
+recursive-include src/PY *.cpp *.h
+recursive-include plugins/PY/ *.py
\ No newline at end of file
diff --git a/collector-agent/CHANGES.md b/collector-agent/CHANGES.md
new file mode 100644
index 000000000..e6c33a3fd
--- /dev/null
+++ b/collector-agent/CHANGES.md
@@ -0,0 +1,2 @@
+## [v0.5.0] start time in ms
+- return current time in ms
\ No newline at end of file
diff --git a/collector-agent/agent/AgentRouter.go b/collector-agent/agent/AgentRouter.go
index a585f8461..c6bd9d217 100644
--- a/collector-agent/agent/AgentRouter.go
+++ b/collector-agent/agent/AgentRouter.go
@@ -162,7 +162,7 @@ func (span *TSpan) GetAppid() string {
 	}
 }
 
-func (span *TSpan) GetAppname() string {
+func (span *TSpan) GetAppName() string {
 	if len(span.AppNameV2) > 0 {
 		return span.AppNameV2
 	} else {
@@ -199,16 +199,16 @@ func (manager *AgentRouter) createAgent(id, name string, agentType int32, startT
 	return &agent
 }
 
-func GetAgentInfo(span *TSpan) (appid, appname string, appServerType int32, startTime string, err error) {
+func GetAgentInfo(span *TSpan) (appid, name string, appServerType int32, startTime string, err error) {
 
 	// new feat: get current startTime
 	startTime = strconv.FormatInt(common.GetConfig().StartTime, 10) + "000"
 	holder := strings.Split(span.TransactionId, "^")
 	if len(holder) < 3 {
 		log.Warn("tid in wrong format")
-	} else if len(holder[1]) == 10 { // seconds format
+	} else if len(holder[1]) <= 10 { // seconds format
 		startTime = holder[1] + "000"
-	} else { // miliseconds format
+	} else { // milliseconds format
 		startTime = holder[1]
 	}
 
@@ -217,10 +217,10 @@ func GetAgentInfo(span *TSpan) (appid, appname string, appServerType int32, star
 		return "", "", 0, "", errors.New("no appid")
 	}
 
-	appname = span.GetAppname()
+	name = span.GetAppName()
 
-	if len(appname) == 0 {
-		return "", "", 0, "", errors.New("no appname")
+	if len(name) == 0 {
+		return "", "", 0, "", errors.New("no appName")
 	}
 
 	appServerType = span.GetAppServerType()
@@ -229,7 +229,7 @@ func GetAgentInfo(span *TSpan) (appid, appname string, appServerType int32, star
 		return "", "", 0, "", errors.New("no AppServerType(FT)")
 	}
 
-	return appid, appname, appServerType, startTime, nil
+	return appid, name, appServerType, startTime, nil
 }
 
 func (manager *AgentRouter) DispatchPacket(packet *RawPacket) error {
@@ -241,10 +241,10 @@ func (manager *AgentRouter) DispatchPacket(packet *RawPacket) error {
 
 	if err := json.Unmarshal(packet.RawData, span); err != nil {
 		log.Warnf("json.Unmarshal err:%v", err)
-		goto PACKET_INVALIED
+		goto PACKET_INVALID
 	}
 
-	if appid, appname, serverType, startTime, err := GetAgentInfo(span); err == nil {
+	if appid, appName, serverType, startTime, err := GetAgentInfo(span); err == nil {
 		manager.rwMutex.RLock()
 		log.Debug("Read-lock is holding")
 		agent, OK := manager.AgentMap[appid]
@@ -258,7 +258,7 @@ func (manager *AgentRouter) DispatchPacket(packet *RawPacket) error {
 			if _t, OK := manager.AgentMap[appid]; OK {
 				agent = _t
 			} else {
-				agent = manager.createAgent(appid, appname, serverType, startTime)
+				agent = manager.createAgent(appid, appName, serverType, startTime)
 			}
 			manager.AgentMap[appid] = agent
 			manager.rwMutex.Unlock()
@@ -277,6 +277,6 @@ func (manager *AgentRouter) DispatchPacket(packet *RawPacket) error {
 		return err
 	}
 
-PACKET_INVALIED:
+PACKET_INVALID:
 	return fmt.Errorf("input packet invalid %s", packet.RawData)
 }
diff --git a/collector-agent/agent/GrpcAgent.go b/collector-agent/agent/GrpcAgent.go
index 9c6724dd7..3204a1c42 100644
--- a/collector-agent/agent/GrpcAgent.go
+++ b/collector-agent/agent/GrpcAgent.go
@@ -463,7 +463,7 @@ func (agent *GrpcAgent) consumeJsonSpan() {
 }
 
 func (agent *GrpcAgent) CheckValid(span *TSpan) bool {
-	if span.GetAppname() != agent.agentName || span.GetAppServerType() != agent.agentType {
+	if span.GetAppName() != agent.agentName || span.GetAppServerType() != agent.agentType {
 		agent.log.Warn("name or FT not equal")
 		return false
 	} else {
diff --git a/collector-agent/makefile b/collector-agent/makefile
index a9acc344c..dba735cff 100644
--- a/collector-agent/makefile
+++ b/collector-agent/makefile
@@ -9,7 +9,7 @@ protoc:
 
 server: protoc
 	go mod tidy
-	go build .
+	go build -ldflags "-X 'github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/server.Version=v0.5.0'" .
 
 clean:
 	rm -rf pinpoint-grpc-idl/proto/v1/*.go
diff --git a/collector-agent/server/SpanServer.go b/collector-agent/server/SpanServer.go
index a79375e67..49c355ab0 100644
--- a/collector-agent/server/SpanServer.go
+++ b/collector-agent/server/SpanServer.go
@@ -3,13 +3,14 @@ package server
 import (
 	"encoding/binary"
 	"encoding/json"
-	"errors"
 	"fmt"
+	"math"
 	"net"
 	"os"
 	"os/signal"
 	"strconv"
 	"sync"
+	"sync/atomic"
 	"syscall"
 	"time"
 
@@ -19,29 +20,31 @@ import (
 	log "github.com/sirupsen/logrus"
 )
 
+var Version = "v0.0.0"
+
 type SpanServer struct {
 	listener    net.Listener
 	quit        chan bool
 	wg          sync.WaitGroup
 	agentRouter agent.I_PacketRouter
+	createTime  int64
+	index_st    int64
+	lastTime    int64
 }
 
 type ServerInfo struct {
 	AppId     string `json:"appid"`
 	AppName   string `json:"appname"`
 	StartTime string `json:"time"`
+	Version   string `json:"version"`
 }
 
-var info = ServerInfo{
-	AppId:     "no",
-	AppName:   "no",
-	StartTime: strconv.FormatInt(time.Now().Unix(), 10),
+type ServerUniqueId struct {
+	UID int64 `json:"uid"`
 }
 
 const CLIENT_HEADER_SIZE = 8
 
-// const CLIENT_MAX_PACKET_SIZE = 4096*100 + CLIENT_HEADER_SIZE
-
 func (server *SpanServer) init() {
 	server.quit = make(chan bool)
 	manager := &agent.AgentRouter{PingId: 1,
@@ -51,6 +54,8 @@ func (server *SpanServer) init() {
 	}
 
 	server.agentRouter = manager
+	server.createTime = time.Now().Unix()
+	server.index_st = 0
 }
 
 func (server *SpanServer) Run() (code int, err error) {
@@ -79,30 +84,43 @@ func (server *SpanServer) Run() (code int, err error) {
 		select {
 		case sig := <-sig:
 			log.Warnf("catch signal %s", sig)
-			return 0, errors.New(fmt.Sprintf("SpanServer exit with signal %s", sig))
+			return 0, fmt.Errorf("SpanServer exit with signal %s", sig)
 		case <-time.After(config.AgentFreeOnlineSurvivalTimeSec * time.Second):
 			server.agentRouter.Clean()
 		}
 	}
 }
 
-func (server *SpanServer) parseInComePacket(size, packetType uint32, body []byte) (err error) {
+func (server *SpanServer) genUniqueId() *ServerUniqueId {
+	return &ServerUniqueId{
+		UID: server.createTime + atomic.AddInt64(&server.index_st, 1),
+	}
+}
+
+func (server *SpanServer) parsePacket(con net.Conn, size, packetType uint32, body []byte) (err error) {
 	log.Debugf("size:%d  packetType:%d body:%s ", size, packetType, string(body[:]))
 
 	//todo parse packetType
-	data := make([]byte, size)
-	copy(data, body)
-	rawPacket := agent.RawPacket{Type: packetType, RawData: data}
+	// data := make([]byte, size)
+	// copy(data, body)
+	rawPacket := agent.RawPacket{Type: packetType, RawData: body}
 
 	switch packetType {
 	case 1: //REQ_UPDATE_SPAN
 		err = server.agentRouter.DispatchPacket(&rawPacket)
 		if err != nil {
-			log.Warnf("dispather packet with an exception: %s", err)
+			log.Warnf("dispatcher packet with an exception: %s", err)
 			return err
 		}
+	case 2: //REQ_UNIQUE_ID
+		uniqueBody, err := json.Marshal(server.genUniqueId())
+		if err == nil {
+			err = server.respToClient(con, 2, uniqueBody)
+		}
+		log.Infof("get genUniqueId")
+		return err
 	default:
-		log.Warnf("unspport type:%d", packetType)
+		log.Warnf("unsupported type:%d", packetType)
 	}
 
 	return nil
@@ -143,7 +161,7 @@ func ParseHeader(buffer []byte) (packetLen, packetType uint32) {
 	return packetLen, packetType
 }
 
-func (server *SpanServer) searchPacket(buffer []byte, start int32, total int32, packetLen, packetType *int32, body *[]byte) (token, needs int32) {
+func (server *SpanServer) matchFullPacket(buffer []byte, start int32, total int32, packetLen, packetType *int32, body *[]byte) (token, needs int32) {
 	// fetch header
 	if total < CLIENT_HEADER_SIZE {
 		return 0, CLIENT_HEADER_SIZE - total
@@ -164,6 +182,49 @@ func (server *SpanServer) searchPacket(buffer []byte, start int32, total int32,
 	return int32(bodyLen) + CLIENT_HEADER_SIZE, 0
 }
 
+func (server *SpanServer) respToClient(con net.Conn, msgType uint32, msgBody []byte) error {
+	if len(msgBody) > math.MaxInt32 {
+		log.Warnf("gets large message(=%d),server skip send to client", len(msgBody))
+		return nil
+	}
+
+	buffer := make([]byte, 8)
+	binary.BigEndian.PutUint32(buffer[0:4], msgType)
+	binary.BigEndian.PutUint32(buffer[4:8], (uint32(len(msgBody))))
+	buffer = append(buffer, msgBody...)
+	totalSize := 8 + len(msgBody)
+	// send handshake message
+	for offset := 0; offset < totalSize; {
+		size, err := con.Write(buffer[offset:])
+		if err != nil {
+			return fmt.Errorf("client:%s channel error:%s", con.RemoteAddr(), err)
+		}
+		offset += size
+	}
+
+	return nil
+}
+
+func (server *SpanServer) genHello() *ServerInfo {
+	info := &ServerInfo{
+		AppId:   "no",
+		AppName: "no",
+		Version: Version,
+	}
+	for {
+		now_in_ms := time.Now().UnixMilli()
+		if now_in_ms == server.lastTime {
+			// force sleep 1ms,avoiding conflict
+			time.Sleep(1 * time.Microsecond)
+			continue
+		}
+		server.lastTime = now_in_ms
+		info.StartTime = strconv.FormatInt(now_in_ms, 10)
+		break
+	}
+	return info
+}
+
 func (server *SpanServer) handleClient(con net.Conn) {
 	defer func() {
 		if err := con.Close(); err != nil {
@@ -172,29 +233,14 @@ func (server *SpanServer) handleClient(con net.Conn) {
 	}()
 
 	log.Infof("client:%s is online", con.RemoteAddr())
-	handshake, err := json.Marshal(&info)
+	handshake, err := json.Marshal(server.genHello())
 	if err != nil {
 		log.Warnf("generate handshake failed.reason:%s", err)
 		return
 	}
 	log.Infof("send handshake msg:%s", handshake)
-	msgSize := len(handshake)
-
-	buffer := make([]byte, 8)
-	binary.BigEndian.PutUint32(buffer[0:4], (0))
-	binary.BigEndian.PutUint32(buffer[4:8], (uint32(msgSize)))
-
-	buffer = append(buffer, handshake...)
-
-	// send handshake message
-	for offset := 0; offset < msgSize; {
-
-		size, err := con.Write(buffer[offset:])
-		if err != nil {
-			log.Warnf("client:%s channel error:%s", con.RemoteAddr(), err)
-		}
-		offset += size
-	}
+	//skip error checking,as con.Read does
+	server.respToClient(con, 0, handshake)
 
 	// fetch data
 	clientInBuf := make([]byte, Setting.RecvBufSize)
@@ -219,13 +265,12 @@ func (server *SpanServer) handleClient(con net.Conn) {
 			break
 		}
 
-	ParseAgin:
+	ParseAgain:
 
 		var body []byte = nil
 		var packetLen, packetType int32
 
-		token, needs := server.searchPacket(clientInBuf, int32(packetOffset), int32(inOffset-packetOffset), &packetLen, &packetType, &body)
-
+		token, needs := server.matchFullPacket(clientInBuf, int32(packetOffset), int32(inOffset-packetOffset), &packetLen, &packetType, &body)
 		if token == 0 {
 			if needs == 0 {
 				log.Error("needs cannot be 0")
@@ -248,10 +293,10 @@ func (server *SpanServer) handleClient(con net.Conn) {
 
 		packetOffset += int(token)
 
-		// get a packet
-		err = server.parseInComePacket(uint32(packetLen), uint32(packetType), body)
+		// gets a packet
+		err = server.parsePacket(con, uint32(packetLen), uint32(packetType), body)
 		if err != nil {
-			log.Warnf("parseInComePacket catches error:%s,client:%s", err, con.RemoteAddr())
+			log.Warnf("parsePacket catches error:%s,client:%s", err, con.RemoteAddr())
 			break
 		}
 
@@ -262,7 +307,7 @@ func (server *SpanServer) handleClient(con net.Conn) {
 			continue
 		}
 
-		goto ParseAgin
+		goto ParseAgain
 
 	}
 
diff --git a/collector-agent/server/setting.go b/collector-agent/server/setting.go
index ed3f71b41..afd6ffd83 100644
--- a/collector-agent/server/setting.go
+++ b/collector-agent/server/setting.go
@@ -1,11 +1,11 @@
 package server
 
-type ServerSetting struct{
-	RecvBufSize int
+type ServerSetting struct {
+	RecvBufSize int // default is 4k
 }
 
-const RECV_BUF_SIZE_DEF = 4096*100
+const RECV_BUF_SIZE_DEF = 4096 * 100
 
 var Setting = &ServerSetting{
 	RecvBufSize: RECV_BUF_SIZE_DEF,
-}
\ No newline at end of file
+}
diff --git a/common/.editorconfig b/common/.editorconfig
new file mode 100644
index 000000000..163988705
--- /dev/null
+++ b/common/.editorconfig
@@ -0,0 +1,59 @@
+[*]
+cpp_indent_braces=false
+cpp_indent_multi_line_relative_to=innermost_parenthesis
+cpp_indent_within_parentheses=indent
+cpp_indent_preserve_within_parentheses=false
+cpp_indent_case_labels=false
+cpp_indent_case_contents=true
+cpp_indent_case_contents_when_block=false
+cpp_indent_lambda_braces_when_parameter=true
+cpp_indent_goto_labels=one_left
+cpp_indent_preprocessor=leftmost_column
+cpp_indent_access_specifiers=false
+cpp_indent_namespace_contents=true
+cpp_indent_preserve_comments=false
+cpp_new_line_before_open_brace_namespace=ignore
+cpp_new_line_before_open_brace_type=ignore
+cpp_new_line_before_open_brace_function=ignore
+cpp_new_line_before_open_brace_block=ignore
+cpp_new_line_before_open_brace_lambda=ignore
+cpp_new_line_scope_braces_on_separate_lines=false
+cpp_new_line_close_brace_same_line_empty_type=false
+cpp_new_line_close_brace_same_line_empty_function=false
+cpp_new_line_before_catch=true
+cpp_new_line_before_else=true
+cpp_new_line_before_while_in_do_while=false
+cpp_space_before_function_open_parenthesis=remove
+cpp_space_within_parameter_list_parentheses=false
+cpp_space_between_empty_parameter_list_parentheses=false
+cpp_space_after_keywords_in_control_flow_statements=true
+cpp_space_within_control_flow_statement_parentheses=false
+cpp_space_before_lambda_open_parenthesis=false
+cpp_space_within_cast_parentheses=false
+cpp_space_after_cast_close_parenthesis=false
+cpp_space_within_expression_parentheses=false
+cpp_space_before_block_open_brace=true
+cpp_space_between_empty_braces=false
+cpp_space_before_initializer_list_open_brace=false
+cpp_space_within_initializer_list_braces=true
+cpp_space_preserve_in_initializer_list=true
+cpp_space_before_open_square_bracket=false
+cpp_space_within_square_brackets=false
+cpp_space_before_empty_square_brackets=false
+cpp_space_between_empty_square_brackets=false
+cpp_space_group_square_brackets=true
+cpp_space_within_lambda_brackets=false
+cpp_space_between_empty_lambda_brackets=false
+cpp_space_before_comma=false
+cpp_space_after_comma=true
+cpp_space_remove_around_member_operators=true
+cpp_space_before_inheritance_colon=true
+cpp_space_before_constructor_colon=true
+cpp_space_remove_before_semicolon=true
+cpp_space_after_semicolon=false
+cpp_space_remove_around_unary_operator=true
+cpp_space_around_binary_operator=insert
+cpp_space_around_assignment_operator=insert
+cpp_space_pointer_reference_alignment=left
+cpp_space_around_ternary_operator=insert
+cpp_wrap_preserve_blocks=one_liners
diff --git a/common/CHANGES.md b/common/CHANGES.md
new file mode 100644
index 000000000..915f71bb8
--- /dev/null
+++ b/common/CHANGES.md
@@ -0,0 +1,4 @@
+## v0.5.0 2024-03-06
+- refactor common library
+- replace start_time with ms format
+- remove dependence of shm
\ No newline at end of file
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index 0ac94d550..d63ec8a57 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -1,24 +1,23 @@
 cmake_minimum_required(VERSION 3.13)
-project(pinpoint VERSION 0.4.25 DESCRIPTION  "pinpoint common library")
+project(pinpoint VERSION 0.5.0 DESCRIPTION  "pinpoint common library")
 
 set(CMAKE_CXX_STANDARD 11)
 
 list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
 
-option(AGENT_WITH_PKGCONFIG_SUPPORT "Generate and install .pc files" ON)
+option(AGENT_WITH_PKGCONFIG_SUPPORT "Generate and install .pc files" OFF)
 
 
-set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS} -Wall -Wextra -fPIC")
-set(CMAKE_CXX_FLAGS   "${CMAKE_CXX_FLAGS}  -Wall -Wextra -fPIC")
-set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}   -g3 -O0 -DCOMMON_DEBUG")   
-set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG  -O2")
-set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}  -g3 -O0 -DCOMMON_DEBUG")
-set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG  -O2")
+# set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}   -g3 -O0 -DCOMMON_DEBUG")   
+# set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG  -O2")
+# set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}  -g3 -O0 -DCOMMON_DEBUG")
+# set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG  -O2")
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
 set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
 set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "")
+set(CMAKE_POSITION_INDEPENDENT_CODE ON)
 add_definitions( -DAGENT_VERSION="${PROJECT_VERSION}")
 
 option (WITH_TEST_CASE "Enable Gtest" OFF)
@@ -29,49 +28,28 @@ if(UNIX AND NOT APPLE)
 endif()
 
 if (WITH_CODECOVERAGE AND LINUX_)
-    # message("WITH_CODECOVERAGE = ON")
     set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
     set(CMAKE_CXX_FLAGS   "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
 endif()
 
-configure_file("${CMAKE_CURRENT_SOURCE_DIR}/include/common.h.in" "${CMAKE_CURRENT_SOURCE_DIR}/include/common.h" @ONLY)
-    
-include_directories("include"
-                    "src"
-                    "jsoncpp/include")
-                  
-link_directories(${CMAKE_BINARY_DIR}/lib)
-
+if(CMAKE_COMPILER_IS_GNUCXX)
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic  -fPIC -Wall -Wextra")
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic  -fPIC -Wall -Wextra")
+endif(CMAKE_COMPILER_IS_GNUCXX)
 add_subdirectory(jsoncpp)
-add_subdirectory(src)
-
-add_library(pinpoint_common_static STATIC $<TARGET_OBJECTS:pinpoint_common_obj> $<TARGET_OBJECTS:jsoncppObj>)
-
-target_include_directories(pinpoint_common_static PUBLIC
-        $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
-        $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
-        $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
-)
-
-if(UNIX AND NOT APPLE)
-    include(GNUInstallDirs)
-    add_library(pinpoint_common_shared SHARED $<TARGET_OBJECTS:pinpoint_common_obj> $<TARGET_OBJECTS:jsoncppObj>)  
-    install(DIRECTORY include/ DESTINATION include/pinpoint_common
-            FILES_MATCHING PATTERN "*.h")
 
-    set_target_properties(pinpoint_common_shared pinpoint_common_static PROPERTIES 
-            VERSION ${PROJECT_VERSION}
-            SOVERSION 1
-            PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/include/common.h")      
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/include)                
 
-    install(TARGETS pinpoint_common_shared pinpoint_common_static ${INSTALL_EXPORT}
-        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
-        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
-        OBJECTS DESTINATION ${CMAKE_INSTALL_LIBDIR}
-        PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/pinpoint_common
-    )
-endif()
+if (WITH_TEST_CASE)
+    include (CTest)
+    enable_testing()
+    find_package(GTest REQUIRED)
+    add_definitions(-DUTEST)
+    add_subdirectory(src)
+    add_subdirectory(test)
+else()
+    add_subdirectory(src)
+endif(WITH_TEST_CASE)
 
 if(AGENT_WITH_PKGCONFIG_SUPPORT)
     include(JoinPaths)
@@ -83,10 +61,3 @@ if(AGENT_WITH_PKGCONFIG_SUPPORT)
     install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pkg-config/pinpoint_common.pc"
         DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
 endif()
-
-if (WITH_TEST_CASE)
-    include (CTest)
-    enable_testing()
-    find_package(GTest REQUIRED)
-    add_subdirectory(test)
-endif(WITH_TEST_CASE)
diff --git a/common/cppcheck.sh b/common/cppcheck.sh
new file mode 100644
index 000000000..0bc9fe3b5
--- /dev/null
+++ b/common/cppcheck.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+cppcheck --language=c++ --std=c++11 --suppress=*:*googletest-src/* --suppress=*:*jsoncpp/* --suppress=*:*.cc --project=./compile_commands.json --enable=all -j10  2>cppcheck.log
\ No newline at end of file
diff --git a/common/include/common.h b/common/include/common.h
index 3a9265058..dd71d5585 100644
--- a/common/include/common.h
+++ b/common/include/common.h
@@ -16,22 +16,18 @@
 #ifndef COMMON_H_
 #define COMMON_H_
 
-#include <stdlib.h>
 #include <stdint.h>
 #include <stdbool.h>
-#include <assert.h>
 
 #if defined(__GNUC__) || defined(__clang__)
-#define DEPRECATED __attribute__((deprecated))
+#define DEPRECATED(msg) __attribute__((deprecated(msg)))
 #elif defined(_MSC_VER)
-#define DEPRECATED __declspec(deprecated)
+#define DEPRECATED(msg) __declspec(deprecated(msg))
 #else
 #define DEPRECATED
 #endif
 
 #define MAX_VEC 512
-#define LOG_SIZE 4096
-#define IN_MSG_BUF_SIZE 4096
 #define NAMING_SIZE 128
 static const int RECONNECT_TIME_SEC = 5;
 typedef enum { RESPONSE_AGENT_INFO = 0, REQ_UPDATE_SPAN = 1 } MSG_TYPE;
@@ -39,8 +35,10 @@ typedef enum { RESPONSE_AGENT_INFO = 0, REQ_UPDATE_SPAN = 1 } MSG_TYPE;
 typedef enum {
   E_LOGGING = 0x1,
   E_DISABLE_GIL = 0x2, // disable gil checking in python
-  E_UTEST = 0x4
-} AGENT_FLAG;
+  // if set this mode, all span must be send immediately
+  // mostly used in some batch script,data loading, data migration
+  // E_NO_SPAN_WAIT = 0x4,
+} E_AGENT_MODE;
 
 #pragma pack(1)
 typedef struct {
@@ -55,31 +53,12 @@ typedef struct collector_agent_s {
   char* appname;
 } CollectorAgentInfo;
 
-///
-typedef struct trace_store_layer {
-  void (*set_cur_trace_cb)(void*);
-  void* (*get_cur_trace_cb)(void);
-} TraceStoreLayer;
-
-#define LOG_SIZE 4096
 #define MAX_ADDRESS_SIZE 256
-typedef void (*VOID_FUNC)(void);
-typedef struct pp_agent_s {
-  char co_host[MAX_ADDRESS_SIZE]; // tcp:ip:port should support dns
-  long timeout_ms;                // always be 0
-  long trace_limit;               // change to long as python need long
-  int agent_type;
-  uint8_t inter_flag;
-  VOID_FUNC get_read_lock;
-  VOID_FUNC get_write_lock;
-  VOID_FUNC release_lock;
-} PPAgentT;
 
 typedef enum {
   E_OFFLINE = 0x1,
   E_TRACE_PASS = 0x2,
   E_TRACE_BLOCK = 0x4,
-  E_READY = 0x8
 } E_AGENT_STATUS;
 
 /**
@@ -87,13 +66,14 @@ typedef enum {
  */
 
 typedef int NodeID;
-typedef NodeID E_NODE_LOC;
+typedef NodeID ParentNodeId;
+typedef int E_NODE_LOC;
 static const NodeID E_INVALID_NODE = -1;
 static const NodeID E_ROOT_NODE = 0;
 static const E_NODE_LOC E_LOC_CURRENT = 0x0;
 static const E_NODE_LOC E_LOC_ROOT = 0x1;
 
-#define PINPOINT_C_AGENT_API_VERSION "0.4.25"
+#define PINPOINT_C_AGENT_API_VERSION "0.5.0"
 
 /**
  * @brief change logs
@@ -110,8 +90,18 @@ static const E_NODE_LOC E_LOC_ROOT = 0x1;
 extern "C" {
 #endif
 
-extern PPAgentT global_agent_info;
-
+/**
+ * @brief set_agent attribution
+ *
+ * @param collector_agent_address
+ * @param timeout_ms
+ * @param trace_limit
+ * @param agent_type
+ * @return true done
+ * @return false failed, check the output
+ */
+bool pinpoint_set_agent(const char* collector_agent_address, long timeout_ms, long trace_limit,
+                        int agent_type);
 /**
  * @brief [tls]
  *  pinpoint_get_per_thread_id and pinpoint_update_per_thread_id are paired API
@@ -124,7 +114,7 @@ void pinpoint_update_per_thread_id(NodeID id);
 
 /**
  *  @brief [tls] start a trace (span) from parentId. if current span is empty, create a span or else
- * create a spanevent
+ * create a span event
  *
  * @param parentId
  * @return -1: failed new traceId related to parentId (caller [parentId] -> callee [NodeID] )
@@ -155,15 +145,6 @@ void pinpoint_add_exception(NodeID, const char* exp);
  */
 NodeID pinpoint_end_trace(NodeID);
 
-/**
- * @brief wake a finished trace: this trace get a new startime, so it could be profile again. the
- * end_trace will update the ["e"] by cumulative time (NOTE: root trace not supported)
- *
- * @param traceId
- * @return int 0 if success, -1 if failed
- */
-int pinpoint_wake_trace(NodeID traceId);
-
 /**
  *  check id->traceNode is root
  * @param
@@ -176,6 +157,8 @@ int pinpoint_trace_is_root(NodeID);
  * @return int 0 : means oK
  *             -1: exception found, check the log
  */
+DEPRECATED(
+    "use pinpoint_end_trace. if you need no span missing, set pinpoint_set_agent with `timeout_ms`")
 int pinpoint_force_end_trace(NodeID, int32_t timeout);
 
 /**
@@ -196,30 +179,24 @@ void pinpoint_add_clue(NodeID _id, const char* key, const char* value, E_NODE_LO
  * @param value
  */
 void pinpoint_set_context_key(NodeID _id, const char* key, const char* value);
-/**
- * [tls] get the corresponding value with key(in current trace)
- * @param size copy into pbuf, not include '\0'
- * @return value size
- */
-int pinpoint_get_context_key(NodeID _id, const char* key, char* pbuf, int buf_size);
-
-void pinpoint_set_context_long(NodeID _id, const char* key, long);
 
 /**
- * @brief the value is a long type
+ * @brief get string context
  *
- * @param _id  node id
- * @param key  string
- * @return int 1: failed
- *              0: success
+ * @param id current trace id
+ * @param key
+ * @param pbuf
+ * @param buf_size maximum buf size
+ * @return int
  */
-int pinpoint_get_context_long(NodeID _id, const char* key, long*);
+int pinpoint_get_context_key(NodeID id, const char* key, char* pbuf, int buf_size);
 /**
- * [tls] if tracelimit enable, check current trace state,
+ * [tls] if trace limited enable, check current trace state,
  * @param timestamp
  * @return 0, sampled or else, not sampled
  */
-int check_tracelimit(int64_t);
+int check_trace_limit(int64_t);
+DEPRECATED("use check_trace_limit") int check_tracelimit(int64_t);
 
 /**
 * @brief [tls] setting current trace status
@@ -233,7 +210,8 @@ int check_tracelimit(int64_t);
 * @param status
 * @return int last status
 */
-uint64_t mark_current_trace_status(NodeID _id, int status);
+uint64_t change_trace_status(NodeID id, int status);
+DEPRECATED("use change_trace_status") uint64_t mark_current_trace_status(NodeID _id, int status);
 
 /**
  * [tls] get an unique auto-increment id
@@ -255,8 +233,14 @@ uint64_t pinpoint_start_time(void);
  * @param error_lineno
  */
 void catch_error(NodeID _id, const char* msg, const char* error_filename, uint32_t error_lineno);
+
+/**
+ * @brief get agent internal logging, mostly for developer
+ *
+ */
 typedef void (*log_msg_cb)(char*);
-void register_error_cb(log_msg_cb error_cb);
+DEPRECATED("use 'register_logging_cb'") void register_error_cb(log_msg_cb call_back);
+void register_logging_cb(log_msg_cb call_back, int enable_trace);
 
 /**
  * @brief for test-case: not send span to collector-agent, pass to handler
@@ -267,7 +251,7 @@ void register_span_handler(void (*handler)(const char*));
 
 void pp_trace(const char* format, ...);
 /**
- * NOTE: only for testcase
+ * NOTE: only for test case
  */
 void reset_unique_id(void);
 const char* pinpoint_agent_version();
diff --git a/common/include/common.h.in b/common/include/common.h.in
index 749b4ef1b..31b8f3949 100644
--- a/common/include/common.h.in
+++ b/common/include/common.h.in
@@ -16,22 +16,18 @@
 #ifndef COMMON_H_
 #define COMMON_H_
 
-#include <stdlib.h>
 #include <stdint.h>
 #include <stdbool.h>
-#include <assert.h>
 
 #if defined(__GNUC__) || defined(__clang__)
-#define DEPRECATED __attribute__((deprecated))
+#define DEPRECATED(msg) __attribute__((deprecated(msg)))
 #elif defined(_MSC_VER)
-#define DEPRECATED __declspec(deprecated)
+#define DEPRECATED(msg) __declspec(deprecated(msg))
 #else
 #define DEPRECATED
 #endif
 
 #define MAX_VEC 512
-#define LOG_SIZE 4096
-#define IN_MSG_BUF_SIZE 4096
 #define NAMING_SIZE 128
 static const int RECONNECT_TIME_SEC = 5;
 typedef enum { RESPONSE_AGENT_INFO = 0, REQ_UPDATE_SPAN = 1 } MSG_TYPE;
@@ -39,8 +35,10 @@ typedef enum { RESPONSE_AGENT_INFO = 0, REQ_UPDATE_SPAN = 1 } MSG_TYPE;
 typedef enum {
   E_LOGGING = 0x1,
   E_DISABLE_GIL = 0x2, // disable gil checking in python
-  E_UTEST = 0x4
-} AGENT_FLAG;
+  // if set this mode, all span must be send immediately
+  // mostly used in some batch script,data loading, data migration
+  // E_NO_SPAN_WAIT = 0x4,
+} E_AGENT_MODE;
 
 #pragma pack(1)
 typedef struct {
@@ -55,31 +53,12 @@ typedef struct collector_agent_s {
   char* appname;
 } CollectorAgentInfo;
 
-///
-typedef struct trace_store_layer {
-  void (*set_cur_trace_cb)(void*);
-  void* (*get_cur_trace_cb)(void);
-} TraceStoreLayer;
-
-#define LOG_SIZE 4096
 #define MAX_ADDRESS_SIZE 256
-typedef void (*VOID_FUNC)(void);
-typedef struct pp_agent_s {
-  char co_host[MAX_ADDRESS_SIZE]; // tcp:ip:port should support dns
-  long timeout_ms;                // always be 0
-  long trace_limit;               // change to long as python need long
-  int agent_type;
-  uint8_t inter_flag;
-  VOID_FUNC get_read_lock;
-  VOID_FUNC get_write_lock;
-  VOID_FUNC release_lock;
-} PPAgentT;
 
 typedef enum {
   E_OFFLINE = 0x1,
   E_TRACE_PASS = 0x2,
   E_TRACE_BLOCK = 0x4,
-  E_READY = 0x8
 } E_AGENT_STATUS;
 
 /**
@@ -87,7 +66,8 @@ typedef enum {
  */
 
 typedef int NodeID;
-typedef NodeID E_NODE_LOC;
+typedef NodeID ParentNodeId;
+typedef int E_NODE_LOC;
 static const NodeID E_INVALID_NODE = -1;
 static const NodeID E_ROOT_NODE = 0;
 static const E_NODE_LOC E_LOC_CURRENT = 0x0;
@@ -110,8 +90,18 @@ static const E_NODE_LOC E_LOC_ROOT = 0x1;
 extern "C" {
 #endif
 
-extern PPAgentT global_agent_info;
-
+/**
+ * @brief set_agent attribution
+ *
+ * @param collector_agent_address
+ * @param timeout_ms
+ * @param trace_limit
+ * @param agent_type
+ * @return true done
+ * @return false failed, check the output
+ */
+bool pinpoint_set_agent(const char* collector_agent_address, long timeout_ms, long trace_limit,
+                        int agent_type);
 /**
  * @brief [tls]
  *  pinpoint_get_per_thread_id and pinpoint_update_per_thread_id are paired API
@@ -124,7 +114,7 @@ void pinpoint_update_per_thread_id(NodeID id);
 
 /**
  *  @brief [tls] start a trace (span) from parentId. if current span is empty, create a span or else
- * create a spanevent
+ * create a span event
  *
  * @param parentId
  * @return -1: failed new traceId related to parentId (caller [parentId] -> callee [NodeID] )
@@ -148,34 +138,27 @@ NodeID pinpoint_start_traceV1(NodeID parentId, const char* opt, ...);
 void pinpoint_add_exception(NodeID, const char* exp);
 
 /**[tls]
- * the same as pinpoint_start_trace. BUT, end a span or a spanevent
+ * the same as pinpoint_start_trace. BUT, end a span or a span event
  * Note: pinpoint_end_trace is thread safe, but you should avoid to call it in the multi-thread, it
  * may send duplicate trace span
  * @return NodeID is parent node id
  */
 NodeID pinpoint_end_trace(NodeID);
 
-/**
- * @brief wake a finished trace: this trace get a new startime, so it could be profile again. the
- * end_trace will update the ["e"] by cumulative time (NOTE: root trace not supported)
- *
- * @param traceId
- * @return int 0 if success, -1 if failed
- */
-int pinpoint_wake_trace(NodeID traceId);
-
 /**
  *  check id->traceNode is root
  * @param
- * @return 1: is root; 0: not root node;-1: A wrong id
+ * @return 1: is root; 0: not root node;-1: nonexistent node 
  */
 int pinpoint_trace_is_root(NodeID);
 
 /**
- *  force end current trace, only called when callstack leaked
+ *  force end current trace, only called when call stack leaked
  * @return int 0 : means oK
  *             -1: exception found, check the log
  */
+DEPRECATED(
+    "use pinpoint_end_trace. if you need no span missing, set pinpoint_set_agent with `timeout_ms`")
 int pinpoint_force_end_trace(NodeID, int32_t timeout);
 
 /**
@@ -196,30 +179,24 @@ void pinpoint_add_clue(NodeID _id, const char* key, const char* value, E_NODE_LO
  * @param value
  */
 void pinpoint_set_context_key(NodeID _id, const char* key, const char* value);
-/**
- * [tls] get the corresponding value with key(in current trace)
- * @param size copy into pbuf, not include '\0'
- * @return value size
- */
-int pinpoint_get_context_key(NodeID _id, const char* key, char* pbuf, int buf_size);
-
-void pinpoint_set_context_long(NodeID _id, const char* key, long);
 
 /**
- * @brief the value is a long type
+ * @brief get string context
  *
- * @param _id  node id
- * @param key  string
- * @return int 1: failed
- *              0: success
+ * @param id current trace id
+ * @param key
+ * @param pbuf
+ * @param buf_size maximum buf size
+ * @return int
  */
-int pinpoint_get_context_long(NodeID _id, const char* key, long*);
+int pinpoint_get_context_key(NodeID id, const char* key, char* pbuf, int buf_size);
 /**
- * [tls] if tracelimit enable, check current trace state,
+ * [tls] if trace limited enable, check current trace state,
  * @param timestamp
  * @return 0, sampled or else, not sampled
  */
-int check_tracelimit(int64_t);
+int check_trace_limit(int64_t);
+DEPRECATED("use check_trace_limit") int check_tracelimit(int64_t);
 
 /**
 * @brief [tls] setting current trace status
@@ -233,7 +210,8 @@ int check_tracelimit(int64_t);
 * @param status
 * @return int last status
 */
-uint64_t mark_current_trace_status(NodeID _id, int status);
+uint64_t change_trace_status(NodeID id, int status);
+DEPRECATED("use change_trace_status") uint64_t mark_current_trace_status(NodeID _id, int status);
 
 /**
  * [tls] get an unique auto-increment id
@@ -255,8 +233,14 @@ uint64_t pinpoint_start_time(void);
  * @param error_lineno
  */
 void catch_error(NodeID _id, const char* msg, const char* error_filename, uint32_t error_lineno);
+
+/**
+ * @brief get agent internal logging, mostly for developer
+ *
+ */
 typedef void (*log_msg_cb)(char*);
-void register_error_cb(log_msg_cb error_cb);
+DEPRECATED("use 'register_logging_cb'") void register_error_cb(log_msg_cb call_back);
+void register_logging_cb(log_msg_cb call_back, int enable_trace);
 
 /**
  * @brief for test-case: not send span to collector-agent, pass to handler
@@ -267,7 +251,7 @@ void register_span_handler(void (*handler)(const char*));
 
 void pp_trace(const char* format, ...);
 /**
- * NOTE: only for testcase
+ * NOTE: only for test case
  */
 void reset_unique_id(void);
 const char* pinpoint_agent_version();
diff --git a/common/jsoncpp/CMakeLists.txt b/common/jsoncpp/CMakeLists.txt
index 5e04ef81b..8f9577737 100644
--- a/common/jsoncpp/CMakeLists.txt
+++ b/common/jsoncpp/CMakeLists.txt
@@ -1,3 +1,8 @@
 aux_source_directory(lib_json/ JSON_SRC)
-add_library(jsoncppObj OBJECT  ${JSON_SRC})
-# add_library(jsoncpp STATIC $<TARGET_OBJECTS:jsoncppObj>)
\ No newline at end of file
+add_library(jsoncpp_static STATIC  ${JSON_SRC})
+
+target_include_directories(jsoncpp_static
+    PUBLIC
+        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> 
+        $<INSTALL_INTERFACE:include>
+)
\ No newline at end of file
diff --git a/common/src/CMakeLists.txt b/common/src/CMakeLists.txt
index 73d899bbe..827ff92a0 100644
--- a/common/src/CMakeLists.txt
+++ b/common/src/CMakeLists.txt
@@ -1,7 +1,31 @@
-LIST(APPEND src_dir . NodePool Cache Context Util ConnectionPool)
-foreach(dir  ${src_dir})
-    aux_source_directory(${dir} SRC_FILES)
-endforeach()
+file(GLOB_RECURSE SRC_FILES
+  "${PROJECT_SOURCE_DIR}/src/*.cpp"
+)
 
-add_library(pinpoint_common_obj OBJECT ${SRC_FILES})
-# add_library(pinpoint_common STATIC $<TARGET_OBJECTS:pinpoint_common_obj> $<TARGET_OBJECTS:jsoncppObj>)
+add_library(pinpoint_common_static STATIC ${SRC_FILES})
+target_link_libraries(pinpoint_common_static jsoncpp_static)
+
+target_include_directories(pinpoint_common_static PUBLIC
+        $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+        $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/../include>
+        $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
+)
+
+add_library(pinpoint_common_shared SHARED ${SRC_FILES}) 
+target_link_libraries(pinpoint_common_shared jsoncpp_static)
+
+install(DIRECTORY include/ DESTINATION include/pinpoint_common
+        FILES_MATCHING PATTERN "*.h")
+
+set_target_properties(pinpoint_common_shared pinpoint_common_static PROPERTIES 
+        VERSION ${PROJECT_VERSION} 
+        SOVERSION 1
+        PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/../include/common.h")      
+
+install(TARGETS pinpoint_common_shared pinpoint_common_static ${INSTALL_EXPORT}
+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+    OBJECTS DESTINATION ${CMAKE_INSTALL_LIBDIR}
+    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/pinpoint_common
+)
\ No newline at end of file
diff --git a/common/src/Cache/Chunk.cpp b/common/src/Cache/Chunk.cpp
index 9eedbac81..2faf4bcd4 100644
--- a/common/src/Cache/Chunk.cpp
+++ b/common/src/Cache/Chunk.cpp
@@ -20,22 +20,22 @@
  *      Author: eeliu
  */
 #include "Chunk.h"
-namespace Cache
-{
-int Chunks::copyDataIntoReadyCK(const void* data, uint32_t length)
-{
-  if (ready_cks.empty()) { return length; }
+namespace Cache {
+int Chunks::copyDataIntoReadyCK(const void* data, uint32_t length) {
+  if (ready_cks.empty()) {
+    return length;
+  }
 
-  Chunk* ck = ready_cks.back();
+  DataChunk* ck = ready_cks.back();
 
-  char* p_ck_r = &ck->data[ck->r_ofs];
+  char* p_ck_r = (char*)ck + sizeof(*ck) + ck->r_ofs;
   uint32_t capacity = ck->block_size - ck->r_ofs;
   if (capacity >= length) {
     memcpy(p_ck_r, data, length);
     ck->r_ofs += length;
     length = 0;
-  } else if (capacity > 0)  // capacity < length
-  {			    // current ck is full
+  } else if (capacity > 0) // capacity < length
+  {                        // current ck is full
     memcpy(p_ck_r, data, capacity);
     length -= capacity;
     ck->r_ofs += capacity;
@@ -44,17 +44,17 @@ int Chunks::copyDataIntoReadyCK(const void* data, uint32_t length)
   return length;
 }
 
-int Chunks::copyDataIntoFreeCK(const void* data, uint32_t length)
-{
-  if (this->free_cks.empty()) { return length; }
-
+int Chunks::copyDataIntoFreeCK(const void* data, uint32_t length) {
+  if (this->free_cks.empty()) {
+    return length;
+  }
 
   iter = this->free_cks.begin();
 
   while (iter != this->free_cks.end() && length > 0) {
-    Chunk* ck = *iter;
-    iter++;
-    char* f_buf_start = &ck->data[ck->r_ofs];
+    DataChunk* ck = *iter;
+    ++iter;
+    char* f_buf_start = (char*)ck + sizeof(*ck) + ck->r_ofs;
     uint32_t ck_capacity = ck->block_size - ck->r_ofs;
     if (ck_capacity >= length) {
       // current data task is done
@@ -62,16 +62,16 @@ int Chunks::copyDataIntoFreeCK(const void* data, uint32_t length)
       ck->r_ofs += length;
       length = 0;
 
-    } else if (ck_capacity > 0)	 //ck_capacity < length
+    } else if (ck_capacity > 0) // ck_capacity < length
     {
       memcpy(f_buf_start, data, ck_capacity);
       length -= ck_capacity;
-      data = (const char*) data + ck_capacity;
+      data = (const char*)data + ck_capacity;
       ck->r_ofs += ck_capacity;
     }
 
     this->ck_free_ck_capacity -= ck->block_size;
-    // remove free in flist
+    // remove free in free list
     this->free_cks.pop_front();
     // append free into rlist_end
     this->ready_cks.push_back(ck);
@@ -80,24 +80,28 @@ int Chunks::copyDataIntoFreeCK(const void* data, uint32_t length)
   return length;
 }
 
-uint32_t Chunks::ck_ceil_to_k(uint32_t i)
-{
-  if (i < threshold) { return threshold; }
+uint32_t Chunks::ck_ceil_to_k(uint32_t i) {
+  if (i < threshold) {
+    return threshold;
+  }
 
   uint32_t k = 0x80000000;
-  while (k && !(k & i)) { k >>= 1; }
+  while (k && !(k & i)) {
+    k >>= 1;
+  }
   return k << 1;
 }
 
-int Chunks::copyDataIntoNewChunk(const void* data, uint32_t length)
-{
-  int mem_size = ck_ceil_to_k(sizeof(Chunk) + length);
+int Chunks::copyDataIntoNewChunk(const void* data, uint32_t length) {
+  int mem_size = ck_ceil_to_k(sizeof(DataChunk) + length);
 
   // new a chunk
-  Chunk* ck = (Chunk*) malloc(mem_size);
-  if (ck == NULL) { return -1; }
-  ck->block_size = mem_size - sizeof(Chunk);
-  memcpy(&ck->data[0], data, length);
+  DataChunk* ck = (DataChunk*)malloc(mem_size);
+  if (ck == NULL) {
+    return -1;
+  }
+  ck->block_size = mem_size - sizeof(DataChunk);
+  memcpy(ck + 1, data, length);
   ck->r_ofs = length;
   ck->l_ofs = 0;
   /// insert into ready list
@@ -106,87 +110,89 @@ int Chunks::copyDataIntoNewChunk(const void* data, uint32_t length)
   return 0;
 }
 
-void Chunks::reduceFreeCK()
-{
+void Chunks::reduceFreeCK() {
   if (!this->free_cks.empty()) {
-    Chunk* c = *this->free_cks.begin();
+    DataChunk* c = *this->free_cks.begin();
     this->free_cks.pop_front();
-    this->ck_alloc_size -= (c->block_size + sizeof(Chunk));
+    this->ck_alloc_size -= (c->block_size + sizeof(DataChunk));
     this->ck_free_ck_capacity -= c->block_size;
     free(c);
   }
 }
 
-void Chunks::checkWaterLevel()
-{
-  while (this->c_resident_size < this->ck_alloc_size && !this->free_cks.empty()) { this->reduceFreeCK(); }
+void Chunks::checkWaterLevel() {
+  while (this->c_resident_size < this->ck_alloc_size && !this->free_cks.empty()) {
+    this->reduceFreeCK();
+  }
 }
 
-
 uint32_t Chunks::getAllocSize() const { return this->ck_alloc_size; }
 
-Chunks::Chunks(uint32_t max_size, uint32_t resident_size) : c_resident_size(resident_size), c_max_size(max_size), threshold(1024)
-{
+Chunks::Chunks(uint32_t max_size, uint32_t resident_size)
+    : c_resident_size(resident_size), c_max_size(max_size), threshold(1024) {
   this->ck_alloc_size = 0;
   this->ck_free_ck_capacity = 0;
-  if (max_size < resident_size) throw std::invalid_argument("chunks: max_size must bigger then resident_size");
+  if (max_size < resident_size)
+    throw std::invalid_argument("chunks: max_size must bigger then resident_size");
 }
 
-Chunks::~Chunks()
-{
+Chunks::~Chunks() {
   while (!this->ready_cks.empty()) {
-    Chunk* c = this->ready_cks.front();
+    DataChunk* c = this->ready_cks.front();
     free(c);
     ready_cks.pop_front();
   }
 
   while (!this->free_cks.empty()) {
-    Chunk* c = *this->free_cks.begin();
+    DataChunk* c = *this->free_cks.begin();
     free(c);
     free_cks.pop_front();
   }
   this->ck_free_ck_capacity = 0;
 }
 
-bool Chunks::useExistingChunk(uint32_t length) const
-{
-  Chunk* c = nullptr;
+bool Chunks::useExistingChunk(uint32_t length) const {
+  DataChunk* c = nullptr;
   if (!this->ready_cks.empty()) {
     c = this->ready_cks.back();
-    uint32_t availiable = c->block_size - c->r_ofs;
-    if (availiable < length) {
+    uint32_t available = c->block_size - c->r_ofs;
+    if (available < length) {
       return false;
     } else {
-      length -= availiable;
+      length -= available;
     }
   }
 
-  if (this->ck_free_ck_capacity >= length) { return true; }
+  if (this->ck_free_ck_capacity >= length) {
+    return true;
+  }
 
   return false;
 }
 
-
-int Chunks::copyDataIntoChunks(const void* data, uint32_t length)
-{
-  const char* p_in = (const char*) data;
+int Chunks::copyDataIntoChunks(const void* data, uint32_t length) {
+  const char* p_in = (const char*)data;
   int ret = 0;
 
   // fill order
   // 1. ready ck
   // 2. free ck
   // 3. create a new ck
-  if ((ret = copyDataIntoReadyCK(p_in, length)) == 0) { goto DONE; }
+  if ((ret = copyDataIntoReadyCK(p_in, length)) == 0) {
+    goto DONE;
+  }
 
   p_in += (length - ret);
   length = ret;
 
-  if ((ret = copyDataIntoFreeCK(p_in, length)) == 0) { goto DONE; }
+  if ((ret = copyDataIntoFreeCK(p_in, length)) == 0) {
+    goto DONE;
+  }
 
   p_in += (length - ret);
   length = ret;
 
-  if ((ret = copyDataIntoNewChunk(p_in, length)) == -1) {
+  if (copyDataIntoNewChunk(p_in, length) == -1) {
     // exhausting memory
     return -1;
   }
@@ -195,42 +201,42 @@ int Chunks::copyDataIntoChunks(const void* data, uint32_t length)
   return 0;
 }
 
-int Chunks::drainOutWithPipe(std::function<int(const char*, uint32_t)> in_pipe_cb)
-{
-  if (this->ready_cks.empty()) { return 0; }
+int Chunks::drainOutWithPipe(std::function<int(const char*, uint32_t)> in_pipe_cb) {
+  if (this->ready_cks.empty()) {
+    return 0;
+  }
   this->iter = this->ready_cks.begin();
 
   while (this->iter != this->ready_cks.end()) {
-    Chunk* cur = *iter;
-    char* cur_buf = &cur->data[cur->l_ofs];
+    DataChunk* cur = *iter;
+    char* cur_buf = (char*)cur + sizeof(DataChunk) + cur->l_ofs;
     uint32_t cur_size = cur->r_ofs - cur->l_ofs;
     // call in_pipe_cb flush the data out
     int ret = in_pipe_cb(cur_buf, cur_size);
     if (ret <= 0) {
       return ret;
-    } else if (ret == (int) cur_size) {	 // current chunk is done, drop current chunk
+    } else if (ret == (int)cur_size) { // current chunk is done, drop current chunk
       // reset read offset
       cur->l_ofs = 0;
-      //reset write offset
+      // reset write offset
       cur->r_ofs = 0;
       // insert into free cks
       this->ck_free_ck_capacity += cur->block_size;
       this->free_cks.push_front(cur);
       // remove from read cks
-      iter++;
+      ++iter;
       this->ready_cks.pop_front();
-    } else if (ret < (int) cur_size) {	// some are failed, resend at next time
-      cur->l_ofs += (uint32_t) ret;
+    } else if (ret < (int)cur_size) { // some are failed, resend at next time
+      cur->l_ofs += (uint32_t)ret;
     }
   }
   this->checkWaterLevel();
   return 0;
 }
 
-void Chunks::resetChunks()
-{
+void Chunks::resetChunks() {
   while (!this->ready_cks.empty()) {
-    Chunk* c = *this->ready_cks.begin();
+    DataChunk* c = *this->ready_cks.begin();
     c->l_ofs = 0;
     c->r_ofs = 0;
     this->ready_cks.pop_front();
@@ -240,4 +246,4 @@ void Chunks::resetChunks()
   this->checkWaterLevel();
 }
 
-}  // namespace Cache
\ No newline at end of file
+} // namespace Cache
\ No newline at end of file
diff --git a/common/src/Cache/Chunk.h b/common/src/Cache/Chunk.h
index a375e1f58..b1db04da6 100644
--- a/common/src/Cache/Chunk.h
+++ b/common/src/Cache/Chunk.h
@@ -24,103 +24,95 @@
 #include <stdlib.h>
 #include <list>
 #include <string.h>
-#include <json/json.h>
+
 #include <assert.h>
 #include <functional>
 #include <iostream>
 
-namespace Cache{
-    
+namespace Cache {
 /// Readme:
 /// 1. not thread safe
-/// 2. check the capacity before copy data  
-class Chunks
-{
-
-    typedef struct chunk_
-    {
-        uint32_t block_size;
-        /**
-         * @brief 
-         * The continuous buffer left offset in data ***(l_ofs)--------------(r_ofs)*****
-         *   for read data from ck
-         */
-        uint32_t l_ofs; 
-
-        /**
-         * @brief  The continuous buffer right offset in data
-         * for write data into ck
-         */
-        uint32_t r_ofs; 
-        char data[0];
-    } Chunk;
-
-    typedef std::list<Chunk*> CKList;
-    typedef CKList::iterator CkIter;
-
-private:
+/// 2. check the capacity before copy data
+class Chunks {
 
-    CkIter iter;
-    CKList ready_cks;  //Wait to send
-    CKList free_cks;  //already send, can be reuse
+  typedef struct {
+    uint32_t block_size;
+    /**
+     * @brief
+     * The continuous buffer left offset in data ***(l_ofs)--------------(r_ofs)*****
+     *   for read data from ck
+     */
+    uint32_t l_ofs;
 
-    const uint32_t c_resident_size;
-    const uint32_t c_max_size;    // if  ck_alloc_size > c_max_size buffer is full
-    uint32_t threshold;
+    /**
+     * @brief  The continuous buffer right offset in data
+     * for write data into ck
+     */
+    uint32_t r_ofs;
+    } DataChunk;
 
-    uint32_t ck_alloc_size;
-    uint32_t ck_free_ck_capacity;
+  typedef std::list<DataChunk*> CKList;
+  typedef CKList::iterator CkIter;
 
 private:
+  CkIter iter;
+  CKList ready_cks; // Wait to send
+  CKList free_cks;  // already send, can be reuse
 
-    uint32_t ck_ceil_to_k(uint32_t i);
-    /**
-     *
-     * @param data
-     * @param length
-     * @return rest size of data
-     */
-    int copyDataIntoReadyCK(const void* data, uint32_t length);
+  const uint32_t c_resident_size;
+  const uint32_t c_max_size; // if  ck_alloc_size > c_max_size buffer is full
+  uint32_t threshold;
+
+  uint32_t ck_alloc_size;
+  uint32_t ck_free_ck_capacity;
 
-    int copyDataIntoFreeCK(const void*data, uint32_t length);
+private:
+  uint32_t ck_ceil_to_k(uint32_t i);
+  /**
+   *
+   * @param data
+   * @param length
+   * @return rest size of data
+   */
+  int copyDataIntoReadyCK(const void* data, uint32_t length);
 
-    int copyDataIntoNewChunk(const void* data, uint32_t length);
+  int copyDataIntoFreeCK(const void* data, uint32_t length);
 
-    void reduceFreeCK();
+  int copyDataIntoNewChunk(const void* data, uint32_t length);
 
-    void checkWaterLevel();
-    // try to use the ready and free list
-    bool useExistingChunk(uint32_t length) const;
+  void reduceFreeCK();
 
-public:
+  void checkWaterLevel();
+  // try to use the ready and free list
+  bool useExistingChunk(uint32_t length) const;
 
-    uint32_t getAllocSize() const;
+public:
+  uint32_t getAllocSize() const;
 
-    Chunks(uint32_t max_size, uint32_t resident_size);
+  Chunks(uint32_t max_size, uint32_t resident_size);
 
-    virtual ~Chunks();
+  virtual ~Chunks();
 
-    int copyDataIntoChunks(const void*data, uint32_t length);
+  int copyDataIntoChunks(const void* data, uint32_t length);
 
-    /**
-     * If you want use the chunk safety, check capacity before use it.
-     * @param length
-     * @return true: chunk can hold length data
-     *              false: length is too large according to max_size
-     */
-    inline bool checkCapacity(uint32_t length) const 
-    {
-        // existing chunk is full and the threshold is reached
-        if( this->useExistingChunk(length) == false && this->ck_alloc_size+ length > this->c_max_size  ){
-           return false;
-        }    
-        return true;
+  /**
+   * If you want use the chunk safety, check capacity before use it.
+   * @param length
+   * @return true: chunk can hold length data
+   *              false: length is too large according to max_size
+   */
+  inline bool checkCapacity(uint32_t length) const {
+    // existing chunk is full and the threshold is reached
+    if (this->useExistingChunk(length) == false &&
+        this->ck_alloc_size + length > this->c_max_size) {
+      return false;
     }
+    return true;
+  }
 
-    int drainOutWithPipe(std::function<int(const char*, uint32_t)> in_pipe_cb);
-
-    void resetChunks();
+  int drainOutWithPipe(std::function<int(const char*, uint32_t)> in_pipe_cb);
 
+  void resetChunks();
 };
-}
+} // namespace Cache
 #endif
diff --git a/common/src/Cache/NodeTreeWriter.cpp b/common/src/Cache/NodeTreeWriter.cpp
deleted file mode 100644
index edee091bb..000000000
--- a/common/src/Cache/NodeTreeWriter.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright 2020 NAVER Corp
-//
-// Licensed 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.
-////////////////////////////////////////////////////////////////////////////////
-/*
- * NodeTreeWriter.cpp
- *
- *  Created on: Sep 21, 2020
- *      Author: eeliu
- */
-
-#include "NodeTreeWriter.h"
-
-namespace Cache
-{
-} /* namespace Cache */
diff --git a/common/src/Cache/NodeTreeWriter.h b/common/src/Cache/NodeTreeWriter.h
index 295d42acf..a4b6ff8c3 100644
--- a/common/src/Cache/NodeTreeWriter.h
+++ b/common/src/Cache/NodeTreeWriter.h
@@ -1,12 +1,12 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Copyright 2020 NAVER Corp
-// 
+//
 // Licensed 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
@@ -22,38 +22,34 @@
 
 #ifndef COMMON_SRC_CACHE_NODETREEWRITER_H_
 #define COMMON_SRC_CACHE_NODETREEWRITER_H_
+// #include <iostream>
+// #include <sstream>
 #include "json/json.h"
-#include <iostream>
-#include <sstream> 
-
+namespace PP {
 namespace Cache {
 namespace Json = AliasJson;
 /*
  * @author eeliu
  * Sep 21, 2020 2:05:59 PM
  */
-class NodeTreeWriter
-{
+class NodeTreeWriter {
 public:
-    NodeTreeWriter()
-    {
-        builder["commentStyle"] = "None";
-        builder["indentation"] = "";
-    }
-    
-    std::string write(const Json::Value& value)
-    {
-        Json::OStringStream out;
-        std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
-        writer->write(value, &out);
-        return out.str();
-    }
+  NodeTreeWriter() {
+    builder["commentStyle"] = "None";
+    builder["indentation"] = "";
+  }
+
+  std::string write(const Json::Value& value) {
+    Json::OStringStream out;
+    std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
+    writer->write(value, &out);
+    return out.str();
+  }
 
 private:
-    Json::StreamWriterBuilder builder;
-    
+  Json::StreamWriterBuilder builder;
 };
 
 } /* namespace Cache */
-
+} // namespace PP
 #endif /* COMMON_SRC_CACHE_NODETREEWRITER_H_ */
diff --git a/common/src/Cache/SafeSharedState.cpp b/common/src/Cache/SafeSharedState.cpp
deleted file mode 100644
index 989c710d2..000000000
--- a/common/src/Cache/SafeSharedState.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright 2020 NAVER Corp
-//
-// Licensed 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.
-////////////////////////////////////////////////////////////////////////////////
-/*
- * SafeSharedState.cpp
- *
- *  Created on: Sep 16, 2020
- *      Author: eeliu
- */
-
-#include "SafeSharedState.h"
-#include <stdexcept>
-namespace Cache
-{
-bool SafeSharedState::checkTraceLimit(int64_t timestamp)
-{
-  time_t ts = (timestamp != -1) ? (timestamp) : (std::time(NULL));
-
-  if (global_agent_info.trace_limit == -1) { return false; }
-
-  if (global_agent_info.trace_limit == 0) {
-    // block without any checking
-    goto BLOCK;
-  }
-
-  if (this->_global_state->timestamp != ts) {
-    this->_global_state->timestamp = ts;
-    this->_global_state->tick = 0;
-    __sync_synchronize();
-  } else if (this->_global_state->tick >= global_agent_info.trace_limit) {
-    goto BLOCK;
-    // note: if offline, just test it in 5secs
-    // }else if(this->isReady() == false){
-    //     goto BLOCK;
-  } else {
-    __sync_add_and_fetch(&this->_global_state->tick, 1);
-  }
-  return false;
-BLOCK:
-  pp_trace("This span dropped. max_trace_limit:%ld current_tick:%lld onLine:%d", global_agent_info.trace_limit, this->_global_state->tick,
-    this->isReady() ? (1) : (0));
-  return true;
-}
-
-
-SafeSharedState::SafeSharedState()
-{
-  // this->shmObj = ;
-  if (attach_shared_memory(&this->shmObj)) {
-    this->_global_state = (SharedState*) this->shmObj.region;
-    return;
-  }
-
-  throw std::runtime_error("can not attach shm memory");
-}
-
-} /* namespace Cache */
diff --git a/common/src/Cache/SafeSharedState.h b/common/src/Cache/SafeSharedState.h
deleted file mode 100644
index c7726b074..000000000
--- a/common/src/Cache/SafeSharedState.h
+++ /dev/null
@@ -1,115 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright 2020 NAVER Corp
-// 
-// Licensed 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.
-////////////////////////////////////////////////////////////////////////////////
-/*
- * SafeSharedState.h
- *
- *  Created on: Sep 16, 2020
- *      Author: eeliu
- */
-
-#ifndef COMMON_SRC_CACHE_SAFESHAREDSTATE_H_
-#define COMMON_SRC_CACHE_SAFESHAREDSTATE_H_
-#include "common.h"
-#include "SharedObj.h"
-#include<ctime>
-
-namespace Cache {
-
-class SafeSharedState
-{
-
-typedef struct _SharedState{
-        int64_t uid;
-        std::time_t timestamp;
-        int64_t tick;
-        int64_t maxtracelimit;
-        uint64_t starttime;
-        int64_t state;
-    }SharedState;
-
-
-public:
-    static SafeSharedState& instance()
-    {
-        static SafeSharedState _shared;
-        return _shared;
-    }
-
-    void free()
-    {
-
-        this->_global_state = nullptr;
-    }
-
-    bool isReady()
-    {
-        if( (global_agent_info.inter_flag & E_UTEST) == E_UTEST )
-        {
-            return true;
-        }
-
-        if( this->_global_state != nullptr &&
-          (this->_global_state->state & E_READY)){
-            return true ;
-        }
-        return false;
-    }
-
-
-    bool checkTraceLimit(int64_t timestamp);
-
-    void updateStartTime(std::time_t startTime)
-    {
-        (void)startTime;
-        // pp_trace("collector-agent starttime:%ld",startTime);
-        // this->_global_state->starttime = startTime;
-        this->_global_state->state |=  E_READY;
-    }
-
-    std::time_t getStartTime()
-    {
-    //    return this->_global_state->starttime;
-        return get_shared_memory_create_time(&this->shmObj);
-    }
-
-
-    uint64_t generateUniqueId()
-    {
-        return __sync_fetch_and_add(&this->_global_state->uid,1);
-    }
-
-    void resetUniqueId()
-    {
-        this->_global_state->uid = 0;
-        __sync_synchronize();
-    }
-
-private:
-
-    SafeSharedState();
-
-    ~SafeSharedState(){
-        detach_shared_memory(&this->shmObj);
-        this->_global_state = nullptr;
-    }
-    
-    SharedState * _global_state;
-    SharedObject_T shmObj ={nullptr,1024,"pinpoint"} ;
-};
-
-} /* namespace Cache */
-
-#endif /* COMMON_SRC_CACHE_SAFESHAREDSTATE_H_ */
diff --git a/common/src/Cache/SharedObj.cpp b/common/src/Cache/SharedObj.cpp
deleted file mode 100644
index 2fb0eaa04..000000000
--- a/common/src/Cache/SharedObj.cpp
+++ /dev/null
@@ -1,241 +0,0 @@
-/*******************************************************************************
- * Copyright 2019 NAVER Corp
- *
- * Licensed 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.
- ******************************************************************************/
-//
-// Created by eeliu on 12/8/2019.
-//
-
-#include <string.h>
-#include <assert.h>
-
-#include "SharedObj.h"
-
-#if defined(__linux__) || defined(_UNIX) ||defined(__APPLE__)
-#define SHARE_OBJ_HEADER "pinpoint.shm"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdio.h>
-
-
-
-#pragma pack(push, 1)
-typedef struct shared_file_header_s{
-    char header[sizeof(SHARE_OBJ_HEADER)];
-    time_t create_time;
-}SharedFileHeaderT;
-#pragma pack(pop)
-
-static inline int padding_pagesize(int length)
-{
-    int64_t pagesize = sysconf(_SC_PAGESIZE);
-    return (pagesize >= length) ? (pagesize):((length + pagesize)&(~pagesize));
-}
-
-static bool set_shm_file_header(int fd,int length)
-{
-    // extend the new file
-    struct stat _stat;
-    fstat(fd,&_stat);
-    assert(_stat.st_size == 0);
-
-    if(ftruncate(fd,length) == -1)
-    {
-        pp_trace("trancate %d failed:%s",fd,strerror(errno));
-        return false;
-    }
-    // due to phpt, remove this line
-    // pp_trace("ftruncate the size to:%ld",length);
-
-    void* addr = mmap(NULL,length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
-    if(addr == MAP_FAILED)
-    {
-        pp_trace("mmap %d length:%d %s ",fd ,length,strerror(errno));
-        return false;
-    }
-    SharedFileHeaderT* header = (SharedFileHeaderT*)addr;
-    strcpy(header->header,SHARE_OBJ_HEADER);
-    header->create_time = time(NULL);
-    munmap(addr,length);
-
-    return true;
-}
-
-static inline bool get_shm_body_region(int fd,int fileSize,SharedObject_T* obj)
-{
-    void* addr = mmap(NULL,fileSize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
-    if(addr == MAP_FAILED)   
-    {
-        pp_trace("mmap %d length:%d %s ",fd ,fileSize,strerror(errno));
-        return false;
-    }
-    obj->region = (char*)addr + sizeof(SharedFileHeaderT);
-    obj->length = fileSize - sizeof(SharedFileHeaderT);
-    return true;
-} 
-
-static int attach_file(const char* filepath,int length)
-{
-    int flag = O_RDWR;
-    mode_t mode = S_IRUSR |S_IWUSR|S_IRGRP|S_IWGRP;
-    // 2021-05-20 10:30:52 +0800
-    // if address exist, just return true
-    int fd = shm_open(filepath,flag,mode);
-    if( fd > 0)
-    {
-        return fd;
-    }
-
-    // not exist 
-    flag |=  O_CREAT | O_EXCL;
-    fd = shm_open(filepath,flag,mode);
-    if(fd == -1){
-        if(errno == EEXIST ){
-            return attach_file(filepath,length);
-        }
-        pp_trace("%s: shm_open:%s error:%s \n",filepath,__FUNCTION__,strerror(errno));
-        return -1;
-    }
-
-    return set_shm_file_header(fd,length) ? (fd):(-1);
-}
-
-static inline void rename_address(char *address,int max_size,const char* prefix,int length){
-    snprintf(address,max_size,"%s-%u-%d.shm",prefix,getuid(),length);
-}
-
-bool attach_shared_memory(SharedObject_T* shm_obj)
-{
-    assert(shm_obj);
-    char shm_name[NAME_MAX]={0};
-    int realLen = padding_pagesize(shm_obj->length);
-    rename_address(shm_name,NAME_MAX,shm_obj->fileprefix,shm_obj->length);
-
-    int fd = attach_file(shm_name,realLen);
-    if(fd == -1){
-        return false;
-    }
-
-    return get_shm_body_region(fd,realLen,shm_obj);
-}
-
-
-bool detach_shared_memory(SharedObject_T* shm_obj)
-{
-    void* body = shm_obj->region;
-    SharedFileHeaderT* header = (SharedFileHeaderT* )((char*)body - sizeof(SharedFileHeaderT));
-    if(strcmp(header->header,SHARE_OBJ_HEADER) == 0){
-        munmap(header,shm_obj->length+sizeof(SharedFileHeaderT));
-        return true;
-    }
-    pp_trace("not found header mark on shm_obj:%p",shm_obj);
-    return false;
-}
-
-time_t get_shared_memory_create_time(SharedObject_T* shm_obj)
-{
-    assert(shm_obj);
-    void* body = shm_obj->region;
-    SharedFileHeaderT* header = (SharedFileHeaderT* )((char*)body - sizeof(SharedFileHeaderT));
-    return header->create_time;
-}
-
-
-#elif _WIN32
-
-#error "No support on win32"
-
-#include <windows.h>
-
-typedef struct shared_object_s{
-    HANDLE hMap;
-    LPVOID region;
-    int length;
-    const char *address;
-}SharedObject_T;
-
-static SharedObject_T object;
-
-#define SHARE_OBJ_NAME "pinpoint-php.shm"
-
-
-bool pre_init_shared_object()
-{
-    memset(&object,0, sizeof(SharedObject_T));
-    object.address = SHARE_OBJ_NAME;
-    return true;
-}
-
-bool init_shared_obj()
-{
-    assert(object.address);
-
-    LPVOID pBuffer = NULL;
-    HANDLE hMap = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, TRUE, object.address);
-    if(hMap == NULL)
-    {
-        hMap = ::CreateFileMapping(INVALID_HANDLE_VALUE,
-                                   NULL,PAGE_READWRITE, 0,4096,object.address);
-        if(hMap == NULL)
-        {
-            goto FAILED;
-        }
-        pBuffer = ::MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
-        if(pBuffer == NULL){
-            goto FAILED;
-        }
-        object.region = pBuffer;
-    }else{
-        object.hMap =hMap;
-        pBuffer = ::MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
-        if(pBuffer == NULL){
-            goto FAILED;
-        }
-        object.region = pBuffer;
-        object.length = 4096;
-    };
-
-    return true;
-FAILED:
-    if(hMap){
-        ::CloseHandle(hMap);
-    }
-
-    //::UnmapViewOfFile(pBuffer);
-
-    pp_trace("init_shared_obj failed with [%ld]",GetLastError());
-    return false;
-}
-
-
-void detach_shared_obj()
-{
-
-    ::UnmapViewOfFile(object.region);
-    ::CloseHandle(object.hMap);
-}
-
-
-#else
-
-#error "not support platform"
-#endif
-
-
diff --git a/common/src/Cache/SharedObj.h b/common/src/Cache/SharedObj.h
deleted file mode 100644
index cb881334b..000000000
--- a/common/src/Cache/SharedObj.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*******************************************************************************
- * Copyright 2019 NAVER Corp
- *
- * Licensed 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.
- ******************************************************************************/
-//
-// Created by eeliu on 12/8/2019.
-//
-
-#ifndef COMMON_SHAREDOBJ_H
-#define COMMON_SHAREDOBJ_H
-
-#include "common.h"
-#include <time.h>
-#ifdef __cplusplus 
-extern "C"{
-#endif
-
-#ifndef NAME_MAX
-#define NAME_MAX 256
-#endif
-
-#define SHM_FILE_PREFIX_SIZE 32
-typedef struct shared_object_s{
-    void*  region;
-    int    length;
-    char   fileprefix[SHM_FILE_PREFIX_SIZE];
-}SharedObject_T;
-
-// void* fetch_shared_obj_addr();
-// bool checking_and_init();
-// void detach_shared_obj();
-
-bool attach_shared_memory(SharedObject_T* shm_obj);
-bool detach_shared_memory(SharedObject_T* shm_obj);
-time_t get_shared_memory_create_time(SharedObject_T* shm_obj);
-#ifdef __cplusplus
-}
-#endif
-
-#endif //COMMON_SHAREDOBJ_H
diff --git a/common/src/Cache/State.cpp b/common/src/Cache/State.cpp
new file mode 100644
index 000000000..dbeab2458
--- /dev/null
+++ b/common/src/Cache/State.cpp
@@ -0,0 +1,53 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright 2024 NAVER Corp
+//
+// Licensed 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.
+////////////////////////////////////////////////////////////////////////////////
+
+#include "State.h"
+#include "common.h"
+#include "header.h"
+namespace PP {
+ProcessState::ProcessState(int64_t trace_limit)
+    : starttime_(get_unix_time_ms()), trace_limit_(trace_limit) {}
+
+void ProcessState::SetStartTime(uint64_t start_time) {
+  pp_trace("set start time:%lld", start_time);
+  if (!ready_) {
+    starttime_ = start_time;
+    ready_ = true;
+  }
+}
+
+bool ProcessState::CheckTraceLimit(int64_t timestamp) {
+  time_t now = (timestamp != -1) ? (timestamp) : (std::time(NULL));
+  if (trace_limit_ == -1) {
+    return false;
+  } else if (trace_limit_ == 0) {
+    goto BLOCK;
+  }
+
+  if (timestamp_ != now) {
+    timestamp_ = now;
+    tick_ = 0;
+  } else if (++tick_ >= trace_limit_) {
+    goto BLOCK;
+  }
+  return false;
+BLOCK:
+  pp_trace("This span dropped. max_trace_limit:%ld current_tick:%lld onLine:%d", trace_limit_,
+           tick_, this->IsReady() ? (1) : (0));
+  return true;
+}
+
+} // namespace PP
diff --git a/common/src/Cache/State.h b/common/src/Cache/State.h
new file mode 100644
index 000000000..6ede83acb
--- /dev/null
+++ b/common/src/Cache/State.h
@@ -0,0 +1,58 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright 2024 NAVER Corp
+//
+// Licensed 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.
+////////////////////////////////////////////////////////////////////////////////
+#pragma once
+
+#include <cstdint>
+#include <ctime>
+#include <memory>
+#include <atomic>
+namespace PP {
+class State {
+public:
+  virtual int64_t GetUniqueId() = 0;
+  virtual uint64_t GetStartTime() = 0;
+  virtual void SetStartTime(uint64_t) = 0;
+  virtual bool IsReady() = 0;
+  virtual void ResetUniqueID() = 0;
+  virtual bool CheckTraceLimit(int64_t timestamp) = 0;
+};
+
+class ProcessState : public State {
+public:
+  int64_t GetUniqueId() override { return uuid_++; }
+  bool IsReady() override { return ready_; }
+  bool CheckTraceLimit(int64_t timestamp) override;
+  void ResetUniqueID() override { uuid_ = 0; }
+  uint64_t GetStartTime() override { return starttime_; }
+  void SetStartTime(uint64_t start_time) override;
+
+public:
+  explicit ProcessState(int64_t trace_limit);
+  ProcessState(const ProcessState&) = delete;
+  virtual ~ProcessState() = default;
+
+private:
+  int64_t tick_ = {0};
+  std::time_t timestamp_ = {0};
+  // default is the unix time in ms
+  uint64_t starttime_;
+  int64_t trace_limit_;
+  std::atomic<std::int64_t> uuid_ = {0};
+  bool ready_ = {false};
+};
+using StatePtr = std::unique_ptr<State>;
+
+} // namespace PP
\ No newline at end of file
diff --git a/common/src/ConnectionPool/SpanConnectionPool.cpp b/common/src/ConnectionPool/SpanConnectionPool.cpp
deleted file mode 100644
index 6a91e37bd..000000000
--- a/common/src/ConnectionPool/SpanConnectionPool.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright 2020 NAVER Corp
-//
-// Licensed 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.
-////////////////////////////////////////////////////////////////////////////////
-/*
- * SpanConnectionPool.cpp
- *
- *  Created on: Aug 28, 2020
- *      Author: eeliu
- */
-
-#include "SpanConnectionPool.h"
-#include "Cache/SafeSharedState.h"
-#include <sstream>
-
-namespace ConnectionPool
-{
-using Cache::SafeSharedState;
-namespace Json = AliasJson;
-SpanConnectionPool::SpanConnectionPool(const char *co_host) : co_host(co_host), con_counter(0) { this->_cPool.push(this->createTrans()); }
-
-TransConnection SpanConnectionPool::createTrans()
-{
-  TransConnection _connect(new TransLayer(this->co_host));
-  using namespace std::placeholders;
-  // _connect->registerPeerMsgCallback(
-  //     std::bind(&SpanConnectionPool::_handleMsgFromCollector,this,_1,_2,_3),
-  //     std::bind(&SpanConnectionPool::_handleTransLayerState,this,_1));
-
-  _connect->registerPeerMsgCallback(std::bind(&SpanConnectionPool::_handleMsgFromCollector, this, _1, _2, _3), nullptr);
-  this->con_counter++;
-
-  return _connect;
-}
-
-//@obsoleted
-// void SpanConnectionPool::_handleTransLayerState(int state)
-// {
-//     if(state == E_OFFLINE)
-//     {
-//         if(global_agent_info.inter_flag & E_UTEST){
-//             SafeSharedState::instance().markONLine();
-//         }
-//         else{
-//             SafeSharedState::instance().markOFFLine();
-//         }
-//     }
-// }
-
-void SpanConnectionPool::_handleMsgFromCollector(int type, const char *buf, size_t len)
-{
-  switch (type) {
-    case RESPONSE_AGENT_INFO:
-      this->_handle_agent_info(type, buf, len);
-      break;
-
-    default:
-      break;
-  }
-}
-
-void SpanConnectionPool::_handle_agent_info(int type, const char *buf, size_t len)
-{
-  Json::Value root;
-  (void) type;
-  Json::CharReaderBuilder builder;
-  builder["collectComments"] = false;
-
-  std::istringstream inss(std::string(buf, len));
-  JSONCPP_STRING errs;
-  bool ok = parseFromStream(builder, inss, &root, &errs);
-
-  if (ok) {
-    // pp_trace("collector-agent say:%s",root.toStyledString().c_str());
-
-    if (root.isMember("time")) { SafeSharedState::instance().updateStartTime(atoll(root["time"].asCString())); }
-  } else {
-    pp_trace("Recieve invalid msg: %.*s from Collector-agent, reason: %s", (int) len, buf, errs.c_str());
-  }
-}
-
-} /* namespace ConnectionPool */
diff --git a/common/src/ConnectionPool/SpanConnectionPool.h b/common/src/ConnectionPool/SpanConnectionPool.h
index 5d142ce1a..85188bfbc 100644
--- a/common/src/ConnectionPool/SpanConnectionPool.h
+++ b/common/src/ConnectionPool/SpanConnectionPool.h
@@ -1,12 +1,12 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Copyright 2020 NAVER Corp
-// 
+//
 // Licensed 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
@@ -22,73 +22,69 @@
 
 #ifndef COMMON_SRC_CONNECTPOOL_SPANCONNECTIONPOOL_H_
 #define COMMON_SRC_CONNECTPOOL_SPANCONNECTIONPOOL_H_
-#include <iostream>
 #include <stack>
 #include <memory>
 #include <mutex>
-#include <atomic>  
+#include <utility>
+#include <vector>
 
 #include "TransLayer.h"
 
 namespace ConnectionPool {
 
-typedef std::unique_ptr<TransLayer> TransConnection;
-
-class SpanConnectionPool
-{
+using RouteMapValueVec = std::vector<RouteMapValueType>;
+class SpanConnectionPool {
 public:
-    SpanConnectionPool(SpanConnectionPool&) =delete;
-    SpanConnectionPool& operator=(const SpanConnectionPool&) =delete;
-    SpanConnectionPool(SpanConnectionPool&&) =delete;
-    SpanConnectionPool& operator=(SpanConnectionPool&&) =delete;
+  SpanConnectionPool(SpanConnectionPool&) = delete;
+  SpanConnectionPool& operator=(const SpanConnectionPool&) = delete;
+  SpanConnectionPool(SpanConnectionPool&&) = delete;
+  SpanConnectionPool& operator=(SpanConnectionPool&&) = delete;
 
 public:
-    SpanConnectionPool(const char* co_host);
-    //for delay initialization
-    SpanConnectionPool(){
-        this->con_counter = 0;
-    };
+  SpanConnectionPool(const char* co_host, RouteMapValueVec&& value_vec)
+      : co_host(co_host), con_counter(0), routeVec_(value_vec) {
+    this->_pool.push(this->createConnection(routeVec_));
+  }
+
+  virtual ~SpanConnectionPool() {}
 
-    void initPool(const char* co_host)
-    {
-        this->co_host = co_host;
-        this->_cPool.push(this->createTrans());
+  TransLayerPtr get() {
+    std::lock_guard<std::mutex> _safe(this->_lock);
+    if (this->_pool.empty()) {
+      return createConnection(routeVec_);
+    } else {
+      TransLayerPtr _con = std::move(_pool.top());
+      _pool.pop();
+      assert(_con);
+      return _con;
     }
+  }
 
-    virtual ~SpanConnectionPool(){}
+  void free(TransLayerPtr& con) {
+    std::lock_guard<std::mutex> _safe(this->_lock);
+    this->_pool.emplace(std::move(con));
+  }
 
-    TransConnection get()
-    {
-        std::lock_guard<std::mutex> _safe(this->_lock);
-        if(this->_cPool.empty())
-        {
-            return TransConnection(new TransLayer(this->co_host));
-        }else{
-            TransConnection _con = std::move(_cPool.top());
-            _cPool.pop();
-            assert(_con);
-            return _con;
-        }
-    }
+private:
+  TransLayerPtr createConnection(const RouteMapValueVec& value_vec) {
+    TransLayerPtr _connect(new TransLayer(this->co_host));
+    using namespace std::placeholders;
 
-    void free(TransConnection& con)
-    {
-        std::lock_guard<std::mutex> _safe(this->_lock);
-        this->_cPool.push(std::move(con));
+    for (auto& value : value_vec) {
+      _connect->RegPeerMsgCallback(value.first, value.second);
     }
 
-private:
-    void _handleMsgFromCollector(int type,const char* buf,size_t len);
-    
-    void _handle_agent_info(int type,const char* buf,size_t len);
+    this->con_counter++;
 
-    TransConnection createTrans();
-    // void _handleTransLayerState(int state);
+    return _connect;
+  }
+  // void _handleTransLayerState(int state);
 private:
-    std::string co_host;
-    uint32_t con_counter;
-    std::stack<TransConnection> _cPool;
-    std::mutex _lock;
+  std::string co_host;
+  uint32_t con_counter;
+  std::stack<TransLayerPtr> _pool;
+  std::mutex _lock;
+  RouteMapValueVec routeVec_;
 };
 
 } /* namespace ConnectionPool */
diff --git a/common/src/ConnectionPool/TransLayer.cpp b/common/src/ConnectionPool/TransLayer.cpp
index 020700af2..6ae12d206 100644
--- a/common/src/ConnectionPool/TransLayer.cpp
+++ b/common/src/ConnectionPool/TransLayer.cpp
@@ -14,14 +14,34 @@
  * the License.
  ******************************************************************************/
 #include "TransLayer.h"
-#include <netdb.h>
+#include "ConnectionPool/sockets.h"
+#include "common.h"
+#include <cctype>
+#include <ctime>
 namespace ConnectionPool {
+
+int strcasecmp_(const char* s1, const char* s2) {
+  const char* p_s1 = s1;
+  const char* p_s2 = s2;
+  while (*p_s1 != '\0' && *p_s2 != '\0') {
+    int p1 = static_cast<int>(*p_s1);
+    int p2 = static_cast<int>(*p_s2);
+    if (std::toupper(p1) != std::toupper(p2)) {
+      return p1 - p2;
+    } else {
+      p_s1++;
+      p_s2++;
+    }
+  }
+  return *p_s2 == '\0' ? 0 : -1;
+}
+
 /**
  * remote: localhost:port
  */
-int TransLayer::connect_stream_remote(const char* remote) {
-  int offset = strlen(remote) - 1;
-
+SOCKET TransLayer::connect_stream_remote(const char* remote) {
+  pp_trace("agent try to connect:(%s)", remote);
+  int offset = (int)strlen(remote) - 1;
   while (remote[offset] != ':') {
     offset--;
     if (offset <= 0) {
@@ -32,15 +52,14 @@ int TransLayer::connect_stream_remote(const char* remote) {
 
   std::string hostname(remote, offset);
   const char* port_str = remote + offset + 1;
-  // int port = atoi(remote+offset+1);
 
   struct addrinfo hints;
   struct addrinfo *result, *rp;
   memset(&hints, 0, sizeof(hints));
   hints.ai_family = AF_UNSPEC;     /* Allow IPv4 or IPv6 */
   hints.ai_socktype = SOCK_STREAM; /* Datagram socket */
-  hints.ai_flags = 0;
-  hints.ai_protocol = 0; /* Any protocol */
+  // hints.ai_flags = 0;
+  hints.ai_protocol = IPPROTO_TCP; /* Any protocol */
 
   int s = 0;
   s = getaddrinfo(hostname.c_str(), port_str, &hints, &result);
@@ -48,35 +67,41 @@ int TransLayer::connect_stream_remote(const char* remote) {
     pp_trace("getaddrinfo failed: hostname:%s msg:%s ", hostname.c_str(), gai_strerror(s));
     return -1;
   }
-  int sfd = -1;
+  SOCKET sfd = INVALID_SOCKET;
   for (rp = result; rp != NULL; rp = rp->ai_next) {
     sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
 
-    struct linger fd_linger = {1, 1}; // open and 1 second
     // mark it as nonblock
-    fcntl(sfd, F_SETFL, fcntl(sfd, F_GETFL, 0) | O_NONBLOCK);
+    set_socket_none_block(sfd);
+    struct linger fd_linger = {1, 1}; // open and 1 second
+#ifdef _WIN32
+    setsockopt(sfd, SOL_SOCKET, SO_LINGER, (char*)&fd_linger, sizeof(fd_linger));
+#else
     setsockopt(sfd, SOL_SOCKET, SO_LINGER, &fd_linger, sizeof(fd_linger));
-
+#endif
     if (sfd == -1)
       continue;
     int ret = connect(sfd, rp->ai_addr, rp->ai_addrlen);
     if (ret == 0) {
       break;
     } else if (ret == -1) {
-      if (errno == EALREADY || errno == EINPROGRESS)
+      if (nonblock_error(err_code())) {
         break;
+      } else {
+        pp_trace("connect failed. error=%d", err_code());
+      }
     }
-
-    close(sfd);
-    sfd = -1;
+    close_socket(sfd);
+    sfd = INVALID_SOCKET;
   }
   freeaddrinfo(result);
 
   return sfd;
 }
-
+#ifdef __linux__
 int TransLayer::connect_unix_remote(const char* remote) {
-  int fd = -1;
+  pp_trace("agent try to connect:(%s)", remote);
+  SOCKET fd = -1;
 #if defined(__APPLE__)
   struct sockaddr_un u_sock = {0, 0, {0}};
 #else
@@ -84,8 +109,8 @@ int TransLayer::connect_unix_remote(const char* remote) {
 #endif
   struct linger fd_linger = {1, 1}; // open and 1 second
   if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
-    pp_trace(" get socket error,(%s)", strerror(errno));
-    goto ERROR;
+    pp_trace(" get socket error error_code = %d", err_code());
+    goto ERR_NETWORK;
   }
 
   u_sock.sun_family = AF_UNIX;
@@ -97,85 +122,126 @@ int TransLayer::connect_unix_remote(const char* remote) {
   setsockopt(fd, SOL_SOCKET, SO_LINGER, &fd_linger, sizeof(fd_linger));
 
   if (connect(fd, (struct sockaddr*)&u_sock, sizeof(u_sock)) != 0) {
-    if (errno != EALREADY || errno != EINPROGRESS) {
-      pp_trace("connect:(%s) failed as (%s)", remote, strerror(errno));
-      goto ERROR;
+    if (err_code() != EALREADY || err_code() != EINPROGRESS) {
+      pp_trace("connect:(%s) failed error_code: %d", remote, err_code());
+      goto ERR_NETWORK;
     }
   }
   pp_trace("connected to %s", remote);
 
   return fd;
 
-ERROR:
+ERR_NETWORK:
   if (fd > 0) {
     close(fd);
   }
 
   return -1;
 }
+#endif
+SOCKET TransLayer::connect_remote(const char* statement) {
+  SOCKET fd = -1;
+  int socket_type_offset = 0;
+  // const char* substring = NULL;
+  if (statement == NULL || statement[0] == '\0') {
+    goto E_INVALID_FORMAT;
+  }
 
-size_t TransLayer::trans_layer_pool(uint32_t timeout) {
+  // check last connect time
+  if (std::time(nullptr) < this->lastConnectTime + RECONNECT_TIME_SEC) {
+    goto RECONNECT_WAITING;
+  } else {
+    this->lastConnectTime = std::time(nullptr);
+  }
+
+  /// unix
+#ifdef __linux__
+  socket_type_offset = strcasecmp_(statement, UNIX_SOCKET);
+  if (socket_type_offset == 0) {
+    // sizeof = len +1, so substring -> /tmp/collector.sock
+    // substring = substring + strlen(UNIX_SOCKET);
+    fd = connect_unix_remote(statement + strlen(TCP_SOCKET));
+    c_fd = fd;
+    goto DONE;
+  }
+#endif
+  ///  tcp tcp:localhost:port
+  socket_type_offset = strcasecmp_(statement, TCP_SOCKET);
+  if (socket_type_offset == 0) {
+    fd = TransLayer::connect_stream_remote(statement + strlen(TCP_SOCKET));
+    c_fd = fd;
+    goto DONE;
+  }
+
+E_INVALID_FORMAT:
+  pp_trace("remote is not valid:%s", statement);
+  return -1;
+RECONNECT_WAITING:
+  return -1;
+DONE:
+  this->_state |= (S_ERROR | S_READING | S_WRITING);
+  return fd;
+}
+
+size_t TransLayer::PoolEventOnce(uint32_t timeout) {
   if (c_fd == -1) {
-    pp_trace("agent try to connect:(%s)", this->co_host.c_str());
     connect_remote(this->co_host.c_str());
-
     if (c_fd == -1) {
       return -1;
     }
   }
 
-  int fd = c_fd;
+  SOCKET fd = c_fd;
   fd_set wfds, efds, rfds;
   FD_ZERO(&efds);
 
   FD_ZERO(&wfds);
   FD_ZERO(&rfds);
 
-  if (this->_state & S_ERROR) {
-    FD_SET(fd, &efds);
-  }
+  // if (this->_state & S_ERROR) {
+  FD_SET(fd, &efds);
+  // }
 
   if (this->_state & S_WRITING) {
     FD_SET(fd, &wfds);
   }
 
-  if (this->_state & S_READING) {
-    FD_SET(fd, &rfds);
-  }
+  // if (this->_state & S_READING) {
+  FD_SET(fd, &rfds);
+  // }
 
-  struct timeval tv = {0, (int)timeout * 1000};
+  struct timeval tv = {timeout / 1000, (int)timeout % 1000};
 
   int retval = select(fd + 1, &rfds, &wfds, &efds, &tv);
-  if (retval == -1) {
+  if (retval == SOCKET_ERROR) {
     // it helped address the macosx issue
-    pp_trace("select return error:(%s)", strerror(errno));
+    pp_trace("select return error_code=%d", err_code());
     return -1;
   } else if (retval > 0) {
     if ((this->_state & S_ERROR) && FD_ISSET(fd, &efds)) {
-      pp_trace("select fd:(%s) ", strerror(errno));
-      goto ERROR;
+      pp_trace("error event");
+      goto ERR_NETWORK;
     }
 
     if ((this->_state & S_WRITING) && FD_ISSET(fd, &wfds)) {
+      pp_trace("write event");
       if (_send_msg_to_collector() == -1) {
-        goto ERROR;
+        goto ERR_NETWORK;
       }
     }
 
     if ((this->_state & S_READING) && FD_ISSET(fd, &rfds)) {
-      if (_recv_msg_from_collector() == -1) {
+      pp_trace("read event");
+      if (recvByteStream() == -1) {
         pp_trace("recv_msg_from_collector error");
-        goto ERROR;
+        goto ERR_NETWORK;
       }
     }
-  } else {
-    // timeout do nothing
-    // total =0  ,timeout
   }
-
+  // timeout
   return 0;
 
-ERROR:
+ERR_NETWORK:
 
   _reset_remote();
 
diff --git a/common/src/ConnectionPool/TransLayer.h b/common/src/ConnectionPool/TransLayer.h
index 2f8ba6de2..ad2b9f429 100644
--- a/common/src/ConnectionPool/TransLayer.h
+++ b/common/src/ConnectionPool/TransLayer.h
@@ -22,21 +22,13 @@
 
 #ifndef INCLUDE_PPTRANSLAYER_H_
 #define INCLUDE_PPTRANSLAYER_H_
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <fcntl.h>
+#include <cstdint>
 #include <functional>
-#include <iostream>
-#include <arpa/inet.h>
-#include <iostream>
-#include <functional>
-
+#include <map>
+#include <memory>
 #include "common.h"
 #include "Cache/Chunk.h"
+#include "sockets.h"
 
 namespace ConnectionPool {
 using Cache::Chunks;
@@ -44,10 +36,14 @@ using Cache::Chunks;
 // note update chunk watermark size
 // for keep large span.
 // BIG span is not friendly to pinpoint-web, show everything equals nothing
-
+#define IN_MSG_BUF_SIZE 4096
 const uint32_t _chunk_max_size = 10 * 1024 * 1024; // 10M
 const uint32_t _chunk_hold_size = 40 * 1024;       // 40k
 
+using MsgHandleFunc = std::function<void(int type, const char* buf, size_t len)>;
+using RouterMsgMap = std::map<int, MsgHandleFunc>;
+using RouteMapValueType = RouterMsgMap::value_type;
+
 class TransLayer {
   enum E_STATE { S_WRITING = 0x1, S_READING = 0x2, S_ERROR = 0x4 };
 
@@ -56,106 +52,45 @@ class TransLayer {
       : co_host(co_host), chunks(_chunk_max_size, _chunk_hold_size), _state(0), lastConnectTime(0),
         c_fd(-1) {}
 
-  void registerPeerMsgCallback(
-      std::function<void(int type, const char* buf, size_t len)> _peerMsgCallback,
-      std::function<void(int state)> chann_error_cb) {
-    if (_peerMsgCallback) {
-      this->peerMsgCallback = _peerMsgCallback;
-    }
-
-    if (chann_error_cb) {
-      this->chann_error_cb = chann_error_cb;
-    }
+  void RegPeerMsgCallback(int type, MsgHandleFunc call_back) { msgRouteMap_[type] = call_back; }
+  void RegStatusChangedCallBack(std::function<void(int)> call_back) {
+    statusChangedCallback_ = call_back;
   }
 
-  size_t trans_layer_pool(uint32_t);
-
-  bool copy_into_send_buffer(const std::string& data);
+  size_t PoolEventOnce(uint32_t);
 
-  // void sendMsgToAgent(const char* pbuf,uint32_t len)
-  // {
-  //     if ( this->chunks.copyDataIntoChunks(pbuf,len) != 0)
-  //     {
-  //         pp_trace("Send buffer is full. size: [%d]",len);
-  //         return ;
-  //     }
-  //     this->_state |=  S_WRITING;
-  // }
+  void Reset() { ResetMsgHandler(); }
 
+  bool copy_into_send_buffer(const std::string& data);
   /**
    * retry in three times
    * @param timeout
    */
-  void forceFlushMsg(uint32_t timeout) {
-#define MAX_RETRY_TIEMS 3
+  void SyncSendAll(uint32_t maxTimeout) {
+#define MAX_RETRY_ITEMS 20
     int retry = 0;
-    timeout = (timeout > 3) ? (timeout) : (3);
-    while ((this->_state & S_WRITING) && retry < MAX_RETRY_TIEMS) {
-      this->trans_layer_pool(timeout / 3);
+    while ((this->_state & S_WRITING) && retry < MAX_RETRY_ITEMS) {
+      this->PoolEventOnce(maxTimeout);
       retry++;
     }
-#undef MAX_RETRY_TIEMS
+#undef MAX_RETRY_ITEMS
   }
 
   ~TransLayer() {
     if (this->c_fd != -1) {
-      close(this->c_fd);
+      close_socket(this->c_fd);
     }
   }
 
-#ifdef UTEST
-
-#else
+#ifndef UTEST
 private:
 #endif
 
-  static int connect_stream_remote(const char* remote);
-
+  static SOCKET connect_stream_remote(const char* remote);
+#ifdef __linux__
   static int connect_unix_remote(const char* remote);
-
-  int connect_remote(const char* statement) {
-    int fd = -1;
-    const char* substring = NULL;
-    if (statement == NULL || statement[0] == '\0') {
-      goto ERROR;
-    }
-
-    // check last connect time
-    if (time(NULL) < this->lastConnectTime + RECONNECT_TIME_SEC) {
-      goto RECONNECT_WAITING;
-    } else {
-      this->lastConnectTime = time(NULL);
-    }
-
-    /// unix
-    substring = strcasestr(statement, UNIX_SOCKET);
-    if (substring == statement) {
-      // sizeof = len +1, so substring -> /tmp/collector.sock
-      substring = substring + strlen(UNIX_SOCKET);
-      fd = connect_unix_remote(substring);
-      c_fd = fd;
-      goto DONE;
-    }
-
-    ///  tcp tcp:localhost:port
-    substring = strcasestr(statement, TCP_SOCKET);
-    if (substring == statement) {
-      // sizeof = len +1, so substring -> /tmp/collector.sock
-      substring = substring + strlen(TCP_SOCKET);
-      fd = TransLayer::connect_stream_remote(substring);
-      c_fd = fd;
-      goto DONE;
-    }
-
-  ERROR:
-    pp_trace("remote is not valid:%s", statement);
-    return -1;
-  RECONNECT_WAITING:
-    return -1;
-  DONE:
-    this->_state |= (S_ERROR | S_READING | S_WRITING);
-    return fd;
-  }
+#endif
+  SOCKET connect_remote(const char* statement);
 
   int _send_msg_to_collector() {
     return chunks.drainOutWithPipe(
@@ -165,13 +100,13 @@ class TransLayer {
   void _reset_remote() {
     if (c_fd > 0) {
       pp_trace("reset peer:%d", c_fd);
-      close(c_fd);
+      close_socket(c_fd);
       c_fd = -1;
       this->_state = 0;
     }
 
-    if (chann_error_cb) {
-      chann_error_cb(E_OFFLINE);
+    if (statusChangedCallback_) {
+      statusChangedCallback_(E_OFFLINE);
     }
 
     chunks.resetChunks();
@@ -181,25 +116,24 @@ class TransLayer {
     const char* buf = data;
     uint32_t buf_ofs = 0;
     while (buf_ofs < length) {
-#ifdef __APPLE__
-      ssize_t ret = send(c_fd, buf + buf_ofs, length - buf_ofs, 0);
+#if defined(__APPLE__) || defined(_WIN32)
+      int ret = send(c_fd, buf + buf_ofs, length - buf_ofs, 0);
 #else
       ssize_t ret = send(c_fd, buf + buf_ofs, length - buf_ofs, MSG_NOSIGNAL);
 #endif
-
       if (ret > 0) {
         buf_ofs += (uint32_t)ret;
         pp_trace("fd %d send size %ld", c_fd, ret);
       } else if (ret == -1) {
-        if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
+        if (nonblock_error(err_code())) {
           this->_state |= S_WRITING;
           return buf_ofs;
         }
-        pp_trace("_do_write_data@%d send data error:(%s) fd:(%d)", __LINE__, strerror(errno), c_fd);
+        pp_trace("_do_write_data@%d send data error:(%d) fd:(%d)", __LINE__, err_code(), c_fd);
         return -1;
       } else {
-        pp_trace("_do_write_data@%d send data return 0 error:(%s) fd:(%d)", __LINE__,
-                 strerror(errno), c_fd);
+        pp_trace("_do_write_data@%d send data return 0 error:(%d) fd:(%d)", __LINE__, err_code(),
+                 c_fd);
         return -1;
       }
     }
@@ -208,13 +142,13 @@ class TransLayer {
     return length;
   }
 
-  int _recv_msg_from_collector() {
+  int recvByteStream() {
     int next_size = 0;
     while (next_size < IN_MSG_BUF_SIZE) {
       int ret = recv(c_fd, in_buf + next_size, IN_MSG_BUF_SIZE - next_size, 0);
       if (ret > 0) {
         int total = ret + next_size;
-        int msg_offset = handle_msg_from_collector(in_buf, total);
+        int msg_offset = HandleMsgStream(in_buf, total);
         if (msg_offset < total) {
           next_size = total - msg_offset;
           memcpy(in_buf, in_buf + msg_offset, next_size);
@@ -222,63 +156,65 @@ class TransLayer {
           next_size = 0;
         }
       } else if (ret == 0) {
-        // peer close
+        pp_trace("server closed. error:%d", err_code());
         return -1;
       } else {
-        if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
+        if (nonblock_error(err_code())) {
           return 0;
+        } else {
+          pp_trace("recv failed. error:%d", err_code());
+          return -1;
         }
-        pp_trace("recv with error:%s", strerror(errno));
-        return -1;
       }
     }
+    pp_trace("recv buf full,maybe a bug");
     return 0;
   }
 
-  int handle_msg_from_collector(const char* buf, size_t len) {
-    size_t offset = 0;
+  int HandleMsgStream(const char* buf, int len) {
+    int offset = 0;
     while (offset + 8 <= len) {
       Header* header = (Header*)buf;
 
-      uint32_t body_len = ntohl(header->length);
+      int body_len = (int)ntohl(header->length);
 
       if (8 + body_len > len) {
         return offset;
       }
 
       uint32_t type = ntohl(header->type);
-      if (peerMsgCallback) {
-        peerMsgCallback(type, buf + 8, len - 8);
+      auto has = msgRouteMap_.find(type);
+      if (has != msgRouteMap_.end()) {
+        msgRouteMap_[type](type, buf + 8, len - 8);
+      } else {
+        pp_trace("unsupported message type:%d from server", type);
       }
-
-      // switch(type){
-      // case RESPONSE_AGENT_INFO:
-      // // TODO add agent_info update
-      //     // handle_agent_info(RESPONSE_AGENT_INFO, buf+8,len - 8);
-      //     break;
-      // default:
-      //     pp_trace("unsupport type:%d",type);
-      // }
-
       offset += (8 + body_len);
     }
     return offset;
   }
 
+private:
+  void ResetMsgHandler() {
+    statusChangedCallback_ = nullptr;
+    msgRouteMap_.clear();
+  }
+
 private:
   const std::string& co_host;
   Chunks chunks;
   int32_t _state;
   char in_buf[IN_MSG_BUF_SIZE] = {0};
-  std::function<void(int)> chann_error_cb;
-  std::function<void(int type, const char* buf, size_t len)> peerMsgCallback;
+  std::function<void(int)> statusChangedCallback_;
+  RouterMsgMap msgRouteMap_;
   const static char* UNIX_SOCKET;
   const static char* TCP_SOCKET;
   time_t lastConnectTime;
 
 public:
-  int c_fd;
+  SOCKET c_fd;
 };
+using TransLayerPtr = std::unique_ptr<TransLayer>;
 } // namespace ConnectionPool
 
 #endif /* INCLUDE_PPTRANSLAYER_H_ */
diff --git a/common/src/ConnectionPool/sockets.h b/common/src/ConnectionPool/sockets.h
new file mode 100644
index 000000000..61d512445
--- /dev/null
+++ b/common/src/ConnectionPool/sockets.h
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright 2019 NAVER Corp
+ *
+ * Licensed 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.
+ ******************************************************************************/
+#pragma once
+// porting from https://learn.microsoft.com/en-us/windows/win32/winsock/complete-client-code
+#if defined(__linux__) || defined(__APPLE__)
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+typedef int SOCKET;
+#define INVALID_SOCKET -1
+#define SOCKET_ERROR -1
+
+inline void set_socket_none_block(SOCKET sock) {
+  fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK);
+}
+
+inline int close_socket(SOCKET fd) { return close(fd); }
+inline int socket_init() { return 0; }
+inline void sock_cleanup() {}
+inline int err_code() { return errno; }
+inline bool nonblock_error(int err_code) {
+  return err_code == EAGAIN || err_code == EWOULDBLOCK || err_code == EINTR ||
+         err_code == EINPROGRESS;
+}
+#elif defined(_WIN32)
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windows.h>
+#pragma comment(lib, "Ws2_32.lib")
+#pragma comment(lib, "Mswsock.lib")
+#pragma comment(lib, "AdvApi32.lib")
+typedef SOCKET SOCKET;
+
+inline void set_socket_none_block(SOCKET sock) {
+  u_long mode = 1;
+  ioctlsocket(sock, FIONBIO, &mode);
+}
+
+inline int close_socket(SOCKET fd) { return closesocket(fd); }
+
+inline int err_code() { return WSAGetLastError(); }
+
+inline int socket_init() {
+  WSADATA wsaData;
+  return WSAStartup(MAKEWORD(2, 2), &wsaData);
+}
+inline void sock_cleanup() { WSACleanup(); }
+inline bool nonblock_error(int err_code) { return err_code == WSAEWOULDBLOCK; }
+#endif
\ No newline at end of file
diff --git a/common/src/Context/ContextType.cpp b/common/src/Context/ContextType.cpp
deleted file mode 100644
index 3d2a27595..000000000
--- a/common/src/Context/ContextType.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright 2020 NAVER Corp
-//
-// Licensed 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.
-////////////////////////////////////////////////////////////////////////////////
-/*
- * ContextType.cpp
- *
- *  Created on: Aug 27, 2020
- *      Author: eeliu
- */
-
-#include "ContextType.h"
-
-namespace Context
-{
-} /* namespace Context */
diff --git a/common/src/Context/ContextType.h b/common/src/Context/ContextType.h
index 6353d2295..7e774411b 100644
--- a/common/src/Context/ContextType.h
+++ b/common/src/Context/ContextType.h
@@ -23,7 +23,6 @@
 #ifndef COMMON_SRC_CONTEXTTYPE_H_
 #define COMMON_SRC_CONTEXTTYPE_H_
 
-#include <stdint.h>
 #include <string>
 #include <stdexcept>
 
@@ -36,7 +35,7 @@ class ContextType {
   virtual ~ContextType() {}
 
   virtual ctype typeIs() { throw std::logic_error("not implementation"); }
-  virtual std::string asStringValue() { throw std::logic_error("not implementation"); }
+  virtual std::string& asStringValue() { throw std::logic_error("not implementation"); }
   virtual long asLongValue() { throw std::logic_error("not implementation"); }
 };
 
@@ -46,7 +45,7 @@ class StringContextType : public ContextType {
 
   virtual ctype typeIs() override { return "String"; }
 
-  virtual std::string asStringValue() override { return this->_value; }
+  virtual std::string& asStringValue() override { return this->_value; }
 
   virtual ~StringContextType() {}
 
diff --git a/common/src/Logging.cpp b/common/src/Logging.cpp
index 2edc9894f..aaeef584a 100644
--- a/common/src/Logging.cpp
+++ b/common/src/Logging.cpp
@@ -17,39 +17,42 @@
 #include "common.h"
 
 #include <stdio.h>
-
+#include <stdarg.h>
 #if defined(__linux__) || defined(_UNIX)
 #include <sys/types.h>
 #include <sys/syscall.h>
-#include <stdarg.h>
 #include <unistd.h>
-#define gettid() syscall(SYS_gettid)
-#define getOSPid getpid
+inline int get_os_pid() { return syscall(SYS_gettid); }
+inline long get_tid() { return getpid(); }
 #endif
 
 #if defined(__APPLE__)
 #include <sys/types.h>
 #include <sys/syscall.h>
-#include <stdarg.h>
 #include <unistd.h>
-#define gettid() (long)getpid()
-#define getOSPid getpid
+
+inline int get_os_pid() { return getpid(); }
+inline long get_tid() { return getpid(); }
 #endif
 
 #if defined(_WIN32)
+#include <windows.h>
 #include <processthreadsapi.h>
-#define getOSPid GetCurrentProcessId
+inline int get_os_pid() { return GetCurrentProcessId(); }
+inline long get_tid() { return GetCurrentThreadId(); }
 #endif
 
-static log_msg_cb _error_cb;
+static log_msg_cb log_call_back_;
+static bool enable_trace_ = 0;
+#define LOG_SIZE 40960
+thread_local char buf[LOG_SIZE] = {0};
 
 static void log_format_out(const char* format, va_list* args) {
-  char buf[LOG_SIZE] = {0};
-  int n = snprintf(buf, LOG_SIZE, "[pinpoint] [%d] [%ld]", getOSPid(), gettid());
+  int n = snprintf(buf, LOG_SIZE, "[pinpoint] [%d] [%ld]", get_os_pid(), get_tid());
   vsnprintf(buf + n, LOG_SIZE - n - 1, format, *args);
 
-  if (_error_cb) {
-    _error_cb(buf);
+  if (log_call_back_) {
+    log_call_back_(buf);
   } else {
     fprintf(stderr, "%s\n", buf);
   }
@@ -59,7 +62,7 @@ static void log_format_out(const char* format, va_list* args) {
  *  Note: the logging should be disable when in Real env
  */
 void pp_trace(const char* format, ...) {
-  if ((global_agent_info.inter_flag & E_LOGGING) == 0) {
+  if (enable_trace_ == false) {
     return;
   }
   va_list args;
@@ -70,4 +73,13 @@ void pp_trace(const char* format, ...) {
 }
 
 // register when thread/module/process start
-void register_error_cb(log_msg_cb error_cb) { _error_cb = error_cb; }
+void register_error_cb(log_msg_cb error_cb) { log_call_back_ = error_cb; }
+
+void register_logging_cb(log_msg_cb call_back, int enable_trace) {
+  if (call_back) {
+    log_call_back_ = call_back;
+  }
+  if (enable_trace) {
+    enable_trace_ = true;
+  }
+}
diff --git a/common/src/NodePool/PoolManager.cpp b/common/src/NodePool/PoolManager.cpp
index 4b109cd8c..03cecc4cb 100644
--- a/common/src/NodePool/PoolManager.cpp
+++ b/common/src/NodePool/PoolManager.cpp
@@ -19,36 +19,35 @@
  *  Created on: Aug 19, 2020
  *      Author: eeliu
  */
-#include <utility>
 
 #include "PoolManager.h"
 
-#include "../Util/Helper.h"
 #include "common.h"
+#include <cassert>
 #include <thread>
 #ifndef UINT32_MAX
 #define UINT32_MAX (0xfffffff)
 #endif
-
+namespace PP {
 namespace NodePool {
-void freeNodeTree(NodeID nodeId) {
+void PoolManager::FreeNodeTree(NodeID nodeId) {
   if (nodeId == E_INVALID_NODE || nodeId == E_ROOT_NODE) {
     return;
   }
 
   NodeID child_id, next_id;
 
-  if (PoolManager::getInstance().Restore(nodeId, child_id, next_id)) {
+  if (ReturnNode(nodeId, child_id, next_id)) {
     if (next_id != E_INVALID_NODE) {
-      freeNodeTree(next_id);
+      FreeNodeTree(next_id);
     }
 
     if (child_id != E_INVALID_NODE) {
-      freeNodeTree(child_id);
+      FreeNodeTree(child_id);
     }
   }
 }
-bool PoolManager::Restore(NodeID id, NodeID& child_id, NodeID& next_id) {
+bool PoolManager::ReturnNode(NodeID id, NodeID& child_id, NodeID& next_id) {
   for (int i = 0; i < 1000; i++) {
     // this node was in using: ref is not zero
     if (this->_restore(id, child_id, next_id, false)) {
@@ -60,13 +59,13 @@ bool PoolManager::Restore(NodeID id, NodeID& child_id, NodeID& next_id) {
   return this->_restore(id, child_id, next_id, true);
 }
 
-// avoiding `locking and waitting`
+// avoiding `locking and waiting`
 bool PoolManager::_restore(NodeID id, NodeID& child_id, NodeID& next_id, bool force) {
   std::lock_guard<std::mutex> _safe(this->_lock);
 
   int32_t index = (int32_t)id - 1;
 
-  if (this->indexInAliveVec(index) == false) {
+  if (this->indexInUsedVec(index) == false) {
     pp_trace("%d not alive !!!", id);
     child_id = E_INVALID_NODE;
     next_id = E_INVALID_NODE;
@@ -74,21 +73,21 @@ bool PoolManager::_restore(NodeID id, NodeID& child_id, NodeID& next_id, bool fo
   }
 
   // check refcount
-  TraceNode& node = this->_fetchNodeBy(id);
+  TraceNode& node = this->getUsedNode(id);
 
-  if (node.checkZoreRef() == false && force == false) {
+  if (node.checkZeroRef() == false && force == false) {
     // DO NOT TOUCH THis Node
     return false;
   } else {
-    this->_aliveNodeSet[index] = false;
-    child_id = node.mChildHeadId;
-    next_id = node.mNextId;
+    this->usedNodeSet_[index] = false;
+    child_id = node.last_child_id_;
+    next_id = node.sibling_id_;
     this->_freeNodeList.push(index);
     return true;
   }
 }
 
-TraceNode& PoolManager::_fetchNodeBy(NodeID id) {
+TraceNode& PoolManager::getUsedNode(NodeID id) {
   // assert(id != E_INVALID_NODE);
   if (id == E_ROOT_NODE) {
     throw std::out_of_range("id should not be 0");
@@ -96,7 +95,7 @@ TraceNode& PoolManager::_fetchNodeBy(NodeID id) {
 
   int32_t index = int32_t(id) - 1;
 
-  if (this->indexInAliveVec(index) == false) {
+  if (this->indexInUsedVec(index) == false) {
     std::string msg = "#";
     msg += std::to_string(id) + " is not alive";
     throw std::out_of_range(msg);
@@ -105,39 +104,64 @@ TraceNode& PoolManager::_fetchNodeBy(NodeID id) {
   return this->nodeIndexVec[index / CELL_SIZE][index % CELL_SIZE];
 }
 
-TraceNode& PoolManager::_getInitNode() noexcept { // create a new node
+TraceNode& PoolManager::getReadyNode() noexcept { // create a new node
   if (this->_freeNodeList.empty()) {
     this->expandOnce();
   }
   // as it holds a _lock, so no more _freeNodeList is empty
   int32_t index = this->_freeNodeList.top();
   this->_freeNodeList.pop();
-  this->_aliveNodeSet[index] = true;
+  this->usedNodeSet_[index] = true;
   return this->nodeIndexVec[index / CELL_SIZE][index % CELL_SIZE].reset(NodeID(index + 1));
 }
 
 TraceNode& PoolManager::_take(NodeID id) {
   if (id != E_ROOT_NODE) {
-    return this->_fetchNodeBy(id);
+    return this->getUsedNode(id);
   } else {
-    return this->_getInitNode();
+    return this->getReadyNode();
   }
 }
 
 void PoolManager::expandOnce() {
-  ADDTRACE();
   // pp_trace("Node pool expanding self! Old size:%ld", this->nodeIndexVec.size() * CELL_SIZE);
   // append new nodes into nodeIndexVec
   this->nodeIndexVec.push_back(std::unique_ptr<TraceNode[]>(new TraceNode[CELL_SIZE]));
   // this->nodeIndexVec.push_back(std::make_unique<TraceNode[]>(CELL_SIZE));
   // append new bitflag into aliveNodeSet
-  this->_aliveNodeSet.insert(this->_aliveNodeSet.end(), this->_emptyAliveSet.begin(),
-                             this->_emptyAliveSet.end());
+  this->usedNodeSet_.insert(this->usedNodeSet_.end(), this->readyNodeSet_.begin(),
+                            this->readyNodeSet_.end());
   for (int32_t id = this->maxId; id < (this->maxId + CELL_SIZE); id++) {
     this->_freeNodeList.push(id);
   }
   this->maxId += CELL_SIZE;
   // pp_trace("Node pool expanding is done! news size:%ld", this->nodeIndexVec.size() * CELL_SIZE);
-  assert(this->nodeIndexVec.size() * CELL_SIZE == this->_aliveNodeSet.size());
+  assert(this->nodeIndexVec.size() * CELL_SIZE == this->usedNodeSet_.size());
+}
+Json::Value empty(Json::nullValue);
+Json::Value& PoolManager::getRootNodeValue(WrapperTraceNodePtr& node) {
+
+  if (node->sibling_id_ != E_INVALID_NODE) {
+    WrapperTraceNodePtr sibling = ReferNode(node->sibling_id_);
+    getRootNodeValue(sibling);
+  }
+
+  if (node->last_child_id_ != E_INVALID_NODE) {
+    WrapperTraceNodePtr child = ReferNode(node->last_child_id_);
+    getRootNodeValue(child);
+  }
+
+  if (node->checkOpt() == false) {
+    return empty;
+  }
+
+  if (node->parent_id_ > E_ROOT_NODE) {
+    WrapperTraceNodePtr parent = ReferNode(node->parent_id_);
+    parent->appendNodeValue("calls", node->EncodeProtocol());
+  }
+
+  return node->EncodeProtocol();
 }
+
 } // namespace NodePool
+} // namespace PP
\ No newline at end of file
diff --git a/common/src/NodePool/PoolManager.h b/common/src/NodePool/PoolManager.h
index 57c4efe48..eef4a43b0 100644
--- a/common/src/NodePool/PoolManager.h
+++ b/common/src/NodePool/PoolManager.h
@@ -23,126 +23,154 @@
 
 #include "common.h"
 #include "TraceNode.h"
-#include <iostream>
+#include "json/value.h"
 #include <vector>
-#include <set>
-#include <list>
 #include <mutex>
+namespace PP {
+namespace NodePool {
+class PoolManager {
+private:
+  TraceNode& getUsedNode(NodeID id);
 
-namespace NodePool
-{
-class PoolManager
-{
- private:
-  TraceNode &_fetchNodeBy(NodeID id);
+  TraceNode& getReadyNode(void) noexcept;
 
-  TraceNode &_getInitNode(void) noexcept;
+  TraceNode& _take(NodeID id);
 
-  TraceNode &_take(NodeID id);
+  bool _restore(NodeID id, NodeID& child_id, NodeID& next_id, bool force);
 
-  bool _restore(NodeID id, NodeID &child_id, NodeID &next_id, bool force);
+  Json::Value& getRootNodeValue(WrapperTraceNodePtr& node);
 
- public:
+  // void gatherChildrenValues(WrapperTraceNodePtr& parent, NodeID child_header);
+
+public:
   /**
-         * @brief take is not safe, you should avoid use under MT
-         * note: try PoolManager::getInstance().GetWrapperNode
-         * @param id
-         * @return TraceNode&
-         */
-  inline TraceNode &Take(NodeID id = E_ROOT_NODE)
-  {
+   * @brief take is not safe, you should avoid use under MT
+   * note: try PoolManager::getInstance().GetWrapperNode
+   * @param id
+   * @return TraceNode&
+   */
+  DEPRECATED("") inline TraceNode& Take(NodeID id = E_ROOT_NODE) {
     std::lock_guard<std::mutex> _safe(this->_lock);
     return this->_take(id);
   }
 
-  inline WrapperTraceNode GetWrapperNode(NodeID id = E_ROOT_NODE)
-  {
+  inline TraceNode& NewNode() {
+    std::lock_guard<std::mutex> _safe(this->_lock);
+    return this->getReadyNode();
+  }
+
+  inline WrapperTraceNodePtr ReferNode(NodeID id) {
     std::lock_guard<std::mutex> _safe(this->_lock);
-    TraceNode &e = this->_take(id);
-    return WrapperTraceNode(&e);
+    TraceNode& e = this->getUsedNode(id);
+    return WrapperTraceNodePtr(e);
+  }
+
+  DEPRECATED("") inline WrapperTraceNodePtr GetWrapperNode(NodeID id = E_ROOT_NODE) {
+    std::lock_guard<std::mutex> _safe(this->_lock);
+    TraceNode& e = this->_take(id);
+    return WrapperTraceNodePtr(e);
   }
   /**
-         * @brief restore id->traceNode to pool
-         *
-         * @param id
-         * @param child_id child id of `id`, if exist
-         * @param next_id next id of `id`, if exist
-         * @return true
-         * @return false
-         */
-  bool Restore(NodeID id, NodeID &child_id, NodeID &next_id);
-
-  inline bool Restore(TraceNode &node)
-  {
+   * @brief restore id->traceNode to pool
+   *
+   * @param id
+   * @param child_id child id of `id`, if exist
+   * @param next_id next id of `id`, if exist
+   * @return true
+   * @return false
+   */
+  bool ReturnNode(NodeID id, NodeID& child_id, NodeID& next_id);
+
+  inline bool ReturnNode(const TraceNode& node) {
     NodeID node1, node2;
-    return this->Restore(node.getId(), node1, node2);
+    return this->ReturnNode(node.getId(), node1, node2);
   }
 
-  uint32_t totoalNodesCount()
-  {
+  uint32_t totalNodesCount() {
     std::lock_guard<std::mutex> _safe(this->_lock);
-    return nodeIndexVec.size() * CELL_SIZE;
+    return (uint32_t)nodeIndexVec.size() * CELL_SIZE;
   }
 
-  uint32_t freeNodesCount()
-  {
+  uint32_t freeNodesCount() {
     std::lock_guard<std::mutex> _safe(this->_lock);
-    return this->_freeNodeList.size();
+    return (uint32_t)this->_freeNodeList.size();
   }
 
-  void foreachAliveNode(std::function<void(TraceNode &node)> func)
-  {
+  void foreachAliveNode(std::function<void(TraceNode& node)> func) {
     std::lock_guard<std::mutex> _safe(this->_lock);
     for (int32_t index = 0; index < this->maxId; index++) {
-      if (this->indexInAliveVec(index)) { func(this->_fetchNodeBy((NodeID)(index + 1))); }
+      if (this->indexInUsedVec(index)) {
+        func(this->getUsedNode((NodeID)(index + 1)));
+      }
     }
   }
 
+  Json::Value& ExpandTraceTreeNodes(NodeID id) {
+    WrapperTraceNodePtr root = ReferNode(id);
+    return ExpandTraceTreeNodes(root);
+  }
+
+  Json::Value& ExpandTraceTreeNodes(WrapperTraceNodePtr& w_root) {
+    return getRootNodeValue(w_root);
+  }
+  Json::Value& ExpandTraceTreeNodes(TraceNode& root) {
+    WrapperTraceNodePtr w_root(root);
+    return getRootNodeValue(w_root);
+  }
+
+  void FreeNodeTree(NodeID nodeId);
+
+  std::string Status() {
+    Json::Value status;
+    status["pool_total_node"] = totalNodesCount();
+    status["pool_free_node"] = freeNodesCount();
+    status["common_libary_version"] = pinpoint_agent_version();
+
+    auto add_alive_node_fun = [&status](TraceNode& node) {
+      status["pool_alive_nodes"].append(node.id_);
+    };
+
+    foreachAliveNode(std::bind(add_alive_node_fun, std::placeholders::_1));
+    return status.toStyledString();
+  }
+
 #ifdef COMMON_DEBUG
-  inline bool NoNodeLeak()
-  {
+  inline bool NoNodeLeak() {
     std::lock_guard<std::mutex> _safe(this->_lock);
     return this->_freeNodeList.size() == nodeIndexVec.size() * CELL_SIZE;
   }
 #endif
   virtual ~PoolManager() {}
 
- public:
-  static PoolManager &getInstance()
-  {
-    static PoolManager _instance;
-    return _instance;
-  }
-#ifndef COMMON_DEBUG
- private:
-#endif
-  PoolManager() : maxId(E_ROOT_NODE)
-  {
-    this->_emptyAliveSet.reserve(CELL_SIZE);
-    for (int i = 0; i < CELL_SIZE; i++) { this->_emptyAliveSet.push_back(false); }
+public:
+  PoolManager() : maxId(E_ROOT_NODE) {
+    this->readyNodeSet_.reserve(CELL_SIZE);
+    for (int i = 0; i < CELL_SIZE; i++) {
+      this->readyNodeSet_.push_back(false);
+    }
     this->expandOnce();
   }
 
- private:
-  inline bool indexInAliveVec(int32_t index)
-  {
-    if (index >= 0 && index < this->maxId) { return this->_aliveNodeSet.at(index); }
+private:
+  inline bool indexInUsedVec(int32_t index) {
+    if (index >= 0 && index < this->maxId) {
+      return this->usedNodeSet_.at(index);
+    }
     return false;
   }
 
   void expandOnce();
 
- private:
+private:
   std::mutex _lock;
   // std::set<NodeID> _aliveNodeSet;
-  std::vector<bool> _aliveNodeSet;
-  std::vector<bool> _emptyAliveSet;
+  std::vector<bool> usedNodeSet_;
+  std::vector<bool> readyNodeSet_;
   int32_t maxId;
   std::stack<int32_t> _freeNodeList;
   static const int CELL_SIZE = 128;
   std::vector<std::unique_ptr<TraceNode[]>> nodeIndexVec;
 };
-void freeNodeTree(NodeID root);
-}  // namespace NodePool
-
+} // namespace NodePool
+} // namespace PP
 #endif /* COMMON_SRC_NODEPOOL_POOLMANAGER_H_ */
diff --git a/common/src/NodePool/TraceNode.cpp b/common/src/NodePool/TraceNode.cpp
index 5e4e111d7..3e1a237e0 100644
--- a/common/src/NodePool/TraceNode.cpp
+++ b/common/src/NodePool/TraceNode.cpp
@@ -21,22 +21,9 @@
  */
 
 #include "TraceNode.h"
-#include "Util/Helper.h"
-#include "PoolManager.h"
 #include "header.h"
-
+namespace PP {
 namespace NodePool {
-// static std::atomic<int64_t> _uid_;
-WrapperTraceNode::WrapperTraceNode(TraceNode* node) : _traceNode(node) {
-  assert(_traceNode != nullptr);
-  _traceNode->addRef();
-}
-
-WrapperTraceNode::~WrapperTraceNode() {
-  if (_traceNode != nullptr) {
-    _traceNode->rmRef();
-  }
-}
 TraceNode::~TraceNode() {}
 
 void TraceNode::clearAttach() {
@@ -44,69 +31,75 @@ void TraceNode::clearAttach() {
   if (!this->_value.empty())
     this->_value.clear(); // Json::Value();
 
-  if (!this->_context.empty())
-    this->_context.clear();
+  if (!this->context_.empty())
+    this->context_.clear();
 
   if (!this->_endTraceCallback.empty())
     this->_endTraceCallback.clear();
 }
 
-void TraceNode::initId(NodeID& id) { this->mPoolIndex = id; }
+void TraceNode::initId(const NodeID& id) { this->id_ = id; }
 
-void TraceNode::addChild(WrapperTraceNode& child) {
+void TraceNode::AddChildTraceNode(WrapperTraceNodePtr& child) {
   std::lock_guard<std::mutex> _safe(this->mlock);
+  assert(id_ != child->id_);
 
-  if (this->mChildHeadId != E_INVALID_NODE)
-    child->mNextId = this->mChildHeadId;
+  if (this->last_child_id_ != E_INVALID_NODE) {
+    child->sibling_id_ = this->last_child_id_;
+  }
 
-  this->mChildHeadId = child->mPoolIndex;
+  this->last_child_id_ = child->id_;
 
-  child->mParentId = this->mPoolIndex;
-  child->mRootIndex = this->mRootIndex;
+  child->parent_id_ = this->id_;
+  child->root_id_ = this->root_id_;
   child->root_start_time = this->root_start_time;
   child->parent_start_time = this->start_time;
 }
 
-void TraceNode::endTimer() {
-  uint64_t end_time = Helper::get_current_msec_stamp();
+void TraceNode::AddChildTraceNode(TraceNode& child) {
+  std::lock_guard<std::mutex> _safe(this->mlock);
+  assert(id_ != child.id_);
 
+  if (this->last_child_id_ != E_INVALID_NODE) {
+    child.sibling_id_ = this->last_child_id_;
+  }
+  this->last_child_id_ = child.id_;
+
+  child.parent_id_ = this->id_;
+  child.root_id_ = this->root_id_;
+  child.root_start_time = this->root_start_time;
+  child.parent_start_time = this->start_time;
+}
+
+void TraceNode::EndTimer() {
+  uint64_t end_time = get_unix_time_ms();
   this->cumulative_time += (end_time - this->start_time);
 }
 
-void TraceNode::wakeUp() { this->start_time = Helper::get_current_msec_stamp(); }
+void TraceNode::WakeUpTimer() { this->start_time = get_unix_time_ms(); }
 
-void TraceNode::convertToSpan() {
+void TraceNode::EndSpan() {
   this->AddTraceDetail(":E", this->cumulative_time);
   this->AddTraceDetail(":S", this->start_time);
-
-  this->AddTraceDetail(":FT", global_agent_info.agent_type);
 }
 
-void TraceNode::convertToSpanEvent() {
+void TraceNode::EndSpanEvent() {
   this->AddTraceDetail(":E", this->cumulative_time);
   this->AddTraceDetail(":S", this->start_time - this->parent_start_time);
 }
 
-// void TraceNode::setTraceParent(WrapperTraceNode &parent, WrapperTraceNode &root)
-// {
-//     std::lock_guard<std::mutex> _safe(this->mlock);
-//     this->mRootIndex = root->mPoolIndex;
-//     this->mParentId = parent->mPoolIndex;
-//     this->root_start_time = root->root_start_time;
-// }
-
-void TraceNode::startTimer() {
-  uint64_t time_in_ms = Helper::get_current_msec_stamp();
+void TraceNode::StartTimer() {
+  uint64_t time_in_ms = get_unix_time_ms();
   this->start_time = time_in_ms;
   this->root_start_time = time_in_ms;
 }
 
 void TraceNode::parseOpt(std::string key, std::string value) {
-  pp_trace(" [%d] add opt: key:%s value:%s", mPoolIndex, key.c_str(), value.c_str());
+  pp_trace(" [%d] add opt: key:%s value:%s", id_, key.c_str(), value.c_str());
   if (key == "TraceMinTimeMs") {
     int64_t min = std::stoll(value);
     auto cb = [=]() -> bool {
-      pp_trace("checkOpt:  [%d] TraceMinTimeMs:%ld cumulative_time:%lu", this->mPoolIndex, min,
+      pp_trace("checkOpt:  [%d] TraceMinTimeMs:%ld cumulative_time:%lu", this->id_, min,
                this->cumulative_time);
       if ((int64_t)this->cumulative_time >= min)
         return true;
@@ -114,7 +107,7 @@ void TraceNode::parseOpt(std::string key, std::string value) {
     };
     this->_endTraceCallback.push_back(cb);
   } else if (key == "TraceOnlyException") {
-    auto cb = [=]() -> bool { return this->mHasExp; };
+    auto cb = [=]() -> bool { return this->set_exp_; };
 
     this->_endTraceCallback.push_back(cb);
   }
@@ -145,3 +138,4 @@ void TraceNode::setOpt(const char* opt, va_list* args) {
   }
 }
 } // namespace NodePool
+} // namespace  PP
\ No newline at end of file
diff --git a/common/src/NodePool/TraceNode.h b/common/src/NodePool/TraceNode.h
index b9fd9ed18..4646440c9 100644
--- a/common/src/NodePool/TraceNode.h
+++ b/common/src/NodePool/TraceNode.h
@@ -23,52 +23,44 @@
 #ifndef COMMON_SRC_TRACENODE_H_
 #define COMMON_SRC_TRACENODE_H_
 #include "common.h"
-#include "json/json.h"
 #include "Context/ContextType.h"
+#include "json/json.h"
 #include <atomic>
-#include <map>
-#include <iostream>
 #include <functional>
+#include <map>
 #include <mutex>
 #include <stdarg.h>
-
+#include <memory>
+#include <vector>
+#include <inttypes.h>
+#include <vector>
+#include <assert.h>
+namespace PP {
 namespace NodePool {
 namespace Json = AliasJson;
 using Context::ContextType;
 using Context::LongContextType;
 using Context::StringContextType;
-class TraceNode;
+class WrapperTraceNodePtr;
 const static int MAX_SUB_TRACE_NODES_LIMIT = 2048;
-class WrapperTraceNode {
-public:
-  WrapperTraceNode() = delete;
-  WrapperTraceNode(const WrapperTraceNode& other) = delete;
-  WrapperTraceNode(WrapperTraceNode&& other) : _traceNode(std::move(other._traceNode)) {
-    other._traceNode = nullptr;
-  }
-
-  WrapperTraceNode& operator=(const WrapperTraceNode& other) = delete;
-
-  WrapperTraceNode(TraceNode* node);
-  TraceNode* operator->() { return _traceNode; }
-  ~WrapperTraceNode();
-
-private:
-  TraceNode* _traceNode;
-};
-
 typedef std::shared_ptr<ContextType> _ContextType_;
+using EndTraceCallBackFunc = std::function<bool()>;
+using EndTraceCallBackFuncVec = std::vector<EndTraceCallBackFunc>;
 class TraceNode {
 public:
-  NodeID mNextId;      // equal brother node
-  NodeID mChildHeadId; // subtree/child tree
+  /**                                 sibling_id_
+   * current_node       <--------------------------------------------- sibling_node
+   *         |-------------------------------------|
+   *                                                v
+   *     child_head_id_ <- next <-next <- ...<-last_child_id_
+   */
+
+  NodeID sibling_id_;    // sibling_id_ is brother node id; it's a next_ptr to child_list
+  NodeID last_child_id_; // last_child_id_ is the end of child_list
 
-  NodeID mParentId;  // parent Id [end_trace] avoiding re-add
-  NodeID mRootIndex; // highway to root node
-  NodeID mPoolIndex;
-  // int64_t mUID;
-  // int64_t mParentUID;
-  // int64_t mRootUID;
+  NodeID parent_id_; // parent Id [end_trace] avoiding re-add
+  NodeID root_id_;   // highway to root node
+  NodeID id_;
 
   uint64_t start_time;
   uint64_t fetal_error_time;
@@ -76,31 +68,31 @@ class TraceNode {
   uint64_t cumulative_time;
   uint64_t root_start_time;
   uint64_t parent_start_time;
-  bool mHasExp;
+  bool set_exp_;
 
 public:
-  void startTimer();
-  void endTimer();
-  void wakeUp();
+  void StartTimer();
+  void EndTimer();
 
-  void convertToSpanEvent();
-  void convertToSpan();
-
-public:
-  void addChild(WrapperTraceNode& child);
-  void remove();
+  DEPRECATED("") void WakeUpTimer();
 
-  inline bool isRoot() const { return this->mRootIndex == mPoolIndex; }
+  void EndSpanEvent();
+  void EndSpan();
 
-  inline bool isLeaf() const { return this->mChildHeadId == E_INVALID_NODE; }
+public:
+  void AddChildTraceNode(TraceNode& child);
+  DEPRECATED("") void AddChildTraceNode(WrapperTraceNodePtr& child);
+  inline bool IsRootNode() const { return this->root_id_ == id_; }
 
 public:
   TraceNode() {
-    this->mPoolIndex = E_INVALID_NODE;
-    this->mRootIndex = E_INVALID_NODE;
+    this->id_ = E_INVALID_NODE;
+    this->root_id_ = E_INVALID_NODE;
     this->resetRelative();
     this->resetStatus();
-    this->_mRef = 0;
+    this->ref_count_ = 0;
+    this->font_type_ = 0;
+    error_.set = false;
   }
 
   virtual ~TraceNode();
@@ -111,48 +103,63 @@ class TraceNode {
     this->initId(id);
     this->resetStatus();
     this->resetRelative();
-    this->_mRef = 0;
+    this->ref_count_ = 0;
     return *this;
   }
 
-  NodeID getId() const { return this->mPoolIndex; }
-
-  Json::Value getJsValue() {
-    std::lock_guard<std::mutex> _safe(this->mlock);
-    return this->_value;
-  }
+  NodeID getId() const { return this->id_; }
 
   void getContext(const char* key, std::string& value) {
     std::lock_guard<std::mutex> _safe(this->mlock);
-    _ContextType_& ctx = this->_context.at(key);
+    _ContextType_& ctx = this->context_.at(key);
     value = ctx->asStringValue();
   }
 
   void getContext(const char* key, long& value) {
     std::lock_guard<std::mutex> _safe(this->mlock);
-    _ContextType_& ctx = this->_context.at(key);
+    _ContextType_& ctx = this->context_.at(key);
     value = ctx->asLongValue();
   }
 
   void setContext(const char* key, const char* buf) {
     std::lock_guard<std::mutex> _safe(this->mlock);
     _ContextType_ context(std::make_shared<StringContextType>(buf));
-    this->_context[key] = context;
+    this->context_[key] = context;
   }
 
   void setContext(const char* key, long l) {
     std::lock_guard<std::mutex> _safe(this->mlock);
     _ContextType_ context(std::make_shared<LongContextType>(l));
-    this->_context[key] = context;
+    this->context_[key] = context;
   }
 
 public:
   TraceNode& operator=(const TraceNode&) = delete;
   TraceNode(const TraceNode&) = delete;
 
-  bool operator==(TraceNode const& _node) const { return this->mPoolIndex == _node.mPoolIndex; }
+  bool operator==(TraceNode const& _node) const { return this->id_ == _node.id_; }
 
-  bool operator!=(TraceNode const& _node) const { return this->mPoolIndex != _node.mPoolIndex; }
+  bool operator!=(TraceNode const& _node) const { return this->id_ != _node.id_; }
+
+private:
+  int font_type_;
+
+  struct Error {
+    std::string message;
+    std::string file_name;
+    uint32_t line_nu;
+    bool set;
+  } error_;
+
+public:
+  void SetFontType(int type) { font_type_ = type; }
+
+  void SetErrorInfo(std::string&& msg, std::string&& filename, uint32_t line) {
+    error_.message = std::move(msg);
+    error_.file_name = std::move(filename);
+    error_.line_nu = line;
+    error_.set = true;
+  }
 
 public:
   void AddTraceDetail(const char* key, const char* v) {
@@ -170,11 +177,16 @@ class TraceNode {
     this->_value[key] = v;
   }
 
-  void AddTraceDetail(const char* key, Json::Value& v) {
+  void AddTraceDetail(const char* key, const Json::Value& v) {
     std::lock_guard<std::mutex> _safe(this->mlock);
     this->_value[key] = v;
   }
 
+  void appendNodeValue(const char* key, Json::Value v) {
+    std::lock_guard<std::mutex> _safe(this->mlock);
+    this->_value[key].append(v);
+  }
+
   void appendNodeValue(const char* key, const char* v) {
     std::lock_guard<std::mutex> _safe(this->mlock);
     this->_value[key].append(v);
@@ -189,13 +201,13 @@ class TraceNode {
 
   void clearAttach();
 
-  void initId(NodeID& id);
+  void initId(const NodeID& id);
 
   inline void resetRelative() {
-    this->mNextId = E_INVALID_NODE;
-    this->mChildHeadId = E_INVALID_NODE;
-    this->mParentId = mPoolIndex;
-    this->mRootIndex = mPoolIndex;
+    this->sibling_id_ = E_INVALID_NODE;
+    this->last_child_id_ = E_INVALID_NODE;
+    this->parent_id_ = E_ROOT_NODE;
+    this->root_id_ = id_;
     this->_subTraceNodeMaxSize = MAX_SUB_TRACE_NODES_LIMIT;
   }
 
@@ -206,7 +218,8 @@ class TraceNode {
     this->start_time = 0;
     this->limit = E_TRACE_PASS;
     this->cumulative_time = 0;
-    this->mHasExp = false;
+    this->set_exp_ = false;
+    error_.set = false;
   }
 
 public:
@@ -215,16 +228,16 @@ class TraceNode {
 
 public:
   int addRef() {
-    _mRef++;
-    return _mRef.load();
+    ref_count_++;
+    return ref_count_.load();
   }
 
   int rmRef() {
-    _mRef--;
-    return _mRef.load();
+    ref_count_--;
+    return ref_count_.load();
   }
 
-  bool checkZoreRef() { return _mRef.load() == 0; }
+  bool checkZeroRef() { return ref_count_.load() == 0; }
 
 public:
   std::string ToString() {
@@ -232,22 +245,23 @@ class TraceNode {
     char pbuf[1024] = {0};
     int len =
         snprintf(pbuf, 1024,
-                 "mNextId:%d mChildListHeaderId:%d mParentId:%d mRootIndex:%d mPoolIndex:%d \n"
-                 "start_time:%lu,fetal_error_time:%lu,limit:%lu,cumulative_time:%lu,root_start_"
-                 "time:%lu,mHasExp:%d \n"
-                 "_mRef:%d\n"
+                 "sibling_id_:%d mChildListHeaderId:%d parent_id_:%d root_id_:%d id_:%d \n"
+                 "start_time:%" PRIu64 ",fetal_error_time:%" PRIu64 ",limit:%" PRIu64
+                 ",cumulative_time:%" PRIu64 " \n"
+                 "root_start_time:%" PRIu64 ",set_exp_:%d \n"
+                 "ref_count_:%d \n"
                  "_value:%s \n"
-                 "_context size:%lu,_endTraceCallback:%lu \n",
-                 (int)this->mNextId, (int)this->mChildHeadId, (int)this->mParentId,
-                 (int)this->mRootIndex, (int)this->mPoolIndex, this->start_time,
-                 this->fetal_error_time, this->limit, this->cumulative_time, this->root_start_time,
-                 this->mHasExp, this->_mRef.load(), this->_value.toStyledString().c_str(),
-                 this->_context.size(), this->_endTraceCallback.size());
+                 "context_ size:%" PRIu64 ",_endTraceCallback:%" PRIu64 " \n",
+                 (int)this->sibling_id_, (int)this->last_child_id_, (int)this->parent_id_,
+                 (int)this->root_id_, (int)this->id_, this->start_time, this->fetal_error_time,
+                 this->limit, this->cumulative_time, this->root_start_time, this->set_exp_,
+                 this->ref_count_.load(), this->_value.toStyledString().c_str(),
+                 this->context_.size(), this->_endTraceCallback.size());
     return std::string(pbuf, len);
   }
 
 private:
-  std::atomic<int> _mRef;
+  std::atomic<int> ref_count_;
   int _subTraceNodeMaxSize;
 
 public:
@@ -260,10 +274,33 @@ class TraceNode {
     }
   }
 
+public:
+  Json::Value& EncodeProtocol() { return _value; }
+
 private:
   Json::Value _value;
-  std::map<std::string, _ContextType_> _context;
-  std::vector<std::function<bool()>> _endTraceCallback;
+  std::map<std::string, _ContextType_> context_;
+  EndTraceCallBackFuncVec _endTraceCallback;
+};
+
+class WrapperTraceNodePtr {
+public:
+  WrapperTraceNodePtr() = delete;
+  WrapperTraceNodePtr(const WrapperTraceNodePtr& other) = delete;
+  WrapperTraceNodePtr(WrapperTraceNodePtr& other) = delete;
+  WrapperTraceNodePtr(WrapperTraceNodePtr&& other) : traceNode_(other.traceNode_) {
+    traceNode_.addRef();
+  }
+
+  WrapperTraceNodePtr& operator=(const WrapperTraceNodePtr& other) = delete;
+
+  WrapperTraceNodePtr(TraceNode& node) : traceNode_(node) { traceNode_.addRef(); }
+  TraceNode* operator->() { return &traceNode_; }
+  ~WrapperTraceNodePtr() { traceNode_.rmRef(); }
+
+private:
+  TraceNode& traceNode_;
 };
 } // namespace NodePool
+} // namespace PP
 #endif /* COMMON_SRC_TRACENODE_H_ */
diff --git a/common/src/Util/Helper.cpp b/common/src/Util/Helper.cpp
deleted file mode 100644
index b8f9a3992..000000000
--- a/common/src/Util/Helper.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright 2020 NAVER Corp
-//
-// Licensed 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.
-////////////////////////////////////////////////////////////////////////////////
-/*
- * Trace.cpp
- *
- *  Created on: Sep 18, 2020
- *      Author: eeliu
- */
-#include <mutex>
-
-#include "Cache/NodeTreeWriter.h"
-#include "NodePool/PoolManager.h"
-#include "Helper.h"
-
-namespace Helper
-{
-namespace Json = AliasJson;
-using Cache::NodeTreeWriter;
-using NodePool::PoolManager;
-
-static NodeTreeWriter _writer;
-static ConnectionPool::SpanConnectionPool _con_pool;
-static std::once_flag _pool_init_flag;
-static Json::Value mergeChildren(WrapperTraceNode &node);
-uint64_t get_current_msec_stamp() noexcept
-{
-  std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
-  time_point<system_clock, milliseconds> current = time_point_cast<std::chrono::milliseconds>(now);
-  return current.time_since_epoch().count();
-}
-
-std::string node_tree_to_string(const Json::Value &value) { return _writer.write(value); }
-
-static void gatcherChildDetailByReverse(Json::Value &detail, WrapperTraceNode &head)
-{
-  if (head->mNextId != E_INVALID_NODE) {
-    // TraceNode &next = PoolManager::getInstance().Take(head.mNextId);
-    WrapperTraceNode next = PoolManager::getInstance().GetWrapperNode(head->mNextId);
-    gatcherChildDetailByReverse(detail, next);
-  }
-  Json::Value childrenDetail = mergeChildren(head);
-  if (!childrenDetail.empty()) { detail.append(childrenDetail); }
-}
-
-Json::Value mergeChildren(WrapperTraceNode &node)
-{
-  if (node->checkOpt() == false) {
-    return Json::Value();
-  } else if (!node->isLeaf()) {
-    // TraceNode &child = PoolManager::getInstance().Take(node.mChildHeadIndex);
-    WrapperTraceNode child = PoolManager::getInstance().GetWrapperNode(node->mChildHeadId);
-
-    Json::Value childTraceDetail;
-    gatcherChildDetailByReverse(childTraceDetail, child);
-    node->AddTraceDetail("calls", childTraceDetail);
-  }
-  return node->getJsValue();
-}
-
-Json::Value mergeTraceNodeTree(NodeID Id) noexcept
-{
-  WrapperTraceNode root = PoolManager::getInstance().GetWrapperNode(Id);
-  return mergeTraceNodeTree(root);
-}
-
-Json::Value mergeTraceNodeTree(WrapperTraceNode &root) { return mergeChildren(root); }
-
-Json::Value mergeTraceNodeTree(TraceNode &root)
-{
-  WrapperTraceNode wroot(&root);
-  return mergeChildren(wroot);
-}
-
-TransConnection getConnection()
-{
-  std::call_once(_pool_init_flag, []() { _con_pool.initPool(global_agent_info.co_host); });
-
-  return _con_pool.get();
-}
-
-void freeConnection(TransConnection &trans)
-{
-  std::call_once(_pool_init_flag, []() { _con_pool.initPool(global_agent_info.co_host); });
-
-  return _con_pool.free(trans);
-}
-
-}  // namespace Helper
diff --git a/common/src/Util/Helper.h b/common/src/Util/Helper.h
deleted file mode 100644
index 7d9240a32..000000000
--- a/common/src/Util/Helper.h
+++ /dev/null
@@ -1,88 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright 2020 NAVER Corp
-//
-// Licensed 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.
-////////////////////////////////////////////////////////////////////////////////
-/*
- * Trace.h
- *
- *  Created on: Sep 14, 2020
- *      Author: eeliu
- */
-
-#ifndef COMMON_SRC_UTIL_HELPER_H_
-#define COMMON_SRC_UTIL_HELPER_H_
-
-#include <stdint.h>
-#include <chrono>
-#include <ratio>
-#include <ctime>
-#include <iostream>
-#include <string.h>
-
-#include "json/json.h"
-#include "json/writer.h"
-
-#include "common.h"
-#include "NodePool/TraceNode.h"
-#include "ConnectionPool/SpanConnectionPool.h"
-
-namespace Helper {
-namespace Json = AliasJson;
-using ConnectionPool::TransConnection;
-using NodePool::TraceNode;
-using NodePool::WrapperTraceNode;
-using std::chrono::duration;
-using std::chrono::duration_cast;
-using std::chrono::milliseconds;
-using std::chrono::steady_clock;
-using std::chrono::system_clock;
-using std::chrono::time_point;
-using std::chrono::time_point_cast;
-typedef struct scope_time_trace {
-  steady_clock::time_point _start_time;
-  std::string _funcName;
-  scope_time_trace(const char* cfunc) {
-    _start_time = steady_clock::now();
-    _funcName = cfunc;
-  }
-  ~scope_time_trace() {
-    milliseconds elapsed = duration_cast<milliseconds>(steady_clock::now() - _start_time);
-    // pp_trace(" [%s] it's take [%ld] miliseconds", _funcName.c_str(), elapsed.count());
-  }
-} STT;
-
-uint64_t get_current_msec_stamp() noexcept;
-
-std::string node_tree_to_string(const Json::Value& value);
-
-Json::Value mergeTraceNodeTree(TraceNode& root);
-Json::Value mergeTraceNodeTree(WrapperTraceNode& root);
-
-Json::Value mergeTraceNodeTree(NodeID Id) noexcept;
-TransConnection getConnection();
-
-void freeConnection(TransConnection&);
-
-} // namespace Helper
-
-#ifndef NDEBUG
-
-#define ADDTRACE() Helper::STT __stt__(__func__)
-#else
-
-#define ADDTRACE()
-
-#endif
-
-#endif /* COMMON_SRC_UTIL_HELPER_H_ */
diff --git a/common/src/common.cpp b/common/src/common.cpp
index e2470979d..0dfed58f0 100644
--- a/common/src/common.cpp
+++ b/common/src/common.cpp
@@ -17,502 +17,562 @@
 // Created by eeliu on 1/3/2020.
 //
 
+#include "common.h"
+#include <cstddef>
+#include <cstdint>
 #include <cstdio>
+#include <cstring>
 #include <functional>
-#include <iostream>
-#include <map>
-#include <memory>
-#include <thread>
 #include <stdexcept>
 #include <stdarg.h>
-#include "common.h"
-
-#include "Cache/SafeSharedState.h"
+#include <functional>
+#include <chrono>
 #include "NodePool/PoolManager.h"
-#include "Util/Helper.h"
 #include "ConnectionPool/SpanConnectionPool.h"
 #include "header.h"
-namespace Json = AliasJson;
-
-using Cache::SafeSharedState;
-using ConnectionPool::TransConnection;
-using Helper::get_current_msec_stamp;
-// using NodePool::PContextType;
-using NodePool::freeNodeTree;
-using NodePool::PoolManager;
-using NodePool::TraceNode;
-using NodePool::WrapperTraceNode;
+#include "Cache/State.h"
+#include "Cache/NodeTreeWriter.h"
 
-const static char* CLUSE = "clues";
-static thread_local NodeID __tls_id = E_ROOT_NODE;
-PPAgentT global_agent_info = {
-    "unix:./pinpoint_test.sock", 1, 10, 1500, 1, nullptr, nullptr, nullptr};
-// send current span with timeout
-static thread_local int _span_timeout = global_agent_info.timeout_ms;
-static std::function<void(const char*)> _SpanHandler_;
+using std::chrono::milliseconds;
+using std::chrono::system_clock;
+using std::chrono::time_point;
+using std::chrono::time_point_cast;
 
-NodeID pinpoint_get_per_thread_id() { return __tls_id; }
+namespace PP {
+namespace Json = AliasJson;
+using Cache::NodeTreeWriter;
+using ConnectionPool::TransLayerPtr;
+using NodePool::TraceNode;
+using NodePool::WrapperTraceNodePtr;
+
+typedef struct {
+  int agent_type;
+} PPAgentT;
+
+static std::function<void(const char*)> _raw_span_watcher_cb = {nullptr};
+class Agent {
+public:
+  Agent() = delete;
+  Agent(const Agent&) = delete;
+  Agent(Agent&&) = delete;
+
+public:
+  Agent(const char* cl_host, long timeout_ms, long trace_limit, int agent_type)
+      : span_timeout_(timeout_ms), agent_type_(agent_type),
+        connection_pool_(cl_host,
+                         {{0, std::bind(&Agent::HandleHelloMsg, this, std::placeholders::_1,
+                                        std::placeholders::_2, std::placeholders::_3)}}) {
+    statePtr_ = std::unique_ptr<ProcessState>(new ProcessState(trace_limit));
+    builder["collectComments"] = false;
+    pp_trace("init agent:%s timeout:%ld trace_limit:%ld agent_type:%d", cl_host, timeout_ms,
+             trace_limit, agent_type_);
+  }
+  ~Agent() {}
 
-void pinpoint_update_per_thread_id(NodeID id) { __tls_id = id; }
+private:
+  void TrySendSpan(const std::string& span, int span_timeout) {
+    TransLayerPtr trans = connection_pool_.get();
 
-static inline void _verify_key(const char* key) {
-  if (key == nullptr || key[0] == ':') {
-    std::string reason = "key:";
-    reason += key;
-    reason += "is invalid";
-    throw std::invalid_argument(reason);
+    if (!trans->copy_into_send_buffer(span)) {
+      pp_trace("drop current span as it's too heavy! size:%lu", span.length());
+    }
+    if (span_timeout > 0) {
+      trans->SyncSendAll(span_timeout);
+    } else {
+      trans->PoolEventOnce(0);
+    }
+    // if network not ready, span will send in next time.
+    connection_pool_.free(trans);
+  }
+  void SendSpanTrace(NodeID root, int timeout) {
+    Json::Value& trace = nodePool_.ExpandTraceTreeNodes(root);
+    std::string spanStr = node_tree_to_string(trace);
+    pp_trace("this span:(%s)", spanStr.c_str());
+    TrySendSpan(spanStr, timeout);
+    if (unlikely(rawSpanHandler_ != nullptr)) {
+      rawSpanHandler_(spanStr.c_str());
+    }
   }
-}
 
-static NodeID do_start_trace(NodeID id, const char* opt = nullptr, va_list* args = nullptr) {
-  if (id <= E_INVALID_NODE) {
-    throw std::out_of_range("invalid node id");
-  } else if (id == E_ROOT_NODE) {
-    TraceNode& trace = PoolManager::getInstance().Take();
-    trace.startTimer();
-    return trace.mPoolIndex;
-  } else {
-    WrapperTraceNode parent = PoolManager::getInstance().GetWrapperNode(id);
+  void HandleHelloMsg(int type, const char* buf, size_t len) {
+    if (statePtr_->IsReady()) {
+      return;
+    }
+
+    Json::Value root;
+    (void)type;
 
-    // get root node
-    WrapperTraceNode root = PoolManager::getInstance().GetWrapperNode(parent->mRootIndex);
+    using Json::parseFromStream;
+    std::istringstream in_stream(std::string(buf, len));
+    bool ok = parseFromStream(builder, in_stream, &root, nullptr);
+    if (!ok) {
+      pp_trace("Receive invalid msg: %.*s from Collector-agent", (int)len, buf);
+    }
 
-    // check subnode limit
-    root->updateRootSubTraceSize();
+    if (root["version"] || root["version"].isString()) {
+      std::string version = root["version"].asString();
+      std::string lowest_version = "v0.5.0";
+      if (version < lowest_version) {
+        pp_trace("collector-agent should be >=v0.5.0, please upgrade it");
+        return;
+      }
+    }
 
-    WrapperTraceNode trace = PoolManager::getInstance().GetWrapperNode();
-    trace->startTimer();
-    parent->addChild(trace);
-    // pass opt
-    if (opt != nullptr) {
-      trace->setOpt(opt, args);
+    if (root["time"] && root["time"].isString()) {
+      statePtr_->SetStartTime(std::stoll(root["time"].asString()));
     }
-    return trace->mPoolIndex;
   }
-}
 
-static void flush_to_agent(std::string& span) {
-  TransConnection trans = Helper::getConnection();
+public:
+  NodeID StartTrace(NodeID id, const char* opt = nullptr, va_list* args = nullptr) {
+    if (id <= E_INVALID_NODE) {
+      throw std::out_of_range("invalid node id");
+    } else if (id == E_ROOT_NODE) {
+      TraceNode& trace = nodePool_.NewNode();
+      trace.StartTimer();
+      // HACK, set :FT into agent,as only agent knowns.
+      trace.AddTraceDetail(":FT", agent_type_);
+      return trace.id_;
+    } else {
+      WrapperTraceNodePtr parent = nodePool_.ReferNode(id);
+
+      // get root node
+      WrapperTraceNodePtr root = nodePool_.ReferNode(parent->root_id_);
+
+      // check subnode limit
+      root->updateRootSubTraceSize();
+      // HACK: a new node only exist in one thread
+      TraceNode& new_trace = nodePool_.NewNode();
+      new_trace.StartTimer();
+      parent->AddChildTraceNode(new_trace);
+      // pass opt
+      if (opt != nullptr) {
+        new_trace.setOpt(opt, args);
+      }
+      return new_trace.id_;
+    }
+  }
+  NodeID EndTrace(NodeID ID, int timeout = 0) {
+    // HACK use cpp scope management
+    {
+      WrapperTraceNodePtr w_trace = nodePool_.ReferNode(ID);
+      if (w_trace->IsRootNode()) {
+        if (w_trace->limit & E_TRACE_PASS) {
+          w_trace->EndTimer();
+          w_trace->EndSpan();
+          if (timeout == 0) {
+            timeout = span_timeout_;
+          }
+          SendSpanTrace(ID, timeout);
+        } else if (w_trace->limit & E_TRACE_BLOCK) {
+          pp_trace("current [%d] span dropped,due to TRACE_BLOCK", w_trace->getId());
+        } else {
+          pp_trace("current [%d] span dropped,due to limit=%ld", w_trace->getId(), w_trace->limit);
+        }
+      } else {
+        w_trace->EndTimer();
+        w_trace->EndSpanEvent();
+        return w_trace->parent_id_;
+      }
+    }
+    // it already is a full trace, every thing is done.
+    nodePool_.FreeNodeTree(ID);
+    return E_ROOT_NODE;
+  }
 
-  if (!trans->copy_into_send_buffer(span)) {
-    pp_trace("drop current span as it's too heavy! size:%lu", span.length());
+  bool IsRootTrace(NodeID id) {
+    WrapperTraceNodePtr w_node = nodePool_.ReferNode(id);
+    return w_node->IsRootNode();
   }
-  trans->trans_layer_pool(_span_timeout);
-  // if network not ready, span will send in next time.
-  Helper::freeConnection(trans);
-}
+  uint64_t ChangeTraceStatus(NodeID id, int status) {
+    WrapperTraceNodePtr w_node = nodePool_.ReferNode(id);
+    WrapperTraceNodePtr w_root = nodePool_.ReferNode(w_node->root_id_);
+    pp_trace("change current [%d] status, before:%lld,now:%d", w_root->getId(), w_root->limit,
+             status);
+    w_root->limit = status;
+    return w_root->limit;
+  }
+  void AnnotateTrace_V1(NodeID id, const char* key, const char* value, E_NODE_LOC flag) {
+    NotInternalKey(key);
 
-void sendSpan(NodeID rootId) {
-  const Json::Value trace = Helper::mergeTraceNodeTree(rootId);
-  std::string spanStr = Helper::node_tree_to_string(trace);
-  if (unlikely(_SpanHandler_ != nullptr)) {
-    _SpanHandler_(spanStr.c_str());
-  } else {
-    pp_trace("this span:(%s)", spanStr.c_str());
-    flush_to_agent(spanStr);
+    WrapperTraceNodePtr w_node = GetWrapperTraceNode(id, flag);
+    w_node->AddTraceDetail(key, value);
+    pp_trace(" [%d] add clue key:%s value:%s", id, key, value);
+  }
+  void AnnotateTrace_V2(NodeID id, const char* key, const char* value, E_NODE_LOC flag) {
+    NotInternalKey(key);
+
+    WrapperTraceNodePtr w_node = GetWrapperTraceNode(id, flag);
+    std::string cvalue = "";
+    cvalue += key;
+    cvalue += ':';
+    cvalue += value;
+    w_node->appendNodeValue("clues", cvalue.c_str());
+    pp_trace(" [%d] add clues:%s:%s", id, key, value);
+  }
+  void AnnotateErrorTrace(NodeID id, const char* msg, const char* error_filename,
+                          uint32_t error_lineno) {
+    WrapperTraceNodePtr w_root = GetWrapperTraceNode(id, E_LOC_ROOT);
+    Json::Value eMsg;
+    eMsg["msg"] = msg;
+    eMsg["file"] = error_filename;
+    eMsg["line"] = error_lineno;
+    w_root->AddTraceDetail("ERR", eMsg);
+  }
+  void AnnotateExceptionTrace(NodeID id, const char* exception) {
+    WrapperTraceNodePtr w_root = GetWrapperTraceNode(id, E_LOC_CURRENT);
+    w_root->AddTraceDetail("EXP", exception);
+    w_root->set_exp_ = true;
+    pp_trace(" [%d] add exp value:%s", id, exception);
   }
-}
 
-NodeID do_end_trace(NodeID Id) {
-  WrapperTraceNode r_node = PoolManager::getInstance().GetWrapperNode(Id);
-  if (r_node->isRoot()) {
-    if (r_node->limit == E_TRACE_PASS) {
-      r_node->endTimer();
-      r_node->convertToSpan();
-      sendSpan(Id);
-    } else if (r_node->limit == E_TRACE_BLOCK) {
-      pp_trace("current [%d] span dropped,due to TRACE_BLOCK", r_node->getId());
+  void AddTraceContext(NodeID id, const char* key, const char* value) {
+    WrapperTraceNodePtr w_node = GetWrapperTraceNode(id, E_LOC_ROOT);
+    w_node->setContext(key, value);
+  }
+  int GetTraceContext(NodeID id, const char* key, char* pbuf, int buf_size) {
+    WrapperTraceNodePtr w_node = GetWrapperTraceNode(id, E_LOC_ROOT);
+    std::string value;
+    w_node->getContext(key, value);
+    if (pbuf != nullptr && buf_size > (int)value.size()) {
+      strncpy(pbuf, value.c_str(), buf_size);
+      return (int)value.size();
     } else {
-      pp_trace("current [%d] span dropped,due to limit=%ld", r_node->getId(), r_node->limit);
+      pp_trace(" [%d] get context key:%s failed. buffer is not enough", id, key);
+      return -1;
     }
-  } else {
-    r_node->endTimer();
-    r_node->convertToSpanEvent();
-    return r_node->mParentId;
-  }
-  // free current node tree
-  return E_ROOT_NODE;
-}
-
-NodeID pinpoint_start_trace(NodeID parentId) {
-  try {
-    NodeID childId = do_start_trace(parentId);
-    pp_trace(" [%d] pinpoint_start child  [%d]", parentId, childId);
-    return childId;
-  } catch (const std::out_of_range& ex) {
-    pp_trace(" start_trace [%d] failed with %s", parentId, ex.what());
-  } catch (const std::runtime_error& ex) {
-    pp_trace(" start_trace [%d] failed with %s", parentId, ex.what());
-  } catch (const std::exception& ex) {
-    pp_trace(" start_trace [%d] failed with %s", parentId, ex.what());
   }
-  return E_INVALID_NODE;
-}
 
-static NodeID do_wake_trace(NodeID& id) {
-  // routine
-  // 1. check id alive
-  // 2. check if it's a root node
-  // 3. update start time
+  uint64_t GetStartTime() { return statePtr_->GetStartTime(); }
 
-  WrapperTraceNode w_node = PoolManager::getInstance().GetWrapperNode(id);
+  int64_t GetUniqueID() { return statePtr_->GetUniqueId(); }
 
-  if (w_node->isRoot()) {
-    pp_trace(" [%d] wake_trace failed, it's a root node", id);
-    return E_INVALID_NODE;
-  }
+  void ResetUniqueID() { statePtr_->ResetUniqueID(); }
 
-  w_node->wakeUp();
+  bool CheckTraceLimit(int64_t timestamp) { return statePtr_->CheckTraceLimit(timestamp); }
 
-  return id;
-}
+  using SpanHandler = void (*)(const char*);
+  void RegisterRawSpanHandler(SpanHandler user_handler) { rawSpanHandler_ = user_handler; }
 
-int pinpoint_wake_trace(NodeID traceId) {
-  try {
-    pp_trace("wake_trace  [%d] ", traceId);
-    return do_wake_trace(traceId);
-  } catch (const std::out_of_range& ex) {
-    pp_trace(" wake_trace [%d] failed with %s", traceId, ex.what());
-  } catch (const std::runtime_error& ex) {
-    pp_trace(" wake_trace [%d] failed with %s", traceId, ex.what());
-  } catch (...) {
-    pp_trace(" wake_trace [%d] failed with unkonw reason", traceId);
+  std::string GetNodePoolStatus() { return nodePool_.Status(); }
+  void DebugNodeId(NodeID id) {
+    try {
+      WrapperTraceNodePtr w_node = nodePool_.ReferNode(id);
+      fprintf(stderr, "nodeid [%d]: { value:%s }", id, w_node->ToString().c_str());
+    } catch (const std::exception& ex) {
+      pp_trace(" debug_nodeid: [%d] Reason: %s", id, ex.what());
+    }
   }
-  return 0;
-}
 
-int pinpoint_force_end_trace(NodeID id, int32_t timeout) {
-  _span_timeout = timeout;
-  while (id != E_ROOT_NODE) {
-    id = pinpoint_end_trace(id);
-    if (id == E_INVALID_NODE)
-      break;
-  }
-  // back to normal
-  _span_timeout = global_agent_info.timeout_ms;
-  return 0;
-}
-
-int pinpoint_trace_is_root(NodeID _id) {
-  try {
-    WrapperTraceNode node = PoolManager::getInstance().GetWrapperNode(_id);
-    return node->isRoot() ? (1) : (0);
-  } catch (const std::out_of_range&) {
-    pp_trace(" [%d] not found", _id);
-  } catch (const std::exception& ex) {
-    pp_trace(" [%d] end trace failed. %s", _id, ex.what());
+private:
+  static inline void NotInternalKey(const char* key) {
+    if (key == nullptr || key[0] == ':') {
+      std::string reason = "key:";
+      reason += key;
+      reason += "is invalid";
+      throw std::invalid_argument(reason);
+    }
   }
-  return -1;
-}
 
-NodeID pinpoint_end_trace(NodeID traceId) {
-  try {
-    NodeID ret = do_end_trace(traceId);
-    if (ret == E_ROOT_NODE) {
-      freeNodeTree(traceId);
+  std::string node_tree_to_string(const Json::Value& value) { return _writer.write(value); }
+
+  inline WrapperTraceNodePtr GetWrapperTraceNode(NodeID id, E_NODE_LOC flag) {
+    WrapperTraceNodePtr w_node = nodePool_.ReferNode(id);
+    if (flag == E_LOC_ROOT) {
+      return nodePool_.ReferNode(w_node->root_id_);
+    } else {
+      return w_node;
     }
-    pp_trace(" [%d] pinpoint_end_trace Done!", traceId);
-    return ret;
-  } catch (const std::out_of_range& ex) {
-    pp_trace("end_trace %d out_of_range exception: %s", traceId, ex.what());
-  } catch (const std::runtime_error& ex) {
-    pp_trace("end_trace %d runtime_error: %s", traceId, ex.what());
-  } catch (const std::exception& ex) {
-    pp_trace("end_trace  [%d] end trace failed. %s", traceId, ex.what());
   }
 
-  return E_INVALID_NODE;
-}
+private:
+  int span_timeout_;
+  int agent_type_;
+  ConnectionPool::SpanConnectionPool connection_pool_;
+  NodePool::PoolManager nodePool_;
+  StatePtr statePtr_;
+  SpanHandler rawSpanHandler_ = {nullptr};
+  Json::CharReaderBuilder builder;
 
-// static int do_remove_trace(NodeID traceId)
-// {
-//     TraceNode&  node = PoolManager::getInstance().getNodeById(traceId);
-//     node.remove();
-//     return 0;
-// }
-
-// int pinpoint_remove_trace(NodeID traceId)
-// {
-//     try
-//     {
-//         NodeID ret = do_remove_trace(traceId);
-//         pp_trace(" [%d] pinpoint_remove_trace Done!",traceId);
-//         return ret;
-//     }catch(const std::out_of_range&){
-//         pp_trace(" [%d] not found",traceId);
-//         return -1;
-//     }catch(const std::exception &ex){
-//         pp_trace(" [%d] end trace failed. %s",traceId,ex.what());
-//         return -1;
-//     }
-// }
-
-uint64_t pinpoint_start_time(void) { return (uint64_t)SafeSharedState::instance().getStartTime(); }
-
-int64_t generate_unique_id() { return SafeSharedState::instance().generateUniqueId(); }
-
-void reset_unique_id(void) { return SafeSharedState::instance().resetUniqueId(); }
-
-uint64_t inline do_mark_current_trace_status(NodeID& _id, E_AGENT_STATUS status) {
-  WrapperTraceNode w_node = PoolManager::getInstance().GetWrapperNode(_id);
-  WrapperTraceNode w_root = PoolManager::getInstance().GetWrapperNode(w_node->mRootIndex);
-  pp_trace("change current [%d] status, before:%lld,now:%d", w_root->getId(), w_root->limit,
-           status);
-  return __sync_lock_test_and_set(&w_root->limit, status);
-}
+public:
+  static thread_local NodeID per_thread_current_id;
+  NodeTreeWriter _writer;
+};
 
-uint64_t mark_current_trace_status(NodeID _id, int status) {
-  try {
-    return do_mark_current_trace_status(_id, (E_AGENT_STATUS)status);
-  } catch (const std::out_of_range& ex) {
-    pp_trace(" %s [%d] failed with %s", __func__, _id, ex.what());
-  } catch (const std::runtime_error& ex) {
-    pp_trace(" %s [%d] failed with %s", __func__, _id, ex.what());
-  } catch (...) {
-    pp_trace(" %s [%d] failed with unkonw reason", __func__, _id);
-  }
-  return 0;
-}
+thread_local NodeID Agent::per_thread_current_id = E_ROOT_NODE;
 
-int check_tracelimit(int64_t timestamp) {
-  return SafeSharedState::instance().checkTraceLimit(timestamp) ? (1) : (0);
-}
+using AgentPtr = std::unique_ptr<Agent>;
+AgentPtr _agentPtr = {nullptr};
 
-static inline WrapperTraceNode locate_node_by_loc(NodeID _id, E_NODE_LOC flag) {
-  WrapperTraceNode w_node = PoolManager::getInstance().GetWrapperNode(_id);
-  if (flag == E_LOC_ROOT) {
-    return PoolManager::getInstance().GetWrapperNode(w_node->mRootIndex);
-  } else {
-    return w_node;
+} // namespace PP
+
+using PP::_agentPtr;
+using PP::Agent;
+using PP::AgentPtr;
+
+NodeID pinpoint_get_per_thread_id() { return Agent::per_thread_current_id; }
+
+void pinpoint_update_per_thread_id(NodeID id) { Agent::per_thread_current_id = id; }
+
+bool pinpoint_set_agent(const char* collector_agent_address, long timeout_ms, long trace_limit,
+                        int agent_type) {
+#ifdef UTEST
+  _agentPtr = AgentPtr(new Agent(collector_agent_address, timeout_ms, trace_limit, agent_type));
+  return true;
+#else
+  if (_agentPtr == nullptr) {
+    _agentPtr = AgentPtr(new Agent(collector_agent_address, timeout_ms, trace_limit, agent_type));
+    return true;
   }
+  return false;
+#endif
 }
 
-static void do_add_clue(NodeID _id, const char* key, const char* value, E_NODE_LOC flag) {
-  WrapperTraceNode w_node = locate_node_by_loc(_id, flag);
-  w_node->AddTraceDetail(key, value);
-  pp_trace(" [%d] add clue key:%s value:%s", _id, key, value);
-}
+void pinpoint_stop_agent() { _agentPtr = nullptr; }
 
-static void do_add_clues(NodeID _id, const char* key, const char* value, E_NODE_LOC flag) {
-  WrapperTraceNode w_node = locate_node_by_loc(_id, flag);
+NodeID pinpoint_start_trace(NodeID parentId) { return pinpoint_start_traceV1(parentId, nullptr); }
 
-  std::string cvalue = "";
-  cvalue += key;
-  cvalue += ':';
-  cvalue += value;
-  w_node->appendNodeValue(CLUSE, cvalue.c_str());
-  pp_trace(" [%d] add clues:%s:%s", _id, key, value);
+NodeID pinpoint_start_traceV1(NodeID parentId, const char* opt, ...) {
+  if (_agentPtr) {
+    try {
+      va_list args;
+      va_start(args, opt);
+      NodeID child = _agentPtr->StartTrace(parentId, opt, &args);
+      pp_trace(" [%d] pinpoint_start child  [%d]", parentId, child);
+      va_end(args);
+      return child;
+    } catch (const std::out_of_range& ex) {
+      pp_trace(" start_trace [%d] failed with %s", parentId, ex.what());
+    } catch (const std::runtime_error& ex) {
+      pp_trace(" start_trace [%d] failed with %s", parentId, ex.what());
+    } catch (const std::exception& ex) {
+      pp_trace(" start_trace [%d] failed with %s", parentId, ex.what());
+    }
+  }
+  return E_INVALID_NODE;
 }
 
-void pinpoint_add_clues(NodeID _id, const char* key, const char* value, E_NODE_LOC flag) {
-  try {
-    _verify_key(key);
-    do_add_clues(_id, key, value, flag);
-  } catch (const std::out_of_range& ex) {
-    pp_trace(" %s [%d] failed. Reason %s,parameters:%s:%s", __func__, _id, ex.what(), key, value);
-  } catch (const std::runtime_error& ex) {
-    pp_trace(" %s [%d] failed. Reason %s,parameters:%s:%s", __func__, _id, ex.what(), key, value);
-  } catch (const std::exception& ex) {
-    pp_trace(" %s [%d] failed. Reason: %s,parameters:%s:%s", __func__, _id, ex.what(), key, value);
+void pinpoint_add_exception(NodeID id, const char* exp) {
+  if (_agentPtr) {
+    try {
+      return _agentPtr->AnnotateExceptionTrace(id, exp);
+    } catch (const std::out_of_range& ex) {
+      pp_trace(" %s [%d] failed. Reason: %s,parameters:%s", __func__, id, ex.what(), exp);
+    } catch (const std::runtime_error& ex) {
+      pp_trace(" %s [%d] failed. Reason: %s,parameters:%s", __func__, id, ex.what(), exp);
+    } catch (const std::exception& ex) {
+      pp_trace(" %s [%d] failed. Reason: %s,parameters:%s", __func__, id, ex.what(), exp);
+    }
   }
 }
 
-void pinpoint_add_clue(NodeID _id, const char* key, const char* value, E_NODE_LOC flag) {
-  try {
-    _verify_key(key);
-    do_add_clue(_id, key, value, flag);
-  } catch (const std::out_of_range& ex) {
-    pp_trace(" %s [%d] failed. Reason: %s,parameters:%s:%s", __func__, _id, ex.what(), key, value);
-  } catch (const std::runtime_error& ex) {
-    pp_trace(" %s [%d] failed. Reason: %s,parameters:%s:%s", __func__, _id, ex.what(), key, value);
-  } catch (const std::exception& ex) {
-    pp_trace(" %s [%d] failed. Reason: %s,parameters:%s:%s", __func__, _id, ex.what(), key, value);
+ParentNodeId pinpoint_end_trace(NodeID id) {
+  if (_agentPtr) {
+    try {
+      NodeID ret = _agentPtr->EndTrace(id);
+      pp_trace(" [%d] pinpoint_end_trace Done!", id);
+      return ret;
+    } catch (const std::out_of_range& ex) {
+      pp_trace("end_trace %d out_of_range exception: %s", id, ex.what());
+    } catch (const std::runtime_error& ex) {
+      pp_trace("end_trace %d runtime_error: %s", id, ex.what());
+    } catch (const std::exception& ex) {
+      pp_trace("end_trace  [%d] end trace failed. %s", id, ex.what());
+    }
   }
+  return E_INVALID_NODE;
 }
 
-static inline void do_set_context_key(NodeID _id, const char* key, const char* value) {
-  WrapperTraceNode w_node = locate_node_by_loc(_id, E_LOC_ROOT);
-  w_node->setContext(key, value);
+int pinpoint_trace_is_root(NodeID id) {
+  if (_agentPtr) {
+    try {
+      if (id == E_ROOT_NODE) {
+        return -1;
+      }
+      return _agentPtr->IsRootTrace(id) ? (1) : (0);
+    } catch (const std::out_of_range&) {
+      pp_trace("not found node=%d ", id);
+    } catch (const std::exception& ex) {
+      pp_trace(" node=%d end trace failed: %s", id, ex.what());
+    }
+  }
+  return -1;
 }
 
-static int do_get_context_key(NodeID _id, const char* key, char* pbuf, int buf_size) {
-  WrapperTraceNode w_node = locate_node_by_loc(_id, E_LOC_ROOT);
-  std::string value;
-  w_node->getContext(key, value);
-  if (pbuf != nullptr && buf_size > (int)value.size()) {
-    strncpy(pbuf, value.c_str(), buf_size);
-    return (int)value.size();
-  } else {
-    pp_trace(" [%d] get context key:%s failed. buffer is not enough", _id, key);
-    return -1;
+int pinpoint_force_end_trace(NodeID id, int32_t timeout) {
+  if (_agentPtr) {
+    try {
+      while (id != E_ROOT_NODE) {
+        id = _agentPtr->EndTrace(id, timeout);
+        if (id == E_INVALID_NODE)
+          break;
+      }
+      pp_trace(" [%d] pinpoint_end_trace Done!", id);
+      return E_ROOT_NODE;
+    } catch (const std::out_of_range& ex) {
+      pp_trace("end_trace %d out_of_range exception: %s", id, ex.what());
+    } catch (const std::runtime_error& ex) {
+      pp_trace("end_trace %d runtime_error: %s", id, ex.what());
+    } catch (const std::exception& ex) {
+      pp_trace("end_trace  [%d] end trace failed. %s", id, ex.what());
+    }
   }
+  return E_INVALID_NODE;
 }
 
-void pinpoint_set_context_key(NodeID _id, const char* key, const char* value) {
-  try {
-    _verify_key(key);
-    do_set_context_key(_id, key, value);
-  } catch (const std::out_of_range& ex) {
-    pp_trace(" %s [%d] failed with out_of_range. %s,parameters:%s:%s", __func__, _id, ex.what(),
-             key, value);
-  } catch (const std::runtime_error& ex) {
-    pp_trace(" %s [%d] failed with runtime_error. %s,parameters:%s:%s", __func__, _id, ex.what(),
-             key, value);
-  } catch (const std::exception& ex) {
-    pp_trace(" %s [%d] failed with %s,parameters:%s:%s", __func__, _id, ex.what(), key, value);
+void pinpoint_add_clues(NodeID id, const char* key, const char* value, E_NODE_LOC flag) {
+  if (_agentPtr) {
+
+    try {
+      _agentPtr->AnnotateTrace_V2(id, key, value, flag);
+    } catch (const std::out_of_range& ex) {
+      pp_trace(" %s [%d] failed. Reason %s,parameters:%s:%s", __func__, id, ex.what(), key, value);
+    } catch (const std::runtime_error& ex) {
+      pp_trace(" %s [%d] failed. Reason %s,parameters:%s:%s", __func__, id, ex.what(), key, value);
+    } catch (const std::exception& ex) {
+      pp_trace(" %s [%d] failed. Reason %s,parameters:%s:%s", __func__, id, ex.what(), key, value);
+    }
   }
 }
 
-static void do_set_long_key(NodeID id, const char* key, long l) {
-  WrapperTraceNode w_node = locate_node_by_loc(id, E_LOC_ROOT);
-  w_node->setContext(key, l);
+void pinpoint_add_clue(NodeID id, const char* key, const char* value, E_NODE_LOC flag) {
+  if (_agentPtr) {
+    try {
+      _agentPtr->AnnotateTrace_V1(id, key, value, flag);
+    } catch (const std::out_of_range& ex) {
+      pp_trace(" %s [%d] failed. Reason: %s,parameters:%s:%s", __func__, id, ex.what(), key, value);
+    } catch (const std::runtime_error& ex) {
+      pp_trace(" %s [%d] failed. Reason: %s,parameters:%s:%s", __func__, id, ex.what(), key, value);
+    } catch (const std::exception& ex) {
+      pp_trace(" %s [%d] failed. Reason: %s,parameters:%s:%s", __func__, id, ex.what(), key, value);
+    }
+  }
 }
 
-void pinpoint_set_context_long(NodeID _id, const char* key, long l) {
-  try {
-    _verify_key(key);
-    do_set_long_key(_id, key, l);
-  } catch (const std::out_of_range& ex) {
-    pp_trace(" %s [%d] failed with %s", __func__, _id, ex.what());
-  } catch (const std::runtime_error& ex) {
-    pp_trace(" %s [%d] failed with %s", __func__, _id, ex.what());
-  } catch (const std::exception& ex) {
-    pp_trace(" %s [%d] failed with %s", __func__, _id, ex.what());
+void pinpoint_set_context_key(NodeID id, const char* key, const char* value) {
+  if (_agentPtr) {
+    try {
+      _agentPtr->AddTraceContext(id, key, value);
+    } catch (const std::out_of_range& ex) {
+      pp_trace(" %s [%d] failed with out_of_range. %s,parameters:%s:%s", __func__, id, ex.what(),
+               key, value);
+    } catch (const std::runtime_error& ex) {
+      pp_trace(" %s [%d] failed with runtime_error. %s,parameters:%s:%s", __func__, id, ex.what(),
+               key, value);
+    } catch (const std::exception& ex) {
+      pp_trace(" %s [%d] failed with %s,parameters:%s:%s", __func__, id, ex.what(), key, value);
+    }
   }
 }
 
-static int do_get_long_key(NodeID _id, const char* key, long* l) {
-  WrapperTraceNode w_node = locate_node_by_loc(_id, E_LOC_ROOT);
-  if (l != nullptr) {
-    long v;
-    w_node->getContext(key, v);
-    *l = v;
+int pinpoint_get_context_key(NodeID id, const char* key, char* pbuf, int buf_size) {
+  if (_agentPtr) {
+    try {
+      return _agentPtr->GetTraceContext(id, key, pbuf, buf_size);
+    } catch (const std::out_of_range& ex) {
+      pp_trace(" %s [%d] failed with %s, parameters:%s", __func__, id, ex.what(), key);
+    } catch (const std::runtime_error& ex) {
+      pp_trace(" %s [%d] failed with %s, parameters:%s", __func__, id, ex.what(), key);
+    } catch (const std::exception& ex) {
+      pp_trace(" %s [%d] failed with %s, parameters:%s", __func__, id, ex.what(), key);
+    }
   }
   return 0;
 }
 
-int pinpoint_get_context_long(NodeID _id, const char* key, long* l) {
-  try {
-    _verify_key(key);
-    do_get_long_key(_id, key, l);
+int check_trace_limit(int64_t timestamp) {
+  if (_agentPtr) {
+    return _agentPtr->CheckTraceLimit(timestamp) ? 1 : 0;
+  } else {
     return 0;
-  } catch (const std::out_of_range& ex) {
-    pp_trace(" %s [%d] failed with %s", __func__, _id, ex.what());
-  } catch (const std::runtime_error& ex) {
-    pp_trace(" %s [%d] failed with %s", __func__, _id, ex.what());
-  } catch (const std::exception& ex) {
-    pp_trace(" %s [%d] failed with %s", __func__, _id, ex.what());
-  }
-  return 1;
-}
-
-int pinpoint_get_context_key(NodeID _id, const char* key, char* pbuf, int buf_size) {
-  try {
-    _verify_key(key);
-    return do_get_context_key(_id, key, pbuf, buf_size);
-  } catch (const std::out_of_range& ex) {
-    pp_trace(" %s [%d] failed with %s, parameters:%s", __func__, _id, ex.what(), key);
-  } catch (const std::runtime_error& ex) {
-    pp_trace(" %s [%d] failed with %s, parameters:%s", __func__, _id, ex.what(), key);
-  } catch (const std::exception& ex) {
-    pp_trace(" %s [%d] failed with %s, parameters:%s", __func__, _id, ex.what(), key);
   }
-  return -1;
 }
 
-void do_catch_error(NodeID _id, const char* msg, const char* error_filename,
-                    uint32_t error_lineno) {
-  WrapperTraceNode w_node = locate_node_by_loc(_id, E_LOC_ROOT);
-
-  Json::Value eMsg;
-  eMsg["msg"] = msg;
-  eMsg["file"] = error_filename;
-  eMsg["line"] = error_lineno;
-  w_node->AddTraceDetail("ERR", eMsg);
-}
+int check_tracelimit(int64_t timestamp) { return check_trace_limit(timestamp); }
 
-void catch_error(NodeID _id, const char* msg, const char* error_filename, uint32_t error_lineno) {
-  try {
-    do_catch_error(_id, msg, error_filename, error_lineno);
-  } catch (const std::out_of_range& ex) {
-    pp_trace(" %s [%d] failed with %s", __func__, _id, ex.what());
-  } catch (const std::runtime_error& ex) {
-    pp_trace(" %s [%d] failed with %s", __func__, _id, ex.what());
-  } catch (const std::exception& ex) {
-    pp_trace(" %s [%d] failed with %s", __func__, _id, ex.what());
+uint64_t change_trace_status(NodeID id, int status) {
+  if (_agentPtr) {
+    try {
+      return _agentPtr->ChangeTraceStatus(id, status);
+    } catch (const std::out_of_range& ex) {
+      pp_trace(" %s [%d] failed with %s", __func__, id, ex.what());
+    } catch (const std::runtime_error& ex) {
+      pp_trace(" %s [%d] failed with %s", __func__, id, ex.what());
+    } catch (...) {
+      pp_trace(" %s [%d] failed with unkonw reason", __func__, id);
+    }
   }
+  return 0;
 }
 
-const char* pinpoint_agent_version() {
-#ifdef AGENT_VERSION
-  static const char* _version_ = AGENT_VERSION;
-#else
-  static const char* _version_ = "x.x.x";
-#endif
-  return _version_;
+uint64_t mark_current_trace_status(NodeID id, int status) {
+  return change_trace_status(id, status);
 }
 
-NodeID pinpoint_start_traceV1(NodeID parentId, const char* opt, ...) {
-  try {
-    va_list args;
-    va_start(args, opt);
-    NodeID childId = do_start_trace(parentId, opt, &args);
-    va_end(args);
-    pp_trace(" [%d] pinpoint_start_traceV1 child  [%d]", parentId, childId);
-    return childId;
-  } catch (const std::out_of_range& ex) {
-    pp_trace(" start_trace [%d] failed with %s", parentId, ex.what());
-  } catch (const std::runtime_error& ex) {
-    pp_trace(" start_trace [%d] failed with %s", parentId, ex.what());
-  } catch (...) {
-    pp_trace(" start_trace [%d] failed with unkonw reason", parentId);
+int64_t generate_unique_id(void) {
+  if (_agentPtr) {
+    return _agentPtr->GetUniqueID();
+  } else {
+    return 0;
   }
-  return E_INVALID_NODE;
 }
 
-static void do_add_exp(NodeID _id, const char* value) {
-  WrapperTraceNode w_root = locate_node_by_loc(_id, E_LOC_CURRENT);
-  w_root->AddTraceDetail("EXP", value);
-  w_root->mHasExp = true;
-  pp_trace(" [%d] add exp value:%s", _id, value);
+uint64_t pinpoint_start_time(void) {
+  if (_agentPtr && _agentPtr->GetStartTime() != 0) {
+    return _agentPtr->GetStartTime();
+  }
+  return get_unix_time_ms();
+}
+
+void catch_error(NodeID id, const char* msg, const char* error_filename, uint32_t error_lineno) {
+  if (_agentPtr) {
+    try {
+      _agentPtr->AnnotateErrorTrace(id, msg, error_filename, error_lineno);
+    } catch (const std::out_of_range& ex) {
+      pp_trace(" %s [%d] failed with %s", __func__, id, ex.what());
+    } catch (const std::runtime_error& ex) {
+      pp_trace(" %s [%d] failed with %s", __func__, id, ex.what());
+    } catch (const std::exception& ex) {
+      pp_trace(" %s [%d] failed with %s", __func__, id, ex.what());
+    }
+  }
 }
 
-void pinpoint_add_exception(NodeID traceId, const char* exp) {
-  try {
-    do_add_exp(traceId, exp);
-  } catch (const std::out_of_range& ex) {
-    pp_trace(" %s [%d] failed. Reason: %s,parameters:%s", __func__, traceId, ex.what(), exp);
-  } catch (const std::runtime_error& ex) {
-    pp_trace(" %s [%d] failed. Reason: %s,parameters:%s", __func__, traceId, ex.what(), exp);
-  } catch (const std::exception& ex) {
-    pp_trace(" %s [%d] failed. Reason: %s,parameters:%s", __func__, traceId, ex.what(), exp);
+void register_span_handler(void (*handler)(const char*)) {
+  if (_agentPtr) {
+    _agentPtr->RegisterRawSpanHandler(handler);
   }
 }
 
-void register_span_handler(void (*handler)(const char*)) {
-  if (likely(handler != nullptr)) {
-    _SpanHandler_ = std::bind(handler, std::placeholders::_1);
+void reset_unique_id(void) {
+  if (_agentPtr) {
+    _agentPtr->ResetUniqueID();
   }
 }
 
 void show_status(void) {
-  Json::Value status;
-  status["pool_total_node"] = PoolManager::getInstance().totoalNodesCount();
-  status["pool_free_node"] = PoolManager::getInstance().freeNodesCount();
-  status["common_libary_version"] = pinpoint_agent_version();
-  auto add_alive_node_fun = [&status](TraceNode& node) {
-    status["pool_alive_nodes"].append(node.mPoolIndex);
-  };
-  PoolManager::getInstance().foreachAliveNode(std::bind(add_alive_node_fun, std::placeholders::_1));
-
-  fprintf(stderr, "%s\n", status.toStyledString().c_str());
+  if (_agentPtr) {
+    fprintf(stderr, "%s\n", _agentPtr->GetNodePoolStatus().c_str());
+  }
 }
 
 void debug_nodeid(NodeID id) {
-  try {
-    WrapperTraceNode r_node = PoolManager::getInstance().GetWrapperNode(id);
-    fprintf(stderr, "nodeid [%d]: { value:%s }", id, r_node->ToString().c_str());
-  } catch (const std::exception& ex) {
-    pp_trace(" debug_nodeid: [%d] Reason: %s", id, ex.what());
+  if (_agentPtr) {
+    _agentPtr->DebugNodeId(id);
   }
+}
+
+const char* pinpoint_agent_version() {
+#ifdef AGENT_VERSION
+  static const char* _version_ = AGENT_VERSION;
+#else
+  static const char* _version_ = PINPOINT_C_AGENT_API_VERSION;
+#endif
+  return _version_;
+}
+
+uint64_t get_unix_time_ms() {
+  std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
+  time_point<system_clock, milliseconds> current = time_point_cast<std::chrono::milliseconds>(now);
+  return current.time_since_epoch().count();
 }
\ No newline at end of file
diff --git a/common/src/header.h b/common/src/header.h
index f4f7ea9f8..13d4730d4 100644
--- a/common/src/header.h
+++ b/common/src/header.h
@@ -1,5 +1,39 @@
+/*******************************************************************************
+ * Copyright 2024 NAVER Corp
+ *
+ * Licensed 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.
+ ******************************************************************************/
 #pragma once
+#include "common.h"
 
+#ifdef __linux__
 #define likely(x) __builtin_expect(!!(x), 1)
 #define unlikely(x) __builtin_expect(!!(x), 0)
-void debug_nodeid(NodeID id);
\ No newline at end of file
+#else
+#define likely(x) (x)
+#define unlikely(x) (x)
+#endif
+
+#ifdef __linux__
+
+#elif defined(_WIN32)
+#include <windows.h>
+
+#define sleep(x) Sleep(x * 1000)
+#define usleep(x) Sleep(x / 1000)
+#else
+#endif
+
+void debug_nodeid(NodeID id);
+uint64_t get_unix_time_ms();
+void pinpoint_stop_agent();
\ No newline at end of file
diff --git a/config.m4 b/config.m4
index 7ac4923e7..2dbfbff93 100644
--- a/config.m4
+++ b/config.m4
@@ -33,15 +33,10 @@ if test "$PHP_PINPOINT_PHP" != "no"; then
   PINPOINT_SRCS="$EXTRA_PHP_SRCS \
     common/src/common.cpp \
     common/src/Logging.cpp \
-    common/src/Util/Helper.cpp \
     common/src/NodePool/TraceNode.cpp \
     common/src/NodePool/PoolManager.cpp \
-    common/src/Context/ContextType.cpp \
     common/src/ConnectionPool/TransLayer.cpp \
-    common/src/ConnectionPool/SpanConnectionPool.cpp \
-    common/src/Cache/SafeSharedState.cpp \
-    common/src/Cache/SharedObj.cpp \
-    common/src/Cache/NodeTreeWriter.cpp \
+    common/src/Cache/State.cpp \
     common/src/Cache/Chunk.cpp \
     "
   PINPOINT_SRCS="$PINPOINT_SRCS \
diff --git a/plugins/PY/pinpointPy/Common.py b/plugins/PY/pinpointPy/Common.py
index 81ff25e6b..5c3b27dd4 100644
--- a/plugins/PY/pinpointPy/Common.py
+++ b/plugins/PY/pinpointPy/Common.py
@@ -255,7 +255,7 @@ def onBefore(self, parentId: int, *args, **kwargs):
         pinpoint.add_context(Defines.PP_TRANSCATION_ID, tid, traceId)
 
         if header.Error:
-            pinpoint.mark_as_error(header.Error, header.Error, traceId, 0)
+            pinpoint.mark_as_error(header.Error, header.Error, 0, traceId)
 
         return traceId, args, kwargs
 
@@ -263,5 +263,5 @@ def onEnd(self, traceId, ret):
         super().onEnd(traceId, ret)
 
     def onException(self, traceId, e):
-        pinpoint.mark_as_error(str(e), "", traceId)
+        pinpoint.mark_as_error(str(e), "", 0, traceId)
         raise e
diff --git a/plugins/PY/pinpointPy/Flask/PinPointMiddleWare.py b/plugins/PY/pinpointPy/Flask/PinPointMiddleWare.py
index 4c253c955..910a48f9c 100644
--- a/plugins/PY/pinpointPy/Flask/PinPointMiddleWare.py
+++ b/plugins/PY/pinpointPy/Flask/PinPointMiddleWare.py
@@ -18,7 +18,7 @@
 #!/usr/bin/env python
 # -*- coding: UTF-8 -*-
 from pinpointPy.Defines import PP_HTTP_STATUS_CODE, PP_URL_TEMPLATED
-from pinpointPy.pinpoint import add_trace_header_v2, add_trace_header
+from pinpointPy.pinpoint import add_trace_header_v2, add_trace_header, mark_as_error
 from pinpointPy.Flask.FlaskPlugins import BaseFlaskPlugins
 from flask import request
 import sys
@@ -42,7 +42,11 @@ def mark_status_code(response):
                         response.headers["UT"] = str(request.url_rule)
                 if response:
                     add_trace_header_v2(PP_HTTP_STATUS_CODE,
-                                        str(response.status), trace_id)
+                                        response.status, trace_id)
+                    # fix bug in https://oss.navercorp.com/pinpoint/pinpoint_c_agent/issues/570
+                    if response.status >= '400':
+                        mark_as_error(
+                            f'status_code:{response.status}', 'FastAPIRequestPlugin', 0, trace_id)
             return response
 
     @BaseFlaskPlugins("Flask Web App")
diff --git a/plugins/PY/pinpointPy/RequestPlugins.py b/plugins/PY/pinpointPy/RequestPlugins.py
index 72879ac1e..4dfab3e80 100644
--- a/plugins/PY/pinpointPy/RequestPlugins.py
+++ b/plugins/PY/pinpointPy/RequestPlugins.py
@@ -142,5 +142,5 @@ def onEnd(self, trace_id, ret):
         return ret
 
     def onException(self, trace_id, e):
-        pinpoint.mark_as_error(str(e), "", trace_id)
+        pinpoint.mark_as_error(str(e), "", 0, trace_id)
         raise e
diff --git a/plugins/PY/pinpointPy/WSGIPlugin.py b/plugins/PY/pinpointPy/WSGIPlugin.py
index e81938294..6bdbcfe07 100644
--- a/plugins/PY/pinpointPy/WSGIPlugin.py
+++ b/plugins/PY/pinpointPy/WSGIPlugin.py
@@ -44,4 +44,4 @@ def onEnd(self, trace_id, ret):
         return ret
 
     def onException(self, traceId, e):
-        pinpoint.mark_as_error(str(e), "", traceId)
+        pinpoint.mark_as_error(str(e), "", 0, traceId)
diff --git a/plugins/PY/pinpointPy/pinpoint.py b/plugins/PY/pinpointPy/pinpoint.py
index c32823587..799ff2461 100644
--- a/plugins/PY/pinpointPy/pinpoint.py
+++ b/plugins/PY/pinpointPy/pinpoint.py
@@ -103,7 +103,7 @@ def trace_has_root(trace_id=-1):
     return _pinpointPy.trace_has_root(trace_id)
 
 
-def mark_as_error(message: str, filename: str = '', trace_id: int = -1, line: int = 0):
+def mark_as_error(message: str, filename: str = '', line: int = 0, trace_id: int = -1):
     _pinpointPy.mark_as_error(message, filename, line, trace_id)
 
 
@@ -115,15 +115,15 @@ def check_trace_limit(time: int = -1) -> bool:
     return _pinpointPy.check_tracelimit(time)
 
 
-def set_agent(app_id_str: str, app_name_str: str, collect_agent_host: str,  trace_limit: int = -1, log_level=logging.INFO):
+def set_agent(app_id_str: str, app_name_str: str, collect_agent_host: str,  trace_limit: int = -1, time_out: int = 0, log_level=logging.INFO):
     global __app_id, __app_name
     __app_id = app_id_str
     __app_name = app_name_str
-    _pinpointPy.set_agent(collect_agent_host, trace_limit)
     if log_level == logging.DEBUG:
         def debug_func(msg: str):
             get_logger().debug(msg=msg)
         _pinpointPy.enable_debug(debug_func)
+    _pinpointPy.set_agent(collect_agent_host, trace_limit, time_out)
     set_logger_level(log_level)
     get_logger().debug(
-        f"appid:{app_id_str} appname:{app_name_str} collector_agent:{collect_agent_host} trace_limit:{trace_limit} log_level:{log_level}")
+        f"appid:{app_id_str} appname:{app_name_str} collector_agent:{collect_agent_host} trace_limit:{trace_limit} timeout:{time_out}ms log_level:{log_level}")
diff --git a/setup.py b/setup.py
deleted file mode 120000
index a9cac7fa4..000000000
--- a/setup.py
+++ /dev/null
@@ -1,1 +0,0 @@
-setup_pypi.py
\ No newline at end of file
diff --git a/setup.py b/setup.py
new file mode 100644
index 000000000..3c8eda7ec
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,60 @@
+from setuptools import setup, Extension, find_namespace_packages
+import platform
+from pathlib import Path
+
+with open("README", "r") as fh:
+    long_description = fh.read()
+
+name = platform.system().lower()
+agent_libraries = []
+extra_compile_args_ = []
+if name == 'windows':
+    pass
+elif name == 'darwin':
+    agent_libraries = ['stdc++']
+    extra_compile_args_.append("-std=c++11")
+elif name == 'linux':
+    agent_libraries = ['rt', 'stdc++']
+    extra_compile_args_.append("-std=c++11")
+else:
+    raise RuntimeError('Unknown platform to us: ' + name)
+###############################################
+
+extFiles = [
+    'src/PY/_pinpoint_py.cpp',
+]
+
+# add pinpoint-common
+
+for a_file in Path("common/src").glob('**/*.cpp'):
+    extFiles.append(str(a_file))
+
+for a_file in Path("common/jsoncpp").glob('**/*.cpp'):
+    extFiles.append(str(a_file))
+
+
+cwd = Path.cwd()
+
+include_dirs_ = [Path(cwd, './common/include'), Path(cwd, './common/jsoncpp/include'),
+                 Path(cwd, './common/src')]
+
+setup(name='pinpointPy',
+      version="1.2.0",  # don't forget update __version__ in pinpointPy/__init__.py
+      author="cd_pinpoint members",
+      author_email='dl_cd_pinpoint@navercorp.com',
+      license='Apache License 2.0',
+      url="https://github.com/pinpoint-apm/pinpoint-c-agent",
+      long_description=long_description,
+      long_description_content_type='text/markdown',
+      ext_modules=[
+          Extension('_pinpointPy',
+                    extFiles,
+                    include_dirs=include_dirs_,
+                    libraries=agent_libraries,
+                    extra_compile_args=extra_compile_args_
+                    )
+      ],
+      package_dir={'': 'plugins/PY'},
+      packages=find_namespace_packages(
+          'plugins/PY', include=['pinpointPy.*', 'pinpointPy']),
+      )
diff --git a/setup_pypi.py b/setup_pypi.py
deleted file mode 100644
index 170a26b46..000000000
--- a/setup_pypi.py
+++ /dev/null
@@ -1,53 +0,0 @@
-from setuptools import setup, Extension, find_namespace_packages, find_packages
-from distutils.command.build_ext import build_ext
-import platform
-from pathlib import Path
-
-with open("README", "r") as fh:
-    long_description = fh.read()
-
-name = platform.system().lower()
-agent_libraries = []
-if name == 'windows':
-    raise RuntimeError('pinpoint-c-agent currently not support MS')
-elif name == 'darwin':
-    agent_libraries = ['stdc++']
-elif name == 'linux':
-    agent_libraries = ['rt', 'stdc++']
-else:
-    raise RuntimeError('Unknow platform to me: '+name)
-###############################################
-
-extFiles = [
-    'src/PY/_pinpoint_py.cpp',
-]
-
-# add pinpoint-common
-
-for a_file in Path("common").glob('**/*.cpp'):
-    extFiles.append(str(a_file))
-
-for a_file in Path("common").glob('**/*.c'):
-    extFiles.append(str(a_file))
-
-setup(name='pinpointPy',
-      version="1.1.0",  # don't forget update __version__ in pinpointPy/__init__.py
-      author="cd_pinpoint members",
-      author_email='dl_cd_pinpoint@navercorp.com',
-      license='Apache License 2.0',
-      url="https://github.com/pinpoint-apm/pinpoint-c-agent",
-      long_description=long_description,
-      long_description_content_type='text/markdown',
-      ext_modules=[
-          Extension('_pinpointPy',
-                    extFiles,
-                    include_dirs=['common/include',
-                                  'common/jsoncpp/include', 'common/src'],
-                    libraries=agent_libraries,
-                    extra_compile_args=['-std=c++11']
-                    )
-      ],
-      package_dir={'': 'plugins/PY'},
-      packages=find_namespace_packages(
-          'plugins/PY', include=['pinpointPy.*', 'pinpointPy']),
-      )
diff --git a/src/CPP/CMakeLists.txt b/src/CPP/CMakeLists.txt
index 5f46c51d0..bc0b465b7 100644
--- a/src/CPP/CMakeLists.txt
+++ b/src/CPP/CMakeLists.txt
@@ -3,13 +3,15 @@ project(common)
 set(CMAKE_CXX_STANDARD 11)
 
 include(FetchContent)
-FetchContent_Declare(
-  pinpoint
-  GIT_REPOSITORY https://github.com/pinpoint-c-agent/pinpoint-c-agent.git
-  # GIT_TAG        74bc39d813d664cb56b78b1506d91932c8131396 
-  # not recommended, please use hash key like `74bc39d813d664cb56b78b1506d91932c8131396`
-  GIT_TAG        origin/dev
-)
+# FetchContent_Declare(
+#   pinpoint
+#   GIT_REPOSITORY https://github.com/pinpoint-c-agent/pinpoint-c-agent.git
+#   # GIT_TAG        74bc39d813d664cb56b78b1506d91932c8131396 
+#   # not recommended, please use hash key like `74bc39d813d664cb56b78b1506d91932c8131396`
+#   GIT_TAG        origin/dev
+# )
+
+FetchContent_Declare(pinpoint SOURCE_DIR ${PROJECT_SOURCE_DIR}/../../)
 
 FetchContent_GetProperties(pinpoint)
 if (NOT pinpoint_POPULATED)
@@ -21,5 +23,11 @@ FetchContent_MakeAvailable(pinpoint)
 
 add_executable(test_pinpoint_cpp test_pinpoint.cpp)
 add_executable(test_pinpoint_c test_pinpoint.c)
+
+if(LINUX_)
 target_link_libraries(test_pinpoint_cpp PRIVATE  pinpoint_common_static rt)
-target_link_libraries(test_pinpoint_c pinpoint_common_static rt)
\ No newline at end of file
+target_link_libraries(test_pinpoint_c pinpoint_common_static rt)
+else()
+target_link_libraries(test_pinpoint_cpp PRIVATE  pinpoint_common_static )
+target_link_libraries(test_pinpoint_c  PRIVATE pinpoint_common_static )
+endif()
\ No newline at end of file
diff --git a/src/PHP/CHANGES.md b/src/PHP/CHANGES.md
new file mode 100644
index 000000000..43cae79cd
--- /dev/null
+++ b/src/PHP/CHANGES.md
@@ -0,0 +1,2 @@
+## 0.5.0
+- support common library v0.5.0
\ No newline at end of file
diff --git a/src/PHP/php_pinpoint_php.h b/src/PHP/php_pinpoint_php.h
index a22459a83..5182b5440 100644
--- a/src/PHP/php_pinpoint_php.h
+++ b/src/PHP/php_pinpoint_php.h
@@ -22,7 +22,7 @@
 extern zend_module_entry pinpoint_php_module_entry;
 #define phpext_pinpoint_php_ptr &pinpoint_php_module_entry
 
-#define PHP_PINPOINT_PHP_VERSION "0.2.1"
+#define PHP_PINPOINT_PHP_VERSION "0.5.0"
 
 #ifdef PHP_WIN32
 #define PHP_PINPOINT_PHP_API __declspec(dllexport)
@@ -38,7 +38,7 @@ extern zend_module_entry pinpoint_php_module_entry;
 
 ZEND_BEGIN_MODULE_GLOBALS(pinpoint_php)
 
-char* co_host; // tcp:ip:port should support dns
+char *co_host; // tcp:ip:port should support dns
 zend_bool utest_flag;
 //    zend_bool   limit;
 zend_bool debug_report;
@@ -54,7 +54,7 @@ ZEND_END_MODULE_GLOBALS(pinpoint_php)
 extern ZEND_DECLARE_MODULE_GLOBALS(pinpoint_php);
 
 #ifdef ZTS
-#define PPG(v) TSRMG(pinpoint_php_globals_id, zend_pinpoint_php_globals*, v)
+#define PPG(v) TSRMG(pinpoint_php_globals_id, zend_pinpoint_php_globals *, v)
 #else
 #define PPG(v) (pinpoint_php_globals.v)
 #endif
diff --git a/src/PHP/pinpoint_php.cpp b/src/PHP/pinpoint_php.cpp
index 98524a60d..a6c6434d8 100644
--- a/src/PHP/pinpoint_php.cpp
+++ b/src/PHP/pinpoint_php.cpp
@@ -69,30 +69,32 @@ PHP_FUNCTION(pinpoint_set_context);
 PHP_FUNCTION(pinpoint_get_context);
 PHP_FUNCTION(pinpoint_mark_as_error);
 PHP_FUNCTION(pinpoint_get_func_ref_args);
-
+PHP_FUNCTION(pinpoint_status);
 ZEND_DECLARE_MODULE_GLOBALS(pinpoint_php)
 
-static void pinpoint_log(char* msg);
+static void pinpoint_log(char *msg);
 
 /* {{{ PHP_INI
  */
 
 PHP_INI_BEGIN()
 
-STD_PHP_INI_ENTRY("pinpoint_php.SendSpanTimeOutMs", "0", PHP_INI_ALL, OnUpdateLong, w_timeout_ms,
-                  zend_pinpoint_php_globals, pinpoint_php_globals)
-
-STD_PHP_INI_ENTRY("pinpoint_php.CollectorHost", "unix:/tmp/collector.sock", PHP_INI_ALL,
-                  OnUpdateString, co_host, zend_pinpoint_php_globals, pinpoint_php_globals)
+STD_PHP_INI_ENTRY("pinpoint_php.SendSpanTimeOutMs", "0", PHP_INI_ALL,
+                  OnUpdateLong, w_timeout_ms, zend_pinpoint_php_globals,
+                  pinpoint_php_globals)
 
-STD_PHP_INI_ENTRY("pinpoint_php.UnitTest", "no", PHP_INI_ALL, OnUpdateBool, utest_flag,
+STD_PHP_INI_ENTRY("pinpoint_php.CollectorHost", "unix:/tmp/collector.sock",
+                  PHP_INI_ALL, OnUpdateString, co_host,
                   zend_pinpoint_php_globals, pinpoint_php_globals)
 
-STD_PHP_INI_ENTRY("pinpoint_php.TraceLimit", "-1", PHP_INI_ALL, OnUpdateLong, tracelimit,
-                  zend_pinpoint_php_globals, pinpoint_php_globals)
+STD_PHP_INI_ENTRY("pinpoint_php.UnitTest", "no", PHP_INI_ALL, OnUpdateBool,
+                  utest_flag, zend_pinpoint_php_globals, pinpoint_php_globals)
 
-STD_PHP_INI_ENTRY("pinpoint_php.DebugReport", "no", PHP_INI_ALL, OnUpdateBool, debug_report,
-                  zend_pinpoint_php_globals, pinpoint_php_globals)
+STD_PHP_INI_ENTRY("pinpoint_php.TraceLimit", "-1", PHP_INI_ALL, OnUpdateLong,
+                  tracelimit, zend_pinpoint_php_globals, pinpoint_php_globals)
+
+STD_PHP_INI_ENTRY("pinpoint_php.DebugReport", "no", PHP_INI_ALL, OnUpdateBool,
+                  debug_report, zend_pinpoint_php_globals, pinpoint_php_globals)
 
 PHP_INI_END()
 
@@ -134,25 +136,29 @@ ZEND_END_ARG_INFO()
 ZEND_BEGIN_ARG_INFO_EX(arginfo_none, 0, 0, 0)
 ZEND_END_ARG_INFO()
 
+// clang-format off
 /* {{{ pinpioint_php_functions[]
  *
  * Every user visible function must have an entry in pinpioint_php_functions[].
  */
 const zend_function_entry pinpoint_php_functions[] = {
-    PHP_FE(pinpoint_start_trace, arginfo_add_id) PHP_FE(pinpoint_end_trace, arginfo_add_id)
-        PHP_FE(pinpoint_unique_id, arginfo_none) PHP_FE(pinpoint_get_func_ref_args, arginfo_none)
-            PHP_FE(pinpoint_drop_trace, arginfo_add_id) PHP_FE(pinpoint_start_time, arginfo_none)
-                PHP_FE(pinpoint_set_context, arginfo_add_id_key_value)
-                    PHP_FE(pinpoint_get_context, arginfo_add_id_value)
-                        PHP_FE(pinpoint_tracelimit, arginfo_add_timestamp)
-                            PHP_FE(pinpoint_mark_as_error, arginfo_add_msg_filename_lineno_id)
-                                PHP_FE(pinpoint_add_clue, arginfo_add_id_key_value_flag)
-                                    PHP_FE(pinpoint_add_clues, arginfo_add_id_key_value_flag)
-                                        PHP_FE_END /* Must be the last line in
-                                                                      pinpioint_php_functions[] */
+  PHP_FE(pinpoint_start_trace, arginfo_add_id) 
+  PHP_FE(pinpoint_end_trace, arginfo_add_id)
+  PHP_FE(pinpoint_unique_id, arginfo_none) 
+  PHP_FE(pinpoint_status, arginfo_none) 
+  PHP_FE(pinpoint_get_func_ref_args, arginfo_none)
+  PHP_FE(pinpoint_drop_trace, arginfo_add_id) 
+  PHP_FE(pinpoint_start_time, arginfo_none)
+  PHP_FE(pinpoint_set_context, arginfo_add_id_key_value)
+  PHP_FE(pinpoint_get_context, arginfo_add_id_value)
+  PHP_FE(pinpoint_tracelimit, arginfo_add_timestamp)
+  PHP_FE(pinpoint_mark_as_error, arginfo_add_msg_filename_lineno_id)
+  PHP_FE(pinpoint_add_clue, arginfo_add_id_key_value_flag)
+  PHP_FE(pinpoint_add_clues, arginfo_add_id_key_value_flag)
+  PHP_FE_END /* Must be the last line in pinpioint_php_functions[] */
 };
 /* }}} */
-
+// clang-format on
 /* {{{ pinpioint_php_module_entry
  */
 zend_module_entry pinpoint_php_module_entry = {
@@ -163,8 +169,10 @@ zend_module_entry pinpoint_php_module_entry = {
     pinpoint_php_functions,
     PHP_MINIT(pinpoint_php),
     PHP_MSHUTDOWN(pinpoint_php),
-    PHP_RINIT(pinpoint_php),     /* Replace with NULL if there's nothing to do at request start */
-    PHP_RSHUTDOWN(pinpoint_php), /* Replace with NULL if there's nothing to do at request end */
+    PHP_RINIT(pinpoint_php), /* Replace with NULL if there's nothing to do at
+                                request start */
+    PHP_RSHUTDOWN(pinpoint_php), /* Replace with NULL if there's nothing to do
+                                    at request end */
     PHP_MINFO(pinpoint_php),
 #if ZEND_MODULE_API_NO >= 20010901
     PHP_PINPOINT_PHP_VERSION,
@@ -172,20 +180,20 @@ zend_module_entry pinpoint_php_module_entry = {
     STANDARD_MODULE_PROPERTIES};
 /* }}} */
 #if PHP_VERSION_ID >= 80100
-void (*old_error_cb)(int type, zend_string* error_filename, const uint32_t error_lineno,
-                     zend_string* message);
+void (*old_error_cb)(int type, zend_string *error_filename,
+                     const uint32_t error_lineno, zend_string *message);
 #elif PHP_VERSION_ID >= 80000
-void (*old_error_cb)(int type, const char* error_filename, const uint32_t error_lineno,
-                     zend_string* message);
+void (*old_error_cb)(int type, const char *error_filename,
+                     const uint32_t error_lineno, zend_string *message);
 #else
-void (*old_error_cb)(int type, const char* error_filename, const uint error_lineno,
-                     const char* format, va_list args);
+void (*old_error_cb)(int type, const char *error_filename,
+                     const uint error_lineno, const char *format, va_list args);
 #endif
 
-#define safe_free(x)                                                                               \
-  if ((x)) {                                                                                       \
-    free((x));                                                                                     \
-    (x) = NULL;                                                                                    \
+#define safe_free(x)                                                           \
+  if ((x)) {                                                                   \
+    free((x));                                                                 \
+    (x) = NULL;                                                                \
   }
 
 PHP_FUNCTION(pinpoint_drop_trace) {
@@ -202,28 +210,29 @@ PHP_FUNCTION(pinpoint_drop_trace) {
   } else {
     id = (NodeID)_id;
   }
-  mark_current_trace_status(id, E_TRACE_BLOCK);
+  change_trace_status(id, E_TRACE_BLOCK);
   RETURN_TRUE;
 }
 
 PHP_FUNCTION(pinpoint_set_context) {
   long _id = -1;
   std::string key;
-  zval* zvalue;
+  zval *zvalue;
 #if PHP_VERSION_ID < 70000
-  char* zkey = NULL;
+  char *zkey = NULL;
   int zkey_len;
 
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &zkey, &zkey_len, &zvalue, &_id) ==
-      FAILURE) {
+  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &zkey, &zkey_len,
+                            &zvalue, &_id) == FAILURE) {
     zend_error(E_ERROR, "key/value required");
     return;
   }
   key = std::string(zkey, zkey_len);
 
 #else
-  zend_string* zkey;
-  if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|l", &zkey, &zvalue, &_id) == FAILURE) {
+  zend_string *zkey;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|l", &zkey, &zvalue, &_id) ==
+      FAILURE) {
     zend_error(E_ERROR, "key/value required");
     return;
   }
@@ -232,7 +241,6 @@ PHP_FUNCTION(pinpoint_set_context) {
 
   if (_id == -1) {
     _id = pinpoint_get_per_thread_id();
-    ;
   }
 
   switch (Z_TYPE_P(zvalue)) {
@@ -254,17 +262,18 @@ PHP_FUNCTION(pinpoint_get_context) {
   long _id = -1;
   std::string key;
 #if PHP_VERSION_ID < 70000
-  char* zkey = NULL;
+  char *zkey = NULL;
   int zkey_len;
 
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &zkey, &zkey_len, &_id) == FAILURE) {
+  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &zkey, &zkey_len,
+                            &_id) == FAILURE) {
     zend_error(E_ERROR, "key/value required");
     return;
   }
   key = std::string(zkey, zkey_len);
 
 #else
-  zend_string* zkey;
+  zend_string *zkey;
   if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &zkey, &_id) == FAILURE) {
     zend_error(E_ERROR, "key/value required");
     return;
@@ -311,21 +320,21 @@ PHP_FUNCTION(pinpoint_start_trace) {
 }
 
 #if PHP_VERSION_ID >= 80100
-void apm_error_cb(int type, zend_string* _error_filename, const uint32_t error_lineno,
-                  zend_string* _message) {
-  char* error_filename = _error_filename->val;
-  char* msg = _message->val;
+void apm_error_cb(int type, zend_string *_error_filename,
+                  const uint32_t error_lineno, zend_string *_message) {
+  char *error_filename = _error_filename->val;
+  char *msg = _message->val;
 
 #elif PHP_VERSION_ID >= 80000
-void apm_error_cb(int type, const char* _error_filename, const uint32_t error_lineno,
-                  zend_string* _message) {
-  char* msg = _message->val;
-  const char* error_filename = _error_filename;
+void apm_error_cb(int type, const char *_error_filename,
+                  const uint32_t error_lineno, zend_string *_message) {
+  char *msg = _message->val;
+  const char *error_filename = _error_filename;
 #else
 
-void apm_error_cb(int type, const char* error_filename, const uint error_lineno, const char* format,
-                  va_list args) {
-  char* msg;
+void apm_error_cb(int type, const char *error_filename, const uint error_lineno,
+                  const char *format, va_list args) {
+  char *msg;
   va_list args_copy;
 #if PHP_VERSION_ID < 80000
   TSRMLS_FETCH();
@@ -380,6 +389,8 @@ PHP_FUNCTION(pinpoint_end_trace) {
   }
 }
 
+PHP_FUNCTION(pinpoint_status) { show_status(); }
+
 PHP_FUNCTION(pinpoint_add_clue) {
   std::string key;
   std::string value;
@@ -389,8 +400,9 @@ PHP_FUNCTION(pinpoint_add_clue) {
   char *zkey = NULL, *zvalue = NULL;
   int zkey_len, value_len;
 
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ll", &zkey, &zkey_len, &zvalue,
-                            &value_len, &_id, &_flag) == FAILURE) {
+  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ll", &zkey,
+                            &zkey_len, &zvalue, &value_len, &_id,
+                            &_flag) == FAILURE) {
     zend_error(E_ERROR, "pinpoint_add_clue() expects (int, string).");
     return;
   }
@@ -398,9 +410,10 @@ PHP_FUNCTION(pinpoint_add_clue) {
   value = std::string(zvalue, value_len);
 
 #else
-  zend_string* zkey;
-  zend_string* zvalue;
-  if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|ll", &zkey, &zvalue, &_id, &_flag) == FAILURE) {
+  zend_string *zkey;
+  zend_string *zvalue;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|ll", &zkey, &zvalue, &_id,
+                            &_flag) == FAILURE) {
     zend_error(E_ERROR, "pinpoint_add_clue() expects (int, string).");
     return;
   }
@@ -422,18 +435,22 @@ PHP_FUNCTION(pinpoint_mark_as_error) {
   char *zkey = NULL, *zvalue = NULL;
   int zkey_len, value_len;
 
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ll", &zkey, &zkey_len, &zvalue,
-                            &value_len, &_lineno, &_id) == FAILURE) {
-    zend_error(E_ERROR, "pinpoint_mark_as_error() expects (string,string,int,int).");
+  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ll", &zkey,
+                            &zkey_len, &zvalue, &value_len, &_lineno,
+                            &_id) == FAILURE) {
+    zend_error(E_ERROR,
+               "pinpoint_mark_as_error() expects (string,string,int,int).");
     return;
   }
   msg = std::string(zkey, zkey_len);
   fileName = std::string(zvalue, value_len);
 #else
-  zend_string* zkey;
-  zend_string* zvalue;
-  if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|ll", &zkey, &zvalue, &_lineno, &_id) == FAILURE) {
-    zend_error(E_ERROR, "pinpoint_mark_as_error() expects (string,string,int,int).");
+  zend_string *zkey;
+  zend_string *zvalue;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|ll", &zkey, &zvalue, &_lineno,
+                            &_id) == FAILURE) {
+    zend_error(E_ERROR,
+               "pinpoint_mark_as_error() expects (string,string,int,int).");
     return;
   }
   msg = std::string(zkey->val, zkey->len);
@@ -452,17 +469,19 @@ PHP_FUNCTION(pinpoint_add_clues) {
   char *zkey = NULL, *zvalue = NULL;
   int zkey_len, value_len;
 
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ll", &zkey, &zkey_len, &zvalue,
-                            &value_len, &_id, &_flag) == FAILURE) {
+  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ll", &zkey,
+                            &zkey_len, &zvalue, &value_len, &_id,
+                            &_flag) == FAILURE) {
     zend_error(E_ERROR, "pinpoint_add_clues() expects (int, string).");
     return;
   }
   key = std::string(zkey, zkey_len);
   value = std::string(zvalue, value_len);
 #else
-  zend_string* zkey;
-  zend_string* zvalue;
-  if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|ll", &zkey, &zvalue, &_id, &_flag) == FAILURE) {
+  zend_string *zkey;
+  zend_string *zvalue;
+  if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|ll", &zkey, &zvalue, &_id,
+                            &_flag) == FAILURE) {
     zend_error(E_ERROR, "pinpoint_add_clues() expects (int, string).");
     return;
   }
@@ -480,10 +499,10 @@ PHP_FUNCTION(pinpoint_add_clues) {
  */
 PHP_FUNCTION(pinpoint_get_func_ref_args) {
 #if PHP_VERSION_ID < 70000
-  void** p;
+  void **p;
   int arg_count;
   int i;
-  zend_execute_data* ex = EG(current_execute_data)->prev_execute_data;
+  zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
 
   if (!ex || !ex->function_state.arguments) {
     zend_error(E_WARNING, "pinpoint_get_func_ref_args():  Called from the "
@@ -499,18 +518,19 @@ PHP_FUNCTION(pinpoint_get_func_ref_args) {
   for (i = 0; i < arg_count; i++) {
     zval *element, *arg;
 
-    arg = *((zval**)(p - (arg_count - i)));
+    arg = *((zval **)(p - (arg_count - i)));
     element = arg;
     Z_ADDREF_P(element);
 
-    zend_hash_next_index_insert(return_value->value.ht, &element, sizeof(zval*), NULL);
+    zend_hash_next_index_insert(return_value->value.ht, &element,
+                                sizeof(zval *), NULL);
   }
 #else
 
   zval *p, *q;
   uint32_t arg_count, first_extra_arg;
   uint32_t i, n;
-  zend_execute_data* ex = EX(prev_execute_data);
+  zend_execute_data *ex = EX(prev_execute_data);
 
   if (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE) {
     zend_error(E_WARNING, "pinpoint_get_func_ref_args():  Called from the "
@@ -546,7 +566,8 @@ PHP_FUNCTION(pinpoint_get_func_ref_args) {
           p++;
           i++;
         }
-        p = ZEND_CALL_VAR_NUM(ex, ex->func->op_array.last_var + ex->func->op_array.T);
+        p = ZEND_CALL_VAR_NUM(ex, ex->func->op_array.last_var +
+                                      ex->func->op_array.T);
       }
       while (i < arg_count) {
         q = p;
@@ -580,7 +601,7 @@ PHP_FUNCTION(pinpoint_tracelimit) {
 
   timestamp = (timestamp == -1) ? (time(NULL)) : (timestamp);
 
-  if (check_tracelimit(timestamp) == 1) {
+  if (check_trace_limit(timestamp) == 1) {
     RETURN_TRUE;
   } else {
     RETURN_FALSE;
@@ -591,7 +612,8 @@ PHP_FUNCTION(pinpoint_tracelimit) {
  */
 /* Uncomment this function if you have INI entries
  */
-static void php_pinpoint_php_init_globals(zend_pinpoint_php_globals* pinpoint_php_globals) {
+static void
+php_pinpoint_php_init_globals(zend_pinpoint_php_globals *pinpoint_php_globals) {
   memset(pinpoint_php_globals, 0, sizeof(zend_pinpoint_php_globals));
 }
 
@@ -606,17 +628,12 @@ PHP_MINIT_FUNCTION(pinpoint_php) {
 
   old_error_cb = zend_error_cb;
   zend_error_cb = apm_error_cb;
-  // global_agent_info.
-  strncpy(global_agent_info.co_host, PPG(co_host), MAX_ADDRESS_SIZE);
-  global_agent_info.inter_flag = PPG(debug_report);
-  global_agent_info.timeout_ms = PPG(w_timeout_ms);
-  global_agent_info.trace_limit = PPG(tracelimit);
-  global_agent_info.agent_type = 1500; // PHP
 
+  pinpoint_set_agent(PPG(co_host), PPG(w_timeout_ms), PPG(tracelimit), 1500);
   if (PPG(utest_flag) == 1) {
-    global_agent_info.inter_flag |= E_UTEST;
+    register_logging_cb(pinpoint_log, 1);
   } else {
-    register_error_cb(pinpoint_log);
+    register_logging_cb(pinpoint_log, 0);
   }
 
   return SUCCESS;
@@ -651,12 +668,10 @@ PHP_RINIT_FUNCTION(pinpoint_php) {
 /* {{{ PHP_RSHUTDOWN_FUNCTION
  */
 PHP_RSHUTDOWN_FUNCTION(pinpoint_php) {
-  NodeID _id = pinpoint_get_per_thread_id();
-  if (_id != 0) {
-    pinpoint_force_end_trace(_id, 300);
-    pinpoint_update_per_thread_id(E_ROOT_NODE);
+  NodeID _parent_id = pinpoint_get_per_thread_id();
+  while (_parent_id != E_INVALID_NODE && _parent_id != E_ROOT_NODE) {
+    _parent_id = pinpoint_end_trace(_parent_id);
   }
-
   return SUCCESS;
 }
 /* }}} */
@@ -674,7 +689,7 @@ PHP_MINFO_FUNCTION(pinpoint_php) {
 }
 /* }}} */
 
-void pinpoint_log(char* msg) {
+void pinpoint_log(char *msg) {
 #if PHP_VERSION_ID >= 70100
   php_log_err_with_severity(msg, LOG_DEBUG);
 #else
diff --git a/src/PY/_pinpoint_py.cpp b/src/PY/_pinpoint_py.cpp
index a19142f2c..790a7c4a7 100644
--- a/src/PY/_pinpoint_py.cpp
+++ b/src/PY/_pinpoint_py.cpp
@@ -13,47 +13,20 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  ******************************************************************************/
+#include "_pinpoint_py.h"
 #include <Python.h>
 #include <string.h>
-#include "_pinpoint_py.h"
 
-static PyObject* py_obj_msg_callback;
+static PyObject *py_obj_msg_callback;
 // global g_collector_host is suck
 // static char* g_collector_host;
 
-#if defined(__linux__) || defined(_UNIX) || defined(__APPLE__)
-#include <sys/types.h>
-#include <unistd.h>
-#include <pthread.h>
-static void _init_common_shared(void) __attribute__((constructor));
-static void _free_common_shared(void) __attribute__((destructor));
-static pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
-
-static void _get_read_lock(void) { pthread_rwlock_rdlock(&rwlock); }
-
-static void _release_lock(void) { pthread_rwlock_unlock(&rwlock); }
-
-static void _get_write_lock(void) { pthread_rwlock_wrlock(&rwlock); }
-
-void _init_common_shared(void) {
-  pthread_rwlock_init(&rwlock, NULL);
-  global_agent_info.get_read_lock = _get_read_lock;
-  global_agent_info.get_write_lock = _get_write_lock;
-  global_agent_info.release_lock = _release_lock;
-}
-
-void _free_common_shared(void) { pthread_rwlock_destroy(&rwlock); }
-#else
-
-#error "your platform not support"
-
-#endif
-
 #define MODNAME "_pinpointPy"
 
 #ifndef CYTHON_UNUSED
 #if defined(__GNUC__)
-#if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+#if !(defined(__cplusplus)) ||                                                 \
+    (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
 #define CYTHON_UNUSED __attribute__((__unused__))
 #else
 #define CYTHON_UNUSED
@@ -68,15 +41,16 @@ void _free_common_shared(void) { pthread_rwlock_destroy(&rwlock); }
 /**
  * void pinpoint_add_clues(const  char* key,const  char* value);
  * */
-static PyObject* py_pinpoint_add_clues(PyObject* self, PyObject* args) {
-  char* key = NULL;
-  char* value = NULL;
+static PyObject *py_pinpoint_add_clues(PyObject *self, PyObject *args) {
+  char *key = NULL;
+  char *value = NULL;
   NodeID id = E_INVALID_NODE;
   int loc = 0;
   if (PyArg_ParseTuple(args, "ss|ii", &key, &value, &id, &loc)) {
     // python is special, use thread-id
-    if (id == -1)
+    if (id == -1) {
       id = pinpoint_get_per_thread_id();
+    }
 
     pinpoint_add_clues(id, key, value, loc);
   }
@@ -86,14 +60,15 @@ static PyObject* py_pinpoint_add_clues(PyObject* self, PyObject* args) {
 /**
  * void pinpoint_add_clue(const  char* key,const  char* value);
  */
-static PyObject* py_pinpoint_add_clue(PyObject* self, PyObject* args) {
-  char* key = NULL;
-  char* value = NULL;
+static PyObject *py_pinpoint_add_clue(PyObject *self, PyObject *args) {
+  char *key = NULL;
+  char *value = NULL;
   int id = -1;
   int loc = 0;
   if (PyArg_ParseTuple(args, "ss|ii", &key, &value, &id, &loc)) {
-    if (id == -1)
+    if (id == -1) {
       id = pinpoint_get_per_thread_id();
+    }
 
     pinpoint_add_clue(id, key, value, loc);
   }
@@ -103,9 +78,9 @@ static PyObject* py_pinpoint_add_clue(PyObject* self, PyObject* args) {
 /**
  * void pinpoint_set_special_key(const  char* key,const  char* value);
  */
-static PyObject* py_pinpoint_context_key(PyObject* self, PyObject* args) {
-  char* key = NULL;
-  char* value = NULL;
+static PyObject *py_pinpoint_context_key(PyObject *self, PyObject *args) {
+  char *key = NULL;
+  char *value = NULL;
   int id = -1;
   if (PyArg_ParseTuple(args, "ss|i", &key, &value, &id)) {
     if (id == -1)
@@ -119,8 +94,8 @@ static PyObject* py_pinpoint_context_key(PyObject* self, PyObject* args) {
 /**
  * const  char* pinpoint_get_special_key(const  char* key);
  */
-static PyObject* py_pinpoint_get_key(PyObject* self, PyObject* args) {
-  char* key = NULL;
+static PyObject *py_pinpoint_get_key(PyObject *self, PyObject *args) {
+  char *key = NULL;
   int id = -1;
   if (PyArg_ParseTuple(args, "s|i", &key, &id)) {
     if (id == -1)
@@ -139,13 +114,13 @@ static PyObject* py_pinpoint_get_key(PyObject* self, PyObject* args) {
 /**
  * bool check_tracelimit(int64_t timestamp);
  */
-static PyObject* py_check_tracelimit(PyObject* self, PyObject* args) {
+static PyObject *py_check_trace_limit(PyObject *self, PyObject *args) {
   int64_t timestamp = -1;
   bool ret;
   if (!PyArg_ParseTuple(args, "|l", &timestamp)) {
     return NULL;
   }
-  ret = check_tracelimit(timestamp);
+  ret = check_trace_limit(timestamp);
   if (ret == true) {
     return Py_BuildValue("O", Py_True);
   } else {
@@ -153,225 +128,165 @@ static PyObject* py_check_tracelimit(PyObject* self, PyObject* args) {
   }
 }
 
-static PyObject* py_force_flush_span(PyObject* self, PyObject* args) {
+static PyObject *py_force_flush_span(PyObject *self, PyObject *args) {
   int32_t timeout = 3;
   int id = -1;
   if (!PyArg_ParseTuple(args, "|ii", &timeout, &id)) {
     return NULL;
   }
 
-  if (id == -1)
+  if (id == E_INVALID_NODE) {
     id = pinpoint_get_per_thread_id();
-
-  if (global_agent_info.inter_flag & E_DISABLE_GIL) {
-    pinpoint_force_end_trace(id, timeout);
-  } else {
-    Py_BEGIN_ALLOW_THREADS pinpoint_force_end_trace(id, timeout);
-    Py_END_ALLOW_THREADS
   }
 
+  pinpoint_force_end_trace(id, timeout);
+
   return Py_BuildValue("O", Py_True);
 }
 
-static inline uint32_t startTraceWithPerThreadId(void) {
-  uint32_t id = pinpoint_start_trace(pinpoint_get_per_thread_id());
+static inline int start_thread_local_trace(void) {
+  int id = pinpoint_start_trace(pinpoint_get_per_thread_id());
   pinpoint_update_per_thread_id(id);
   return id;
 }
 
-static PyObject* py_pinpoint_start_trace(PyObject* self, PyObject* args) {
-  int ret = 0;
+static PyObject *py_pinpoint_start_trace(PyObject *self, PyObject *args) {
   int32_t id = -1;
 
   if (!PyArg_ParseTuple(args, "|i", &id)) {
     return NULL;
   }
-
-  if (global_agent_info.inter_flag & E_DISABLE_GIL) {
-    if (id == -1) {
-      ret = startTraceWithPerThreadId();
-    } else {
-      ret = pinpoint_start_trace(id);
-    }
+  int new_id = -1;
+  if (id == -1) {
+    new_id = start_thread_local_trace();
   } else {
-    Py_BEGIN_ALLOW_THREADS if (id == -1) { ret = startTraceWithPerThreadId(); }
-    else {
-      ret = pinpoint_start_trace(id);
-    }
-    Py_END_ALLOW_THREADS
+    new_id = pinpoint_start_trace(id);
   }
 
-  return Py_BuildValue("i", ret);
+  return Py_BuildValue("i", new_id);
 }
 
-static inline int endTraceWithPerThreadId(void) {
-  NodeID cid = pinpoint_get_per_thread_id();
-  NodeID id = pinpoint_end_trace(cid);
-  pinpoint_update_per_thread_id(id);
-  return id;
+static inline int end_thread_local_trace(void) {
+  NodeID local_id = pinpoint_get_per_thread_id();
+  NodeID parent_id = pinpoint_end_trace(local_id);
+  pinpoint_update_per_thread_id(parent_id);
+  return parent_id;
 }
 
-static PyObject* py_pinpoint_end_trace(PyObject* self, PyObject* args) {
+static PyObject *py_pinpoint_end_trace(PyObject *self, PyObject *args) {
   NodeID ret = 0;
   int32_t id = -1;
   if (!PyArg_ParseTuple(args, "|i", &id)) {
     return NULL;
   }
 
-  if (global_agent_info.inter_flag & E_DISABLE_GIL) {
-    if (id == -1) {
-      ret = endTraceWithPerThreadId();
-    } else {
-      ret = pinpoint_end_trace(id);
-    }
+  if (id == -1) {
+    ret = end_thread_local_trace();
   } else {
-    Py_BEGIN_ALLOW_THREADS
-
-        if (id == -1) {
-      ret = endTraceWithPerThreadId();
-    }
-    else {
-      ret = pinpoint_end_trace(id);
-    }
-
-    Py_END_ALLOW_THREADS
+    ret = pinpoint_end_trace(id);
   }
 
   return Py_BuildValue("i", ret);
 }
 
-static PyObject* py_generate_unique_id(PyObject* self, CYTHON_UNUSED PyObject* unused) {
+static PyObject *py_generate_unique_id(PyObject *self,
+                                       CYTHON_UNUSED PyObject *unused) {
   uint64_t ret = generate_unique_id();
   return Py_BuildValue("l", ret);
 }
 
-static PyObject* py_trace_has_root(PyObject* self, PyObject* args) {
+static PyObject *py_trace_has_root(PyObject *self, PyObject *args) {
   int id = -1;
   if (!PyArg_ParseTuple(args, "|i", &id)) {
     return NULL;
   }
-  if (id == -1) {
+  if (id == E_INVALID_NODE) {
     id = pinpoint_get_per_thread_id();
   }
-
-  if (id == 0) {
-    return Py_BuildValue("O", Py_False);
-  } else {
-    // check the input id
-    int ret = pinpoint_trace_is_root(id);
-    if (ret == -1) {
-      PyErr_SetString(PyExc_Exception, "input traceId is not exist");
-      return Py_BuildValue("O", Py_False);
-      ;
-    }
+  int ret = pinpoint_trace_is_root(id);
+  if (ret != -1) {
     return Py_BuildValue("O", Py_True);
+  } else {
+    return Py_BuildValue("O", Py_False);
   }
 }
 
-static PyObject* py_pinpoint_drop_trace(PyObject* self, PyObject* args) {
+static PyObject *py_pinpoint_drop_trace(PyObject *self, PyObject *args) {
   int id = -1;
 
   if (!PyArg_ParseTuple(args, "|i", &id)) {
     return NULL;
   }
 
-  if (id == -1)
+  if (id == -1) {
     id = pinpoint_get_per_thread_id();
+  }
 
   mark_current_trace_status(id, E_TRACE_BLOCK);
 
   return Py_BuildValue("O", Py_True);
 }
 
-static PyObject* py_pinpoint_start_time(PyObject* self, CYTHON_UNUSED PyObject* unused) {
+static PyObject *py_pinpoint_start_time(PyObject *self,
+                                        CYTHON_UNUSED PyObject *unused) {
   uint64_t start_time = pinpoint_start_time();
-  return Py_BuildValue("l", start_time);
+  return Py_BuildValue("K", start_time);
 }
 
-// origin from https://docs.python.org/3/extending/extending.html#calling-python-functions-from-c
+// origin from
+// https://docs.python.org/3/extending/extending.html#calling-python-functions-from-c
 
-static void msg_log_error_cb(char* msg) {
+static void msg_log_error_cb(char *msg) {
   if (py_obj_msg_callback && msg) {
-    PyObject* arglist;
-    PyObject* result;
+    PyObject *arglist;
+    PyObject *result;
     arglist = Py_BuildValue("(s)", msg);
     result = PyObject_CallObject(py_obj_msg_callback, arglist);
     if (result == NULL) {
-      fprintf(stderr, "%s", msg);
-      PyErr_SetString(PyExc_TypeError, msg);
-      return;
+      fprintf(stderr, "callback with error:%s", msg);
+    } else {
+      Py_XDECREF(result); // I don't care return
     }
-    Py_XDECREF(result); // I don't care return
     Py_DECREF(arglist);
   }
 }
 
-static PyObject* py_pinpoint_enable_utest(PyObject* self, PyObject* args) {
-  global_agent_info.inter_flag |= E_LOGGING;
-  global_agent_info.inter_flag |= E_DISABLE_GIL;
-
-  PyObject* temp;
-  if (PyArg_ParseTuple(args, "O:callback", &temp)) {
-    if (PyCallable_Check(temp)) {
-      Py_XINCREF(temp);
-      Py_XDECREF(py_obj_msg_callback);
-      py_obj_msg_callback = temp;
-      register_error_cb(msg_log_error_cb);
-    }
-  }
-  // disable logging callback
-  global_agent_info.inter_flag |= E_UTEST;
-
+static PyObject *py_pinpoint_enable_debug(PyObject *, PyObject *) {
+  // remove callback
+  // as https://oss.navercorp.com/pinpoint/pinpoint_c_agent/issues/569
+  register_logging_cb(nullptr, 1);
   return Py_BuildValue("O", Py_True);
 }
 
-bool set_collector_host(const char* host) {
-  if (strcasestr(host, "unix") || strcasestr(host, "tcp")) {
-    strncpy(global_agent_info.co_host, host, MAX_ADDRESS_SIZE);
-    return true;
-  }
-  PyErr_SetString(PyExc_TypeError, "collector_host must start with unix/tcp");
-  return false;
-}
-
 /**
  * def set_agent(collector_host=, trace_limit=,enable_coroutines=)
  */
-static PyObject* py_set_agent(PyObject* self, PyObject* args, PyObject* keywds) {
+static PyObject *py_set_agent(PyObject *self, PyObject *args,
+                              PyObject *keywds) {
   // PyObject* setting;
   bool ret = false;
   char default_host[] = "collector_host";
   char default_tracelimit[] = "trace_limit";
-  char* kwlist[] = {default_host, default_tracelimit, NULL};
-  char* collector_host = nullptr; //   = "unix:/tmp/collector-agent.sock";
+  char default_timeout[] = "time_out_ms";
+  char *kwlist[] = {default_host, default_tracelimit, default_timeout, NULL};
+  char *collector_host = nullptr; //   = "unix:/tmp/collector-agent.sock";
   long trace_limit = -1;
-  if (PyArg_ParseTupleAndKeywords(args, keywds, "s|l", kwlist, &collector_host, &trace_limit)) {
-    global_agent_info.get_write_lock();
-    ret = set_collector_host(collector_host);
-    if (!ret) {
-      goto END_OF_PARSE;
-    }
-
-    global_agent_info.trace_limit = trace_limit;
+  long timeout_ms = 0;
+  if (PyArg_ParseTupleAndKeywords(args, keywds, "s|ll", kwlist, &collector_host,
+                                  &trace_limit, &timeout_ms)) {
 
     pp_trace("collector_host:%s", collector_host);
     pp_trace("trace_limit:%ld", trace_limit);
-
-  END_OF_PARSE:
-    global_agent_info.release_lock();
-
-    if (ret == true) {
-      return Py_BuildValue("O", Py_True);
-    }
-    return NULL;
+    pinpoint_set_agent(collector_host, timeout_ms, trace_limit, 1700);
+    return Py_BuildValue("O", Py_True);
   } else {
     return NULL;
   }
 }
 
-static PyObject* py_pinpoint_mark_an_error(PyObject* self, PyObject* args) {
-  char* msg = NULL;
-  char* file_name = NULL;
+static PyObject *py_pinpoint_mark_an_error(PyObject *self, PyObject *args) {
+  char *msg = NULL;
+  char *file_name = NULL;
   uint32_t line_no = 0;
   NodeID id = -1;
   if (PyArg_ParseTuple(args, "ssi|i", &msg, &file_name, &line_no, &id)) {
@@ -387,42 +302,48 @@ static PyObject* py_pinpoint_mark_an_error(PyObject* self, PyObject* args) {
 /* Module method table */
 static PyMethodDef PinpointMethods[] = {
     {"start_trace", py_pinpoint_start_trace, METH_VARARGS,
-     "def start_trace(int id=-1):# create a new trace and insert into trace chain"},
+     "def start_trace(int id=-1):# create a new trace and insert into trace "
+     "chain"},
     {"end_trace", py_pinpoint_end_trace, METH_VARARGS,
      "def end_trace(int id=-1):# end currently matched trace"},
     {"unique_id", py_generate_unique_id, METH_NOARGS, "def unique_id()-> long"},
     {"trace_has_root", py_trace_has_root, METH_VARARGS,
-     "def trace_has_root(int id=-1)-> long # check current whether have a root. \n True: \nFalse: "
+     "def trace_has_root(int id=-1)-> long # check current whether have a "
+     "root. \n True: \nFalse: "
      "\n Note: If the id is invalid, return false"},
     {"drop_trace", py_pinpoint_drop_trace, METH_VARARGS,
      "def drop_trace(int id=-1):# drop this trace"},
-    {"start_time", py_pinpoint_start_time, METH_NOARGS, "def start_time()->long"},
+    {"start_time", py_pinpoint_start_time, METH_NOARGS,
+     "def start_time()->long"},
     {"add_clues", py_pinpoint_add_clues, METH_VARARGS,
      "def add_clues(string key,string value,int id=-1,int loc=0)"},
     {"add_clue", py_pinpoint_add_clue, METH_VARARGS,
      "def add_clue(string key,string value,int id=-1,int loc=0)"},
     {"set_context_key", py_pinpoint_context_key, METH_VARARGS,
-     "def set_context_key(string key,string value,int id=-1): # create a key-value pair that bases "
+     "def set_context_key(string key,string value,int id=-1): # create a "
+     "key-value pair that bases "
      "on current trace chain"},
     {"get_context_key", py_pinpoint_get_key, METH_VARARGS,
      "def get_context_key(string key,int id=-1)->string "},
-    {"check_tracelimit", py_check_tracelimit, METH_VARARGS,
+    {"check_tracelimit", py_check_trace_limit, METH_VARARGS,
      "def check_tracelimit(long timestamp=-1): #check trace whether is limit"},
-    {"enable_debug", py_pinpoint_enable_utest, METH_VARARGS,
+    {"enable_debug", py_pinpoint_enable_debug, METH_VARARGS,
      "def enable_debug(callback):#enable logging output(callback )"},
     {"force_flush_trace", py_force_flush_span, METH_VARARGS,
-     "def force_flush_trace(timeout=3,int id=-1): #force flush span during timeout"},
+     "def force_flush_trace(timeout=3,int id=-1): #force flush span during "
+     "timeout"},
     {"mark_as_error", py_pinpoint_mark_an_error, METH_VARARGS,
-     "def mark_as_error(string msg,string file_name,uint line_no,int id=-1): #Found an error in "
+     "def mark_as_error(string msg,string file_name,uint line_no,int id=-1): "
+     "#Found an error in "
      "this trace"},
     {"set_agent", (PyCFunction)py_set_agent, METH_VARARGS | METH_KEYWORDS,
      "def set_agent(collector_host=\"unix:/tmp/collector-agent.sock or "
-     "tcp:host:port\",trace_limit=-1): # set pinpint collector information"},
+     "tcp:host:port\",trace_limit=-1): # set pinpoint collector information"},
     {NULL, NULL, 0, NULL}};
 
 #if PY_MAJOR_VERSION > 2
 
-static void free_pinpoint_module(void* module) {
+static void free_pinpoint_module(void *module) {
   Py_XDECREF(py_obj_msg_callback);
 
   if (py_obj_msg_callback) {
@@ -437,8 +358,8 @@ static struct PyModuleDef _pinpointPymodule = {
 
     MODNAME,                              /* name of module */
     "python agent for pinpoint platform", /* Doc string (may be NULL) */
-    -1,                                   /* Size of per-interpreter state or -1 */
-    PinpointMethods,                      /* Method table */
+    -1,              /* Size of per-interpreter state or -1 */
+    PinpointMethods, /* Method table */
     NULL,
     NULL,
     NULL,
@@ -448,14 +369,7 @@ static struct PyModuleDef _pinpointPymodule = {
 /* Module initialization function */
 PyMODINIT_FUNC PyInit__pinpointPy(void) {
 
-  global_agent_info.agent_type = 1700;
-  strncpy(global_agent_info.co_host, "unix:/tmp/collector.sock", MAX_ADDRESS_SIZE);
-  global_agent_info.inter_flag = 0;
-  global_agent_info.timeout_ms = 0;
-  global_agent_info.trace_limit = -1;
-  register_error_cb(NULL);
-
-  PyObject* m = PyModule_Create(&_pinpointPymodule);
+  PyObject *m = PyModule_Create(&_pinpointPymodule);
   if (m == NULL)
     return NULL;
 
@@ -466,19 +380,11 @@ PyMODINIT_FUNC PyInit__pinpointPy(void) {
 PyDoc_STRVAR(pinpointPy__doc__, "python agent for pinpoint platform");
 
 PyMODINIT_FUNC init_pinpointPy(void) {
-  PyObject* m;
+  PyObject *m;
 
   m = Py_InitModule3(MODNAME, PinpointMethods, pinpointPy__doc__);
   if (m == NULL)
     return;
-
-  global_agent_info.agent_type = 1700;
-  strncpy(global_agent_info.co_host, "unix:/tmp/collector.sock", MAX_ADDRESS_SIZE);
-  global_agent_info.inter_flag = 0;
-  global_agent_info.timeout_ms = 0;
-  global_agent_info.trace_limit = -1;
-
-  register_error_cb(NULL);
 }
 
 #endif


Test patch:
diff --git a/collector-agent/agent/AgentRouter_test.go b/collector-agent/agent/AgentRouter_test.go
index 4156365d4..97f9eae1a 100644
--- a/collector-agent/agent/AgentRouter_test.go
+++ b/collector-agent/agent/AgentRouter_test.go
@@ -43,8 +43,8 @@ func TestTspan(t *testing.T) {
 		t.Error(tspan.GetStartTime())
 	}
 
-	if tspan.GetAppname() != "APP-2" {
-		t.Error(tspan.GetAppname())
+	if tspan.GetAppName() != "APP-2" {
+		t.Error(tspan.GetAppName())
 
 	}
 
diff --git a/collector-agent/server/server_test.go b/collector-agent/server/server_test.go
index cb90e64b2..68767a60c 100644
--- a/collector-agent/server/server_test.go
+++ b/collector-agent/server/server_test.go
@@ -5,6 +5,7 @@ import (
 	"net"
 	"os"
 	"strconv"
+	"strings"
 	"testing"
 	"time"
 
@@ -58,28 +59,36 @@ func generateUnvaalidPacket01() (buf []byte) {
 	return buf
 }
 
-func generateUnvaalidPacket02() (buf []byte) {
+func genUniqueIdBody() []byte {
+	msg := make([]byte, 8)
+	binary.BigEndian.PutUint32(msg[0:4], (uint32(2)))
+	binary.BigEndian.PutUint32(msg[4:8], (0))
+	return msg
+}
+
+func generateInvalidPacket02() (buf []byte) {
 	buf = make([]byte, 8)
 	binary.BigEndian.PutUint32(buf[0:4], (uint32(5220154)))
 	binary.BigEndian.PutUint32(buf[4:8], (1))
 	return buf
 }
 
-func generateUnvaalidPacket03() (buf []byte) {
+func generateInvalidPacket03() (buf []byte) {
 	buffer := make([]byte, 8)
 	binary.BigEndian.PutUint32(buffer[0:4], uint32(0))
 	binary.BigEndian.PutUint32(buffer[4:8], (1))
 	return buffer
 }
 
-func handleWrite(t *testing.T, conn net.Conn, done chan string) {
+func handleWrite(t *testing.T, conn net.Conn) {
 	defer conn.Close()
-
+	conn.Write(genUniqueIdBody())
+	readId(t, conn)
 	for i := 0; i < 5; i++ {
-		// _time := time.Now().Unix()
-		// msg := `{"E":17,"FT":1500,"S":` + strconv.FormatInt(_time, 10) + `,"AppId":"c_test_app_01","Appname":"c_test_name_01","calls":[{"E":7,"S":4,"clues":["-1:I'mthe parameters"],"name":"test_func","stp":"1301"},{"E":2,"S":11,"SQL":"select 1*3;","dst":"localhost:3307","name":"mysql::excute","stp":"2101"},{"E":4,"EXP":"test this exception","S":13,"clues":["40:/support/c-cpp-php-python","46:300"],"dst":"www.pinpoint-wonderful.com","name":"httpclient","nsid":"87969596","stp":"9800"}],"client":"127.0.0.1","clues":["46:200"],"name":"C_CPP Request","server":"HTTP_HOST","sid":"53562116","stp":"1500","tid":"c_test_app^1614586481657^5801","uri":"test_url"}`
+		_time := time.Now().Unix()
+		msg := `{"E":17,"FT":1500,"S":` + strconv.FormatInt(_time, 10) + `,"AppId":"c_test_app_01","Appname":"c_test_name_01","calls":[{"E":7,"S":4,"clues":["-1:I'mthe parameters"],"name":"test_func","stp":"1301"},{"E":2,"S":11,"SQL":"select 1*3;","dst":"localhost:3307","name":"mysql::excute","stp":"2101"},{"E":4,"EXP":"test this exception","S":13,"clues":["40:/support/c-cpp-php-python","46:300"],"dst":"www.pinpoint-wonderful.com","name":"httpclient","nsid":"87969596","stp":"9800"}],"client":"127.0.0.1","clues":["46:200"],"name":"C_CPP Request","server":"HTTP_HOST","sid":"53562116","stp":"1500","tid":"c_test_app^1614586481657^5801","uri":"test_url"}`
 
-		msg := `{"E":1,"FT":1500,"NP":"t=1617083759.535 D=0.000","S":1617083759798,"appid":"app-2","appname":"APP-2","calls":[{"E":1,"S":0,"clues":["-1:input parameters","14:return value"],"name":"app\\AppDate::outputDate","stp":"1501"}],"client":"10.34.135.145","clues":["46:200"],"name":"PHP Request: fpm-fcgi","server":"10.34.130.152:8000","sid":"726125302","stp":"1500","tid":"app-2^1617083747^5506","uri":"/index.php?type=get_date"}`
+		// msg := `{"E":1,"FT":1500,"NP":"t=1617083759.535 D=0.000","S":1617083759798,"appid":"app-2","appname":"APP-2","calls":[{"E":1,"S":0,"clues":["-1:input parameters","14:return value"],"name":"app\\AppDate::outputDate","stp":"1501"}],"client":"10.34.135.145","clues":["46:200"],"name":"PHP Request: fpm-fcgi","server":"10.34.130.152:8000","sid":"726125302","stp":"1500","tid":"app-2^1617083747^5506","uri":"/index.php?type=get_date"}`
 		buffer := generateValidPacket(msg)
 		_, e := conn.Write(buffer)
 		if e != nil {
@@ -88,21 +97,35 @@ func handleWrite(t *testing.T, conn net.Conn, done chan string) {
 		}
 		time.Sleep(100 * time.Millisecond)
 	}
+	conn.Write(genUniqueIdBody())
+	readId(t, conn)
 
-	conn.Write(generateUnvaalidPacket03())
-	conn.Write(generateUnvaalidPacket02())
+	conn.Write(generateInvalidPacket03())
+	conn.Write(generateInvalidPacket02())
+}
 
-	done <- "done"
+func readHello(t *testing.T, conn net.Conn) {
+	time.Sleep(5 * time.Second)
+	buf := make([]byte, 1280)
+	conn.Read(buf)
+	// if err != nil {
+	// 	t.Error("Error to read message because of ", err)
+	// 	return
+	// }
+	hello := string(buf[8:])
+	if !strings.HasPrefix(hello, "{\"appid\":\"") {
+		t.Error(hello)
+	}
 }
 
-func handleRead(t *testing.T, conn net.Conn, done chan string) {
-	buf := make([]byte, 128)
-	reqLen, err := conn.Read(buf)
-	if err != nil {
-		t.Error("Error to read message because of ", err)
-		return
+func readId(t *testing.T, conn net.Conn) {
+	time.Sleep(5 * time.Second)
+	buf := make([]byte, 1280)
+	conn.Read(buf)
+	id := string(buf[8:])
+	if !strings.HasPrefix(id, "{\"uid\"") {
+		t.Error(id)
 	}
-	done <- strconv.Itoa(reqLen)
 }
 
 func TestJsonServer(t *testing.T) {
@@ -113,14 +136,8 @@ func TestJsonServer(t *testing.T) {
 	if err != nil {
 		t.Error(err)
 	}
-	done := make(chan string)
-
-	go handleWrite(t, conn, done)
-	go handleRead(t, conn, done)
-
-	<-done
-	<-done
-	//time.Sleep(5 * time.Second)
+	readHello(t, conn)
+	handleWrite(t, conn)
 }
 
 func TestMain(m *testing.M) {
diff --git a/common/test/test_chunk.cc b/common/src/Cache/test_chunk.cc
similarity index 72%
rename from common/test/test_chunk.cc
rename to common/src/Cache/test_chunk.cc
index 1cd0f3cd4..bf4f2461e 100644
--- a/common/test/test_chunk.cc
+++ b/common/src/Cache/test_chunk.cc
@@ -1,26 +1,22 @@
-#include <gtest/gtest.h>
+#include "gtest/gtest.h"
 #include "Cache/Chunk.h"
-#include "json/json.h"
 using namespace testing;
 using Cache::Chunks;
 
-static int checkData(const void* buf, uint length, void* dst)
-{
+static int checkData(const void* buf, uint32_t length, void* dst) {
   int ret = 0;
   if (length < 25) {
     ret = length;
   } else {
     ret = length / 2;
   }
-  std::string* str = (std::string*) dst;
-  str->append((const char*) buf, ret);
+  std::string* str = (std::string*)dst;
+  str->append((const char*)buf, ret);
 
   return ret;
 }
 
-
-TEST(chunk, all_in_one)
-{
+TEST(chunk, all_in_one) {
   Chunks chunks(1024 * 4, 128);
   std::string out, ret;
   //    int size = 0;
@@ -37,7 +33,8 @@ TEST(chunk, all_in_one)
   out.append(buf3, 1024);
 
   // in and out
-  chunks.drainOutWithPipe(std::bind(&checkData, std::placeholders::_1, std::placeholders::_2, &ret));
+  chunks.drainOutWithPipe(
+      std::bind(&checkData, std::placeholders::_1, std::placeholders::_2, &ret));
 
   EXPECT_TRUE(ret == out);
 
@@ -58,7 +55,8 @@ TEST(chunk, all_in_one)
   out.append(buf3, 1024);
 
   ret.clear();
-  chunks.drainOutWithPipe(std::bind(&checkData, std::placeholders::_1, std::placeholders::_2, &ret));
+  chunks.drainOutWithPipe(
+      std::bind(&checkData, std::placeholders::_1, std::placeholders::_2, &ret));
   EXPECT_TRUE(chunks.getAllocSize() == 0);
   EXPECT_TRUE(ret == out);
 }
diff --git a/common/src/Cache/test_state.cc b/common/src/Cache/test_state.cc
new file mode 100644
index 000000000..96e005b73
--- /dev/null
+++ b/common/src/Cache/test_state.cc
@@ -0,0 +1,37 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright 2024 NAVER Corp
+//
+// Licensed 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.
+////////////////////////////////////////////////////////////////////////////////
+
+#include "gtest/gtest.h"
+#include "State.h"
+
+using PP::ProcessState;
+TEST(ProcessState, api) {
+  PP::StatePtr statePtr_ = std::unique_ptr<ProcessState>(new ProcessState(20));
+  EXPECT_NE(statePtr_->GetStartTime(), 0);
+  statePtr_->SetStartTime(1234567896);
+  EXPECT_EQ(statePtr_->GetStartTime(), 1234567896);
+  statePtr_->GetUniqueId();
+  statePtr_->ResetUniqueID();
+}
+
+TEST(ProcessState, CheckTraceLimit) {
+  PP::StatePtr statePtr_ = std::unique_ptr<ProcessState>(new ProcessState(4));
+  EXPECT_FALSE(statePtr_->CheckTraceLimit(-1));
+  EXPECT_FALSE(statePtr_->CheckTraceLimit(-1));
+  EXPECT_FALSE(statePtr_->CheckTraceLimit(-1));
+  EXPECT_FALSE(statePtr_->CheckTraceLimit(-1));
+  EXPECT_TRUE(statePtr_->CheckTraceLimit(-1));
+}
\ No newline at end of file
diff --git a/common/src/ConnectionPool/test_trans_layer.cc b/common/src/ConnectionPool/test_trans_layer.cc
new file mode 100644
index 000000000..38f1d3a46
--- /dev/null
+++ b/common/src/ConnectionPool/test_trans_layer.cc
@@ -0,0 +1,138 @@
+﻿
+#include <errno.h>
+#include <functional>
+#include <string>
+#include <gtest/gtest.h>
+#include "json/json.h"
+#include <thread>
+#include "SpanConnectionPool.h"
+#include "sockets.h"
+#include "header.h"
+using namespace testing;
+using ConnectionPool::SpanConnectionPool;
+using ConnectionPool::TransLayer;
+using ConnectionPool::TransLayerPtr;
+namespace Json = AliasJson;
+
+#define tcp_socket "127.0.0.1:5896"
+
+bool run = true;
+
+void sig_exit(int signm) {
+  (void)signm;
+  run = false;
+}
+
+void fake_server() {
+  SOCKET fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+#if defined(__linux__) || defined(__APPLE__)
+  struct sockaddr_in sin;
+  using SOCKET_ADDR_PTR = struct sockaddr*;
+// typedef  SOCKET_ADDR_PTR;
+#elif defined(_WIN32)
+  SOCKADDR_IN sin;
+  using SOCKET_ADDR_PTR = LPSOCKADDR;
+#endif
+  sin.sin_family = AF_INET;
+  sin.sin_port = htons(5896);
+  sin.sin_addr.s_addr = inet_addr("127.0.0.1");
+
+  if (bind(fd, (SOCKET_ADDR_PTR)&sin, sizeof(sin)) == SOCKET_ERROR) {
+    pp_trace("bind server socket failed:%s", strerror(errno));
+    return;
+  }
+  listen(fd, 10);
+  char buffer[1024] = {0};
+  struct sockaddr_in client_addr;
+  socklen_t addrlen = sizeof(client_addr);
+  SOCKET cfd = accept(fd, (struct sockaddr*)&client_addr, &addrlen);
+  if (cfd == INVALID_SOCKET) {
+    pp_trace("accept failed with error=%d", err_code());
+    return;
+  }
+  // assert(cfd != INVALID_SOCKET);
+  pp_trace("recv cfd:%d", cfd);
+  Json::Value agentInfo;
+
+  agentInfo["time"] = 1234567;
+  agentInfo["id"] = "test-app";
+  agentInfo["name"] = "test-name";
+
+  Json::FastWriter writer;
+  std::string msg = writer.write(agentInfo);
+  strcpy((char*)buffer + sizeof(Header), msg.c_str());
+
+  int len = msg.length();
+  Header* header = (Header*)buffer;
+  header->type = htonl(RESPONSE_AGENT_INFO);
+  header->length = htonl(len);
+  int ret = send(cfd, buffer, len + sizeof(*header), 0);
+  pp_trace("send [%d] [%d] %s ", cfd, ret, strerror(errno));
+  recv(cfd, buffer, 1024, 0);
+  close_socket(cfd);
+}
+
+void handle_agent_info(int type, const char* buf, size_t len) {
+  printf("recv: %s", buf);
+  EXPECT_EQ(type, RESPONSE_AGENT_INFO);
+  Json::Value root;
+  Json::Reader reader;
+  reader.parse(buf, buf + len, root);
+  EXPECT_EQ(root["time"].asInt64(), 1234567);
+  EXPECT_STREQ(root["id"].asCString(), "test-app");
+  EXPECT_STREQ(root["name"].asCString(), "test-name");
+  run = false;
+}
+
+TEST(translayer, connect_remote) {
+  TransLayer layer(tcp_socket);
+  int ret = layer.connect_remote(tcp_socket);
+  EXPECT_EQ(ret, -1);
+}
+
+TEST(translayer, tcp_socket_case) {
+  std::thread server(fake_server);
+  sleep(3);
+  std::string remote = "tcp:" tcp_socket;
+  TransLayer layer(remote);
+  using namespace std::placeholders;
+  layer.RegPeerMsgCallback(0, std::bind(handle_agent_info, _1, _2, _3));
+  while (run) {
+    layer.PoolEventOnce(3000);
+  }
+  std::string data = "msg-1918";
+  layer.copy_into_send_buffer(data);
+  layer.SyncSendAll(10);
+  // waitpid(pid, 0, 0);
+  server.join();
+}
+
+TEST(translayer, stream_socket_layer) {
+  int fd = -1;
+  fd = TransLayer::connect_stream_remote("www.naver.com:80");
+  EXPECT_GT(fd, 2);
+  close_socket(fd);
+
+  fd = TransLayer::connect_stream_remote("172.217.175.68:80");
+  EXPECT_GT(fd, 2);
+  close_socket(fd);
+
+  fd = TransLayer::connect_stream_remote("-.217.175.68:80");
+  EXPECT_EQ(fd, -1);
+
+  fd = TransLayer::connect_stream_remote("-.217.175.68:-80");
+  EXPECT_EQ(fd, -1);
+
+  fd = TransLayer::connect_stream_remote("-.217.175.68");
+  EXPECT_EQ(fd, -1);
+
+  fd = TransLayer::connect_stream_remote(":90");
+  EXPECT_EQ(fd, -1);
+}
+
+TEST(translayer, API) {
+  SpanConnectionPool _pool("unix:./pinpoint_test.sock", {{}});
+  auto _conn = _pool.get();
+  EXPECT_EQ(_conn->connect_stream_remote("-.217.175.68:-80"), -1);
+  _pool.free(_conn);
+}
\ No newline at end of file
diff --git a/common/test/test_node.cc b/common/src/NodePool/test_node.cc
similarity index 65%
rename from common/test/test_node.cc
rename to common/src/NodePool/test_node.cc
index 9115de7bf..28d89ffec 100644
--- a/common/test/test_node.cc
+++ b/common/src/NodePool/test_node.cc
@@ -1,28 +1,26 @@
 #include "common.h"
+#include "json/value.h"
 #include <gtest/gtest.h>
-#include "Util/Helper.h"
 #include "header.h"
 #include "NodePool/PoolManager.h"
 #include <condition_variable>
 #include <thread>
 #include <chrono>
-
-using NodePool::PoolManager;
-using NodePool::TraceNode;
-using NodePool::WrapperTraceNode;
+#include <string>
+#include <cstdlib>
+#include <ctime>
+#include <iostream>
+
+using PP::NodePool::PoolManager;
+using PP::NodePool::TraceNode;
+using PP::NodePool::WrapperTraceNodePtr;
 using namespace testing;
-using NodePool::freeNodeTree;
 namespace Json = AliasJson;
-
+PoolManager nodePool_;
 std::mutex cv_m;
 std::condition_variable cv;
 NodeID rootId = E_ROOT_NODE;
 
-int usedNode() {
-  return PoolManager::getInstance().totoalNodesCount() -
-         PoolManager::getInstance().freeNodesCount();
-}
-
 // note: as it known, there may leak some node
 void func() {
   std::unique_lock<std::mutex> lk(cv_m);
@@ -33,9 +31,10 @@ void func() {
     rootId = pinpoint_start_trace(rootId);
     pinpoint_set_context_key(rootId, "xxxx", "bbbbbb");
     std::this_thread::yield();
-    char buf[1024];
-    pinpoint_get_context_key(rootId, "xxxx", buf, 1024);
-    std::cout << "read value:" << buf << " ";
+    char buf[1024] = {0};
+    auto len = pinpoint_get_context_key(rootId, "xxxx", buf, 1024);
+    assert(len > 0);
+    std::cout << rootId << "read value:" << buf << std::endl;
     pinpoint_add_clues(rootId, "xxxx", "bbbbbbss", E_LOC_CURRENT);
     std::this_thread::yield();
     pinpoint_add_clue(rootId, "xxx", "bbbbbb", E_LOC_CURRENT);
@@ -68,25 +67,6 @@ TEST(node, multipleThread) {
   // EXPECT_TRUE(PoolManager::getInstance().NoNodeLeak());
 }
 
-TEST(node, wakeTrace) {
-  NodeID root = pinpoint_start_trace(E_ROOT_NODE);
-  NodeID child1 = pinpoint_start_trace(root);
-
-  pinpoint_end_trace(child1);
-
-  pinpoint_wake_trace(child1);
-  pinpoint_wake_trace(root);
-  pinpoint_wake_trace(NodeID(159));
-  pinpoint_wake_trace(NodeID(1027));
-  pinpoint_wake_trace(-1);
-  // do something
-  sleep(1);
-  pinpoint_end_trace(child1);
-
-  pinpoint_end_trace(root);
-  // EXPECT_TRUE(PoolManager::getInstance().NoNodeLeak());
-}
-
 void test_opt(TraceNode& node, const char* opt, ...) {
   va_list args;
   va_start(args, opt);
@@ -95,7 +75,8 @@ void test_opt(TraceNode& node, const char* opt, ...) {
 }
 
 TEST(node, opt) {
-  TraceNode& node = PoolManager::getInstance().Take();
+
+  TraceNode& node = nodePool_.Take();
 
   test_opt(node, "TraceMinTimeMs:23", "TraceOnlyException", nullptr);
 
@@ -105,20 +86,23 @@ TEST(node, opt) {
   EXPECT_TRUE(node.checkOpt());
 
   node.cumulative_time = 0;
-  node.mHasExp = true;
+  node.set_exp_ = true;
   EXPECT_TRUE(node.checkOpt());
-  node.mHasExp = false;
+  node.set_exp_ = false;
   EXPECT_FALSE(node.checkOpt());
 
-  PoolManager::getInstance().Restore(node);
+  nodePool_.ReturnNode(node);
   // EXPECT_TRUE(PoolManager::getInstance().NoNodeLeak());
 }
 
 static std::string span;
-void capture(const char* msg) { span = msg; }
+void capture(const char* msg) {
+  pp_trace("capture:%s", msg);
+  span = std::string(msg);
+}
 //./bin/TestCommon --gtest_filter=node.pinpoint_start_traceV1
 TEST(node, pinpoint_start_traceV1) {
-  auto count = usedNode();
+  pinpoint_set_agent("tcp:127.0.0.1:9999", 0, -1, 7000);
   register_span_handler(capture);
   NodeID root, child1;
   root = pinpoint_start_trace(E_ROOT_NODE);
@@ -161,7 +145,8 @@ TEST(node, pinpoint_start_traceV1) {
   pinpoint_end_trace(child1);
 
   pinpoint_end_trace(root);
-  std::cout << span << std::endl;
+  pp_trace("span:%s", span.c_str());
+  EXPECT_TRUE(span.length() > 0);
   EXPECT_TRUE(span.find("Take1sec") != span.npos);
   EXPECT_TRUE(span.find("Exception") != span.npos);
   EXPECT_TRUE(span.find("TraceMinTimeMs:2000") == span.npos);
@@ -169,11 +154,10 @@ TEST(node, pinpoint_start_traceV1) {
 
   EXPECT_TRUE(span.find("childFromTraceMinTimeMs:23-3") == span.npos);
   EXPECT_TRUE(span.find("childFromTraceMinTimeMs:23-2") == span.npos);
-  EXPECT_EQ(count, usedNode());
 }
 
 TEST(node, leak_node) {
-  auto count = PoolManager::getInstance().freeNodesCount();
+  auto count = nodePool_.freeNodesCount();
   NodeID root, child1, child2;
   root = pinpoint_start_trace(E_ROOT_NODE);
   child1 = pinpoint_start_trace(root);
@@ -184,13 +168,68 @@ TEST(node, leak_node) {
   pinpoint_end_trace(child1);
   pinpoint_end_trace(child2);
 
-  EXPECT_EQ(count, PoolManager::getInstance().freeNodesCount());
+  EXPECT_EQ(count, nodePool_.freeNodesCount());
   show_status();
 }
+std::set<std::string> removed_keys = {":E", ":S"};
+void Remove(Json::Value& v) {
+  Json::Value::Members mem = v.getMemberNames();
+  for (auto iter = mem.begin(); iter != mem.end(); iter++) {
+    if (removed_keys.find(*iter) != removed_keys.end()) {
+      v.removeMember(*iter);
+    }
+
+    if (*iter == "calls") {
+      for (long i = 0; i < v[*iter].size(); i++) {
+        Remove(v["calls"][(int)i]);
+      }
+    }
+  }
+
+  return;
+}
+
+bool check_span_order(std::string& i1, std::string& i2) {
+  Json::Value v_i1, v_i2;
+  Json::Reader reader;
+  reader.parse(i1, v_i1, false);
+  reader.parse(i2, v_i2, false);
+  Remove(v_i1);
+  Remove(v_i2);
+  pp_trace("%s", v_i1.toStyledString().c_str());
+  pp_trace("%s", v_i2.toStyledString().c_str());
+  return v_i1.toStyledString() == v_i2.toStyledString();
+}
+
+TEST(node, call_order) {
+  register_span_handler(capture);
+  NodeID root, child1, child2;
+  root = pinpoint_start_trace(E_ROOT_NODE);
+  pinpoint_add_clue(root, "name:", "root", E_LOC_CURRENT);
+  child1 = pinpoint_start_trace(root);
+  pinpoint_add_clue(child1, "name:", "child1", E_LOC_CURRENT);
+  child2 = pinpoint_start_trace(child1);
+  pinpoint_add_clue(child2, "name:", "child2", E_LOC_CURRENT);
+  child2 = pinpoint_start_trace(child1);
+  pinpoint_add_clue(child2, "name:", "child3", E_LOC_CURRENT);
+  pinpoint_end_trace(child2);
+  child2 = pinpoint_start_trace(child1);
+  pinpoint_add_clue(child2, "name:", "child4", E_LOC_CURRENT);
+  pinpoint_end_trace(child2);
+  child2 = pinpoint_start_trace(child1);
+  pinpoint_add_clue(child2, "name:", "child5", E_LOC_CURRENT);
+  pinpoint_end_trace(child2);
+  pinpoint_end_trace(child1);
+  pinpoint_end_trace(root);
+
+  std::string exp =
+      R"({":E":0,":FT":7000,":S":1710408777521,"calls":[{":E":0,":S":0,"calls":[{"name:":"child2"},{":E":0,":S":0,"name:":"child3"},{":E":0,":S":0,"name:":"child4"},{":E":0,":S":0,"name:":"child5"}],"name:":"child1"}],"name:":"root"})";
+  EXPECT_TRUE(check_span_order(span, exp));
+}
 
 TEST(node, tons_of_nodes_01) {
-  auto count = usedNode(); // PoolManager::getInstance().totoalNodesCount() -
-                           // PoolManager::getInstance().freeNodesCount();
+  pinpoint_set_agent("tcp:127.0.0.1:9999", 7000, -1, 7000);
+  // auto count = usedNode();
   NodeID root = pinpoint_start_trace(E_ROOT_NODE);
   for (int i = 0; i < 1000; i++) {
     NodeID child1 = pinpoint_start_trace(root);
@@ -198,9 +237,8 @@ TEST(node, tons_of_nodes_01) {
   }
   pinpoint_end_trace(root);
 
-  EXPECT_EQ(count, usedNode()); //);
+  // EXPECT_EQ(count, usedNode()); //);
 
-  count = usedNode();
   root = pinpoint_start_trace(E_ROOT_NODE);
   NodeID child1 = root;
   for (int i = 0; i < 1000; i++) {
@@ -211,30 +249,59 @@ TEST(node, tons_of_nodes_01) {
   }
   mark_current_trace_status(root, E_TRACE_BLOCK);
   pinpoint_end_trace(root);
-
-  EXPECT_EQ(count, usedNode());
 }
-
-TEST(node, tons_of_nodes_2k) {
-  auto count = usedNode(); // PoolManager::getInstance().totoalNodesCount() -
-                           // PoolManager::getInstance().freeNodesCount();
+// HACK here reproduce a bug in win11, not found any solution
+// unknown file: error: SEH exception with code 0xc00000fd thrown in the test body.
+// static int loop = 0;
+// int test_loop(Json::Value& value, int i) {
+//   loop++;
+//   if (i == 0) {
+//     return 0;
+//   }
+//   printf("%d \n", loop);
+//   if (i % 2) {
+//     Json::Value v;
+//     test_loop(v, i - 1);
+//     value["calls"].append(v);
+//   } else {
+//     test_loop(value, i - 1);
+//   }
+
+//   if (i % 3) {
+//     value["id"] = 2;
+//   }
+//   return 0;
+// }
+
+// TEST(node, test_json) {
+//   // std::srand(std::time(nullptr));
+//   // Json::Value pvalue;
+//   // // for (int i = 0; i < 2000; i++) {
+//   // test_loop(pvalue, 1000);
+//   // // }
+//   // printf("%s", pvalue.toStyledString().c_str());
+//   char* p = (char*)10;
+//   *p = 10;
+// }
+// HACK: window crash when nodes reached 1k
+// solution: use pspanchunk protocol
+TEST(node, tons_of_nodes_1k) {
   NodeID root = pinpoint_start_trace(E_ROOT_NODE);
   NodeID next = root;
-  for (int i = 0; i < 2000; i++) {
+  for (int i = 0; i < 1000; i++) {
     NodeID child = pinpoint_start_trace(next);
+    pinpoint_add_clue(child, "id", std::to_string(child).c_str(), E_LOC_CURRENT);
     pinpoint_end_trace(child);
+
     if (i % 2 == 0) {
       next = child;
     }
   }
   pinpoint_end_trace(root);
-
-  EXPECT_EQ(count, usedNode());
+  show_status();
 }
 
 TEST(node, tons_of_nodes_leak) {
-  auto count = usedNode();
-
   NodeID root, child_1, child_2;
   root = pinpoint_start_trace(E_ROOT_NODE);
 
@@ -245,52 +312,48 @@ TEST(node, tons_of_nodes_leak) {
 
   pinpoint_end_trace(root);
   pinpoint_end_trace(child_1);
-  EXPECT_EQ(count, usedNode());
 }
 
 TEST(node, tons_of_nodes_free_all) {
-  auto count = usedNode();
 
   NodeID root, child_1, child_2;
   root = pinpoint_start_trace(E_ROOT_NODE);
 
   child_1 = pinpoint_start_trace(root);
   child_2 = pinpoint_start_trace(child_1);
-  freeNodeTree(root);
   pinpoint_end_trace(child_2);
 
   pinpoint_end_trace(root);
   pinpoint_end_trace(child_1);
-  EXPECT_EQ(count, usedNode());
 }
 //./bin/TestCommon --gtest_filter=node.free_when_add
 TEST(node, free_when_add) {
-  auto count = usedNode();
+  auto getUsedNode = [&]() { return nodePool_.totalNodesCount() - nodePool_.freeNodesCount(); };
+  auto usedNode = getUsedNode();
   NodeID root;
   auto make_it_busy = [&]() {
-    auto w_root = PoolManager::getInstance().GetWrapperNode();
-    root = w_root->mPoolIndex;
-    auto w_child = PoolManager::getInstance().GetWrapperNode();
-    w_root->addChild(w_child);
+    auto w_root = nodePool_.GetWrapperNode();
+    root = w_root->id_;
+    auto w_child = nodePool_.GetWrapperNode();
+    w_root->AddChildTraceNode(w_child);
     w_child->AddTraceDetail("E_ROOT_NODE", 234);
     std::this_thread::sleep_for(std::chrono::seconds(2));
   };
   std::thread t(make_it_busy);
   std::this_thread::sleep_for(std::chrono::seconds(1));
-  auto start = Helper::get_current_msec_stamp();
-  freeNodeTree(root);
-  freeNodeTree(E_INVALID_NODE);
-  freeNodeTree(E_ROOT_NODE);
-  auto end = Helper::get_current_msec_stamp() - start;
-  printf("it takes: %ld to free ", end);
+  auto start = get_unix_time_ms();
+  nodePool_.FreeNodeTree(root);
+  nodePool_.FreeNodeTree(E_INVALID_NODE);
+  nodePool_.FreeNodeTree(E_ROOT_NODE);
+  auto end = get_unix_time_ms() - start;
+  printf("it takes: %ld to free ", (long)end);
   t.join();
-  EXPECT_EQ(count, usedNode());
+  EXPECT_EQ(usedNode, getUsedNode());
   EXPECT_TRUE(end >= 100);
 }
 
 //./bin/TestCommon --gtest_filter=node.orphan_node
 TEST(node, orphan_node) {
-  auto count = usedNode();
   NodeID root, child_1, orphan;
   root = pinpoint_start_trace(E_ROOT_NODE);
   child_1 = pinpoint_start_trace(root);
@@ -305,11 +368,10 @@ TEST(node, orphan_node) {
   debug_nodeid(orphan);
   pinpoint_end_trace(child_1);
   pinpoint_end_trace(root);
-  EXPECT_EQ(count, usedNode());
 }
 //./bin/TestCommon --gtest_filter=node.orphan_node_01
 TEST(node, orphan_node_01) {
-  auto count = usedNode();
+  pinpoint_set_agent("tcp:127.0.0.1:9999", 7000, -1, 7000);
   NodeID root, child_1, orphan;
   root = pinpoint_start_trace(E_ROOT_NODE);
   child_1 = pinpoint_start_trace(root);
@@ -318,12 +380,10 @@ TEST(node, orphan_node_01) {
 
   pinpoint_end_trace(child_1);
   pinpoint_end_trace(orphan);
-
-  EXPECT_EQ(count, usedNode());
 }
 //./bin/TestCommon --gtest_filter=node.orphan_root_parent_end
 TEST(node, orphan_parent_root_end) {
-  auto count = usedNode();
+  pinpoint_set_agent("tcp:127.0.0.1:9999", 7000, -1, 7000);
   NodeID root, child_1, orphan;
   root = pinpoint_start_trace(E_ROOT_NODE);
   child_1 = pinpoint_start_trace(root);
@@ -332,12 +392,10 @@ TEST(node, orphan_parent_root_end) {
   pinpoint_end_trace(root);
 
   pinpoint_end_trace(orphan);
-
-  EXPECT_EQ(count, usedNode());
 }
 
 TEST(node, orphan_root_parent_end) {
-  auto count = usedNode();
+  pinpoint_set_agent("tcp:127.0.0.1:9999", 7000, -1, 7000);
   NodeID root, child_1, orphan;
   root = pinpoint_start_trace(E_ROOT_NODE);
   child_1 = pinpoint_start_trace(root);
@@ -346,12 +404,10 @@ TEST(node, orphan_root_parent_end) {
   pinpoint_end_trace(child_1);
 
   pinpoint_end_trace(orphan);
-
-  EXPECT_EQ(count, usedNode());
 }
 // ./bin/TestCommon --gtest_filter=node.end_trace_in_mt
 TEST(node, end_trace_in_mt) {
-  auto count = usedNode();
+  pinpoint_set_agent("tcp:127.0.0.1:9999", 7000, -1, 7000);
   NodeID root = pinpoint_start_trace(E_ROOT_NODE);
   NodeID next = root;
   // limit size 100; due to
@@ -381,11 +437,10 @@ TEST(node, end_trace_in_mt) {
   cv.notify_all();
   for (auto& thread : threads)
     thread.join();
-  EXPECT_EQ(count, usedNode());
 }
 // ./bin/TestCommon --gtest_filter=node.max_sub_nodes
 TEST(node, max_sub_nodes) {
-  auto count = usedNode();
+  pinpoint_set_agent("tcp:127.0.0.1:9999", 7000, -1, 7000);
   NodeID root = pinpoint_start_trace(E_ROOT_NODE);
   while (true) {
     NodeID next = pinpoint_start_trace(root);
@@ -395,5 +450,4 @@ TEST(node, max_sub_nodes) {
     pinpoint_end_trace(next);
   }
   pinpoint_end_trace(root);
-  EXPECT_EQ(count, usedNode());
 }
\ No newline at end of file
diff --git a/common/test/test_node_pool.cc b/common/src/NodePool/test_node_pool.cc
similarity index 52%
rename from common/test/test_node_pool.cc
rename to common/src/NodePool/test_node_pool.cc
index 8229eef46..e4265121f 100644
--- a/common/test/test_node_pool.cc
+++ b/common/src/NodePool/test_node_pool.cc
@@ -1,27 +1,38 @@
-#include "NodePool/PoolManager.h"
+#include "NodePool/TraceNode.h"
+#include "PoolManager.h"
 #include "common.h"
+#include "header.h"
 #include <thread>
 #include <gtest/gtest.h>
+
 using namespace testing;
-using NodePool::PoolManager;
-using NodePool::TraceNode;
+using PP::NodePool::PoolManager;
+using PP::NodePool::TraceNode;
 
-TEST(poolManger, get_and_give_back)
-{
-  NodePool::PoolManager pool;
+TEST(poolManger, get_and_give_back) {
+  PoolManager pool;
   // new
-  TraceNode &_node = pool.Take();
-  void *p = &_node;
+  TraceNode& _node = pool.Take();
+  void* p = &_node;
   NodeID id = _node.getId();
   NodeID child, next;
   // give back
-  pool.Restore(id, child, next);
+  pool.ReturnNode(id, child, next);
   EXPECT_EQ(child, E_INVALID_NODE);
   EXPECT_EQ(next, E_INVALID_NODE);
-  TraceNode &_node_01 = pool.Take();
+  TraceNode& _node_01 = pool.Take();
+
+  TraceNode& new_node = pool.NewNode();
+  NodeID new_id = new_node.id_;
+
+  auto ref_node = pool.ReferNode(new_id);
+  EXPECT_EQ(ref_node->id_, new_node.id_);
+
+  pool.ReturnNode(new_id, child, next);
+  EXPECT_THROW(pool.ReferNode(new_id), std::out_of_range);
 
   // ref current
-  TraceNode &ref_new_node = pool.Take(_node_01.getId());
+  TraceNode& ref_new_node = pool.Take(_node_01.getId());
 
   EXPECT_EQ(p, &_node);
   EXPECT_EQ(ref_new_node, _node);
@@ -31,26 +42,24 @@ TEST(poolManger, get_and_give_back)
   EXPECT_THROW(pool.Take(NodeID(10000)), std::out_of_range);
 }
 
-static NodePool::PoolManager g_pool;
+static PoolManager g_pool;
 
-void test_node_pool(bool &result)
-{
+void test_node_pool(bool& result) {
   NodeID it = E_INVALID_NODE;
   for (int i = 0; i < 1000; i++) {
-    TraceNode &_node = g_pool.Take();
+    TraceNode& _node = g_pool.Take();
     usleep(1000);
     if (_node.getId() == it) {
       result = false;
       return;
     }
-    g_pool.Restore(_node);
+    g_pool.ReturnNode(_node);
     // g_pool.freeNode(_node.getId());
   }
   result = true;
 }
 
-TEST(poolManger, get_and_give_back_tls)
-{
+TEST(poolManger, get_and_give_back_tls) {
   bool rth1, rth2;
   std::thread t1(test_node_pool, std::ref(rth1));
   std::thread t2(test_node_pool, std::ref(rth2));
diff --git a/common/test/test_common.cc b/common/src/test_common.cc
similarity index 79%
rename from common/test/test_common.cc
rename to common/src/test_common.cc
index b82106e6a..b6bf9b660 100644
--- a/common/test/test_common.cc
+++ b/common/src/test_common.cc
@@ -1,41 +1,27 @@
-﻿#include <gtest/gtest.h>
-#include <locale.h>
-#include <regex.h>
+﻿#include "gtest/gtest.h"
+// #include <locale.h>
+// #include <regex.h>
 #include <thread>
 #include <chrono>
 #include "common.h"
 
 using namespace testing;
-
 std::string ouputMsg;
-void cc_log_error_cb(char* msg) { ouputMsg += msg; }
+void cc_log_error_cb(const char* msg) { ouputMsg = msg; }
 
 TEST(common, uid_all_in_one) {
-  // register_error_cb(cc_log_error_cb);
-  // test_trace();
+
+  pinpoint_set_agent("tcp:127.0.0.1:9999", 7000, -1, 7000);
+
   int64_t startId = generate_unique_id();
   generate_unique_id();
   generate_unique_id();
   generate_unique_id();
   EXPECT_EQ(generate_unique_id(), 4 + startId);
-
-#define _100K 100000
-
-  pid_t pid = fork();
-  if (pid == 0) {
-    for (int i = 0; i < _100K; i++)
-      generate_unique_id();
-    exit(0);
-  }
-
-  for (int i = 0; i < _100K; i++)
-    generate_unique_id();
-  waitpid(pid, NULL, 0);
-  //[0~9999]
-  EXPECT_EQ(generate_unique_id(), (startId + 2 * _100K + 5));
 }
 
 TEST(common, start_end_trace) {
+  register_span_handler(cc_log_error_cb);
   NodeID id = pinpoint_start_trace(E_ROOT_NODE);
   mark_current_trace_status(id, E_OFFLINE);
   EXPECT_EQ(pinpoint_trace_is_root(id), 1);
@@ -44,6 +30,7 @@ TEST(common, start_end_trace) {
   mark_current_trace_status(id, E_OFFLINE);
   EXPECT_EQ(pinpoint_trace_is_root(NodeID(-1023)), -1);
   EXPECT_EQ(pinpoint_trace_is_root(NodeID(1023)), -1);
+  EXPECT_EQ(pinpoint_trace_is_root(NodeID(0)), -1);
   id = pinpoint_start_trace(id);
 
   mark_current_trace_status(id, E_TRACE_PASS);
@@ -58,9 +45,13 @@ TEST(common, start_end_trace) {
   mark_current_trace_status(1024, E_TRACE_BLOCK);
   catch_error(-1024, "sdfasfas", "fsafdsfasd", 234);
   catch_error(0, "sdfasfas", "fsafdsfasd", 234);
+  EXPECT_TRUE(ouputMsg.find("ERR") != std::string::npos);
+  // pp_trace("%s", ouputMsg.c_str());
 }
 
 TEST(common, context_check) {
+  pinpoint_set_agent("tcp:127.0.0.1:9999", 7000, -1, 7000);
+
   NodeID id = pinpoint_start_trace(E_ROOT_NODE);
   std::string str = "fdafadf";
   pinpoint_add_clues(id, "fasdfas", str.c_str(), E_LOC_CURRENT);
@@ -85,13 +76,7 @@ TEST(common, context_check) {
 
   EXPECT_STREQ(buf, "fadfaffadf");
 
-  pinpoint_set_context_long(id, "1024", 1024);
-  pinpoint_set_context_long(NodeID(0), "1024", 1024);
-  pinpoint_set_context_long(NodeID(1205), "1024", 1024);
   pinpoint_set_context_key(id, "adfadf23", "fadfaffadf");
-  long value;
-  EXPECT_EQ(pinpoint_get_context_long(id, "1024", &value), 0);
-  EXPECT_EQ(value, 1024);
 
   pinpoint_set_context_key(id, ":interl", "abc");
   pinpoint_add_clue(id, ":internal", "abc", E_LOC_CURRENT);
@@ -100,20 +85,16 @@ TEST(common, context_check) {
   pinpoint_add_clues(id, ":internal-abc", "abc", E_LOC_CURRENT);
   pinpoint_add_clues(id, ":internal-abc-1", "abc", E_LOC_ROOT);
 
-  pinpoint_set_context_long(id, ":internal-abc-2", 12563);
-
-  long out;
-
-  EXPECT_NE(pinpoint_get_context_long(id, ":internal-abc-2", &out), 0);
-
   char outBuf[128] = {0};
-
-  EXPECT_EQ(pinpoint_get_context_key(id, ":interl", outBuf, sizeof(outBuf)), -1);
+  // no limitation on context key
+  EXPECT_EQ(pinpoint_get_context_key(id, ":interl", outBuf, sizeof(outBuf)), 3);
 
   pinpoint_end_trace(id);
 }
 
 TEST(common, error_checking) {
+  pinpoint_set_agent("tcp:127.0.0.1:9999", 7000, -1, 7000);
+
   NodeID id = pinpoint_start_trace(E_ROOT_NODE);
   EXPECT_EQ(pinpoint_trace_is_root(id), 1);
   id = pinpoint_end_trace(id);
@@ -124,6 +105,8 @@ TEST(common, error_checking) {
 }
 
 static void test_per_thread_id_odd() {
+  pinpoint_set_agent("tcp:127.0.0.1:9999", 7000, -1, 7000);
+
   NodeID id = pinpoint_get_per_thread_id();
   EXPECT_EQ(id, 0);
   id = NodeID(1);
@@ -153,6 +136,8 @@ static void test_per_thread_id_even() {
 }
 
 TEST(common, per_threadid) {
+  pinpoint_set_agent("tcp:127.0.0.1:9999", 7000, -1, 7000);
+
   std::thread f1(test_per_thread_id_odd);
   std::thread f2(test_per_thread_id_even);
   f1.join();
@@ -160,6 +145,8 @@ TEST(common, per_threadid) {
 }
 
 TEST(common, force_end_trace) {
+  pinpoint_set_agent("tcp:127.0.0.1:9999", 0, -1, 7000);
+
   NodeID id = pinpoint_start_trace(E_ROOT_NODE);
   id = pinpoint_end_trace(id);
   id = pinpoint_start_trace(id);
@@ -181,11 +168,15 @@ TEST(common, force_end_trace) {
 
 TEST(common, version) { EXPECT_STREQ(pinpoint_agent_version(), AGENT_VERSION); }
 
-//./bin/unittest --gtest_filter=common.id_1
-TEST(common, id_1) {
+TEST(common, invalid_host) {
+  pinpoint_set_agent("tcp:0.0.0.0.0:9999", 7000, -1, 7000);
   NodeID id = pinpoint_start_trace(E_ROOT_NODE);
-  for (int i = 0; i < 1280; i++) {
-    id = pinpoint_start_trace(id);
-  }
-  pinpoint_set_context_long(id, "1024", 1024);
+  id = pinpoint_end_trace(id);
 }
+
+TEST(common, pp_trace) {
+  pp_trace("测试中文编码 \n");
+  pp_trace("한국어 인코딩 테스트 \n");
+  pp_trace("日本語エンコーディングをテストする \n");
+  pp_trace("%s %s \n", "日本語エンコーディングをテストする ", "combine");
+}
\ No newline at end of file
diff --git a/common/test/test_util.cc b/common/src/test_util.cc
similarity index 56%
rename from common/test/test_util.cc
rename to common/src/test_util.cc
index a1d6767f1..00ee55407 100644
--- a/common/test/test_util.cc
+++ b/common/src/test_util.cc
@@ -21,55 +21,14 @@
  */
 
 #include <gtest/gtest.h>
-#include <thread>
-#include "common.h"
-#include "Util/Helper.h"
-#include "Cache/SafeSharedState.h"
 #include "NodePool/PoolManager.h"
-#include <stdarg.h>
-using Cache::SafeSharedState;
-using Helper::STT;
 using std::chrono::seconds;
 namespace Json = AliasJson;
-using NodePool::PoolManager;
-using NodePool::TraceNode;
-TEST(util, sst)
-{
-  ADDTRACE();
 
-  std::this_thread::sleep_for(seconds(1));
-}
-
-TEST(util, onOFFline)
-{
-  SafeSharedState &_state = SafeSharedState::instance();
-  EXPECT_FALSE(_state.isReady());
-  _state.updateStartTime(1316615272);
-  // EXPECT_EQ(1316615272, _state.getStartTime());
-  EXPECT_TRUE(_state.isReady());
-}
-
-TEST(util, time_in_msec)
-{
-  uint64_t time = Helper::get_current_msec_stamp();
-  std::this_thread::sleep_for(seconds(1));
-  EXPECT_GE(Helper::get_current_msec_stamp(), time + 1000);
-}
-// restrict typeva_start
-TEST(util, test_node_to_string)
-{
-  Json::Value _value;
+using PP::NodePool::PoolManager;
+using PP::NodePool::TraceNode;
 
-  _value["a"] = 1;
-  _value["b"] = 1;
-  _value["d"] = 1;
-
-  std::string str = Helper::node_tree_to_string(_value);
-  EXPECT_STREQ(str.c_str(), "{\"a\":1,\"b\":1,\"d\":1}");
-}
-
-int sum(int n_args, ...)
-{
+int sum(int n_args, ...) {
   va_list ap;
   va_start(ap, n_args);
   int var = n_args;
@@ -85,23 +44,21 @@ int sum(int n_args, ...)
   return total;
 }
 //./bin/unittest --gtest_filter=util.variadic_func
-TEST(util, variadic_func_int)
-{
+TEST(util, variadic_func_int) {
   EXPECT_EQ(sum(1, 2, 3, 4, 5, 6, 0), 21);
   EXPECT_EQ(sum(1, 2, 3, 5, 0), 11);
 }
 
-int opt(const char *start, ...)
-{
+int opt(const char* start, ...) {
   va_list ap;
   va_start(ap, start);
-  const char *var = start;
+  const char* var = start;
 
   int total = 0;
   while (var != nullptr) {
     printf("%s\n", var);
     total++;
-    var = va_arg(ap, const char *);
+    var = va_arg(ap, const char*);
   }
 
   va_end(ap);
@@ -109,40 +66,38 @@ int opt(const char *start, ...)
   return total;
 }
 //./bin/unittest --gtest_filter=util.variadic_func_str
-TEST(util, variadic_func_str)
-{
+TEST(util, variadic_func_str) {
   EXPECT_EQ(opt("a", "b", "c", "d", nullptr), 4);
   EXPECT_EQ(opt("a", "b", "c", nullptr), 3);
 }
 
-TEST(util, mergeTraceNodeTree)
-{
-  TraceNode &n1 = PoolManager::getInstance().Take();
-  TraceNode &n2 = PoolManager::getInstance().Take();
-  TraceNode &n3 = PoolManager::getInstance().Take();
-  TraceNode &n4 = PoolManager::getInstance().Take();
-
-  n2.mParentId = n1.mPoolIndex;
-  n1.mChildHeadId = n2.mPoolIndex;
-  n3.mParentId = n2.mPoolIndex;
-  n4.mParentId = n2.mPoolIndex;
-  n3.mNextId = n4.mPoolIndex;
-  n2.mChildHeadId = n3.mPoolIndex;
-
-  Json::Value var = Helper::mergeTraceNodeTree(n1);
-  std::cout << var.toStyledString();
+TEST(util, mergeTraceNodeTree) {
+  PoolManager node_pool;
+  TraceNode& n1 = node_pool.Take();
+  TraceNode& n2 = node_pool.Take();
+  TraceNode& n3 = node_pool.Take();
+  TraceNode& n4 = node_pool.Take();
+
+  n2.parent_id_ = n1.id_;
+  n1.last_child_id_ = n2.id_;
+  n3.parent_id_ = n2.id_;
+  n4.parent_id_ = n2.id_;
+  n3.sibling_id_ = n4.id_;
+  n2.last_child_id_ = n3.id_;
+
+  // Json::Value var = node_pool.ExpandTraceTreeNodes(n1);
+  // std::cout << var.toStyledString();
 }
 
 std::string span;
 
-void captureSpan(const char *s) { span = s; }
+void captureSpan(const char* s) { span = s; }
 
-TEST(util, mergeTraceNodeTree_1)
-{
+TEST(util, mergeTraceNodeTree_1) {
+  pinpoint_set_agent("tcp:127.0.0.1:9999", 0, -1, 7000);
   register_span_handler(captureSpan);
 
   NodeID id1, id2, id3, id4;
-  Json::Value var;
   id1 = pinpoint_start_trace(E_ROOT_NODE);
   pinpoint_add_clue(id1, "name", "id1", E_LOC_CURRENT);
   id2 = pinpoint_start_trace(id1);
@@ -160,4 +115,4 @@ TEST(util, mergeTraceNodeTree_1)
   EXPECT_TRUE(span.find("id2") != span.npos);
   EXPECT_TRUE(span.find("id3") != span.npos);
   EXPECT_TRUE(span.find("calls") != span.npos);
-}
+}
\ No newline at end of file
diff --git a/common/test/CMakeLists.txt b/common/test/CMakeLists.txt
index 218f223c8..931530817 100644
--- a/common/test/CMakeLists.txt
+++ b/common/test/CMakeLists.txt
@@ -1,19 +1,15 @@
-aux_source_directory(. TEST_SRC)
-
-add_executable(TestCommon ${TEST_SRC})
-target_compile_definitions(TestCommon PRIVATE "-DUTEST -DCOMMON_DEBUG")
-
-# message("${CMAKE_BINARY_DIR}/lib")
+file(GLOB_RECURSE TEST_SRC
+  "${PROJECT_SOURCE_DIR}/src/test_*.cc"
+)
+add_executable(TestCommon ${TEST_SRC} test_main.cc)
+target_include_directories(TestCommon PUBLIC ${PROJECT_SOURCE_DIR}/jsoncpp/include)
 if (WITH_CODECOVERAGE AND LINUX_)
-    # message("enable -lgcov")
-    target_link_libraries(TestCommon pinpoint_common_static gtest_main rt gcov )
-elseif(APPLE)
-    target_link_libraries(TestCommon pinpoint_common_static gtest_main)
-elseif(MSVC)
-    message( FATAL_ERROR "pinpoint-c-agent not support windows, if you need create an issue https://github.com/pinpoint-apm/pinpoint-c-agent/issues" )
+# message("enable -lgcov")
+target_link_libraries(TestCommon pinpoint_common_static gtest_main rt gcov )
 else()
-    message("------------------------------")
-    target_link_libraries(TestCommon pinpoint_common_static gtest_main rt)
+target_link_libraries(TestCommon pinpoint_common_static gtest_main)
 endif()
 
-add_test(TestCommon TestCommon)
\ No newline at end of file
+add_test(TestCommon TestCommon)
+add_executable(main test_main.cpp)
+target_link_libraries(main pinpoint_common_static)
\ No newline at end of file
diff --git a/common/test/WindowsTestEnv.wsb b/common/test/WindowsTestEnv.wsb
new file mode 100644
index 000000000..37ba0e767
--- /dev/null
+++ b/common/test/WindowsTestEnv.wsb
@@ -0,0 +1,5 @@
+<Configuration>
+  <VGpu>Disable</VGpu>
+  <Networking>Enable</Networking>
+  <MemoryInMB>2048</MemoryInMB>
+/Configuration>
\ No newline at end of file
diff --git a/common/test/test_genUniqId.cc b/common/test/test_genUniqId.cc
deleted file mode 100644
index 4e9cdd0c9..000000000
--- a/common/test/test_genUniqId.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-#include <gtest/gtest.h>
-#include "common.h"
-
-#include <sys/types.h>
-#include <sys/wait.h>
-
-using namespace testing;
-
-
-TEST(common, unique_id)
-{
-  static const int TIMES = 10000000;
-  int64_t last = -1;
-  // reset the unique id
-  reset_unique_id();
-  pid_t pid = fork();
-  if (pid == 0) {  // child
-    for (int i = 0; i < TIMES; i++) {
-      int64_t uid = generate_unique_id();
-      ASSERT_NE(uid, last);
-      last = uid;
-    }
-    exit(0);
-  } else {
-    for (int i = 0; i < TIMES; i++) {
-      int64_t uid = generate_unique_id();
-      ASSERT_NE(uid, last);
-      last = uid;
-    }
-  }
-
-  int state;
-  int w = waitpid(pid, &state, WUNTRACED | WCONTINUED);
-  if (w == -1) {
-    perror("waitpid");
-    exit(EXIT_FAILURE);
-  }
-  int64_t id = generate_unique_id();
-  EXPECT_EQ(id, TIMES * 2);
-  // reset the shm
-}
diff --git a/common/test/test_main.cc b/common/test/test_main.cc
index cf02d52c8..f1bf784ec 100644
--- a/common/test/test_main.cc
+++ b/common/test/test_main.cc
@@ -1,17 +1,16 @@
 ﻿#include <gtest/gtest.h>
-#include <cstdlib>
-#include <iostream>
-#include <sys/mman.h>
-#include <sys/stat.h> /* For mode constants */
-#include <fcntl.h>
 #include "common.h"
-
-void remove_shm_file() { shm_unlink("pinpoint-php.shm"); }
-
-int main(int argc, char **argv)
-{
-  std::atexit(remove_shm_file);
-  register_error_cb(NULL);
+#include "ConnectionPool/sockets.h"
+#include "header.h"
+void log_msg_cb_(char* msg) { printf("%s", msg); }
+int main(int argc, char** argv) {
+  socket_init();
+  pinpoint_set_agent("tcp:127.0.0.1:9999", 0, -1, 7000);
+  register_logging_cb(log_msg_cb_, 1);
   ::testing::InitGoogleTest(&argc, argv);
-  return RUN_ALL_TESTS();
+  // initial_crash_collection();
+  auto ret = RUN_ALL_TESTS();
+  sock_cleanup();
+  pinpoint_stop_agent();
+  return ret;
 }
\ No newline at end of file
diff --git a/common/test/test_main.cpp b/common/test/test_main.cpp
new file mode 100644
index 000000000..dfc16dd46
--- /dev/null
+++ b/common/test/test_main.cpp
@@ -0,0 +1,23 @@
+#include "common.h"
+// #include <iostream>
+#include <string>
+
+int main(int argc, char const* argv[]) {
+  pinpoint_set_agent("tcp:127.0.0.1:9999", 0, -1, 7000);
+  register_logging_cb(nullptr, 1);
+  NodeID root = pinpoint_start_trace(E_ROOT_NODE);
+
+  NodeID next = root;
+  for (int i = 0; i < 1000; i++) {
+    NodeID child = pinpoint_start_trace(next);
+    pinpoint_add_clue(child, "id", std::to_string(child).c_str(), E_LOC_CURRENT);
+    pinpoint_end_trace(child);
+
+    if (i % 2 == 0) {
+      next = child;
+    }
+  }
+  pinpoint_end_trace(root);
+  show_status();
+  return 0;
+}
diff --git a/common/test/test_trans_layer.cc b/common/test/test_trans_layer.cc
deleted file mode 100644
index 60da29cc9..000000000
--- a/common/test/test_trans_layer.cc
+++ /dev/null
@@ -1,138 +0,0 @@
-﻿#include <unistd.h>
-#include <errno.h>
-#include <functional>
-#include <iostream>
-#include <string>
-#include <gtest/gtest.h>
-
-#include "ConnectionPool/SpanConnectionPool.h"
-#include "json/json.h"
-
-using namespace testing;
-using ConnectionPool::SpanConnectionPool;
-using ConnectionPool::TransConnection;
-using ConnectionPool::TransLayer;
-namespace Json = AliasJson;
-
-#define unix_socket "./pinpoint_test.sock"
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-bool run = true;
-
-void sig_exit(int signm)
-{
-  (void) signm;
-  run = false;
-}
-
-int fack_server()
-{
-  int fd = socket(AF_UNIX, SOCK_STREAM, 0);
-  struct sockaddr_un address = {0, {0}};
-  address.sun_family = AF_UNIX;
-  strncpy(address.sun_path, unix_socket, sizeof(address.sun_path) - 1);
-  remove(unix_socket);
-  if (bind(fd, (struct sockaddr *) &address, sizeof(address)) == -1) {
-    pp_trace("bind server socket failed:%s", strerror(errno));
-    return 0;
-  }
-  listen(fd, 10);
-  char buffer[1024] = {0};
-  struct sockaddr addr;
-  socklen_t addrlen;
-  int cfd = accept(fd, &addr, &addrlen);
-  assert(cfd != -1);
-  pp_trace("recv cfd:%d", cfd);
-  Json::Value agentInfo;
-
-  agentInfo["time"] = 1234567;
-  agentInfo["id"] = "test-app";
-  agentInfo["name"] = "test-name";
-
-  Json::FastWriter writer;
-  std::string msg = writer.write(agentInfo);
-  strcpy((char *) buffer + sizeof(Header), msg.c_str());
-
-  int len = msg.length();
-  Header *header = (Header *) buffer;
-  header->type = htonl(RESPONSE_AGENT_INFO);
-  header->length = htonl(len);
-  int ret = send(cfd, buffer, len + sizeof(*header), 0);
-  pp_trace("send[%d] [%d] %s ", cfd, ret, strerror(errno));
-  recv(cfd, buffer, 1024, 0);
-  close(cfd);
-  return 0;
-}
-
-void handle_agent_info(int type, const char *buf, size_t len)
-{
-  printf("%s", buf);
-  EXPECT_EQ(type, RESPONSE_AGENT_INFO);
-  Json::Value root;
-  Json::Reader reader;
-  reader.parse(buf, buf + len, root);
-  EXPECT_EQ(root["time"].asInt64(), 1234567);
-  EXPECT_STREQ(root["id"].asCString(), "test-app");
-  EXPECT_STREQ(root["name"].asCString(), "test-name");
-  run = false;
-}
-
-TEST(translayer, unix_socket_layer)
-{
-  pid_t pid = fork();
-  if (pid == 0) {
-    fack_server();
-    exit(0);
-  }
-  sleep(3);
-  std::string remote = global_agent_info.co_host;
-  TransLayer layer(remote);
-  using namespace std::placeholders;
-  layer.registerPeerMsgCallback(std::bind(handle_agent_info, _1, _2, _3), NULL);
-  while (run) { layer.trans_layer_pool(300); }
-  std::string data = "msg-1918";
-  layer.copy_into_send_buffer(data);
-  layer.forceFlushMsg(10);
-  waitpid(pid, 0, 0);
-}
-
-TEST(translayer, stream_socket_layer)
-{
-  int fd = -1;
-  fd = TransLayer::connect_stream_remote("www.naver.com:80");
-  EXPECT_GT(fd, 2);
-  close(fd);
-
-  fd = TransLayer::connect_stream_remote("172.217.175.68:80");
-  EXPECT_GT(fd, 2);
-  close(fd);
-
-  fd = TransLayer::connect_stream_remote("-.217.175.68:80");
-  EXPECT_EQ(fd, -1);
-
-  fd = TransLayer::connect_stream_remote("-.217.175.68:-80");
-  EXPECT_EQ(fd, -1);
-
-  fd = TransLayer::connect_stream_remote("-.217.175.68");
-  EXPECT_EQ(fd, -1);
-
-  fd = TransLayer::connect_stream_remote(":90");
-  EXPECT_EQ(fd, -1);
-}
-
-TEST(ConnectionPool, API)
-{
-  std::string remote = global_agent_info.co_host;
-  SpanConnectionPool _pool(remote.c_str());
-
-  // SpanConnectionPool _pool1 = _pool;
-  // (void)_pool1;
-
-  TransConnection _conn = _pool.get();
-
-  EXPECT_EQ(_conn->connect_stream_remote("-.217.175.68:-80"), -1);
-
-  _pool.free(_conn);
-}
-
-#pragma GCC diagnostic pop
\ No newline at end of file
diff --git a/setup_pypi_test.py b/setup_pypi_test.py
index a336ab061..ac42177b5 100644
--- a/setup_pypi_test.py
+++ b/setup_pypi_test.py
@@ -1,5 +1,4 @@
-from setuptools import setup, Extension, find_namespace_packages, find_packages
-from distutils.command.build_ext import build_ext
+from setuptools import setup, Extension, find_namespace_packages
 import platform
 from pathlib import Path
 
@@ -8,14 +7,17 @@
 
 name = platform.system().lower()
 agent_libraries = []
+extra_compile_args_ = []
 if name == 'windows':
-    raise RuntimeError('pinpoint-c-agent currently not support MS')
+    pass
 elif name == 'darwin':
     agent_libraries = ['stdc++']
+    extra_compile_args_.append("-std=c++11")
 elif name == 'linux':
     agent_libraries = ['rt', 'stdc++']
+    extra_compile_args_.append("-std=c++11")
 else:
-    raise RuntimeError('Unknow platform to me: '+name)
+    raise RuntimeError('Unknown platform to us: ' + name)
 ###############################################
 
 extFiles = [
@@ -24,14 +26,18 @@
 
 # add pinpoint-common
 
-for a_file in Path("common").glob('**/*.cpp'):
+for a_file in Path("common/src").glob('**/*.cpp'):
     extFiles.append(str(a_file))
 
-for a_file in Path("common").glob('**/*.c'):
+for a_file in Path("common/jsoncpp").glob('**/*.cpp'):
     extFiles.append(str(a_file))
 
+cwd = Path.cwd()
+include_dirs_ = [Path(cwd, './common/include'), Path(cwd, './common/jsoncpp/include'),
+                 Path(cwd, './common/src')]
+
 setup(name='pinpointPy',
-      version="1.1.1",  # don't forget update __version__ in pinpointPy/__init__.py
+      version="1.2.5",  # don't forget update __version__ in pinpointPy/__init__.py
       author="cd_pinpoint members",
       author_email='dl_cd_pinpoint@navercorp.com',
       license='Apache License 2.0',
@@ -41,10 +47,9 @@
       ext_modules=[
           Extension('_pinpointPy',
                     extFiles,
-                    include_dirs=['common/include',
-                                  'common/jsoncpp/include', 'common/src'],
+                    include_dirs=include_dirs_,
                     libraries=agent_libraries,
-                    extra_compile_args=['-std=c++11']
+                    extra_compile_args=extra_compile_args_
                     )
       ],
       package_dir={'': 'plugins/PY'},
diff --git a/src/CPP/test_pinpoint.c b/src/CPP/test_pinpoint.c
index 3b9df7140..c1d74f8e4 100644
--- a/src/CPP/test_pinpoint.c
+++ b/src/CPP/test_pinpoint.c
@@ -20,8 +20,12 @@
 #include <stdio.h>
 #include <time.h>
 #include <stdlib.h>
+#if defined(_WIN32)
+#include <windows.h>
+#define usleep(x) Sleep(x/1000)
+#elif defined(__linux__) || defined(__APPLE__)
 #include <unistd.h>
-
+#endif
 int32_t id = 0;
 const char* app_id = "c_test_app";
 const char* app_name = "c_test_name";
@@ -40,7 +44,7 @@ char* get_tid() {
 
 void random_sleep() {
   int32_t delay = rand() % 10;
-  usleep(delay * 10000);
+  usleep(delay * 1000);
 }
 
 void test_httpclient() {
@@ -108,8 +112,8 @@ void test_req() {
 }
 
 int main(int argc, char const* argv[]) {
-  PPAgentT agent_info = {"tcp:127.0.0.1:9999", 1000, -1, 1300, 1, NULL, NULL, NULL};
-  global_agent_info = agent_info;
+  pinpoint_set_agent("tcp:127.0.0.1:9999", 0, -1, 1300);
+  register_logging_cb(NULL, 1);
   char appid[] = "cd.dev.test";
   char appname[] = "cd.dev.test";
   app_id = getenv("APPID");
diff --git a/src/CPP/test_pinpoint.cpp b/src/CPP/test_pinpoint.cpp
index 95aba3b49..4e67556d8 100644
--- a/src/CPP/test_pinpoint.cpp
+++ b/src/CPP/test_pinpoint.cpp
@@ -16,15 +16,16 @@
 
 #include "common.h"
 #include "pinpoint_define.h"
+#include <chrono>
 #include <iostream>
+#include <stdlib.h>
 #include <string>
+#include <thread>
 #include <time.h>
-#include <stdlib.h>
-#include <unistd.h>
 
 thread_local NodeID id = E_ROOT_NODE;
-const char* app_id = "cd.dev.test.cpp";
-const char* app_name = "cd.dev.test.cpp";
+const char *app_id = "cd.dev.test.cpp";
+const char *app_name = "cd.dev.test.cpp";
 
 std::string get_sid() { return std::to_string(rand() % 100000000l); }
 
@@ -36,16 +37,18 @@ std::string get_tid() {
 
 void random_sleep() {
   int32_t delay = rand() % 100;
-  usleep(delay * 10000);
+  std::this_thread::sleep_for(std::chrono::milliseconds(delay));
 }
 
 void test_httpclient() {
   id = pinpoint_start_trace(id);
   pinpoint_add_clue(id, PP_INTERCEPTOR_NAME, "httpclient", E_LOC_CURRENT);
-  pinpoint_add_clue(id, PP_DESTINATION, "www.pinpoint-wonderful.com", E_LOC_CURRENT);
+  pinpoint_add_clue(id, PP_DESTINATION, "www.pinpoint-wonderful.com",
+                    E_LOC_CURRENT);
   pinpoint_add_clue(id, PP_SERVER_TYPE, PP_C_CPP_REMOTE_METHOD, E_LOC_CURRENT);
   pinpoint_add_clue(id, PP_NEXT_SPAN_ID, get_sid().c_str(), E_LOC_CURRENT);
-  pinpoint_add_clues(id, PP_HTTP_URL, "/support/c-cpp-php-python", E_LOC_CURRENT);
+  pinpoint_add_clues(id, PP_HTTP_URL, "/support/c-cpp-php-python",
+                     E_LOC_CURRENT);
   pinpoint_add_clue(id, PP_ADD_EXCEPTION, "test this exception", E_LOC_CURRENT);
   pinpoint_add_clues(id, PP_HTTP_STATUS_CODE, "300", E_LOC_CURRENT);
 
@@ -105,9 +108,9 @@ void test_req() {
   id = pinpoint_end_trace(id);
 }
 
-int main(int argc, char const* argv[]) {
-  PPAgentT agent_info = {"tcp:127.0.0.1:9999", 1000, -1, 1300, 0, NULL, NULL, NULL};
-  global_agent_info = agent_info;
+int main(int argc, char const *argv[]) {
+  pinpoint_set_agent("tcp:127.0.0.1:9999", 0, -1, 1300);
+  register_logging_cb(nullptr, 1);
   srand(time(nullptr));
   int i = 0;
   for (; i < 3; i++) {
diff --git a/src/PY/test/testCoroutines.py b/src/PY/test/testCoroutines.py
index db10a0fcb..06c2f6ad0 100644
--- a/src/PY/test/testCoroutines.py
+++ b/src/PY/test/testCoroutines.py
@@ -7,14 +7,15 @@
 
 pinpointId = contextvars.ContextVar('pinpoint_id')
 pinpointId.set(0)
+
+
 class TestInCoroutines(TestCase):
     @classmethod
     def setUpClass(cls):
         # _pinpointPy.enable_debug(None)
-        _pinpointPy.set_agent(collector_host="unix:/tmp/unexist.sock")
-    
+        _pinpointPy.set_agent(collector_host="tcp:127.0.0.1:9999")
 
-    @unittest.skipIf(hex(sys.hexversion) <'0x30701f0', "python version must 3.7.1+")
+    @unittest.skipIf(hex(sys.hexversion) < '0x30701f0', "python version must 3.7.1+")
     def testCoroFlow(self):
         def decorator_pinpoint(func):
             async def pinpoint_trace(*args, **kwargs):
@@ -22,14 +23,14 @@ async def pinpoint_trace(*args, **kwargs):
                 id = _pinpointPy.start_trace(id)
                 pinpointId.set(id)
                 func_name = func.__name__
-                _pinpointPy.add_clue('name',func_name,id,0)
-                _pinpointPy.add_clues('start','3434',id)
-                _pinpointPy.set_context_key('sid','12345',id)
-                value = _pinpointPy.get_context_key('sid',id)
-                self.assertEqual(value,'12345')
+                _pinpointPy.add_clue('name', func_name, id, 0)
+                _pinpointPy.add_clues('start', '3434', id)
+                _pinpointPy.set_context_key('sid', '12345', id)
+                value = _pinpointPy.get_context_key('sid', id)
+                self.assertEqual(value, '12345')
 
                 ret = await func(*args, **kwargs)
-                _pinpointPy.add_clue('end','3434',id)
+                _pinpointPy.add_clue('end', '3434', id)
                 id = _pinpointPy.end_trace(id)
             return pinpoint_trace
 
@@ -61,7 +62,5 @@ async def main():
         asyncio.run(main())
 
 
-
 if __name__ == '__main__':
     unittest.main()
-    
\ No newline at end of file
diff --git a/src/PY/test/testIssues.py b/src/PY/test/testIssues.py
new file mode 100644
index 000000000..01796cf43
--- /dev/null
+++ b/src/PY/test/testIssues.py
@@ -0,0 +1,34 @@
+from unittest import TestCase
+import unittest
+import pinpointPy
+import logging
+
+from pinpointPy.tests import TestCase, GenTestHeader
+from pinpointPy import PinTransaction
+from pinpointPy.CommonPlugin import PinpointCommonPlugin
+from pinpointPy import use_thread_local_context
+
+
+def output(msg):
+    print(msg)
+
+
+class TestAgent(TestCase):
+    @classmethod
+    def setUpClass(cls):
+        # _pinpointPy.enable_debug(None)
+
+        pinpointPy.set_agent(
+            "test", "test", "tcp:0.0.0.0:5623", -1, 0, logging.DEBUG)
+        use_thread_local_context()
+
+    @PinTransaction("testcase", GenTestHeader())
+    def test_569(self):
+        @PinpointCommonPlugin('foo')
+        def foo():
+            print('foo')
+        foo()
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/src/PY/test/testPinpoint.py b/src/PY/test/testPinpoint.py
index b75069736..79f7f951e 100644
--- a/src/PY/test/testPinpoint.py
+++ b/src/PY/test/testPinpoint.py
@@ -7,12 +7,26 @@
 def output(msg):
     print(msg)
 
+
 class TestAgent(TestCase):
-     
+
     def setUp(self):
-        # self.assertTrue(_pinpointPy.enable_debug(output))
-        # self.assertTrue(_pinpointPy.enable_debug(None))
-        self.assertTrue(_pinpointPy.set_agent(collector_host='unix:/tmp/collector-agent.sock'))
+        def debug_func(msg: str):
+            print(msg)
+        _pinpointPy.enable_debug(debug_func)
+        self.assertTrue(_pinpointPy.set_agent(
+            collector_host='unix:/tmp/collector-agent.sock'))
+
+    def test_invalid_input(self):
+        id = _pinpointPy.start_trace()
+        _pinpointPy.end_trace()
+
+    def test_encode(self):
+        _pinpointPy.start_trace()
+        _pinpointPy.add_clues("CN", "测试中文编码")
+        _pinpointPy.add_clues("KR", "한국어 인코딩 테스트 ")
+        _pinpointPy.add_clues("JP", "日本語エンコーディングをテストする ")
+        _pinpointPy.end_trace()
 
     def test_trace_life(self):
         self.assertFalse(_pinpointPy.trace_has_root())
@@ -22,17 +36,15 @@ def test_trace_life(self):
         self.assertTrue(_pinpointPy.trace_has_root())
         _pinpointPy.start_trace()
         _pinpointPy.start_trace()
-        # self.assertRaises(Exception,lambda: _pinpointPy.trace_has_root(1025))
-        # self.assertRaises(Exception,lambda: _pinpointPy.trace_has_root(-1025))
 
-        _pinpointPy.add_clue("key","value")
-        _pinpointPy.add_clue("key","value3")
-        _pinpointPy.set_context_key('sid','12345')
+        _pinpointPy.add_clue("key", "value")
+        _pinpointPy.add_clue("key", "value3")
+        _pinpointPy.set_context_key('sid', '12345')
         value = _pinpointPy.get_context_key('sid')
-        self.assertEqual(value,'12345')
-        _pinpointPy.add_clues("key","values")
-        _pinpointPy.add_clues("key","values")
-        _pinpointPy.add_clues("key","values")
+        self.assertEqual(value, '12345')
+        _pinpointPy.add_clues("key", "values")
+        _pinpointPy.add_clues("key", "values")
+        _pinpointPy.add_clues("key", "values")
 
         _pinpointPy.end_trace()
         _pinpointPy.end_trace()
@@ -42,10 +54,14 @@ def test_trace_life(self):
         self.assertFalse(_pinpointPy.trace_has_root())
 
     def test_set_collector_host(self):
-        self.assertTrue(_pinpointPy.set_agent(collector_host='unix:/tmp/collector1.sock'))
-        self.assertTrue(_pinpointPy.set_agent(collector_host='Unix:/tmp/collector1.sock'))
-        self.assertTrue(_pinpointPy.set_agent(collector_host='TCP:dev-collector:11331'))
-        self.assertTrue(_pinpointPy.set_agent(collector_host='Tcp:dev-collector:11331'))
+        self.assertTrue(_pinpointPy.set_agent(
+            collector_host='unix:/tmp/collector1.sock'))
+        self.assertTrue(_pinpointPy.set_agent(
+            collector_host='Unix:/tmp/collector1.sock'))
+        self.assertTrue(_pinpointPy.set_agent(
+            collector_host='TCP:dev-collector:11331'))
+        self.assertTrue(_pinpointPy.set_agent(
+            collector_host='Tcp:dev-collector:11331'))
 
         try:
             _pinpointPy.set_agent(collector_host='dev-collector:11331')
@@ -53,16 +69,22 @@ def test_set_collector_host(self):
         except:
             pass
         try:
-            self.assertFalse(_pinpointPy.set_agent(collector_host='/tmp/collector1.sock'))
+            self.assertFalse(_pinpointPy.set_agent(
+                collector_host='/tmp/collector1.sock'))
             self.assertFalse(1)
         except:
             pass
-        
-        self.assertTrue(_pinpointPy.set_agent(collector_host='Tcp:dev-collector:11331',trace_limit=1000))
 
+        self.assertTrue(_pinpointPy.set_agent(
+            collector_host='Tcp:dev-collector:11331', trace_limit=1000))
+
+    def test_set_collector_host(self):
+        self.assertGreater(_pinpointPy.start_time(), 0,
+                           "_pinpointPy.start_time() in wrong format")
 
 # _pinpointPy.start_trace()
 # _pinpointPy.end_trace()
 
+
 if __name__ == '__main__':
-    unittest.main()
\ No newline at end of file
+    unittest.main()
diff --git a/src/PY/test/testUnderProcessMode.py b/src/PY/test/testUnderProcessMode.py
index 3070be174..0a57b6e91 100644
--- a/src/PY/test/testUnderProcessMode.py
+++ b/src/PY/test/testUnderProcessMode.py
@@ -6,29 +6,32 @@
 import random
 import platform
 
+
 class TestUnderProcessMode(TestCase):
 
     def tearDown(self):
         _pinpointPy.force_flush_trace(4)
 
     def _test_api_flow(self):
-        self.assertTrue(_pinpointPy.set_agent(collector_host='unix:/tmp/unexist.sock'))
+        self.assertTrue(_pinpointPy.set_agent(
+            collector_host='tcp:127.0.0.1:9999'))
         # self.assertTrue(_pinpointPy.enable_debug(None))
 
         while True:
-            id = str(random.randint(1,10000000))
+            id = str(random.randint(1, 10000000))
             _pinpointPy.start_trace()
-            _pinpointPy.set_context_key('sid',id)
-            _pinpointPy.add_clue("key","value3")
-            _pinpointPy.add_clues("key","value3")
+            _pinpointPy.set_context_key('sid', id)
+            _pinpointPy.add_clue("key", "value3")
+            _pinpointPy.add_clues("key", "value3")
             value = _pinpointPy.get_context_key('sid')
-            self.assertEqual(value,id)
-            _pinpointPy.mark_as_error("fghjk","fghjkl",234234)
+            self.assertEqual(value, id)
+            _pinpointPy.mark_as_error("fghjk", "fghjkl", 234234)
             _pinpointPy.end_trace()
             _pinpointPy.force_flush_trace()
             _pinpointPy.drop_trace()
 
-    @unittest.skipIf(platform.system() == "Darwin","skip Darwin")
+    @unittest.skipIf(platform.system() == "Darwin", "skip Darwin")
+    @unittest.skipIf(platform.system() == "Windows", "skip Windows")
     def test_process(self):
         p1 = Process(target=self._test_api_flow)
         p1.start()
@@ -44,5 +47,6 @@ def test_process(self):
         p2.join()
         p3.join()
 
+
 if __name__ == '__main__':
-    unittest.main()
\ No newline at end of file
+    unittest.main()
diff --git a/src/PY/test/testUnderThreadMode.py b/src/PY/test/testUnderThreadMode.py
index a685d8c4a..be4d21849 100644
--- a/src/PY/test/testUnderThreadMode.py
+++ b/src/PY/test/testUnderThreadMode.py
@@ -14,19 +14,19 @@ def tearDown(self):
         _pinpointPy.force_flush_trace(4)
 
     def _test_api_flow(self):
-        self.assertTrue(_pinpointPy.set_agent(collector_host='unix:/tmp/notexist.sock'))
-        # self.assertTrue(_pinpointPy.enable_debug(None))
+        self.assertTrue(_pinpointPy.set_agent(
+            collector_host='tcp:127.0.0.1:9999'))
 
         while self.thread_running:
             self.assertFalse(_pinpointPy.trace_has_root())
             _pinpointPy.start_trace()
             self.assertTrue(_pinpointPy.trace_has_root())
-            _pinpointPy.set_context_key('sid','12345678')
-            _pinpointPy.add_clue("key","value3")
-            _pinpointPy.add_clues("key","value3")
+            _pinpointPy.set_context_key('sid', '12345678')
+            _pinpointPy.add_clue("key", "value3")
+            _pinpointPy.add_clues("key", "value3")
             value = _pinpointPy.get_context_key('sid')
-            self.assertEqual(value,'12345678')
-            _pinpointPy.mark_as_error("fghjk","fghjkl",234234)
+            self.assertEqual(value, '12345678')
+            _pinpointPy.mark_as_error("fghjk", "fghjkl", 234234)
             _pinpointPy.end_trace()
             _pinpointPy.force_flush_trace()
             _pinpointPy.drop_trace()
@@ -34,7 +34,6 @@ def _test_api_flow(self):
             self.assertFalse(value)
             self.assertFalse(_pinpointPy.trace_has_root())
 
-
     def test_thread_safe(self):
         thread1 = Thread(target=self._test_api_flow)
         thread2 = Thread(target=self._test_api_flow)
@@ -48,5 +47,6 @@ def test_thread_safe(self):
         thread2.join()
         thread3.join()
 
+
 if __name__ == '__main__':
-    unittest.main()
\ No newline at end of file
+    unittest.main()
diff --git a/testapps/PY/app.py b/testapps/PY/app.py
index 333516819..2d1a99da4 100644
--- a/testapps/PY/app.py
+++ b/testapps/PY/app.py
@@ -57,7 +57,8 @@
 
 app = Flask(__name__)
 
-set_agent("cd.dev.test.py", "cd.dev.test.py", 'tcp:dev-collector:10000', -1,logging.DEBUG)
+set_agent("cd.dev.test.py", "cd.dev.test.py",
+          'tcp:dev-collector:10000', -1, 0, logging.DEBUG)
 
 app.wsgi_app = PinPointMiddleWare(app, app.wsgi_app)
 
@@ -375,4 +376,4 @@ def signin():
 
 
 if __name__ == '__main__':
-    app.run(host='0.0.0.0', port=80, processes=4, threaded=False)
+    app.run(host='0.0.0.0', port=80)
diff --git a/testapps/backend/app.py b/testapps/backend/app.py
index b294a1f48..fc648e251 100644
--- a/testapps/backend/app.py
+++ b/testapps/backend/app.py
@@ -57,7 +57,8 @@
 
 app = Flask(__name__)
 
-set_agent("cd.dev.test.py.backend", "cd.dev.test.py.backend", 'tcp:dev-collector:10000', -1,logging.DEBUG)
+set_agent("cd.dev.test.py.backend", "cd.dev.test.py.backend",
+          'tcp:dev-collector:10000', -1, 0, logging.DEBUG)
 
 app.wsgi_app = PinPointMiddleWare(app, app.wsgi_app)
 
diff --git a/testapps/django/mysite/mysite/settings.py b/testapps/django/mysite/mysite/settings.py
index 4da12cb1a..d03e6608e 100644
--- a/testapps/django/mysite/mysite/settings.py
+++ b/testapps/django/mysite/mysite/settings.py
@@ -46,7 +46,7 @@
 use_thread_local_context()
 monkey_patch_for_pinpoint()
 set_agent("cd.dev.test.py", "cd.dev.test.py",
-          'tcp:dev-collector:10000', -1, logging.DEBUG)
+          'tcp:dev-collector:10000', -1, 0, logging.DEBUG)
 
 MIDDLEWARE = [
     'pinpointPy.Django.DjangoMiddleWare',
diff --git a/testapps/fastapi/main.py b/testapps/fastapi/main.py
index fba5eb4a9..d6cc81612 100644
--- a/testapps/fastapi/main.py
+++ b/testapps/fastapi/main.py
@@ -1,7 +1,7 @@
 import logging
 from fastapi import FastAPI, Request, Response, Depends, HTTPException
 from starlette.middleware import Middleware
-from pinpointPy.Fastapi import PinPointMiddleWare, async_monkey_patch_for_pinpoint, use_starlette_context, asyn_monkey_patch_for_pinpoint
+from pinpointPy.Fastapi import PinPointMiddleWare, async_monkey_patch_for_pinpoint, use_starlette_context, asyn_monkey_patch_for_pinpoint, CommonPlugin
 from pinpointPy import set_agent, monkey_patch_for_pinpoint
 from sqlalchemy.orm import Session
 from starlette_context.middleware import ContextMiddleware
@@ -49,7 +49,7 @@ async def dispatch(self, request: Request, call_next):
 
 
 set_agent("cd.dev.test.py", "cd.dev.test.py",
-          'tcp:dev-collector:10000', -1, logging.DEBUG)
+          'tcp:dev-collector:10000', -1, 0, logging.DEBUG)
 
 use_starlette_context()
 monkey_patch_for_pinpoint()
@@ -98,10 +98,23 @@ async def root():
     return {"message": "Hello World"}
 
 
+@CommonPlugin("test1")
+async def test1():
+    pass
+
+
+@CommonPlugin("test")
+async def test():
+    await test1()
+    await test1()
+
+
 @app.get("/test-requests", tags=['sync-libraries'])
 async def test_requests(request: Request, url='http://www.example.com'):
     import requests
     x = requests.get(url)
+    await test()
+    await test()
     return {"response": x.status_code}
 
 
diff --git a/tests/add_root_trace.phpt b/tests/add_root_trace.phpt
index cf6975ea4..cb9894d37 100644
--- a/tests/add_root_trace.phpt
+++ b/tests/add_root_trace.phpt
@@ -31,7 +31,7 @@ $id = pinpoint_end_trace($id);
 [pinpoint] [%d] [%d] [126] add clue key:name value:Foo2
 [pinpoint] [%d] [%d] [126] pinpoint_end_trace Done!
 [pinpoint] [%d] [%d] [127] pinpoint_end_trace Done!
-[pinpoint] [%d] [%d]this span:({":E":%d,":FT":1500,":S":%d,"calls":[{":E":%d,":S":%d,"calls":[{":E":0,":S":%d,"name":"Foo2"}],"clues":["name:Foo1"]}],"clues":["global:global_value"],"global":"global_value","name":"Foo"})
-[pinpoint] [%d] [%d]agent try to connect:(unix:/unexist_file.sock)
-[pinpoint] [%d] [%d]connect:(/unexist_file.sock) failed as (No such file or directory)
+[pinpoint] [%d] [%d]this span:({":E":%d,":FT":1500,":S":%d,"calls":[{":E":%d,":S":%d,"calls":[{":E":%d,":S":%d,"name":"Foo2"}],"clues":["name:Foo1"]}],"clues":["global:global_value"],"global":"global_value","name":"Foo"})
+[pinpoint] [%d] [%d]agent try to connect:(:/unexist_file.sock)
+[pinpoint] [%d] [%d]connect:(:/unexist_file.sock) failed error_code: 2
 [pinpoint] [%d] [%d] [128] pinpoint_end_trace Done!
\ No newline at end of file
diff --git a/tests/mark_as_error.phpt b/tests/mark_as_error.phpt
index de202333f..8159cfcbf 100644
--- a/tests/mark_as_error.phpt
+++ b/tests/mark_as_error.phpt
@@ -21,7 +21,7 @@ echo pinpoint_end_trace()."\n";
 [pinpoint] [%d] [%d] [128] add clue key:args value:a,$b
 [pinpoint] [%d] [%d] [128] add clue key:ret value:a,$b
 [pinpoint] [%d] [%d]this span:({":E":%d,":FT":1500,":S":%d,"ERR":{"file":"filename you cared","line":1023,"msg":"message you cared"},"args":"a,$b","ret":"a,$b"})
-[pinpoint] [%d] [%d]agent try to connect:(unix:/unexist_file.sock)
-[pinpoint] [%d] [%d]connect:(/unexist_file.sock) failed as (No such file or directory)
+[pinpoint] [%d] [%d]agent try to connect:(:/unexist_file.sock)
+[pinpoint] [%d] [%d]connect:(:/unexist_file.sock) failed error_code: 2
 [pinpoint] [%d] [%d] [128] pinpoint_end_trace Done!
 0
\ No newline at end of file
diff --git a/tests/stack_fetal_error.phpt b/tests/stack_fetal_error.phpt
index ffe52d39a..9e2e3a448 100644
--- a/tests/stack_fetal_error.phpt
+++ b/tests/stack_fetal_error.phpt
@@ -62,6 +62,6 @@ Stack trace:
   thrown in %s on line 27
 [pinpoint] [%d] [%d] [127] pinpoint_end_trace Done!
 [pinpoint] [%d] [%d]this span:({":E":%d,":FT":1500,":S":%d,"ERR":{"file":"%s","line":27,"msg":"Uncaught Exception: I am testting in %s:27\nStack trace:\n#0 %s(34): Test()\n#1 {main}\n  thrown"},"calls":[{":E":%d,":S":%d,"name":"Foo"}]})
-[pinpoint] [%d] [%d]agent try to connect:(unix:/unexist_file.sock)
-[pinpoint] [%d] [%d]connect:(/unexist_file.sock) failed as (No such file or directory)
+[pinpoint] [%d] [%d]agent try to connect:(:/unexist_file.sock)
+[pinpoint] [%d] [%d]connect:(:/unexist_file.sock) failed error_code: 2
 [pinpoint] [%d] [%d] [128] pinpoint_end_trace Done!
\ No newline at end of file
diff --git a/tests/trace_api_context.phpt b/tests/trace_api_context.phpt
index 969852fbc..01291c0dd 100644
--- a/tests/trace_api_context.phpt
+++ b/tests/trace_api_context.phpt
@@ -4,7 +4,7 @@ Check  call statck
 <?php if (!extension_loaded("pinpoint_php")) print "skip"; ?>
 --INI--
 pinpoint_php.CollectorHost=unix:/unexist_file.sock
-pinpoint_php.SendSpanTimeOutMs=200
+pinpoint_php.SendSpanTimeOutMs=0
 pinpoint_php.UnitTest=true
 ;pinpoint_php._limit for internal use. User do not use it
 pinpoint_php._limit=yes
@@ -40,7 +40,7 @@ var_dump(pinpoint_get_context('not exist',$id));
 
 $id = pinpoint_end_trace($id);
 pinpoint_end_trace($id);
-
+pinpoint_status();
 ?>
 --EXPECTF--
 [pinpoint] [%d] [%d] [0] pinpoint_start child  [128]
@@ -50,8 +50,8 @@ string(1) "c"
 [pinpoint] [%d] [%d] pinpoint_get_context_key [128] failed with map::at, parameters:not exist
 bool(false)
 [pinpoint] [%d] [%d]this span:({":E":%d,":FT":1500,":S":%d})
-[pinpoint] [%d] [%d]agent try to connect:(unix:/unexist_file.sock)
-[pinpoint] [%d] [%d]connect:(/unexist_file.sock) failed as (No such file or directory)
+[pinpoint] [%d] [%d]agent try to connect:(:/unexist_file.sock)
+[pinpoint] [%d] [%d]connect:(:/unexist_file.sock) failed error_code: 2
 [pinpoint] [%d] [%d] [128] pinpoint_end_trace Done!
 [pinpoint] [%d] [%d] [0] pinpoint_start child  [128]
 [pinpoint] [%d] [%d] [128] pinpoint_start child  [127]
@@ -62,5 +62,9 @@ string(1) "a"
 bool(false)
 [pinpoint] [%d] [%d] [127] pinpoint_end_trace Done!
 [pinpoint] [%d] [%d]this span:({":E":%d,":FT":1500,":S":%d,"calls":[{":E":%d,":S":%d}]})
-[pinpoint] [%d] [%d]agent try to connect:(unix:/unexist_file.sock)
-[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done!
\ No newline at end of file
+[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done!
+{
+	"common_libary_version" : "0.5.0",
+	"pool_free_node" : 128,
+	"pool_total_node" : 128
+}
\ No newline at end of file
diff --git a/tests/trace_api_context_tcp.phpt b/tests/trace_api_context_tcp.phpt
index bfb35ab61..3dbe1fad9 100644
--- a/tests/trace_api_context_tcp.phpt
+++ b/tests/trace_api_context_tcp.phpt
@@ -4,7 +4,7 @@ Check  call statck
 <?php if (!extension_loaded("pinpoint_php")) print "skip"; ?>
 --INI--
 pinpoint_php.CollectorHost=tcp:127.0.0.1:9999
-pinpoint_php.SendSpanTimeOutMs=200
+pinpoint_php.SendSpanTimeOutMs=0
 pinpoint_php.UnitTest=true
 ;pinpoint_php._limit for internal use. User do not use it
 pinpoint_php._limit=yes
@@ -40,7 +40,7 @@ var_dump(pinpoint_get_context('not exist',$id));
 
 $id = pinpoint_end_trace($id);
 pinpoint_end_trace($id);
-
+pinpoint_status();
 ?>
 --EXPECTF--
 [pinpoint] [%d] [%d] [0] pinpoint_start child  [128]
@@ -50,8 +50,9 @@ string(1) "c"
 [pinpoint] [%d] [%d] pinpoint_get_context_key [128] failed with map::at, parameters:not exist
 bool(false)
 [pinpoint] [%d] [%d]this span:({":E":%d,":FT":1500,":S":%d})
-[pinpoint] [%d] [%d]agent try to connect:(tcp:127.0.0.1:9999)
-[pinpoint] [%d] [%d]_do_write_data@198 send data error:(Connection refused) fd:(3)
+[pinpoint] [%d] [%d]agent try to connect:(127.0.0.1:9999)
+[pinpoint] [%d] [%d]write event
+[pinpoint] [%d] [%d]_do_write_data@%d send data error:(%d) fd:(3)
 [pinpoint] [%d] [%d]reset peer:3
 [pinpoint] [%d] [%d] [128] pinpoint_end_trace Done!
 [pinpoint] [%d] [%d] [0] pinpoint_start child  [128]
@@ -63,5 +64,9 @@ string(1) "a"
 bool(false)
 [pinpoint] [%d] [%d] [127] pinpoint_end_trace Done!
 [pinpoint] [%d] [%d]this span:({":E":%d,":FT":1500,":S":%d,"calls":[{":E":%d,":S":%d}]})
-[pinpoint] [%d] [%d]agent try to connect:(tcp:127.0.0.1:9999)
-[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done!
\ No newline at end of file
+[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done!
+{
+	"common_libary_version" : "0.5.0",
+	"pool_free_node" : 128,
+	"pool_total_node" : 128
+}
\ No newline at end of file
diff --git a/tests/trace_api_test.phpt b/tests/trace_api_test.phpt
index d17404e33..0cbdfd6d1 100644
--- a/tests/trace_api_test.phpt
+++ b/tests/trace_api_test.phpt
@@ -4,7 +4,7 @@ Check  call statck
 <?php if (!extension_loaded("pinpoint_php")) print "skip"; ?>
 --INI--
 pinpoint_php.CollectorHost=unix:/unexist_file.sock
-pinpoint_php.SendSpanTimeOutMs=200
+pinpoint_php.SendSpanTimeOutMs=0
 pinpoint_php.UnitTest=true
 ;pinpoint_php._limit for internal use. User do not use it
 pinpoint_php._limit=yes
@@ -129,7 +129,7 @@ echo pinpoint_end_trace()."\n";
 [pinpoint] [%d] [%d] [128] add clue key:args value:a,$b
 [pinpoint] [%d] [%d] [128] add clue key:ret value:a,$b
 [pinpoint] [%d] [%d]this span:({":E":%d,":FT":1500,":S":%d,"args":"a,$b","calls":[{":E":%d,":S":%d,"clues":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,"clues":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,"clues":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,"clues":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,"clues":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,"clues":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,"clues":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,"clues":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,"clues":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,"clues":["1:234,3432","2:234"],"name":"Foo"}],"name":"ouput_234","ret":"a,$b"})
-[pinpoint] [%d] [%d]agent try to connect:(unix:/unexist_file.sock)
-[pinpoint] [%d] [%d]connect:(/unexist_file.sock) failed as (No such file or directory)
+[pinpoint] [%d] [%d]agent try to connect:(:/unexist_file.sock)
+[pinpoint] [%d] [%d]connect:(:/unexist_file.sock) failed error_code: 2
 [pinpoint] [%d] [%d] [128] pinpoint_end_trace Done!
 0
\ No newline at end of file
diff --git a/tests/trace_api_with_id.phpt b/tests/trace_api_with_id.phpt
index 499a6b2e0..631a851ed 100644
--- a/tests/trace_api_with_id.phpt
+++ b/tests/trace_api_with_id.phpt
@@ -60,7 +60,7 @@ $id = pinpoint_end_trace($id);
 [pinpoint] [%d] [%d] [127] add clue key:EXP value:too heavy, throw it
 [pinpoint] [%d] [%d] [127] pinpoint_end_trace Done!
 [pinpoint] [%d] [%d]this span:({":E":%d,":FT":1500,":S":%d,"calls":[{":E":%d,":S":%d,"EXP":"too heavy, throw it","calls":[{":E":%d,":S":%d,"name":"Foo2"},{":E":%d,":S":%d,"clues":["name:Foo3"],"name":"Foo4"}],"clues":["name:Foo1","name:Foo5"]}],"name":"Foo"})
-[pinpoint] [%d] [%d]agent try to connect:(unix:/unexist_file.sock)
-[pinpoint] [%d] [%d]connect:(/unexist_file.sock) failed as (No such file or directory)
+[pinpoint] [%d] [%d]agent try to connect:(:/unexist_file.sock)
+[pinpoint] [%d] [%d]connect:(:/unexist_file.sock) failed error_code: 2
 [pinpoint] [%d] [%d] [128] pinpoint_end_trace Done!
 Uncaught exception: too heavy, throw it
\ No newline at end of file
diff --git a/tests/trace_limit_test-i448.phpt b/tests/trace_limit_test-i448.phpt
index 483723c48..8a727e867 100644
--- a/tests/trace_limit_test-i448.phpt
+++ b/tests/trace_limit_test-i448.phpt
@@ -42,7 +42,7 @@ string(1) "a"
 [pinpoint] [%d] [%d] pinpoint_get_context_key [127] failed with map::at, parameters:not exist
 bool(false)
 [pinpoint] [%d] [%d] [127] pinpoint_end_trace Done!
-[pinpoint] [%d] [%d]This span dropped. max_trace_limit:0 current_tick:0 onLine:1
+[pinpoint] [%d] [%d]This span dropped. max_trace_limit:0 current_tick:0 onLine:0
 [pinpoint] [%d] [%d]change current [128] status, before:2,now:4
 [pinpoint] [%d] [%d]current [128] span dropped,due to TRACE_BLOCK
 [pinpoint] [%d] [%d] [128] pinpoint_end_trace Done!
\ No newline at end of file
diff --git a/tests/trace_limit_test.phpt b/tests/trace_limit_test.phpt
index 14c521e99..8cc4324f1 100644
--- a/tests/trace_limit_test.phpt
+++ b/tests/trace_limit_test.phpt
@@ -19,5 +19,5 @@ if(pinpoint_tracelimit() || pinpoint_tracelimit() ||pinpoint_tracelimit() || pin
     echo "pinpoint_tracelimit failed";
 }
 --EXPECTF--
-[pinpoint] [%d] [%d]This span dropped. max_trace_limit:2 current_tick:2 onLine:1
+[pinpoint] [%d] [%d]This span dropped. max_trace_limit:2 current_tick:2 onLine:0
 pass
\ No newline at end of file