You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by mi...@apache.org on 2023/02/09 03:48:25 UTC

[shardingsphere-on-cloud] branch main updated: feat: init pitr agent server project (#195)

This is an automated email from the ASF dual-hosted git repository.

miaoliyao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/shardingsphere-on-cloud.git


The following commit(s) were added to refs/heads/main by this push:
     new 58381e6  feat: init pitr agent server project (#195)
58381e6 is described below

commit 58381e68f97efd1a6f2fd247e1b2121a1f388c93
Author: lltgo <ll...@outlook.com>
AuthorDate: Thu Feb 9 11:48:19 2023 +0800

    feat: init pitr agent server project (#195)
---
 .gitignore                                         |   1 +
 pitr/agent/Makefile                                |   0
 pitr/agent/README.md                               |  14 +++
 pitr/agent/go.mod                                  |  41 +++++++
 pitr/agent/go.sum                                  | 132 ++++++++++++++++++++
 pitr/agent/internal/cons/error.go                  |  27 ++++
 pitr/agent/internal/cons/http_header.go            |  22 ++++
 pitr/agent/internal/handler/backup.go              |  24 ++++
 .../internal/handler/middleware/http_header.go     |  36 ++++++
 pitr/agent/internal/handler/middleware/logger.go   |  63 ++++++++++
 pitr/agent/internal/handler/middleware/recovery.go |  45 +++++++
 .../handler/middleware/uniform_err_resp.go         |  44 +++++++
 pitr/agent/internal/handler/resotre.go             |  24 ++++
 pitr/agent/internal/handler/show.go                |  24 ++++
 pitr/agent/internal/pkg/opengauss.go               |  18 +++
 pitr/agent/internal/pkg/pkg_test.go                |  30 +++++
 pitr/agent/main.go                                 | 136 +++++++++++++++++++++
 pitr/agent/pkg/logging/field.go                    |  46 +++++++
 pitr/agent/pkg/logging/log.go                      |  69 +++++++++++
 pitr/agent/pkg/logging/zap_log.go                  |  82 +++++++++++++
 pitr/agent/pkg/responder/resp.go                   |  95 ++++++++++++++
 pitr/agent/pkg/strutil/rand_string.go              |  58 +++++++++
 pitr/agent/pkg/strutil/rand_string_test.go         |  34 ++++++
 pitr/agent/pkg/strutil/strutil_test.go             |  30 +++++
 pitr/agent/pkg/syncutils/recover_func.go           |  41 +++++++
 pitr/agent/pkg/xerror/error.go                     |  47 +++++++
 pitr/agent/pkg/xerror/error_test.go                |  50 ++++++++
 27 files changed, 1233 insertions(+)

diff --git a/.gitignore b/.gitignore
index 1620240..1048a23 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,6 +20,7 @@ testbin/*
 
 # editor and IDE paraphernalia
 .vscode
+.fleet
 .idea
 *.swp
 *.swo
diff --git a/pitr/agent/Makefile b/pitr/agent/Makefile
new file mode 100644
index 0000000..e69de29
diff --git a/pitr/agent/README.md b/pitr/agent/README.md
new file mode 100644
index 0000000..d1f300c
--- /dev/null
+++ b/pitr/agent/README.md
@@ -0,0 +1,14 @@
+# PITR/AGENT
+
+PITR agent server for openGauss.
+
+## project description
+
+### layout
+
+* `internal`:For internal code, use golang internal directory to isolate references.
+	- `cons`: Constant directory.
+    - `handler`: HTTP handler.
+    - `pkg`: Business logic related packages.
+* `pkg`: Business logic independent packages.
+
diff --git a/pitr/agent/go.mod b/pitr/agent/go.mod
new file mode 100644
index 0000000..ec5028c
--- /dev/null
+++ b/pitr/agent/go.mod
@@ -0,0 +1,41 @@
+module github.com/apache/pitr/agent
+
+go 1.20
+
+require (
+	github.com/gofiber/fiber/v2 v2.42.0
+	github.com/onsi/ginkgo/v2 v2.8.0
+	github.com/onsi/gomega v1.26.0
+	go.uber.org/zap v1.24.0
+)
+
+require (
+	github.com/andybalholm/brotli v1.0.4 // indirect
+	github.com/go-logr/logr v1.2.3 // indirect
+	github.com/google/go-cmp v0.5.9 // indirect
+	github.com/google/uuid v1.3.0 // indirect
+	github.com/klauspost/compress v1.15.9 // indirect
+	github.com/kr/pretty v0.3.0 // indirect
+	github.com/mattn/go-colorable v0.1.13 // indirect
+	github.com/mattn/go-isatty v0.0.17 // indirect
+	github.com/mattn/go-runewidth v0.0.14 // indirect
+	github.com/philhofer/fwd v1.1.1 // indirect
+	github.com/pkg/errors v0.9.1 // indirect
+	github.com/rivo/uniseg v0.2.0 // indirect
+	github.com/rogpeppe/go-internal v1.8.0 // indirect
+	github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 // indirect
+	github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d // indirect
+	github.com/stretchr/testify v1.8.1 // indirect
+	github.com/tinylib/msgp v1.1.6 // indirect
+	github.com/valyala/bytebufferpool v1.0.0 // indirect
+	github.com/valyala/fasthttp v1.44.0 // indirect
+	github.com/valyala/tcplisten v1.0.0 // indirect
+	go.uber.org/atomic v1.9.0 // indirect
+	go.uber.org/multierr v1.8.0 // indirect
+	golang.org/x/net v0.5.0 // indirect
+	golang.org/x/sys v0.4.0 // indirect
+	golang.org/x/text v0.6.0 // indirect
+	google.golang.org/protobuf v1.28.1 // indirect
+	gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
+)
diff --git a/pitr/agent/go.sum b/pitr/agent/go.sum
new file mode 100644
index 0000000..aaa8ca3
--- /dev/null
+++ b/pitr/agent/go.sum
@@ -0,0 +1,132 @@
+github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
+github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
+github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
+github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/gofiber/fiber/v2 v2.42.0 h1:Fnp7ybWvS+sjNQsFvkhf4G8OhXswvB6Vee8hM/LyS+8=
+github.com/gofiber/fiber/v2 v2.42.0/go.mod h1:3+SGNjqMh5VQH5Vz2Wdi43zTIV16ktlFd3x3R6O1Zlc=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
+github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
+github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
+github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
+github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/onsi/ginkgo/v2 v2.8.0 h1:pAM+oBNPrpXRs+E/8spkeGx9QgekbRVyr74EUvRVOUI=
+github.com/onsi/ginkgo/v2 v2.8.0/go.mod h1:6JsQiECmxCa3V5st74AL/AmsV482EDdVrGaVW6z3oYU=
+github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q=
+github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
+github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ=
+github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
+github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
+github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
+github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
+github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
+github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 h1:rmMl4fXJhKMNWl+K+r/fq4FbbKI+Ia2m9hYBLm2h4G4=
+github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94/go.mod h1:90zrgN3D/WJsDd1iXHT96alCoN2KJo6/4x1DZC3wZs8=
+github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d h1:Q+gqLBOPkFGHyCJxXMRqtUgUbTjI8/Ze8vu8GGyNFwo=
+github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/tinylib/msgp v1.1.6 h1:i+SbKraHhnrf9M5MYmvQhFnbLhAXSDWF8WWsuyRdocw=
+github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw=
+github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
+github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
+github.com/valyala/fasthttp v1.44.0 h1:R+gLUhldIsfg1HokMuQjdQ5bh9nuXHPIfvkYUu9eR5Q=
+github.com/valyala/fasthttp v1.44.0/go.mod h1:f6VbjjoI3z1NDOZOv17o6RvtRSWxC77seBFc2uWtgiY=
+github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
+github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
+go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
+go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
+go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
+go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
+go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
+golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
+golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
+golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
+golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
+google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/pitr/agent/internal/cons/error.go b/pitr/agent/internal/cons/error.go
new file mode 100644
index 0000000..cb912c0
--- /dev/null
+++ b/pitr/agent/internal/cons/error.go
@@ -0,0 +1,27 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package cons
+
+import (
+	"github.com/apache/pitr/agent/pkg/xerror"
+)
+
+var (
+	Internal          = xerror.New(10000, "Internal error.")
+	InvalidHttpHeader = xerror.New(10001, "Invalid http header.")
+)
diff --git a/pitr/agent/internal/cons/http_header.go b/pitr/agent/internal/cons/http_header.go
new file mode 100644
index 0000000..17d3fa4
--- /dev/null
+++ b/pitr/agent/internal/cons/http_header.go
@@ -0,0 +1,22 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package cons
+
+const (
+	RequestID string = "request-id"
+)
diff --git a/pitr/agent/internal/handler/backup.go b/pitr/agent/internal/handler/backup.go
new file mode 100644
index 0000000..a736b6d
--- /dev/null
+++ b/pitr/agent/internal/handler/backup.go
@@ -0,0 +1,24 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package handler
+
+import "github.com/gofiber/fiber/v2"
+
+func Backup(ctx *fiber.Ctx) error {
+	return nil
+}
diff --git a/pitr/agent/internal/handler/middleware/http_header.go b/pitr/agent/internal/handler/middleware/http_header.go
new file mode 100644
index 0000000..3faa663
--- /dev/null
+++ b/pitr/agent/internal/handler/middleware/http_header.go
@@ -0,0 +1,36 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package middleware
+
+import (
+	"strings"
+
+	"github.com/gofiber/fiber/v2"
+
+	"github.com/apache/pitr/agent/internal/cons"
+	"github.com/apache/pitr/agent/pkg/responder"
+)
+
+func RequestIDChecker() fiber.Handler {
+	return func(ctx *fiber.Ctx) error {
+		if id := ctx.Get(cons.RequestID); strings.Trim(id, " ") == "" {
+			return responder.Error(ctx, cons.InvalidHttpHeader)
+		}
+		return ctx.Next()
+	}
+}
diff --git a/pitr/agent/internal/handler/middleware/logger.go b/pitr/agent/internal/handler/middleware/logger.go
new file mode 100644
index 0000000..7df23cb
--- /dev/null
+++ b/pitr/agent/internal/handler/middleware/logger.go
@@ -0,0 +1,63 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package middleware
+
+import (
+	"fmt"
+	"time"
+
+	"github.com/gofiber/fiber/v2"
+
+	"github.com/apache/pitr/agent/internal/cons"
+	"github.com/apache/pitr/agent/pkg/logging"
+)
+
+func Logger(log logging.ILog) fiber.Handler {
+	return func(ctx *fiber.Ctx) error {
+		var (
+			start = time.Now()
+		)
+		err := ctx.Next()
+		m := map[logging.FieldKey]string{
+			logging.Duration:   fmt.Sprintf("%dms", time.Since(start).Milliseconds()),
+			logging.Path:       ctx.Route().Path,
+			logging.RequestUri: string(ctx.Request().RequestURI()),
+			logging.RequestID:  ctx.Get(cons.RequestID),
+			logging.HttpStatus: fmt.Sprintf("%d", ctx.Response().StatusCode()),
+			logging.HttpMethod: ctx.Method(),
+		}
+		if err != nil {
+			m[logging.ErrorKey] = err.Error()
+		}
+		log.Fields(m).Info("logger-middleware")
+		return err
+	}
+}
+
+// AccessLog logging Access log.
+func AccessLog(log logging.ILog) fiber.Handler {
+	return func(ctx *fiber.Ctx) error {
+		log.Fields(map[logging.FieldKey]string{
+			logging.Path:       ctx.Route().Path,
+			logging.RequestUri: string(ctx.Request().RequestURI()),
+			logging.RequestID:  ctx.Get(cons.RequestID),
+			logging.HttpMethod: ctx.Method(),
+		}).Info("Access log")
+		return ctx.Next()
+	}
+}
diff --git a/pitr/agent/internal/handler/middleware/recovery.go b/pitr/agent/internal/handler/middleware/recovery.go
new file mode 100644
index 0000000..9af2638
--- /dev/null
+++ b/pitr/agent/internal/handler/middleware/recovery.go
@@ -0,0 +1,45 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package middleware
+
+import (
+	"fmt"
+	"runtime/debug"
+
+	"github.com/gofiber/fiber/v2"
+
+	"github.com/apache/pitr/agent/internal/cons"
+	"github.com/apache/pitr/agent/pkg/logging"
+	"github.com/apache/pitr/agent/pkg/responder"
+)
+
+func Recover(log logging.ILog) fiber.Handler {
+	return func(ctx *fiber.Ctx) error {
+		defer func() {
+			if r := recover(); r != nil {
+				log.Fields(map[logging.FieldKey]string{
+					logging.RequestID: ctx.Get(cons.RequestID),
+					logging.ErrorKey:  fmt.Sprint(r),
+					logging.Stack:     string(debug.Stack()),
+				}).Error("Global recover.")
+				_ = responder.Error(ctx, cons.Internal)
+			}
+		}()
+		return ctx.Next()
+	}
+}
diff --git a/pitr/agent/internal/handler/middleware/uniform_err_resp.go b/pitr/agent/internal/handler/middleware/uniform_err_resp.go
new file mode 100644
index 0000000..cbdb250
--- /dev/null
+++ b/pitr/agent/internal/handler/middleware/uniform_err_resp.go
@@ -0,0 +1,44 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package middleware
+
+import (
+	"github.com/gofiber/fiber/v2"
+
+	"github.com/apache/pitr/agent/internal/cons"
+	"github.com/apache/pitr/agent/pkg/logging"
+	"github.com/apache/pitr/agent/pkg/responder"
+	"github.com/apache/pitr/agent/pkg/xerror"
+)
+
+func UniformErrResp(log logging.ILog) fiber.Handler {
+	return func(ctx *fiber.Ctx) error {
+		err := ctx.Next()
+		if err == nil {
+			return nil
+		}
+		log.Fields(map[logging.FieldKey]string{
+			logging.ErrorKey:  err.Error(),
+			logging.RequestID: ctx.Get(cons.RequestID),
+		}).Error("UniformErrResp:an error occurred")
+		if e, b := xerror.FromError(err); b {
+			return responder.Error(ctx, e)
+		}
+		return responder.Error(ctx, cons.Internal)
+	}
+}
diff --git a/pitr/agent/internal/handler/resotre.go b/pitr/agent/internal/handler/resotre.go
new file mode 100644
index 0000000..bdf7a51
--- /dev/null
+++ b/pitr/agent/internal/handler/resotre.go
@@ -0,0 +1,24 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package handler
+
+import "github.com/gofiber/fiber/v2"
+
+func Restore(ctx *fiber.Ctx) error {
+	return nil
+}
diff --git a/pitr/agent/internal/handler/show.go b/pitr/agent/internal/handler/show.go
new file mode 100644
index 0000000..e92efd7
--- /dev/null
+++ b/pitr/agent/internal/handler/show.go
@@ -0,0 +1,24 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package handler
+
+import "github.com/gofiber/fiber/v2"
+
+func Show(ctx *fiber.Ctx) error {
+	return nil
+}
diff --git a/pitr/agent/internal/pkg/opengauss.go b/pitr/agent/internal/pkg/opengauss.go
new file mode 100644
index 0000000..f68e726
--- /dev/null
+++ b/pitr/agent/internal/pkg/opengauss.go
@@ -0,0 +1,18 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package pkg
diff --git a/pitr/agent/internal/pkg/pkg_test.go b/pitr/agent/internal/pkg/pkg_test.go
new file mode 100644
index 0000000..4085223
--- /dev/null
+++ b/pitr/agent/internal/pkg/pkg_test.go
@@ -0,0 +1,30 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package pkg
+
+import (
+	"testing"
+
+	. "github.com/onsi/ginkgo/v2"
+	. "github.com/onsi/gomega"
+)
+
+func TestPkg(t *testing.T) {
+	RegisterFailHandler(Fail)
+	RunSpecs(t, "Pkg suit")
+}
diff --git a/pitr/agent/main.go b/pitr/agent/main.go
new file mode 100644
index 0000000..9ce1a7e
--- /dev/null
+++ b/pitr/agent/main.go
@@ -0,0 +1,136 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package main
+
+import (
+	"flag"
+	"fmt"
+	"os"
+	"os/signal"
+	"syscall"
+
+	"github.com/apache/pitr/agent/internal/handler"
+
+	"github.com/apache/pitr/agent/internal/handler/middleware"
+	"github.com/apache/pitr/agent/pkg/responder"
+
+	"github.com/gofiber/fiber/v2"
+	"go.uber.org/zap"
+	"go.uber.org/zap/zapcore"
+
+	"github.com/apache/pitr/agent/pkg/logging"
+)
+
+const (
+	debugLogLevel = "debug"
+)
+
+var (
+	app *fiber.App
+	log logging.ILog
+)
+
+var (
+	logLevel string
+	port     string
+)
+
+func init() {
+	// TODO 参数全部通过 flag 输入
+	flag.StringVar(&logLevel, "logLevel", "info", "optional:log level,option values:info or debug,info is default")
+	flag.StringVar(&port, "port", "8888", "optional:8888 is default")
+}
+
+func main() {
+	flag.Parse()
+
+	var level = zapcore.InfoLevel
+	if logLevel == debugLogLevel {
+		level = zapcore.DebugLevel
+	}
+
+	prodConfig := zap.NewProductionConfig()
+	prodConfig.EncoderConfig.EncodeTime = zapcore.RFC3339TimeEncoder
+	prodConfig.Level = zap.NewAtomicLevelAt(level)
+	logger, err := prodConfig.Build(
+		zap.AddCallerSkip(1),
+		zap.AddStacktrace(zapcore.FatalLevel),
+	)
+	if err != nil {
+		panic(fmt.Errorf("an unknown error occured in the zap-log"))
+	}
+
+	log = logging.Init(logger)
+	app = fiber.New()
+
+	go func() {
+		if err := Serve(port); err != nil {
+			panic(err)
+		}
+	}()
+	log.Info("app startup successfully.")
+
+	quit := make(chan os.Signal, 1)
+	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
+	<-quit
+
+	WindUp()
+	log.Info("app has exited...")
+}
+
+// Serve run an http server on the specified port.
+func Serve(port string) error {
+	app.Use(
+		middleware.Recover(logging.Log()),
+		middleware.UniformErrResp(logging.Log()),
+	)
+
+	app.Get("/ping", func(ctx *fiber.Ctx) error {
+		return responder.Success(ctx, "pong")
+	})
+
+	app.Use(
+		middleware.AccessLog(logging.Log()),
+		middleware.Logger(logging.Log()),
+	)
+
+	app.Route("/api", func(r fiber.Router) {
+		r.Use(middleware.RequestIDChecker())
+
+		r.Post("/backup", handler.Backup)
+		r.Post("/restore", handler.Restore)
+		r.Post("/show", handler.Show)
+	})
+
+	// 404
+	app.Use(func(ctx *fiber.Ctx) error {
+		return responder.NotFound(ctx, "API not found")
+	})
+
+	return app.Listen(fmt.Sprintf(":%s", port))
+}
+
+func WindUp() {
+	if app != nil {
+		if err := app.Shutdown(); err != nil {
+			log.Field(logging.ErrorKey, err.Error()).Error("http app closed failure")
+		}
+	}
+
+	log.Info("app windup successfully.")
+}
diff --git a/pitr/agent/pkg/logging/field.go b/pitr/agent/pkg/logging/field.go
new file mode 100644
index 0000000..2119278
--- /dev/null
+++ b/pitr/agent/pkg/logging/field.go
@@ -0,0 +1,46 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package logging
+
+type ILog interface {
+	Field(k FieldKey, v string) ILog
+	Fields(m map[FieldKey]string) ILog
+
+	Debug(s string)
+	Info(s string)
+	Warn(s string)
+	Error(s string)
+	Panic(s string)
+}
+
+type FieldKey string
+
+func (f FieldKey) String() string {
+	return string(f)
+}
+
+const (
+	ErrorKey   FieldKey = "error"
+	RequestID  FieldKey = "requestID"
+	Stack      FieldKey = "stack"
+	Duration   FieldKey = "duration"
+	Path       FieldKey = "path"       // original routing path
+	RequestUri FieldKey = "requestUri" // http requesting uri
+	HttpMethod FieldKey = "httpMethod"
+	HttpStatus FieldKey = "httpStatus"
+)
diff --git a/pitr/agent/pkg/logging/log.go b/pitr/agent/pkg/logging/log.go
new file mode 100644
index 0000000..b2d2209
--- /dev/null
+++ b/pitr/agent/pkg/logging/log.go
@@ -0,0 +1,69 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package logging
+
+import "go.uber.org/zap"
+
+var l *ZapLogger
+
+func Log() ILog {
+	return l
+}
+
+func Init(logger *zap.Logger) ILog {
+	l = &ZapLogger{logger: logger}
+	return l
+}
+
+func Field(k FieldKey, v string) ILog {
+	m := map[FieldKey]string{k: v}
+	for k, v := range l.fields {
+		m[k] = v
+	}
+	return &ZapLogger{logger: l.logger, fields: m}
+}
+
+func Fields(m map[FieldKey]string) ILog {
+	if m == nil {
+		m = map[FieldKey]string{}
+	}
+	for k, v := range l.fields {
+		m[k] = v
+	}
+	return &ZapLogger{logger: l.logger, fields: m}
+}
+
+func Debug(s string) {
+	l.logger.Debug(s, fields(l)...)
+}
+
+func Info(s string) {
+	l.logger.Info(s, fields(l)...)
+}
+
+func Warn(s string) {
+	l.logger.Warn(s, fields(l)...)
+}
+
+func Error(s string) {
+	l.logger.Error(s, fields(l)...)
+}
+
+func Panic(s string) {
+	l.logger.Panic(s, fields(l)...)
+}
diff --git a/pitr/agent/pkg/logging/zap_log.go b/pitr/agent/pkg/logging/zap_log.go
new file mode 100644
index 0000000..cfda378
--- /dev/null
+++ b/pitr/agent/pkg/logging/zap_log.go
@@ -0,0 +1,82 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package logging
+
+import (
+	"go.uber.org/zap"
+	"go.uber.org/zap/zapcore"
+)
+
+type ZapLogger struct {
+	fields map[FieldKey]string
+	logger *zap.Logger
+}
+
+func NewLog(l *zap.Logger) ILog {
+	return &ZapLogger{logger: l}
+}
+
+func (z *ZapLogger) Field(k FieldKey, v string) ILog {
+	m := map[FieldKey]string{k: v}
+	for k, v := range z.fields {
+		m[k] = v
+	}
+	return &ZapLogger{logger: z.logger, fields: m}
+}
+
+func (z *ZapLogger) Fields(m map[FieldKey]string) ILog {
+	if m == nil {
+		m = map[FieldKey]string{}
+	}
+	for k, v := range z.fields {
+		m[k] = v
+	}
+	return &ZapLogger{logger: z.logger, fields: m}
+}
+
+func (z *ZapLogger) Debug(s string) {
+	z.logger.Debug(s, fields(z)...)
+}
+
+func (z *ZapLogger) Info(s string) {
+	z.logger.Info(s, fields(z)...)
+}
+
+func (z *ZapLogger) Warn(s string) {
+	z.logger.Warn(s, fields(z)...)
+}
+
+func (z *ZapLogger) Error(s string) {
+	z.logger.Error(s, fields(z)...)
+}
+
+func (z *ZapLogger) Panic(s string) {
+	z.logger.Panic(s, fields(z)...)
+}
+
+func fields(z *ZapLogger) []zap.Field {
+	fields := make([]zap.Field, 0, len(z.fields))
+	for k, v := range z.fields {
+		fields = append(fields, zap.Field{
+			Key:    k.String(),
+			Type:   zapcore.StringType,
+			String: v,
+		})
+	}
+	return fields
+}
diff --git a/pitr/agent/pkg/responder/resp.go b/pitr/agent/pkg/responder/resp.go
new file mode 100644
index 0000000..652fd90
--- /dev/null
+++ b/pitr/agent/pkg/responder/resp.go
@@ -0,0 +1,95 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package responder
+
+import (
+	"net/http"
+
+	"github.com/gofiber/fiber/v2"
+
+	"github.com/apache/pitr/agent/pkg/xerror"
+)
+
+var (
+	unknownErrCode = -1
+	unknownErrMsg  = "Unknown error"
+
+	successCode = 0
+	successMsg  = "Success"
+)
+
+type resp struct {
+	Code int    `json:"code" validate:"required"`
+	Msg  string `json:"msg" validate:"required"`
+	Data any    `json:"data"`
+}
+
+func Success(ctx *fiber.Ctx, data any) error {
+	ctx.Status(http.StatusOK)
+	return ctx.JSON(&resp{
+		Code: successCode,
+		Msg:  successMsg,
+		Data: data,
+	})
+}
+
+func Error(ctx *fiber.Ctx, e error) error {
+	if e == nil {
+		return xerror.New(unknownErrCode, unknownErrMsg)
+	}
+	ctx.Status(http.StatusOK)
+	err, ok := xerror.FromError(e)
+	if ok {
+		return ctx.JSON(&resp{
+			Code: err.Code,
+			Msg:  err.Msg,
+		})
+	}
+	return ctx.JSON(&resp{
+		Code: unknownErrCode,
+		Msg:  unknownErrMsg,
+	})
+}
+
+func ErrorWitData(ctx *fiber.Ctx, e error, data any) error {
+	if e == nil {
+		return xerror.New(unknownErrCode, unknownErrMsg)
+	}
+	ctx.Status(http.StatusOK)
+
+	if err, ok := xerror.FromError(e); ok {
+		return ctx.JSON(&resp{
+			Code: err.Code,
+			Msg:  err.Msg,
+			Data: data,
+		})
+	}
+	return ctx.JSON(&resp{
+		Code: unknownErrCode,
+		Msg:  unknownErrMsg,
+		Data: data,
+	})
+}
+
+func NotFound(ctx *fiber.Ctx, msg string) error {
+	ctx.Status(http.StatusNotFound)
+	return ctx.JSON(&resp{
+		Code: successCode,
+		Msg:  msg,
+	})
+}
diff --git a/pitr/agent/pkg/strutil/rand_string.go b/pitr/agent/pkg/strutil/rand_string.go
new file mode 100644
index 0000000..769b7b7
--- /dev/null
+++ b/pitr/agent/pkg/strutil/rand_string.go
@@ -0,0 +1,58 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package strutil
+
+import (
+	"math/rand"
+	"strconv"
+	"time"
+)
+
+const (
+	charSet  = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+	charSize = len(charSet)
+)
+
+const (
+	digitSet  = "1234567890"
+	digitSize = len(digitSet)
+)
+
+func Random(n uint) string {
+	rand.Seed(time.Now().UnixNano())
+	bs := make([]byte, 0, n)
+	for i := uint(0); i < n; i++ {
+		bs = append(bs, charSet[rand.Intn(charSize)])
+	}
+	return string(bs)
+}
+
+func RandomInt(n uint) int64 {
+	rand.Seed(time.Now().UnixNano())
+	bs := make([]byte, 0, n)
+	bs = append(bs, digitSet[rand.Intn(digitSize-1)])
+	for i := uint(0); i < n-1; i++ {
+		bs = append(bs, digitSet[rand.Intn(digitSize)])
+	}
+	v, _ := strconv.ParseInt(string(bs), 10, 64)
+	return v
+}
+
+func RandomUint(n uint) uint64 {
+	return uint64(RandomInt(n))
+}
diff --git a/pitr/agent/pkg/strutil/rand_string_test.go b/pitr/agent/pkg/strutil/rand_string_test.go
new file mode 100644
index 0000000..f2e3720
--- /dev/null
+++ b/pitr/agent/pkg/strutil/rand_string_test.go
@@ -0,0 +1,34 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package strutil
+
+import "testing"
+
+func TestRandom(t *testing.T) {
+	one, two := Random(20), Random(20)
+	if one == two {
+		t.Fail()
+	}
+}
+
+func TestRandomInt(t *testing.T) {
+	one, two := RandomInt(9), RandomInt(9)
+	if one == two {
+		t.Fail()
+	}
+}
diff --git a/pitr/agent/pkg/strutil/strutil_test.go b/pitr/agent/pkg/strutil/strutil_test.go
new file mode 100644
index 0000000..50a2a74
--- /dev/null
+++ b/pitr/agent/pkg/strutil/strutil_test.go
@@ -0,0 +1,30 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package strutil
+
+import (
+	"testing"
+
+	. "github.com/onsi/ginkgo/v2"
+	. "github.com/onsi/gomega"
+)
+
+func TestStrUtil(t *testing.T) {
+	RegisterFailHandler(Fail)
+	RunSpecs(t, "String util suit")
+}
diff --git a/pitr/agent/pkg/syncutils/recover_func.go b/pitr/agent/pkg/syncutils/recover_func.go
new file mode 100644
index 0000000..75bcc89
--- /dev/null
+++ b/pitr/agent/pkg/syncutils/recover_func.go
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package syncutils
+
+import (
+	"fmt"
+
+	"github.com/apache/pitr/agent/pkg/logging"
+)
+
+func NewRecoverFuncWithErrRet(msg string, log logging.ILog, fn func() error) func() error {
+	return func() error {
+		defer func() {
+			r := recover()
+			if r != nil {
+				if err, ok := r.(error); ok {
+					log.Error(fmt.Sprintf("NewRecoverFuncWithErrRet[msg=%s],err=%s", msg, err))
+				} else {
+					log.Error(fmt.Sprintf("NewRecoverFuncWithErrRet[msg=%s],recover msg=%+v", msg, r))
+				}
+			}
+		}()
+
+		return fn()
+	}
+}
diff --git a/pitr/agent/pkg/xerror/error.go b/pitr/agent/pkg/xerror/error.go
new file mode 100644
index 0000000..db3e919
--- /dev/null
+++ b/pitr/agent/pkg/xerror/error.go
@@ -0,0 +1,47 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package xerror
+
+import (
+	"errors"
+	"fmt"
+)
+
+type xerr struct {
+	Code int
+	Msg  string
+}
+
+func New(code int, msg string) error {
+	return &xerr{
+		Code: code,
+		Msg:  msg,
+	}
+}
+
+func (e *xerr) Error() string {
+	return fmt.Sprintf("%d-%s", e.Code, e.Msg)
+}
+
+func FromError(err error) (*xerr, bool) {
+	var e *xerr
+	if errors.As(err, &e) {
+		return e, true
+	}
+	return nil, false
+}
diff --git a/pitr/agent/pkg/xerror/error_test.go b/pitr/agent/pkg/xerror/error_test.go
new file mode 100644
index 0000000..30089f7
--- /dev/null
+++ b/pitr/agent/pkg/xerror/error_test.go
@@ -0,0 +1,50 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package xerror
+
+import (
+	"errors"
+	"fmt"
+	"testing"
+)
+
+func TestFromError(t *testing.T) {
+	var e error
+	_, b := FromError(e)
+	if b {
+		t.Fail()
+	}
+
+	e = errors.New("error type")
+	_, b = FromError(e)
+	if b {
+		t.Fail()
+	}
+
+	daoErr := fmt.Errorf("xerror:%w", errors.New("not found"))
+	serviceErr := fmt.Errorf("xerror:%s,wrap=%w", daoErr, &xerr{Code: 999})
+	_, b = FromError(serviceErr)
+	if !b {
+		t.Fail()
+	}
+
+	_, b = FromError(serviceErr)
+	if !b {
+		t.Fail()
+	}
+}