From 5ed2744cacc202d95b8c8b455c900795664ac83f Mon Sep 17 00:00:00 2001 From: eeliu <27064129+eeliu@users.noreply.github.com> Date: Thu, 10 Oct 2024 13:55:51 +0800 Subject: [PATCH] Async API for CXX plugins (#686) [spanChunk ] common library - pack pinpoint-common - add cpp example - add get depth - remove unused code - fixed CI - test_pinpoint.cpp and test_pinpoint.c - common library support spanChunk - rename calls to fols - add thread_local pool - support "Async Invocation .." - testapps/cpp example --- .dockerignore | 3 +- .github/workflows/main.yml | 2 +- .github/workflows/release.yml | 14 +- DOC/C-CPP/Readme.md | 15 +- README.md | 1 + collector-agent/1.cap | Bin 0 -> 693 bytes collector-agent/Dockerfile | 2 +- collector-agent/agent/AgentRouter.go | 68 +- collector-agent/agent/AgentRouter_test.go | 47 +- collector-agent/agent/ErrorAnalysis.go | 64 +- collector-agent/agent/ErrorAnalysis_test.go | 9 +- collector-agent/agent/Filter.go | 1 + collector-agent/agent/GrpcAgent.go | 592 ++++++++++-------- collector-agent/agent/GrpcAgent_test.go | 126 ++++ collector-agent/agent/RequestCounter.go | 48 +- collector-agent/agent/RequestCounter_test.go | 6 +- collector-agent/agent/SpanSender.go | 291 +++++---- collector-agent/agent/SpanSender_test.go | 8 +- collector-agent/agent/Stat.go | 80 --- collector-agent/agent/UrlTemplate.go | 2 + collector-agent/agent/UrlTemplate_test.go | 11 +- collector-agent/agent/spanChunk.yaml | 42 ++ collector-agent/common/Defines.go | 20 +- collector-agent/common/Utils.go | 26 +- collector-agent/common/config.go | 199 +++--- collector-agent/go.mod | 2 +- collector-agent/server.go | 103 ++- collector-agent/server/Server.go | 309 +++++++++ collector-agent/server/ServerEnv.go | 118 ---- collector-agent/server/SpanServer.go | 316 ---------- collector-agent/server/server_test.go | 87 +-- collector-agent/server/setting.go | 11 - collector-agent/start-collector-agent.sh | 26 +- common/CHANGES.md | 6 + common/CMakeLists.txt | 8 +- common/LICENSE | 201 ++++++ common/include/common.h | 37 +- common/include/common.h.in | 43 +- common/readme.md | 5 - .../src/ConnectionPool/SpanConnectionPool.h | 1 - common/src/ConnectionPool/TransLayer.cpp | 18 +- common/src/ConnectionPool/TransLayer.h | 12 +- common/src/ConnectionPool/test_trans_layer.cc | 3 +- common/src/Logging.cpp | 6 +- common/src/NodePool/PoolManager.cpp | 128 ++-- common/src/NodePool/PoolManager.h | 132 ++-- common/src/NodePool/TraceNode.cpp | 123 ++-- common/src/NodePool/TraceNode.h | 279 ++++----- common/src/NodePool/test_node.cc | 366 ++++------- common/src/NodePool/test_node_pool.cc | 71 --- common/src/common.cpp | 230 ++++--- common/src/test_common.cc | 246 +++++++- common/src/test_util.cc | 13 +- common/test/test_main.cpp | 2 +- php_pinpoint_php.h | 5 +- pinpoint_php.cpp | 97 ++- plugins/PY/pinpointPy/__init__.py | 2 +- plugins/PY/pinpointPy/pinpoint.py | 8 + setup.py | 4 +- src/CPP/CMakeLists.txt | 26 +- src/CPP/pinpoint_define.h | 90 +-- src/CPP/test_pinpoint.c | 74 ++- src/CPP/test_pinpoint.cpp | 152 +++-- src/PY/_pinpoint_py.cpp | 25 +- src/PY/test/testPinpoint.py | 4 + src/PY/test/testUnderThreadMode.py | 3 + testapps/.dockerignore | 4 +- testapps/SimplePHP/kafka_consumer.php | 57 ++ testapps/SimplePHP/php.ini | 3 + testapps/SimplePHP/run.php | 35 +- testapps/SimplePHP/run_all.sh | 7 + testapps/SimplePHP/simplephp.dockerfile | 26 +- testapps/SimplePHP/src/MessageHandler.php | 11 + testapps/compose.yaml | 65 +- testapps/cpp/CMakeLists.txt | 24 + testapps/cpp/cpp.dockerfile | 10 + testapps/cpp/image.png | Bin 0 -> 81549 bytes testapps/cpp/pinpoint_define.h | 82 +++ testapps/cpp/pinpoint_helper.h | 113 ++++ testapps/cpp/readme.md | 37 ++ testapps/cpp/server.cpp | 98 +++ tests/add_root_trace.phpt | 28 +- tests/app_info_test.phpt | 2 +- tests/drop_trace_test.phpt | 12 +- tests/mark_as_error.phpt | 14 +- tests/node_test.phpt | 16 +- tests/pinpoint_get_caller_arg.phpt | 14 +- tests/pinpoint_get_this.phpt | 4 +- tests/pinpoint_join_cut_curl_7.phpt | 119 ++-- tests/pinpoint_join_cut_curl_8.phpt | 116 ++-- tests/pinpoint_join_cut_extend_pdo.phpt | 20 +- tests/pinpoint_join_cut_mysqli.phpt | 28 +- tests/pinpoint_join_cut_pdo.phpt | 44 +- tests/pinpoint_join_cut_pdo_8.phpt | 44 +- tests/pinpoint_join_cut_redis.phpt | 192 +++--- tests/stack_fetal_error.phpt | 22 +- tests/trace_api_context.phpt | 26 +- tests/trace_api_context_tcp.phpt | 30 +- tests/trace_api_test.phpt | 116 ++-- tests/trace_api_with_id.phpt | 36 +- tests/trace_had_root.phpt | 40 ++ tests/trace_limit_test-i448.phpt | 16 +- tests/trace_limit_test.phpt | 2 +- tests_macos/add_root_trace.phpt | 26 +- tests_macos/aop_helper_api.phpt | 194 ------ tests_macos/drop_trace_test.phpt | 12 +- tests_macos/mark_as_error.phpt | 12 +- tests_macos/node_test.phpt | 16 +- tests_macos/pinpoint_get_caller_arg.phpt | 14 +- tests_macos/pinpoint_get_this.phpt | 4 +- tests_macos/pinpoint_join_cut_curl_7.phpt | 122 ++-- tests_macos/pinpoint_join_cut_curl_8.phpt | 118 ++-- tests_macos/pinpoint_join_cut_extend_pdo.phpt | 24 +- tests_macos/pinpoint_join_cut_mysqli.phpt | 30 +- tests_macos/pinpoint_join_cut_pdo.phpt | 44 +- tests_macos/pinpoint_join_cut_pdo_8.phpt | 44 +- tests_macos/pinpoint_join_cut_redis.phpt | 193 +++--- tests_macos/stack_fetal_error.phpt | 20 +- tests_macos/trace_api_context.phpt | 70 +++ tests_macos/trace_api_context_tcp.phpt | 26 +- tests_macos/trace_api_test.phpt | 116 ++-- tests_macos/trace_api_with_id.phpt | 34 +- tests_macos/trace_had_root.phpt | 40 ++ tests_macos/trace_limit_test-i448.phpt | 16 +- tests_macos/trace_limit_test.phpt | 2 +- tests_win32/add_root_trace.phpt | 28 +- tests_win32/aop_helper_api.phpt | 194 ------ tests_win32/drop_trace_test.phpt | 12 +- tests_win32/mark_as_error.phpt | 14 +- tests_win32/node_test.phpt | 16 +- tests_win32/pinpoint_get_caller_arg.phpt | 14 +- tests_win32/pinpoint_get_this.phpt | 4 +- tests_win32/pinpoint_join_cut_curl_7.phpt | 6 +- tests_win32/pinpoint_join_cut_curl_8.phpt | 119 ++-- tests_win32/pinpoint_join_cut_mysqli.phpt | 34 +- tests_win32/pinpoint_join_cut_pdo_8.phpt | 46 +- tests_win32/pinpoint_join_cut_redis.phpt | 200 +++--- tests_win32/stack_fetal_error.phpt | 22 +- tests_win32/trace_api_context_tcp.phpt | 27 +- tests_win32/trace_api_test.phpt | 116 ++-- tests_win32/trace_api_with_id.phpt | 36 +- tests_win32/trace_had_root.phpt | 40 ++ tests_win32/trace_limit_test-i448.phpt | 16 +- tests_win32/trace_limit_test.phpt | 2 +- 144 files changed, 4860 insertions(+), 3845 deletions(-) create mode 100644 collector-agent/1.cap create mode 100644 collector-agent/agent/GrpcAgent_test.go delete mode 100644 collector-agent/agent/Stat.go create mode 100644 collector-agent/agent/spanChunk.yaml create mode 100644 collector-agent/server/Server.go delete mode 100644 collector-agent/server/ServerEnv.go delete mode 100644 collector-agent/server/SpanServer.go delete mode 100644 collector-agent/server/setting.go create mode 100644 common/LICENSE delete mode 100644 common/src/NodePool/test_node_pool.cc create mode 100644 testapps/SimplePHP/kafka_consumer.php create mode 100644 testapps/SimplePHP/run_all.sh create mode 100644 testapps/SimplePHP/src/MessageHandler.php create mode 100644 testapps/cpp/CMakeLists.txt create mode 100644 testapps/cpp/cpp.dockerfile create mode 100644 testapps/cpp/image.png create mode 100644 testapps/cpp/pinpoint_define.h create mode 100644 testapps/cpp/pinpoint_helper.h create mode 100644 testapps/cpp/readme.md create mode 100644 testapps/cpp/server.cpp create mode 100644 tests/trace_had_root.phpt delete mode 100644 tests_macos/aop_helper_api.phpt create mode 100644 tests_macos/trace_api_context.phpt create mode 100644 tests_macos/trace_had_root.phpt delete mode 100644 tests_win32/aop_helper_api.phpt create mode 100644 tests_win32/trace_had_root.phpt diff --git a/.dockerignore b/.dockerignore index 92aacae52..a419b9b58 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,4 @@ .* **/__pycache__ -CollectorAgent \ No newline at end of file +CollectorAgent +**/build/ \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2a69beaa8..4e098935a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -284,7 +284,7 @@ jobs: Collector-agent: strategy: matrix: - go-version: [1.18.x] + go-version: [1.19.x] os: [ubuntu-latest,windows-latest,macos-latest] runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8921ba83a..7677bede5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,7 +21,7 @@ jobs: md5=($(md5sum ${{ env.MODULE_PAK }} )) PACK_NAME=${{ env.MODULE_PAK }}-${md5}-$(date '+%Y-%m-%d').tar.gz mv ${{ env.MODULE_PAK }} $PACK_NAME - echo "PACK=$PACK_NAME" >> $GITHUB_OUTPUT + echo "PACK=$PACK_NAME" >> $GITHUB_OUTPUT - name: Release php_package id: rel_php_pak uses: softprops/action-gh-release@v2 @@ -39,4 +39,14 @@ jobs: uses: softprops/action-gh-release@v2 if: startsWith(github.ref, 'refs/tags/') with: - files: install_pinpoint_php.sh \ No newline at end of file + files: install_pinpoint_php.sh + + - name: pack pinpoint-common + run: | + tar zcvf pinpoint-common.tar.gz common + + - name: Release pinpoint-common + uses: softprops/action-gh-release@v2 + if: startsWith(github.ref, 'refs/tags/') + with: + files: pinpoint-common.tar.gz \ No newline at end of file diff --git a/DOC/C-CPP/Readme.md b/DOC/C-CPP/Readme.md index 747af1979..98f780e98 100644 --- a/DOC/C-CPP/Readme.md +++ b/DOC/C-CPP/Readme.md @@ -7,20 +7,11 @@ While, check examples `src/CPP/test_pinpoint.cpp` and `src/CPP/test_pinpoint.c`. | Dependency | Version | | ---------- | ---------- | -| cmake | 3.2+ | -| GCC | GCC `4.7+` | +| cmake | 3.15+ | +| GCC | GCC `4.9` | +| CPP | with `std=c++11` | -#### Build ->@obsoleted -Use CMake `add_subdirectory`; -[CMakeLists.txt example](../../src/CPP/CMakeLists.txt) - -``` -$ mkdir build -$ cd build -$ cmake .. && make -``` #### Integrate in your own project > Use cmake FetchContent diff --git a/README.md b/README.md index e0a62b2df..f433a8439 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ **Visit [our official website](http://pinpoint-apm.github.io/pinpoint/) for more information and [the Latest updates on Pinpoint](https://pinpoint-apm.github.io/pinpoint/news.html)** +> [v0.7](https://github.com/pinpoint-apm/pinpoint-c-agent/tree/v0.7) async api version # Pinpoint `C` Agent diff --git a/collector-agent/1.cap b/collector-agent/1.cap new file mode 100644 index 0000000000000000000000000000000000000000..bfd93f5b592ce09a980d822e3e84dccff1fa4bc5 GIT binary patch literal 693 zcmca|c+)~A1{MYcU}0bcaw6Q=((ed!GI#;mAdCz+7+e_`Y_=#mFgUPv%&2EzU0e;VCnkm)d!zXMHn0@?(^$N=nSlPyYMH_wNe40UrH(DbGT0Valj z8bCKPLfi{7735Y%aZZMbK%+ny8Gub}&U*tg@oXE+M5tSvKyGc20Ge11H}NAZ6o96< zS1TnJ6lA6-St;e^E9rnZd5O8HFm6dEm~CioWMN`vVq$J&YH12oRhC**oSB~oR8?l6 zXQpSOR10#TG|+)~ysQlN@;sOWk-U5n&C4JMevAg1sQ8l^kBND2!Ct-sGZE_Li(oGc gA_rnZ6wE{`ye4i@0lRT7%tRzNUTP3QH!&d!0Flp?ApigX literal 0 HcmV?d00001 diff --git a/collector-agent/Dockerfile b/collector-agent/Dockerfile index 51edae974..16e033b52 100644 --- a/collector-agent/Dockerfile +++ b/collector-agent/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.18-alpine3.17 as builder +FROM golang:1.19-alpine3.17 as builder WORKDIR /apps USER root RUN apk add --no-cache make protobuf-dev git diff --git a/collector-agent/agent/AgentRouter.go b/collector-agent/agent/AgentRouter.go index 00a530518..aa0d0736c 100644 --- a/collector-agent/agent/AgentRouter.go +++ b/collector-agent/agent/AgentRouter.go @@ -11,7 +11,7 @@ import ( "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/common" - log "github.com/sirupsen/logrus" + "github.com/sirupsen/logrus" ) type RawPacket struct { @@ -27,13 +27,25 @@ type I_PacketRouter interface { type AgentRouter struct { AgentMap map[string]*GrpcAgent PingId int32 - Quit chan bool - WG *sync.WaitGroup rwMutex sync.RWMutex + Config *common.Config + Log *logrus.Logger +} + +func CreateAgentRouter(config *common.Config) *AgentRouter { + router := &AgentRouter{ + PingId: 1, + AgentMap: make(map[string]*GrpcAgent), + Config: config, + Log: config.Log, + } + return router } type TSpanEvent struct { Name string `json:"name"` + Sequence int32 `json:":seq"` + Depth int32 `json:":depth"` ExceptionInfo string `json:"EXP,omitempty"` ExceptionInfoV2 *TExceptionInfo `json:"EXP_V2,omitempty"` DestinationId string `json:"dst,omitempty"` @@ -44,9 +56,9 @@ type TSpanEvent struct { StartElapsedV2 int32 `json:":S"` EndElapsedV2 int32 `json:":E"` ServiceType int32 `json:"stp,string"` - Clues []string `json:"clues,omitempty"` - Calls []*TSpanEvent `json:"calls,omitempty"` - SqlMeta string `json:"SQL,omitempty"` + Annotations []string `json:"anno,omitempty"` + SqlMeta *string `json:"SQL,omitempty"` + AsyId int32 `json:"asyId,string,omitempty"` } func (spanEv *TSpanEvent) GetEndElapsed() int32 { @@ -77,6 +89,11 @@ type TExceptionInfo struct { StartTime int64 `json:":S"` } +type TAsyncId struct { + AsyncId int32 `json:"id"` + Sequence int32 `json:"seq"` +} + type TSpan struct { AppServerType int32 `json:"FT"` AppServerTypeV2 int32 `json:":FT"` @@ -91,8 +108,8 @@ type TSpan struct { AppIdV2 string `json:":appid"` AppName string `json:"appname"` AppNameV2 string `json:":appname"` - Calls []*TSpanEvent `json:"calls"` - Clues []string `json:"clues,omitempty"` + Follows []*TSpanEvent `json:"event"` + Annotations []string `json:"anno,omitempty"` SpanName string `json:"name"` SpanId int64 `json:"sid,string"` ServerType int32 `json:"stp,string"` @@ -108,6 +125,7 @@ type TSpan struct { ErrorMarked int32 `json:"EA,omitempty"` NginxHeader string `json:"NP,omitempty"` ApacheHeader string `json:"AP,omitempty"` + LocalAsyncId *TAsyncId `json:"asy,omitempty"` } func (span *TSpan) IsFailed() bool { @@ -117,7 +135,7 @@ func (span *TSpan) IsFailed() bool { return false } -//note +// note // FindHistogramLevel must come with histogramSize func (span *TSpan) FindHistogramLevel() int { if span.GetElapsedTime() <= 100 { @@ -180,12 +198,11 @@ func (span *TSpan) GetAppName() string { } func (manager *AgentRouter) Clean() { - config := common.GetConfig() ctime := time.Now().Unix() manager.rwMutex.RLock() for id, agent := range manager.AgentMap { - if agent.GetLastBusyTime()+int64(config.AgentFreeOnlineSurvivalTimeSec) < ctime { - log.Warnf("agent:%s expired after:%d sec. busyTime:%d", agent, config.AgentFreeOnlineSurvivalTimeSec, agent.GetLastBusyTime()) + if agent.GetLastBusyTime()+int64(manager.Config.AgentReTryTimeout) < ctime { + manager.Log.Warnf("agent:%s expired after:%d sec. busyTime:%d", agent, manager.Config.AgentReTryTimeout, agent.GetLastBusyTime()) manager.rwMutex.RUnlock() manager.rwMutex.Lock() delete(manager.AgentMap, id) @@ -198,13 +215,13 @@ func (manager *AgentRouter) Clean() { manager.rwMutex.RUnlock() } -func GetAgentInfo(span *TSpan) (appid, name string, appServerType int32, startTime string, err error) { +func (manager *AgentRouter) 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" + startTime = strconv.FormatInt(manager.Config.StartTime, 10) + "000" holder := strings.Split(span.TransactionId, "^") if len(holder) < 3 { - log.Warn("tid in wrong format") + manager.Log.Warn("tid in wrong format") } else if len(holder[1]) <= 10 { // seconds format startTime = holder[1] + "000" } else { // milliseconds format @@ -240,33 +257,34 @@ func (manager *AgentRouter) DispatchPacket(packet *RawPacket) error { } if err := json.Unmarshal(packet.RawData, span); err != nil { - log.Warnf("json.Unmarshal err:%v", err) + manager.Log.Warnf("json.Unmarshal err:%v", err) goto PACKET_INVALID } - if appid, appName, serverType, startTime, err := GetAgentInfo(span); err == nil { + if appid, appName, serverType, startTime, err := manager.GetAgentInfo(span); err == nil { manager.rwMutex.RLock() - log.Debug("Read-lock is holding") + manager.Log.Debug("Read-lock is holding") agent, OK := manager.AgentMap[appid] if !OK { // create a new agent manager.rwMutex.RUnlock() - log.Infof("agent:%s not find, create a new agent.", appid) - log.Debug("Try to get write-lock") + manager.Log.Infof("agent:%s not find, create a new agent.", appid) + manager.Log.Debug("Try to get write-lock") manager.rwMutex.Lock() - log.Debug("Write-lock is holding") + manager.Log.Debug("Write-lock is holding") if _t, OK := manager.AgentMap[appid]; OK { agent = _t } else { - agent = createGrpcAgent(appid, appName, serverType, manager.PingId, startTime) + agent = CreateGrpcAgent(appid, appName, serverType, manager.PingId, startTime, manager.Config) + agent.StartServe() manager.PingId += 1 } manager.AgentMap[appid] = agent manager.rwMutex.Unlock() - log.Debug("Write-lock is release") + manager.Log.Debug("Write-lock is release") } else { manager.rwMutex.RUnlock() - log.Debug("Read-lock is release") + manager.Log.Debug("Read-lock is release") } agent.CheckValid(span) @@ -274,7 +292,7 @@ func (manager *AgentRouter) DispatchPacket(packet *RawPacket) error { return nil } else { - log.Warn(err) + manager.Log.Warn(err) return err } diff --git a/collector-agent/agent/AgentRouter_test.go b/collector-agent/agent/AgentRouter_test.go index a281ace91..6b85ccf00 100644 --- a/collector-agent/agent/AgentRouter_test.go +++ b/collector-agent/agent/AgentRouter_test.go @@ -1,20 +1,15 @@ package agent import ( + "context" "encoding/json" "testing" + "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/common" "google.golang.org/grpc/metadata" ) func TestGetAgentInfo(t *testing.T) { - // spanMap := map[string]interface{}{ - // "appid": "sfdaefe", - // "appname": "sfdaefe", - // "FT": float64(23412), - // "tid": "234123424^41234^2333", - // } - spanMap := &TSpan{ AppId: "sfdaefe", AppName: "sfdaefe", @@ -23,7 +18,9 @@ func TestGetAgentInfo(t *testing.T) { TransactionId: "234123424^41234^2333", } - id, name, ft, startTime, err := GetAgentInfo(spanMap) + router := CreateAgentRouter(common.CreateTestConfig()) + + id, name, ft, startTime, err := router.GetAgentInfo(spanMap) if id != "sfdaefe" && name != "sfdaefe" && ft != 23412 && startTime != "234123424" && err != nil { t.Error(spanMap) @@ -48,7 +45,8 @@ func Test_EASpan(t *testing.T) { "test": "2", "test2": "string", }) - ea := createErrorAnalysisFilter(md) + config := common.CreateTestConfig() + ea := createErrorAnalysisFilter(context.Background(), md, config, config.LogEntry) meta := ea.scanTSpanTree(&tSpan) if len(meta.Exceptions) == 0 { @@ -57,8 +55,7 @@ func Test_EASpan(t *testing.T) { } func TestTspan(t *testing.T) { - msg := `{"E":1,"FT":1500,":FT":1500,"ptype":"1500","pname":"abc_d","psid":"23563","NP":"t=1617083759.535 D=0.000","S":1617083759798,"appid":"app-2",":appid":"app-2", - ":appname":"APP-2","appname":"APP-2","calls":[{"E":1,"calls":[{"E":1,"S":0,"clues":["-1:input parameters","14:return value"],"name":"abc"}],"S":0,"clues":["-1:input parameters","14:return value"],"name":"app\\AppDate::abc","SQL":"select* from abc"}],"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","Ah":"123.35.36.3/host","EXP":"exp","ERR":{"msg":"error_msg","file":"file.cc","line":123}}` + msg := `{":E":1,":FT":1500,":S":1728466073494,"appid":"cd.dev.test.run","appname":"cd.dev.test.php","client":"localhost","event":[{":E":0,":S":1,":depth":1,":seq":0,"name":"SimplePHP\\MessageHandler::handle_message_in_kafka","stp":"1501"}],"name":"RdKafka\\KafkaConsumer::consume","server":"localhost","sid":"2057154795","stp":"1500","tid":"cd.dev.test.run^1728466064272^0","uri":"abc","EXP":"xxxxx","ERR":{"msg":"asbc","file":"files","line":233}} ` var tspan TSpan err := json.Unmarshal([]byte(msg), &tspan) @@ -66,16 +63,16 @@ func TestTspan(t *testing.T) { t.Error(err) } - if tspan.GetStartTime() != 1617083759798 { + if tspan.GetStartTime() != 1728466073494 { t.Error(tspan.GetStartTime()) } - if tspan.GetAppName() != "APP-2" { + if tspan.GetAppName() != "cd.dev.test.php" { t.Error(tspan.GetAppName()) } - if tspan.SpanId != 726125302 { + if tspan.SpanId != 2057154795 { t.Error(tspan.SpanId) } @@ -83,7 +80,7 @@ func TestTspan(t *testing.T) { t.Error(tspan.ServerType) } - if tspan.ExceptionInfo != "exp" { + if tspan.ExceptionInfo != "xxxxx" { t.Error(tspan.ExceptionInfo) } @@ -91,19 +88,19 @@ func TestTspan(t *testing.T) { t.Error("no error info") } - if len(tspan.Calls) == 0 { + if len(tspan.Follows) == 0 { t.Error("no calls") } - for _, ev := range tspan.Calls { - evCalls := ev.Calls - if len(evCalls) == 0 { - t.Error("no calls") - } - if evCalls[0].Name == "app\\AppDate::abc" { - t.Error("calls no name") - } + // for _, ev := range tspan.Calls { + // evCalls := ev.Calls + // if len(evCalls) == 0 { + // t.Error("no calls") + // } + // if evCalls[0].Name == "app\\AppDate::abc" { + // t.Error("calls no name") + // } - } + // } } diff --git a/collector-agent/agent/ErrorAnalysis.go b/collector-agent/agent/ErrorAnalysis.go index 159000d42..ad9e19fc7 100644 --- a/collector-agent/agent/ErrorAnalysis.go +++ b/collector-agent/agent/ErrorAnalysis.go @@ -1,44 +1,55 @@ package agent import ( + "context" + "sync" + "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/common" v1 "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/pinpoint-grpc-idl-go/proto/v1" - log "github.com/sirupsen/logrus" + "github.com/sirupsen/logrus" "google.golang.org/grpc/metadata" ) type ErrorAnalysisFilter struct { - md metadata.MD - // only one gocoroutine working on chn, so no needs to lock it - id int64 + md metadata.MD + id int64 + config *common.Config + log *logrus.Entry + wg sync.WaitGroup + ctx context.Context } -func createErrorAnalysisFilter(base metadata.MD) *ErrorAnalysisFilter { - eaf := &ErrorAnalysisFilter{ - md: base, - id: 0, +func createErrorAnalysisFilter(ctx context.Context, base metadata.MD, config *common.Config, entry *logrus.Entry) *ErrorAnalysisFilter { + return &ErrorAnalysisFilter{ + md: base, + id: 0, + config: config, + log: entry, + ctx: ctx, } - return eaf } +func (e *ErrorAnalysisFilter) Stop() {} + func (e *ErrorAnalysisFilter) sendExpMetaData(meta *v1.PExceptionMetaData) { - config := common.GetConfig() - conn, err := common.CreateGrpcConnection(config.AgentAddress) + defer e.wg.Done() + + conn, err := e.config.CreateGrpcConnection(e.ctx, e.config.User.AgentAddress) if err != nil { - log.Warnf("connect:%s failed. %s", config.AgentAddress, err) + e.log.Warnf("connect:%s failed. %s", e.config.User.AgentAddress, err) return } defer conn.Close() client := v1.NewMetadataClient(conn) - ctx, cancel := common.BuildPinpointCtx(config.MetaDataTimeWait, e.md) + ctx, cancel := common.BuildMdContextWithTimeout(e.config.MetaDataTimeWait, e.md) defer cancel() result, err := client.RequestExceptionMetaData(ctx, meta) if err != nil { - log.Warnf("RequestExceptionMetaData failed. reason: %v", err) + e.log.Warnf("RequestExceptionMetaData failed. reason: %v", err) } - log.Debugf("RequestExceptionMetaData %v %v", meta, result) + e.log.Debugf("RequestExceptionMetaData %v %v", meta, result) } func (e *ErrorAnalysisFilter) parseException(spanEv []*TSpanEvent, exceptions *[]*v1.PException, @@ -59,13 +70,15 @@ func (e *ErrorAnalysisFilter) parseException(spanEv []*TSpanEvent, exceptions *[ exp.ExceptionDepth = depth + 1 *exceptions = append(*exceptions, exp) - if len(ev.Calls) > 0 { - e.parseException(ev.Calls, exceptions, exp.ExceptionId, exp.ExceptionDepth, ev.ExceptionInfoV2, startTime) - } + // TODO + // if len(ev.Calls) > 0 { + // e.parseException(ev.Calls, exceptions, exp.ExceptionId, exp.ExceptionDepth, ev.ExceptionInfoV2, startTime) + // } } else { - if len(ev.Calls) > 0 { - e.parseException(ev.Calls, exceptions, parentErrorId, depth, parentExp, startTime) - } + // TODO + // if len(ev.Calls) > 0 { + // e.parseException(ev.Calls, exceptions, parentErrorId, depth, parentExp, startTime) + // } } } return nil @@ -94,9 +107,9 @@ func (e *ErrorAnalysisFilter) scanTSpanTree(span *TSpan) *v1.PExceptionMetaData StartTime: span.ExceptionInfoV2.StartTime + startTime, } spanExp = append(spanExp, exp) - e.parseException(span.Calls, &spanExp, exp.ExceptionId, depth, span.ExceptionInfoV2, startTime) + e.parseException(span.Follows, &spanExp, exp.ExceptionId, depth, span.ExceptionInfoV2, startTime) } else { - e.parseException(span.Calls, &spanExp, 0, depth, nil, startTime) + e.parseException(span.Follows, &spanExp, 0, depth, nil, startTime) } e_md.Exceptions = spanExp @@ -106,12 +119,11 @@ func (e *ErrorAnalysisFilter) scanTSpanTree(span *TSpan) *v1.PExceptionMetaData func (e *ErrorAnalysisFilter) Interceptor(span *TSpan) bool { if span.ErrorMarked == 1 { - // parse the error meta := e.scanTSpanTree(span) - // plan one: send once + e.wg.Add(1) go e.sendExpMetaData(meta) } else { - log.Debugf("ErrorAnalysisFilter Interceptor, not exception mark") + e.log.Debugf("ErrorAnalysisFilter Interceptor, not exception mark") } return true } diff --git a/collector-agent/agent/ErrorAnalysis_test.go b/collector-agent/agent/ErrorAnalysis_test.go index bf07685a4..55371637a 100644 --- a/collector-agent/agent/ErrorAnalysis_test.go +++ b/collector-agent/agent/ErrorAnalysis_test.go @@ -1,8 +1,10 @@ package agent import ( + "context" "testing" + "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/common" "google.golang.org/grpc/metadata" ) @@ -11,7 +13,8 @@ func TestErrorAnalysisFilter_Interceptor(t *testing.T) { "test": "2", "test2": "string", }) - ea := createErrorAnalysisFilter(md) + config := common.CreateTestConfig() + ea := createErrorAnalysisFilter(context.Background(), md, config, config.LogEntry) cases := []*TSpan{ { @@ -23,7 +26,7 @@ func TestErrorAnalysisFilter_Interceptor(t *testing.T) { { ErrorMarked: 1, ExceptionInfo: "abc", - Calls: []*TSpanEvent{ + Follows: []*TSpanEvent{ { ExceptionInfo: "abc", }, @@ -35,7 +38,7 @@ func TestErrorAnalysisFilter_Interceptor(t *testing.T) { { ErrorMarked: 0, ExceptionInfo: "abc", - Calls: []*TSpanEvent{ + Follows: []*TSpanEvent{ { ExceptionInfo: "abc", }, diff --git a/collector-agent/agent/Filter.go b/collector-agent/agent/Filter.go index cef2a98fc..1b57e7141 100644 --- a/collector-agent/agent/Filter.go +++ b/collector-agent/agent/Filter.go @@ -2,4 +2,5 @@ package agent type Filter interface { Interceptor(span *TSpan) bool + Stop() } diff --git a/collector-agent/agent/GrpcAgent.go b/collector-agent/agent/GrpcAgent.go index ac68bdaad..fe0b8699a 100644 --- a/collector-agent/agent/GrpcAgent.go +++ b/collector-agent/agent/GrpcAgent.go @@ -10,58 +10,88 @@ import ( "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/common" v1 "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/pinpoint-grpc-idl-go/proto/v1" + "github.com/shirou/gopsutil/cpu" + "github.com/shirou/gopsutil/v3/mem" - log "github.com/sirupsen/logrus" + "github.com/sirupsen/logrus" "google.golang.org/grpc" "google.golang.org/grpc/metadata" "google.golang.org/protobuf/types/known/wrapperspb" ) type GrpcAgent struct { - AgentId string - agentName string - agentType int32 - StartTime string - BaseMD metadata.MD - pingMd metadata.MD - PingId int32 - spanFilters []Filter - spanSender *SpanSender - AgentOnLine bool - requestCounter RequestProfiler - utReport *UrlTemplateReport - tasksGroup sync.WaitGroup - tSpanBufCh chan *TSpan - ExitCh chan bool - log *log.Entry - errorAnalysisFilter *ErrorAnalysisFilter + config *common.Config + AgentId string + agentName string + agentType int32 + StartTime string + metadata metadata.MD + pingMd metadata.MD + PingId int32 + spanFilters []Filter + AgentOnLine bool + reqCounter *RequestCounter + utReport *UrlTemplateReport + tasksGroup sync.WaitGroup + tSpanBufCh chan *TSpan + ctx context.Context + cancel_ctx context.CancelFunc + log *logrus.Entry } -func createGrpcAgent(id, name string, agentType, pingId int32, startTime string) *GrpcAgent { - agent := &GrpcAgent{PingId: pingId, AgentOnLine: false} - agent.Init(id, name, agentType, startTime) - agent.Start() +func CreateGrpcAgent(id, name string, agentType, pingId int32, startTime string, config *common.Config) *GrpcAgent { + agent := &GrpcAgent{ + PingId: pingId, + AgentOnLine: false, + config: config, + log: config.Log.WithField("app-id", id), + AgentId: id, + agentName: name, + agentType: agentType, + StartTime: startTime, + metadata: metadata.New(map[string]string{ + "starttime": startTime, + "agentid": id, + "applicationname": name, + }), + pingMd: metadata.New(map[string]string{ + "starttime": startTime, + "agentid": id, + "applicationname": name, + "socketid": strconv.FormatInt(int64(pingId), 10), + }), + utReport: CreateUrlTemplateReport(), + tSpanBufCh: make(chan *TSpan, config.AgentChannelSize), + } + + agent.ctx, agent.cancel_ctx = context.WithCancel(context.Background()) + agent.reqCounter = createRequestCounter(config) + agent.runBackgroundTasks() + config.Log.Infof("agent:%v is launched", agent) - log.Infof("agent:%v is launched", agent) return agent } func (agent *GrpcAgent) SendSpan(span *TSpan) { defer func() { if r := recover(); r != nil { - log.Warnf("sendSpan met:%s", r) + agent.log.Warnf("sendSpan met:%s", r) } }() agent.tSpanBufCh <- span } func (agent *GrpcAgent) GetLastBusyTime() int64 { - return agent.requestCounter.CTime + return agent.reqCounter.CTime } func (agent *GrpcAgent) Stop() { - agent.log.Warn("I'm exiting") - close(agent.ExitCh) + agent.log.Infof("I'm exiting") + agent.cancel_ctx() + for _, filter := range agent.spanFilters { + filter.Stop() + } + agent.tasksGroup.Wait() agent.log.Warn("I'm exit") } @@ -70,94 +100,98 @@ func (agent *GrpcAgent) AddFilter(filter Filter) { agent.spanFilters = append(agent.spanFilters, filter) } -func (agent *GrpcAgent) Interceptor(_ *TSpan) bool { - if !agent.AgentOnLine { - agent.log.Debugf("span dropped,as agent offline") - } +// func (agent *GrpcAgent) Interceptor(_ *TSpan) bool { +// if !agent.AgentOnLine { +// agent.log.Debugf("agent offline") +// } - //note log url templated - - return agent.AgentOnLine -} +// return true +// } func (agent *GrpcAgent) String() string { return fmt.Sprintf("id:%s name:%s type:%d startTime:%s", agent.AgentId, agent.agentName, agent.agentType, agent.StartTime) } -func (agent *GrpcAgent) handleRegisterAgent() error { - - commandTask := sync.WaitGroup{} - defer commandTask.Wait() +func (a *GrpcAgent) createMdCtxWithTime(dur time.Duration, md metadata.MD) (ctx context.Context, cancel context.CancelFunc) { + ctx, cancel = context.WithTimeout(a.ctx, dur) + ctx = metadata.NewOutgoingContext(ctx, md) + return ctx, cancel +} - config := common.GetConfig() - agent.log.Debugf("connect AgentChannel:%s for agentOnline", config.AgentAddress) +func (a *GrpcAgent) createMdCtx(md metadata.MD) (ctx context.Context, cancel context.CancelFunc) { + ctx, cancel = context.WithCancel(a.ctx) + ctx = metadata.NewOutgoingContext(ctx, md) + return ctx, cancel +} - conn, err := common.CreateGrpcConnection(config.AgentAddress) - if err != nil { - agent.log.Warnf("connect %s timeout", config.AgentAddress) - return errors.New("connect pinpoint-collector timeout") - } +func (a *GrpcAgent) keepPing(conn *grpc.ClientConn, wg *sync.WaitGroup) { + defer wg.Done() + client := v1.NewAgentClient(conn) - defer func() { - agent.log.Info("client activity close grpc connection") - if err := conn.Close(); err != nil { - agent.log.Warnf("close connection:%s", err) - } - }() + ctx, cancelRequestAgent := a.createMdCtxWithTime(a.config.GrpcConTextTimeOut, a.metadata) + defer cancelRequestAgent() - client := v1.NewAgentClient(conn) - ctx, cancel := common.BuildPinpointCtx(config.GrpcConTextTimeOut, agent.BaseMD) - defer cancel() - pbAgentInfo := common.GetPBAgentInfo(agent.agentType) - agent.log.Debugf("RequestAgentInfo pbAgentInfo:%v", pbAgentInfo) - if res, err := client.RequestAgentInfo(ctx, pbAgentInfo); err != nil { - errorMsg := fmt.Sprintf("RequestAgentInfo failed. %s", err) - agent.log.Warn(errorMsg) - return errors.New(errorMsg) - } else { - agent.log.Debugf("RequestAgentInfo response:%s", res) + agent_info := common.GetPBAgentInfo(a.agentType, a.config) + a.log.Debugf("request agentInfo:%v", agent_info) + if _, err := client.RequestAgentInfo(ctx, agent_info); err != nil { + a.log.Warnf("create RequestAgentInfo failed with %v", err) + return } // send ping - pingCtx := metadata.NewOutgoingContext(context.Background(), agent.pingMd) - - stream, err := client.PingSession(pingCtx) + ping_ctx, cancelPingFunc := a.createMdCtx(a.pingMd) + defer cancelPingFunc() + stream, err := client.PingSession(ping_ctx) if err != nil { - return err + a.log.Warnf("create PingSession failed with %v", err) + return } - defer func() { - if err := stream.CloseSend(); err != nil { - agent.log.Warnf("unwanted err when stream.CloseSend:%s", err) - } - }() - - // handle command - go agent.handleCommand(conn, &commandTask) - - agent.log.Info("agent online ") - agent.AgentOnLine = true - - defer func() { agent.AgentOnLine = false }() + defer stream.CloseSend() ping := v1.PPing{} for { // send ping - agent.log.Infof("ping %s %v", agent.AgentId, agent.pingMd) + a.log.Infof("ping %s %v", a.AgentId, a.pingMd) if err := stream.Send(&ping); err != nil { - agent.log.Warnf("agentOnline Send ping failed. %s", err) - return err + a.log.Warnf("agentOnline Send ping failed. %s", err) + break } // recv ping if _, err := stream.Recv(); err != nil { - agent.log.Warnf("agentOnline recv ping failed. %s", err) - return err + a.log.Warnf("agentOnline recv ping failed. %s", err) + break } - if common.WaitChannelEvent(agent.ExitCh, config.PingInterval) == common.E_AGENT_STOPPING { - return errors.New("catch exit during ping") + if common.WaitEventsWithTime(a.ctx, a.config.PingInterval) == common.E_AGENT_STOPPING { + break } } + a.AgentOnLine = false +} + +func (a *GrpcAgent) handleRegisterAgent() error { + + a.log.Infof("connect AgentChannel:%s for agentOnline", a.config.User.AgentAddress) + conn, err := a.config.CreateGrpcConnection(a.ctx, a.config.User.AgentAddress) + if err != nil { + a.log.Warnf("connect %s timeout", a.config.User.AgentAddress) + return errors.New("connect pinpoint-collector timeout") + } + defer conn.Close() + + var cmd_wg sync.WaitGroup + defer cmd_wg.Wait() + + cmd_wg.Add(1) + go a.handleCommand(conn, &cmd_wg) + + a.AgentOnLine = true + + cmd_wg.Add(1) + go a.keepPing(conn, &cmd_wg) + + return nil } func (agent *GrpcAgent) keepAgentOnline() { @@ -165,11 +199,10 @@ func (agent *GrpcAgent) keepAgentOnline() { for { if err := agent.handleRegisterAgent(); err != nil { - agent.log.Infof("agent online exit:%s ", err) + agent.log.Infof("agent exit. reason: %s ", err) } - config := common.GetConfig() - if common.WaitChannelEvent(agent.ExitCh, config.AgentReTryTimeout) == common.E_AGENT_STOPPING { + if common.WaitEventsWithTime(agent.ctx, agent.config.AgentReTryTimeout) == common.E_AGENT_STOPPING { break } } @@ -177,12 +210,12 @@ func (agent *GrpcAgent) keepAgentOnline() { func (agent *GrpcAgent) registerFilter() { // online/off - agent.log.Debug("register agent filter") - agent.AddFilter(agent) + // agent.log.Debug("register agent filter") + // agent.AddFilter(agent) // req count agent.log.Debug("register requestCounter filter") - agent.AddFilter(&agent.requestCounter) + agent.AddFilter(agent.reqCounter) // req UrlTemplateReport agent.log.Debug("register UrlTemplate Report filter") @@ -190,81 +223,151 @@ func (agent *GrpcAgent) registerFilter() { // req ErrorAnalysis agent.log.Debug("register errorAnalysis Report error") - agent.AddFilter(agent.errorAnalysisFilter) + errorAnalysisFilter := createErrorAnalysisFilter(agent.ctx, agent.metadata, agent.config, agent.log) + agent.AddFilter(errorAnalysisFilter) // send span agent.log.Debug("register spanSender filter") - agent.AddFilter(agent.spanSender) + spanSender := createSpanSender(agent.metadata, agent.ctx, &agent.tasksGroup, agent.config, agent.log) + agent.AddFilter(spanSender) + +} + +func (a *GrpcAgent) CollectPStateMessage() *v1.PStatMessage { + + max, avg := a.reqCounter.GetMaxAvg() + responseTime := v1.PResponseTime{ + Max: int64(max), + Avg: int64(avg), + } + + v, _ := mem.VirtualMemory() + + jvmGc := v1.PJvmGc{ + Type: v1.PJvmGcType_JVM_GC_TYPE_PARALLEL, + JvmMemoryHeapUsed: int64(v.Used), + JvmMemoryHeapMax: int64(v.Total), + JvmMemoryNonHeapUsed: int64(v.Buffers), + JvmMemoryNonHeapMax: int64(v.Cached), + JvmGcOldCount: 0, + JvmGcOldTime: 0, + JvmGcDetailed: &v1.PJvmGcDetailed{}, + } + // cpu.Percent calculate cpu in config.StatInterval + totalPer, err := cpu.PercentWithContext(a.ctx, a.config.StatInterval*time.Second, false) + totalCpuUsage := 0.0 + if err == nil { + totalCpuUsage = totalPer[0] / 100 + } + + cpuload := v1.PCpuLoad{ + SystemCpuLoad: totalCpuUsage, + JvmCpuLoad: totalCpuUsage, + } + var activeTraceCount []int32 + for _, value := range a.reqCounter.GetReqTimeProfiler() { + activeTraceCount = append(activeTraceCount, int32(value)) + } + + agentStat := v1.PAgentStat{ + ResponseTime: &responseTime, + Gc: &jvmGc, + CollectInterval: int64(a.config.StatInterval), + Timestamp: int64(time.Now().UnixNano() / int64(time.Millisecond)), + CpuLoad: &cpuload, + Transaction: &v1.PTransaction{}, + ActiveTrace: &v1.PActiveTrace{ + Histogram: &v1.PActiveTraceHistogram{ + Version: 1, + HistogramSchemaType: 2, //NORMAL SCHEMA + ActiveTraceCount: activeTraceCount, + }, + }, + DataSourceList: nil, + Deadlock: nil, + FileDescriptor: nil, + DirectBuffer: nil, + Metadata: "", + } + + pStateAgentStat := v1.PStatMessage_AgentStat{ + AgentStat: &agentStat, + } + + sateMessage := v1.PStatMessage{ + Field: &pStateAgentStat, + } + + return &sateMessage +} + +func (a *GrpcAgent) handleRequestStat(client v1.Stat_SendAgentStatClient, wg *sync.WaitGroup) { + defer wg.Done() + for { + msg := a.CollectPStateMessage() + a.log.Debugf("PStatMessage: %v", msg) + if err := client.Send(msg); err != nil { + a.log.Warn(err) + break + } + + if common.WaitEventsWithTime(a.ctx, 0) == common.E_AGENT_STOPPING { + break + } + } +} + +func (agent *GrpcAgent) handleUrlReportStat(client v1.Stat_SendAgentStatClient, wg *sync.WaitGroup) { + defer wg.Done() + for { + msg := agent.utReport.MoveUtReport() + + agent.log.Debugf("ut report:%v", msg) + if err := client.Send(msg); err != nil { + agent.log.Warn(err) + break + } + //config.StatInterval + if common.WaitEventsWithTime(agent.ctx, 30*time.Second) == common.E_AGENT_STOPPING { + break + } + } } func (agent *GrpcAgent) sendStat() { - config := common.GetConfig() - agent.log.Debugf("connect StatAddress:%s", config.StatAddress) + agent.log.Debugf("connect StatAddress:%s", agent.config.User.StatAddress) - conn, err := common.CreateGrpcConnection(config.StatAddress) + conn, err := agent.config.CreateGrpcConnection(agent.ctx, agent.config.User.StatAddress) if err != nil { - errorMsg := fmt.Sprintf("Dial %s failed err:%s", config.StatAddress, err) + errorMsg := fmt.Sprintf("Dial %s failed err:%s", agent.config.User.StatAddress, err) agent.log.Warn(errorMsg) return } - defer func() { - if err := conn.Close(); err != nil { - agent.log.Warnf("conn close with:%s", err) - } - }() + defer conn.Close() - ctx, _ := common.BuildPinpointCtx(-1, agent.pingMd) + ctx, cancel := agent.createMdCtx(agent.pingMd) + + defer cancel() client := v1.NewStatClient(conn) stream, err := client.SendAgentStat(ctx) if err != nil { - errorMsg := fmt.Sprintf("create stat client failed:%s", config.StatAddress) - agent.log.Warn(errorMsg) + agent.log.Warnf("create stat client failed:%s", agent.config.User.StatAddress) return } var wg sync.WaitGroup + defer wg.Wait() + wg.Add(1) - go func() { - for { - msg := CollectPStateMessage(agent.requestCounter.GetMaxAvg, agent.requestCounter.GetReqTimeProfiler) - - agent.log.Debugf("PStatMessage: %v", msg) - if err := stream.Send(msg); err != nil { - agent.log.Warn(err) - break - } - //config.StatInterval - if common.WaitChannelEvent(agent.ExitCh, 0) == common.E_AGENT_STOPPING { - break - } - } - wg.Done() - }() - // wg.Add(1) - // todo send uri templated + go agent.handleRequestStat(stream, &wg) + wg.Add(1) - go func() { - for { - msg := agent.utReport.MoveUtReport() - - agent.log.Debugf("%v", msg) - if err := stream.Send(msg); err != nil { - agent.log.Warn(err) - break - } - //config.StatInterval - if common.WaitChannelEvent(agent.ExitCh, 30) == common.E_AGENT_STOPPING { - break - } - } - wg.Done() - }() - wg.Wait() + go agent.handleUrlReportStat(stream, &wg) } func (agent *GrpcAgent) uploadStatInfo() { @@ -274,116 +377,83 @@ func (agent *GrpcAgent) uploadStatInfo() { for { agent.sendStat() - config := common.GetConfig() - if common.WaitChannelEvent(agent.ExitCh, config.StatInterval) == common.E_AGENT_STOPPING { + if common.WaitEventsWithTime(agent.ctx, agent.config.StatInterval) == common.E_AGENT_STOPPING { return } } } -func (agent *GrpcAgent) Init(id, _name string, _type int32, StartTime string) { - agent.log = log.WithFields(log.Fields{"appid": id}) - - agent.AgentId = id - agent.agentName = _name - agent.agentType = _type - agent.StartTime = StartTime - agent.BaseMD = metadata.New(map[string]string{ - "starttime": StartTime, - "agentid": id, - "applicationname": _name, - }) - - pingIdStr := strconv.FormatInt(int64(agent.PingId), 10) - - agent.pingMd = metadata.New(map[string]string{ - "starttime": agent.StartTime, - "agentid": agent.AgentId, - "applicationname": agent.agentName, - "socketid": pingIdStr, - }) - - agent.utReport = CreateUrlTemplateReport() - - config := common.GetConfig() - - agent.tSpanBufCh = make(chan *TSpan, config.AgentChannelSize) - agent.ExitCh = make(chan bool) - agent.spanSender = createSpanSender(agent.BaseMD, agent.ExitCh, &agent.tasksGroup, agent.log) - agent.requestCounter.CTime = time.Now().Unix() - - agent.errorAnalysisFilter = createErrorAnalysisFilter(agent.BaseMD) +func (agent *GrpcAgent) runBackgroundTasks() { agent.registerFilter() + agent.tasksGroup.Add(1) - // start agentOnline go agent.keepAgentOnline() - // send stat + agent.tasksGroup.Add(1) go agent.uploadStatInfo() - } -func (agent *GrpcAgent) Start() { +func (agent *GrpcAgent) StartServe() { agent.tasksGroup.Add(1) - go agent.consumeJsonSpan() + go agent.handleTSpanFromBuf() } func (agent *GrpcAgent) collectorActiveThreadCount(conn *grpc.ClientConn, responseId int32, interval time.Duration, wg *sync.WaitGroup) { - wg.Add(1) defer wg.Done() client := v1.NewProfilerCommandServiceClient(conn) - ctx, _ := common.BuildPinpointCtx(-1, agent.pingMd) - - if activeThreadCountClient, err := client.CommandStreamActiveThreadCount(ctx); err == nil { - sequenceId := int32(1) - for { - // agent.log.Debugf("ResponseId %d", responseId) - response := v1.PCmdStreamResponse{ - ResponseId: responseId, - SequenceId: sequenceId, - Message: &wrapperspb.StringValue{ - Value: "hello", - }, - } - sequenceId += 1 - - res := v1.PCmdActiveThreadCountRes{ - CommonStreamResponse: &response, - } + ctx, _ := common.BuildMdContextWithTimeout(agent.config.GrpcConTextTimeOut, agent.pingMd) - for _, value := range agent.requestCounter.GetReqTimeProfiler() { - res.ActiveThreadCount = append(res.ActiveThreadCount, int32(value)) - } + stream_client, err := client.CommandStreamActiveThreadCount(ctx) + if err != nil { + agent.log.Warnf("CommandStreamActiveThreadCount failed:%v", err) + } + sequenceId := int32(1) + for { + response := v1.PCmdStreamResponse{ + ResponseId: responseId, + SequenceId: sequenceId, + Message: &wrapperspb.StringValue{ + Value: "hello", + }, + } + sequenceId += 1 - res.TimeStamp = time.Now().Unix() - res.HistogramSchemaType = 2 + res := v1.PCmdActiveThreadCountRes{ + CommonStreamResponse: &response, + } - // agent.log.Debugf("try to send PCmdActiveThreadCountRes:%v", res) + for _, value := range agent.reqCounter.GetReqTimeProfiler() { + res.ActiveThreadCount = append(res.ActiveThreadCount, int32(value)) + } - if err := activeThreadCountClient.Send(&res); err != nil { - agent.log.Warnf("collectorActiveThreadCount:responseId:%d end with:%s", responseId, err) - break - } + res.TimeStamp = time.Now().Unix() + res.HistogramSchemaType = 2 - if common.WaitChannelEvent(agent.ExitCh, interval) == common.E_AGENT_STOPPING { - agent.log.Warnf("catch exit during send collectorActiveThreadCount") - break - } + if err := stream_client.Send(&res); err != nil { + agent.log.Warnf("collectorActiveThreadCount:responseId:%d end with:%s", responseId, err) + break } + if common.WaitEventsWithTime(agent.ctx, interval) == common.E_AGENT_STOPPING { + agent.log.Warnf("catch exit during send collectorActiveThreadCount") + break + } } } func (agent *GrpcAgent) genCmdHandshake() *v1.PCmdMessage { handshake := v1.PCmdServiceHandshake{} - handshake.SupportCommandServiceKey = append(handshake.SupportCommandServiceKey, int32(v1.PCommandType_PING)) - handshake.SupportCommandServiceKey = append(handshake.SupportCommandServiceKey, int32(v1.PCommandType_PONG)) - handshake.SupportCommandServiceKey = append(handshake.SupportCommandServiceKey, int32(v1.PCommandType_ECHO)) - handshake.SupportCommandServiceKey = append(handshake.SupportCommandServiceKey, int32(v1.PCommandType_ACTIVE_THREAD_COUNT)) - handshake.SupportCommandServiceKey = append(handshake.SupportCommandServiceKey, int32(v1.PCommandType_ACTIVE_THREAD_DUMP)) - handshake.SupportCommandServiceKey = append(handshake.SupportCommandServiceKey, int32(v1.PCommandType_ACTIVE_THREAD_LIGHT_DUMP)) + handshake.SupportCommandServiceKey = append( + handshake.SupportCommandServiceKey, + int32(v1.PCommandType_PING), + int32(v1.PCommandType_PONG), + int32(v1.PCommandType_ECHO), + int32(v1.PCommandType_ACTIVE_THREAD_COUNT), + int32(v1.PCommandType_ACTIVE_THREAD_DUMP), + int32(v1.PCommandType_ACTIVE_THREAD_LIGHT_DUMP), + ) return &v1.PCmdMessage{ Message: &v1.PCmdMessage_HandshakeMessage{ @@ -394,16 +464,16 @@ func (agent *GrpcAgent) genCmdHandshake() *v1.PCmdMessage { func (agent *GrpcAgent) handleCommand(conn *grpc.ClientConn, wg *sync.WaitGroup) { defer wg.Done() - wg.Add(1) - cmdWg := sync.WaitGroup{} - defer cmdWg.Wait() + var cmd_tasks sync.WaitGroup + defer cmd_tasks.Wait() client := v1.NewProfilerCommandServiceClient(conn) //config.AgentReTryTimeout - ctx, _ := common.BuildPinpointCtx(-1, agent.pingMd) + ctx, cancel_func := agent.createMdCtx(agent.pingMd) + defer cancel_func() - //todo update HandleCommand to HandleCommandV2 + //TODO update HandleCommand to HandleCommandV2 commandClient, err := client.HandleCommand(ctx) if err != nil { @@ -411,58 +481,56 @@ func (agent *GrpcAgent) handleCommand(conn *grpc.ClientConn, wg *sync.WaitGroup) return } - // send handleshake + // send handle shake if err := commandClient.Send(agent.genCmdHandshake()); err != nil { agent.log.Warnf("handleCommand Send got err:%s", err) return } + agent.log.Debugf("send command handshake %s", agent.genCmdHandshake()) for { - if cmd, err := commandClient.Recv(); err != nil { - agent.log.Warnf("handleCommand.Recv got err:%s", err) + cmd, err := commandClient.Recv() + if err != nil { + agent.log.Infof("handleCommand.Recv got err:%s", err) return - } else { - agent.log.Infof("appid:%s handleCommand: get cmd %s", agent.AgentId, cmd) - switch cmd.Command.(type) { - case *v1.PCmdRequest_CommandEcho: - { - agent.log.Debug("PCmdRequest_CommandEcho") - } - case *v1.PCmdRequest_CommandActiveThreadCount: - // create a new coro to send active thread - go agent.collectorActiveThreadCount(conn, cmd.RequestId, 1, &cmdWg) - case *v1.PCmdRequest_CommandActiveThreadDump: - agent.log.Debug("PCmdRequest_CommandActiveThreadDump") - case *v1.PCmdRequest_CommandActiveThreadLightDump: - response := v1.PCmdResponse{ - ResponseId: cmd.RequestId, - } - - dumpRes := v1.PCmdActiveThreadLightDumpRes{ - Type: "java", - SubType: "oracle", - Version: "1.8.105", - CommonResponse: &response, - } + } - go func(in *v1.PCmdActiveThreadLightDumpRes) { - defer cmdWg.Done() - cmdWg.Add(1) + agent.log.Infof("appid:%s handleCommand: get cmd %s", agent.AgentId, cmd) + switch cmd.Command.(type) { + case *v1.PCmdRequest_CommandEcho: + agent.log.Debug("PCmdRequest_CommandEcho") + case *v1.PCmdRequest_CommandActiveThreadCount: + // create a new coro to send active thread + agent.log.Debug("PCmdRequest_CommandActiveThreadCount") + cmd_tasks.Add(1) + go agent.collectorActiveThreadCount(conn, cmd.RequestId, 1, &cmd_tasks) + case *v1.PCmdRequest_CommandActiveThreadDump: + agent.log.Debug("PCmdRequest_CommandActiveThreadDump") + case *v1.PCmdRequest_CommandActiveThreadLightDump: + agent.log.Debug("PCmdRequest_CommandActiveThreadLightDump") + response := v1.PCmdResponse{ + ResponseId: cmd.RequestId, + } - if _, err := client.CommandActiveThreadLightDump(ctx, in); err != nil { - agent.log.Warnf("CommandActiveThreadLightDump failed! err:%s", err) - } - }(&dumpRes) + dumpRes := v1.PCmdActiveThreadLightDumpRes{ + Type: "java", + SubType: "oracle", + Version: "1.8.105", + CommonResponse: &response, + } - default: - agent.log.Warnf("unknown command type %v", cmd) + if _, err := client.CommandActiveThreadLightDump(ctx, &dumpRes); err != nil { + agent.log.Warnf("CommandActiveThreadLightDump failed! err:%s", err) } + + default: + agent.log.Warnf("unknown command type %v", cmd) } } } -func (agent *GrpcAgent) consumeJsonSpan() { +func (agent *GrpcAgent) handleTSpanFromBuf() { defer agent.tasksGroup.Done() for { select { @@ -472,7 +540,7 @@ func (agent *GrpcAgent) consumeJsonSpan() { break } } - case <-agent.spanSender.exitCh: + case <-agent.ctx.Done(): agent.log.Warn("consumeJsonSpan task done, as agent exit") return } diff --git a/collector-agent/agent/GrpcAgent_test.go b/collector-agent/agent/GrpcAgent_test.go new file mode 100644 index 000000000..4234aaa48 --- /dev/null +++ b/collector-agent/agent/GrpcAgent_test.go @@ -0,0 +1,126 @@ +package agent + +import ( + "fmt" + "strconv" + "testing" + "time" + + "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/common" +) + +/** +GRPC_TRACE="all" +GRPC_VERBOSITY="DEBUG" +GODEBUG="http2debug=2" +GRPC_GO_LOG_VERBOSITY_LEVEL=99 +GRPC_GO_LOG_SEVERITY_LEVEL=info +unset GODEBUG +*/ + +func Test_GrpcAgentBackgroundTask(t *testing.T) { + config := common.CreateTestConfig() + startTime := time.Now().UTC().UnixMicro() + agent := CreateGrpcAgent("cd.dev.test.ci", "cd.dev.test", 1500, 1, strconv.FormatInt(startTime, 10), config) + t.Logf("wait 10sec") + time.Sleep(5 * time.Second) + agent.Stop() +} + +func Test_async_call_map(t *testing.T) { + config := common.CreateTestConfig() + startTime := time.Now().Unix() + agent := CreateGrpcAgent("cd.dev.test.ci", "cd.dev.test", 1500, 1, strconv.FormatInt(startTime, 10), config) + agent.StartServe() + tid := fmt.Sprintf("cd.dev.test.ci^%d^%d", startTime, 1) + + span := &TSpan{AppServerType: 1500, AppServerTypeV2: 1500, StartTimeV2: startTime, ElapsedTime: 100, ElapsedTimeV2: 103, AppId: "cd.dev.test.ci", AppIdV2: "cd.dev.test.ci", AppName: "cd.dev.test", AppNameV2: "cd.dev.test", SpanName: "test-ci-main", SpanId: 454525, ServerType: 1500, TransactionId: tid, Uri: "/", RemoteAddr: "15.36.89.23", EndPoint: "localhost:5265", + Follows: []*TSpanEvent{ + { + Name: "test-1", + Sequence: 0, + ServiceType: 1501, + Depth: 1, + // AsyId: 1, + StartElapsed: int32(time.Now().UTC().UnixMicro()) + 4, + EndElapsed: 10, + }, + { + Name: "test-3", + Sequence: 2, + Depth: 2, + ServiceType: 1501, + AsyId: 2578, + StartElapsed: int32(time.Now().UTC().UnixMicro()) + 30, + EndElapsed: 20, + }, + { + Name: "test-2", + Sequence: 1, + Depth: 2, + ServiceType: 1501, + AsyId: 1589, + StartElapsed: int32(time.Now().UTC().UnixMicro()) + 30, + EndElapsed: 20, + }}, + } + + chunk := &TSpan{ + TransactionId: tid, + SpanId: 454525, + StartTime: startTime + 7898, + AppServerType: 1500, + EndPoint: "localhost:5265", + LocalAsyncId: &TAsyncId{AsyncId: 1589, Sequence: 2}, + Follows: []*TSpanEvent{ + { + Name: "thread_func", + Depth: 1, + EndElapsed: 300, + ServiceType: 100, + }, + { + Name: "test-7", + Depth: 2, + Sequence: 1, + EndElapsed: 5000, + ServiceType: 9054, + }, + }, + } + + chunk2 := &TSpan{ + TransactionId: tid, + SpanId: 454525, + StartTime: startTime + 7898, + AppServerType: 1500, + EndPoint: "localhost:5265", + LocalAsyncId: &TAsyncId{AsyncId: 2578, Sequence: 1}, + Follows: []*TSpanEvent{ + { + Name: "thread_fun_01", + Depth: 1, + EndElapsed: 200, + ServiceType: 100, + }, + { + Name: "test-7-chunk2", + Depth: 2, + Sequence: 1, + EndElapsed: 2000, + ServiceType: 9054, + }, + }, + } + + agent.SendSpan(chunk) + agent.SendSpan(span) + + // t.Log("sleep 10sec") + time.Sleep(5 * time.Second) + agent.SendSpan(chunk2) + time.Sleep(5 * time.Second) + agent.Stop() + // t.Error("---") + t.Log("every thing is fine") +} diff --git a/collector-agent/agent/RequestCounter.go b/collector-agent/agent/RequestCounter.go index 041c3f661..c3921121d 100644 --- a/collector-agent/agent/RequestCounter.go +++ b/collector-agent/agent/RequestCounter.go @@ -7,14 +7,26 @@ import ( "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/common" ) -type RequestProfiler struct { - reqProfiler [4]uint16 +type RequestCounter struct { + counter [4]uint16 reqProfileLastTime, reqTop1LastTime, CTime int64 max, total, times uint32 + config *common.Config +} + +func createRequestCounter(config *common.Config) *RequestCounter { + return &RequestCounter{ + config: config, + CTime: time.Now().Unix(), + } +} + +func (*RequestCounter) Stop() { + } // exp in seconds -func (*RequestProfiler) getReqLevel(exp uint32) int32 { +func (*RequestCounter) getReqLevel(exp uint32) int32 { if exp <= 1 { return 0 } else if exp <= 3 { @@ -26,20 +38,20 @@ func (*RequestProfiler) getReqLevel(exp uint32) int32 { } } -func (reqProf *RequestProfiler) updateReqTimeProfile(exp uint32) { +func (reqProf *RequestCounter) updateReqTimeProfile(exp uint32) { if reqProf.reqProfileLastTime != reqProf.CTime { - for i := range reqProf.reqProfiler { - reqProf.reqProfiler[i] = 0 + for i := range reqProf.counter { + reqProf.counter[i] = 0 } } - reqProf.reqProfiler[reqProf.getReqLevel(exp)] += 1 + reqProf.counter[reqProf.getReqLevel(exp)] += 1 reqProf.reqProfileLastTime = reqProf.CTime } -func (reqProf *RequestProfiler) updateReqTop1TimeSummary(exp uint32) { - config := common.GetConfig() - if reqProf.CTime >= (reqProf.reqTop1LastTime + int64(config.StatInterval) + 1) { // reset response time summary +func (reqProf *RequestCounter) updateReqTop1TimeSummary(exp uint32) { + + if reqProf.CTime >= (reqProf.reqTop1LastTime + int64(reqProf.config.StatInterval) + 1) { // reset response time summary reqProf.reqTop1LastTime = reqProf.CTime reqProf.total = 0 reqProf.times = 0 @@ -54,25 +66,29 @@ func (reqProf *RequestProfiler) updateReqTop1TimeSummary(exp uint32) { reqProf.times += 1 } -func (reqProf *RequestProfiler) GetMaxAvg() (max, avg uint32) { - config := common.GetConfig() - if time.Now().Unix() < (reqProf.reqTop1LastTime + int64(config.StatInterval) + 1) { +func (reqProf *RequestCounter) GetMaxAvg() (max, avg uint32) { + if time.Now().Unix() < (reqProf.reqTop1LastTime+int64(reqProf.config.StatInterval)+1) && reqProf.times > 0 { return reqProf.max, reqProf.total / reqProf.times } else { return 0, 0 } } -func (reqProf *RequestProfiler) GetReqTimeProfiler() [4]uint16 { +func (reqProf *RequestCounter) GetReqTimeProfiler() [4]uint16 { now := time.Now().Unix() if now < reqProf.reqProfileLastTime+2 { - return reqProf.reqProfiler + return reqProf.counter } else { return [4]uint16{0, 0, 0, 0} } } -func (reqProf *RequestProfiler) Interceptor(span *TSpan) bool { +func (reqProf *RequestCounter) Interceptor(span *TSpan) bool { + + if span.LocalAsyncId != nil { + return true + } + reqProf.CTime = time.Now().Unix() elapsed := span.GetElapsedTime() diff --git a/collector-agent/agent/RequestCounter_test.go b/collector-agent/agent/RequestCounter_test.go index 3dc2084de..ed2079bcd 100644 --- a/collector-agent/agent/RequestCounter_test.go +++ b/collector-agent/agent/RequestCounter_test.go @@ -8,8 +8,8 @@ import ( ) func TestRequestProfiler_Interceptor(t *testing.T) { - profiler := RequestProfiler{} - config := common.GetConfig() + config := common.CreateTestConfig() + profiler := createRequestCounter(config) config.StatInterval = 30 spans := []TSpan{ {ElapsedTime: 10}, @@ -42,7 +42,7 @@ func BenchmarkRequestProfiler_Interceptor(b *testing.B) { spanMap := TSpan{ ElapsedTime: 234, } - req := RequestProfiler{} + req := RequestCounter{} for i := 0; i < b.N; i++ { req.Interceptor(&spanMap) } diff --git a/collector-agent/agent/SpanSender.go b/collector-agent/agent/SpanSender.go index f5efb4db8..b5e92f200 100644 --- a/collector-agent/agent/SpanSender.go +++ b/collector-agent/agent/SpanSender.go @@ -2,7 +2,6 @@ package agent import ( "context" - "errors" "fmt" "strconv" "strings" @@ -11,9 +10,9 @@ import ( "github.com/golang/protobuf/ptypes/wrappers" "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/common" v1 "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/pinpoint-grpc-idl-go/proto/v1" + "github.com/sirupsen/logrus" "github.com/spaolacci/murmur3" - log "github.com/sirupsen/logrus" "google.golang.org/grpc/metadata" "google.golang.org/protobuf/types/known/wrapperspb" ) @@ -23,103 +22,89 @@ type ApiIdMap map[string]interface{} var unique_id_count = int32(1) type SpanSender struct { - sequenceId int32 - idMap ApiIdMap - Md metadata.MD - exitCh chan bool + sequenceId int32 + idMap ApiIdMap + Md metadata.MD + // exitCh chan bool + ctx context.Context spanMessageBufferCh chan *v1.PSpanMessage sendStreamRespCh chan int32 wg *sync.WaitGroup - log *log.Entry + log *logrus.Entry + config *common.Config } -func createSpanSender(base metadata.MD, exitCh chan bool, agent_wg *sync.WaitGroup, log *log.Entry) *SpanSender { +func createSpanSender(base metadata.MD, ctx context.Context, agent_wg *sync.WaitGroup, config *common.Config, entry *logrus.Entry) *SpanSender { sender := &SpanSender{ - Md: base, - exitCh: exitCh, - idMap: make(ApiIdMap), - wg: agent_wg, - log: log, + Md: base, + ctx: ctx, + idMap: make(ApiIdMap), + wg: agent_wg, + log: entry, + config: config, + spanMessageBufferCh: make(chan *v1.PSpanMessage, config.AgentChannelSize), + sendStreamRespCh: make(chan int32, 1), } - sender.Init() + sender.StartServe() return sender } -func (spanSender *SpanSender) sendSpan() { - config := common.GetConfig() - conn, err := common.CreateGrpcConnection(config.SpanAddress) +func (s *SpanSender) Stop() {} + +func (s *SpanSender) sendSpan() { + conn, err := s.config.CreateGrpcConnection(s.ctx, s.config.User.SpanAddress) if err != nil { - spanSender.log.Warnf("connect:%s failed. %s", config.SpanAddress, err) + s.log.Warnf("connect:%s failed. %s", s.config.User.SpanAddress, err) return } defer conn.Close() client := v1.NewSpanClient(conn) - ctx := metadata.NewOutgoingContext(context.Background(), spanSender.Md) - + ctx := metadata.NewOutgoingContext(s.ctx, s.Md) stream, err := client.SendSpan(ctx) if err != nil { - spanSender.log.Warnf("create stream failed. %s", err) + s.log.Warnf("create stream failed. %s", err) return } defer stream.CloseSend() - - // for span := range spanSender.spanMessageBufferCh { - // spanSender.log.Debugf("send %v", span) - - // if err := stream.Send(span); err != nil { - // spanSender.log.Warnf("send span failed with:%s", err) - // // response the stream is not available - // spanSender.sendStreamRespCh <- 500 - // return - // } - // } - // watch exitCh for { select { - case span := <-spanSender.spanMessageBufferCh: - spanSender.log.Debugf("send %v", span) + case span := <-s.spanMessageBufferCh: + s.log.Debugf("send %v", span) if err := stream.Send(span); err != nil { - spanSender.log.Warnf("send span failed with:%s", err) + s.log.Warnf("send span failed with:%s", err) // response the stream is not available - spanSender.sendStreamRespCh <- 500 + s.sendStreamRespCh <- 500 return } - case <-spanSender.exitCh: - spanSender.log.Warn("sendSpan failed with agent exiting") + case <-s.ctx.Done(): + s.log.Warn("sendSpan failed with agent exiting") return } } } -func (spanSender *SpanSender) sendThread() { +func (spanSender *SpanSender) sendTask() { defer spanSender.wg.Done() for { spanSender.sendSpan() - config := common.GetConfig() - if common.WaitChannelEvent(spanSender.exitCh, config.SpanTimeWait) == common.E_AGENT_STOPPING { + if common.WaitEventsWithTime(spanSender.ctx, spanSender.config.SpanTimeWait) == common.E_AGENT_STOPPING { break } } spanSender.log.Info("sendThread exit") } -func (spanSender *SpanSender) Init() { - // spanSender.sqlMeta = MetaData{MetaDataType: common.META_SQL_UID, IDMap: make(PARAMS_TYPE), Sender: spanSender} - // spanSender.apiMeta = MetaData{MetaDataType: common.META_API, IDMap: make(PARAMS_TYPE), Sender: spanSender} - // spanSender.stringMeta = MetaData{MetaDataType: common.META_STRING, IDMap: make(PARAMS_TYPE), Sender: spanSender} - - spanSender.spanMessageBufferCh = make(chan *v1.PSpanMessage, common.GetConfig().AgentChannelSize) - spanSender.sendStreamRespCh = make(chan int32, 1) - spanSender.log.Debug("SpanSender::Init span spanSender thread start") - for i := int32(0); i < common.GetConfig().SpanStreamParallelismSize; i++ { +func (spanSender *SpanSender) StartServe() { + spanSender.log.Debug("SpanSender::StartServe span spanSender thread start") + for i := int32(0); i < spanSender.config.SpanStreamParallelismSize; i++ { spanSender.wg.Add(1) - go spanSender.sendThread() + go spanSender.sendTask() } - spanSender.log.Debug("SpanSender::Init done") + spanSender.log.Debug("SpanSender::StartServe done") } func (spanSender *SpanSender) cleanAllMetaData() { @@ -127,22 +112,11 @@ func (spanSender *SpanSender) cleanAllMetaData() { spanSender.idMap = make(ApiIdMap) } -func (spanSender *SpanSender) makePinpointSpanEv(genSpan *v1.PSpan, spanEv *TSpanEvent, depth int32) error { - if pbSpanEv, err := spanSender.createPinpointSpanEv(spanEv); err == nil { - pbSpanEv.Sequence = spanSender.sequenceId - spanSender.sequenceId += 1 - pbSpanEv.Depth = depth - genSpan.SpanEvent = append(genSpan.SpanEvent, pbSpanEv) - for _, call := range spanEv.Calls { - spanSender.makePinpointSpanEv(genSpan, call, depth+1) - } - return nil - } else { - return err - } +func (spanSender *SpanSender) makeSpanEvent(spanEv *TSpanEvent) *v1.PSpanEvent { + return spanSender.createPinpointSpanEv(spanEv) } -func (spanSender *SpanSender) getMetaApiId(name string, metaType int32) int32 { +func (spanSender *SpanSender) getMetaApiId(name string, metaType common.Meta_Type) int32 { id, ok := spanSender.idMap[name] if ok { return id.(int32) @@ -168,10 +142,24 @@ func (spanSender *SpanSender) getSqlUidMetaApiId(name string) []byte { } } -func (spanSender *SpanSender) createPinpointSpanEv(spanEv *TSpanEvent) (*v1.PSpanEvent, error) { - pbSpanEv := &v1.PSpanEvent{} +func (spanSender *SpanSender) createPinpointSpanEv(spanEv *TSpanEvent) *v1.PSpanEvent { + pbSpanEv := &v1.PSpanEvent{ + StartElapsed: spanEv.GetStartElapsed(), + EndElapsed: spanEv.GetEndElapsed(), + ServiceType: spanEv.ServiceType, + Depth: spanEv.Depth, + Sequence: spanEv.Sequence, + AsyncEvent: spanEv.AsyId, + } - pbSpanEv.ApiId = spanSender.getMetaApiId(spanEv.Name, common.META_Default_api) + // TODO check serverType is 100 ,100 should be META_INVOCATION_API + // from https://github.com/pinpoint-apm/pinpoint/blob/91af11b99d94c7ce5076a8bf468bf02480eb129d/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/method/AsyncMethodDescriptor.java#L26 + const API_INVOCATION_SERVICE_TYPE = 100 + if spanEv.ServiceType == API_INVOCATION_SERVICE_TYPE { + pbSpanEv.ApiId = spanSender.getMetaApiId(spanEv.Name, common.META_INVOCATION_API) + } else { + pbSpanEv.ApiId = spanSender.getMetaApiId(spanEv.Name, common.META_Default_api) + } if len(spanEv.ExceptionInfo) > 0 { id := spanSender.getMetaApiId("___EXP___", common.META_String_api) @@ -181,7 +169,7 @@ func (spanSender *SpanSender) createPinpointSpanEv(spanEv *TSpanEvent) (*v1.PSpa pbSpanEv.ExceptionInfo.StringValue = &stringValue } - nextEv := v1.PMessageEvent{ + nextEv := &v1.PMessageEvent{ DestinationId: spanEv.DestinationId, NextSpanId: spanEv.NextSpanId, EndPoint: spanEv.EndPoint, @@ -189,15 +177,11 @@ func (spanSender *SpanSender) createPinpointSpanEv(spanEv *TSpanEvent) (*v1.PSpa pbSpanEv.NextEvent = &v1.PNextEvent{ Field: &v1.PNextEvent_MessageEvent{ - MessageEvent: &nextEv}, + MessageEvent: nextEv, + }, } - pbSpanEv.StartElapsed = spanEv.GetStartElapsed() - - pbSpanEv.EndElapsed = spanEv.GetEndElapsed() - - pbSpanEv.ServiceType = spanEv.ServiceType - for _, ann := range spanEv.Clues { + for _, ann := range spanEv.Annotations { iColon := strings.Index(ann, ":") if value, err := strconv.ParseInt(ann[0:iColon], 10, 32); err == nil { stringValue := v1.PAnnotationValue_StringValue{StringValue: ann[iColon+1:]} @@ -213,12 +197,12 @@ func (spanSender *SpanSender) createPinpointSpanEv(spanEv *TSpanEvent) (*v1.PSpa } } - if len(spanEv.SqlMeta) > 0 { - id := spanSender.getSqlUidMetaApiId(spanEv.SqlMeta) + if spanEv.SqlMeta != nil { + id := spanSender.getSqlUidMetaApiId(*spanEv.SqlMeta) sqlByteSv := &v1.PBytesStringStringValue{ BytesValue: id, StringValue1: &wrappers.StringValue{ - Value: spanEv.SqlMeta, + Value: *spanEv.SqlMeta, }, } pbSpanEv.Annotation = append(pbSpanEv.Annotation, &v1.PAnnotation{ @@ -231,28 +215,41 @@ func (spanSender *SpanSender) createPinpointSpanEv(spanEv *TSpanEvent) (*v1.PSpa }) } - return pbSpanEv, nil + return pbSpanEv +} + +func (spanSender *SpanSender) makeSpanChunk(span *TSpan) (*v1.PSpanChunk, error) { + chunk := &v1.PSpanChunk{Version: 1, + TransactionId: common.TypeV1_String_TransactionId(span.TransactionId), + SpanId: span.SpanId, + KeyTime: span.GetStartTime(), + ApplicationServiceType: span.AppServerType, + EndPoint: span.EndPoint, + LocalAsyncId: &v1.PLocalAsyncId{ + AsyncId: span.LocalAsyncId.AsyncId, + Sequence: span.LocalAsyncId.Sequence, + }, + } + return chunk, nil } func (spanSender *SpanSender) makePinpointSpan(span *TSpan) (*v1.PSpan, error) { spanSender.sequenceId = 0 - pbSpan := &v1.PSpan{} - pbSpan.Version = 1 - pbSpan.ApiId = spanSender.getMetaApiId(span.GetAppid(), common.META_Web_request_api) - - pbSpan.ServiceType = span.ServerType - - pbSpan.ApplicationServiceType = span.GetAppServerType() - - pbSpan.ParentSpanId = span.ParentSpanId - - pbSpan.TransactionId = common.TypeV1_String_TransactionId(span.TransactionId) - - pbSpan.SpanId = span.SpanId - - pbSpan.StartTime = span.GetStartTime() + pbSpan := &v1.PSpan{ + ParentSpanId: -1, + Version: 1, + ServiceType: span.ServerType, + ApplicationServiceType: span.GetAppServerType(), + SpanId: span.SpanId, + StartTime: span.GetStartTime(), + Elapsed: span.GetElapsedTime(), + TransactionId: common.TypeV1_String_TransactionId(span.TransactionId), + ApiId: spanSender.getMetaApiId(span.SpanName, common.META_Web_request_api), + } - pbSpan.Elapsed = span.GetElapsedTime() + if span.ParentSpanId > 0 { + pbSpan.ParentSpanId = span.ParentSpanId + } parentInfo := v1.PParentInfo{ ParentApplicationName: span.ParentApplicationName, @@ -260,7 +257,12 @@ func (spanSender *SpanSender) makePinpointSpan(span *TSpan) (*v1.PSpan, error) { AcceptorHost: span.AcceptorHost, } - acceptEv := v1.PAcceptEvent{Rpc: span.Uri, EndPoint: span.EndPoint, RemoteAddr: span.RemoteAddr, ParentInfo: &parentInfo} + acceptEv := v1.PAcceptEvent{ + Rpc: span.Uri, + EndPoint: span.EndPoint, + RemoteAddr: span.RemoteAddr, + ParentInfo: &parentInfo, + } pbSpan.AcceptEvent = &acceptEv // changes: ERRs's priority bigger EXP, so ERR will replace EXP @@ -282,7 +284,7 @@ func (spanSender *SpanSender) makePinpointSpan(span *TSpan) (*v1.PSpan, error) { } } - for _, annotation := range span.Clues { + for _, annotation := range span.Annotations { iColon := strings.Index(annotation, ":") if iColon > 0 { if value, err := strconv.ParseInt(annotation[0:iColon], 10, 32); err == nil { @@ -301,26 +303,26 @@ func (spanSender *SpanSender) makePinpointSpan(span *TSpan) (*v1.PSpan, error) { // collector data from nginx-header if len(span.NginxHeader) > 0 { - pvalue := v1.PAnnotationValue_LongIntIntByteByteStringValue{ + ann := v1.PAnnotationValue_LongIntIntByteByteStringValue{ LongIntIntByteByteStringValue: &v1.PLongIntIntByteByteStringValue{}, } - pvalue.LongIntIntByteByteStringValue.IntValue1 = 2 + ann.LongIntIntByteByteStringValue.IntValue1 = 2 ngFormat := common.ParseStringField(span.NginxHeader) if value, OK := ngFormat["D"]; OK { if value, err := common.ParseDotFormatToTime(value); err == nil { - pvalue.LongIntIntByteByteStringValue.IntValue2 = int32(value) + ann.LongIntIntByteByteStringValue.IntValue2 = int32(value) } } if value, OK := ngFormat["t"]; OK { if value, err := common.ParseDotFormatToTime(value); err == nil { - pvalue.LongIntIntByteByteStringValue.LongValue = value + ann.LongIntIntByteByteStringValue.LongValue = value } } annotation := v1.PAnnotation{ Key: 300, Value: &v1.PAnnotationValue{ - Field: &pvalue, + Field: &ann, }, } pbSpan.Annotation = append(pbSpan.Annotation, &annotation) @@ -366,27 +368,40 @@ func (spanSender *SpanSender) makePinpointSpan(span *TSpan) (*v1.PSpan, error) { return pbSpan, nil } -func (spanSender *SpanSender) makeSpan(span *TSpan) (*v1.PSpan, error) { - if pSpan, err := spanSender.makePinpointSpan(span); err == nil { - for _, call := range span.Calls { - spanSender.makePinpointSpanEv(pSpan, call, 1) - } - return pSpan, nil +func (spanSender *SpanSender) makeSpanOrSpanChunk(span *TSpan) (*v1.PSpan, *v1.PSpanChunk, error) { + + var spanEv []*v1.PSpanEvent + for _, call := range span.Follows { + spanEv = append(spanEv, spanSender.makeSpanEvent(call)) + } + + if span.LocalAsyncId == nil { + pSpan, _ := spanSender.makePinpointSpan(span) + pSpan.SpanEvent = spanEv + return pSpan, nil, nil } else { - return nil, err + chunk, _ := spanSender.makeSpanChunk(span) + chunk.SpanEvent = spanEv + return nil, chunk, nil } } func (spanSender *SpanSender) Interceptor(span *TSpan) bool { spanSender.log.Debug("span spanSender interceptor") - if pbSpan, err := spanSender.makeSpan(span); err == nil { - // recv the channel status - select { - case spanSender.spanMessageBufferCh <- &v1.PSpanMessage{ - Field: &v1.PSpanMessage_Span{ + if pbSpan, pbChunk, err := spanSender.makeSpanOrSpanChunk(span); err == nil { + spanMessage := &v1.PSpanMessage{} + if pbSpan != nil { + spanMessage.Field = &v1.PSpanMessage_Span{ Span: pbSpan, - }, - }: + } + } else { + spanMessage.Field = &v1.PSpanMessage_SpanChunk{ + SpanChunk: pbChunk, + } + } + + select { + case spanSender.spanMessageBufferCh <- spanMessage: case statusCode := <-spanSender.sendStreamRespCh: spanSender.log.Warnf("span send stream is offline statusCode:%d, clear all string/sql/api meta data", statusCode) spanSender.cleanAllMetaData() @@ -399,40 +414,42 @@ func (spanSender *SpanSender) Interceptor(span *TSpan) bool { return true } -func (spanSender *SpanSender) SenderGrpcMetaData(name string, metaType int32) error { - config := common.GetConfig() - conn, err := common.CreateGrpcConnection(config.AgentAddress) +func (spanSender *SpanSender) SenderGrpcMetaData(name string, metaType common.Meta_Type) { + conn, err := spanSender.config.CreateGrpcConnection(spanSender.ctx, spanSender.config.User.AgentAddress) if err != nil { - spanSender.log.Warnf("connect:%s failed. %s", config.AgentAddress, err) - return errors.New("SenderGrpcMetaData: connect failed") + spanSender.log.Warnf("connect:%s failed. %s", spanSender.config.User.AgentAddress, err) + return } defer conn.Close() client := v1.NewMetadataClient(conn) - ctx, cancel := common.BuildPinpointCtx(config.MetaDataTimeWait, spanSender.Md) + ctx, cancel := context.WithTimeout(spanSender.ctx, spanSender.config.MetaDataTimeWait) + + ctx = metadata.NewOutgoingContext(ctx, spanSender.Md) + defer cancel() switch metaType { case common.META_Default_api: { id := spanSender.idMap[name].(int32) - apiMeta := v1.PApiMetaData{ApiId: id, ApiInfo: name, Type: common.API_DEFAULT} + apiMeta := v1.PApiMetaData{ApiId: id, ApiInfo: name, Type: int32(common.API_DEFAULT)} if _, err = client.RequestApiMetaData(ctx, &apiMeta); err != nil { spanSender.log.Warnf("agentOnline api meta failed %s", err) - return errors.New("SenderGrpcMetaData: PApiMetaData failed") + delete(spanSender.idMap, name) } } case common.META_Web_request_api: { id := spanSender.idMap[name].(int32) - apiMeta := v1.PApiMetaData{ApiId: id, ApiInfo: name, Type: common.API_WEB_REQUEST} + apiMeta := v1.PApiMetaData{ApiId: id, ApiInfo: name, Type: int32(common.API_WEB_REQUEST)} if _, err = client.RequestApiMetaData(ctx, &apiMeta); err != nil { spanSender.log.Warnf("agentOnline api meta failed %s", err) - return errors.New("SenderGrpcMetaData: PApiMetaData failed") + delete(spanSender.idMap, name) } } case common.META_String_api: @@ -445,7 +462,7 @@ func (spanSender *SpanSender) SenderGrpcMetaData(name string, metaType int32) er if _, err = client.RequestStringMetaData(ctx, &metaMeta); err != nil { spanSender.log.Warnf("agentOnline api meta failed %s", err) - return errors.New("SenderGrpcMetaData: RequestStringMetaData failed") + delete(spanSender.idMap, name) } } @@ -458,13 +475,21 @@ func (spanSender *SpanSender) SenderGrpcMetaData(name string, metaType int32) er } if _, err = client.RequestSqlUidMetaData(ctx, &sqlUidMeta); err != nil { spanSender.log.Warnf("agentOnline api meta failed %s", err) - return errors.New("SenderGrpcMetaData: RequestSqlUidMetaData failed") + delete(spanSender.idMap, name) + } + } + case common.META_INVOCATION_API: + { + id := spanSender.idMap[name].(int32) + apiMeta := v1.PApiMetaData{ApiId: id, ApiInfo: name, Type: int32(common.API_INVOCATION)} + if _, err = client.RequestApiMetaData(ctx, &apiMeta); err != nil { + spanSender.log.Warnf("agentOnline api meta failed %s", err) + delete(spanSender.idMap, name) } } default: spanSender.log.Warnf("SenderGrpcMetaData: No such Type:%d", metaType) } - spanSender.log.Debugf("send metaData %s", name) - return nil + spanSender.log.Debugf("send metaData name:%s type:%d ", name, metaType) } diff --git a/collector-agent/agent/SpanSender_test.go b/collector-agent/agent/SpanSender_test.go index fdbe90513..0c301c049 100644 --- a/collector-agent/agent/SpanSender_test.go +++ b/collector-agent/agent/SpanSender_test.go @@ -1,17 +1,17 @@ package agent import ( + "context" "sync" "testing" - log "github.com/sirupsen/logrus" + "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/common" ) func TestSqlUidFormat(t *testing.T) { - // test chan - exitCh := make(chan bool) // chan bool var wg sync.WaitGroup - sender := createSpanSender(nil, exitCh, &wg, log.WithField("test", nil)) + config := common.CreateTestConfig() + sender := createSpanSender(nil, context.Background(), &wg, config, config.LogEntry) id := sender.getSqlUidMetaApiId("INSERT INTO chengji_m VALUES (%s, %s, %s)") t.Logf("%v", string(id)) diff --git a/collector-agent/agent/Stat.go b/collector-agent/agent/Stat.go deleted file mode 100644 index d043eceb6..000000000 --- a/collector-agent/agent/Stat.go +++ /dev/null @@ -1,80 +0,0 @@ -package agent - -import ( - "time" - - "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/common" - v1 "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/pinpoint-grpc-idl-go/proto/v1" - - "github.com/shirou/gopsutil/cpu" - "github.com/shirou/gopsutil/v3/mem" -) - -//type convert func(int) string - -type GetMaxAvg func() (max, avg uint32) -type GetReqTimeCounter func() [4]uint16 - -func CollectPStateMessage(getMaxAvr GetMaxAvg, getReqTimeCounter GetReqTimeCounter) *v1.PStatMessage { - config := common.GetConfig() - max, avg := getMaxAvr() - responseTime := v1.PResponseTime{ - Max: int64(max), - Avg: int64(avg), - } - - v, _ := mem.VirtualMemory() - - jvmGc := v1.PJvmGc{ - Type: v1.PJvmGcType_JVM_GC_TYPE_PARALLEL, - JvmMemoryHeapUsed: int64(v.Used), - JvmMemoryHeapMax: int64(v.Total), - JvmMemoryNonHeapUsed: int64(v.Buffers), - JvmMemoryNonHeapMax: int64(v.Cached), - JvmGcOldCount: 0, - JvmGcOldTime: 0, - JvmGcDetailed: &v1.PJvmGcDetailed{}, - } - // cpu.Percent calcuate cpu in config.StatInterval - totalPer, _ := cpu.Percent(config.StatInterval*time.Second, false) - totalCpuUsage := totalPer[0] / 100 - cpuload := v1.PCpuLoad{ - SystemCpuLoad: totalCpuUsage, - JvmCpuLoad: totalCpuUsage, - } - var activeTraceCount []int32 - for _, value := range getReqTimeCounter() { - activeTraceCount = append(activeTraceCount, int32(value)) - } - - agentStat := v1.PAgentStat{ - ResponseTime: &responseTime, - Gc: &jvmGc, - CollectInterval: int64(config.StatInterval), - Timestamp: int64(time.Now().UnixNano() / int64(time.Millisecond)), - CpuLoad: &cpuload, - Transaction: &v1.PTransaction{}, - ActiveTrace: &v1.PActiveTrace{ - Histogram: &v1.PActiveTraceHistogram{ - Version: 1, - HistogramSchemaType: 2, //NORMAL SCHEMA - ActiveTraceCount: activeTraceCount, - }, - }, - DataSourceList: nil, - Deadlock: nil, - FileDescriptor: nil, - DirectBuffer: nil, - Metadata: "", - } - - pStateAgentStat := v1.PStatMessage_AgentStat{ - AgentStat: &agentStat, - } - - sateMessage := v1.PStatMessage{ - Field: &pStateAgentStat, - } - - return &sateMessage -} diff --git a/collector-agent/agent/UrlTemplate.go b/collector-agent/agent/UrlTemplate.go index 9e176766f..c6780d8ae 100644 --- a/collector-agent/agent/UrlTemplate.go +++ b/collector-agent/agent/UrlTemplate.go @@ -53,6 +53,8 @@ type UrlTemplateReport struct { mu sync.Mutex } +func (utr *UrlTemplateReport) Stop() {} + func (utr *UrlTemplateReport) Interceptor(span *TSpan) bool { if len(span.UT) > 0 { // found uri templated diff --git a/collector-agent/agent/UrlTemplate_test.go b/collector-agent/agent/UrlTemplate_test.go index 8ed71d33d..cf000b0b8 100644 --- a/collector-agent/agent/UrlTemplate_test.go +++ b/collector-agent/agent/UrlTemplate_test.go @@ -7,24 +7,27 @@ import ( ) func TestUrlTemplateReport(t *testing.T) { + + uri := "/hello" + uri_1 := "/hello_exp" spans := []TSpan{ { - UT: "/hello", + UT: uri, Uri: "/hello", ElapsedTime: 32, }, { - UT: "/hello", + UT: uri, Uri: "/hello", ElapsedTime: 320, }, { - UT: "/hello", + UT: uri, Uri: "/hello", ElapsedTime: 3200, }, { - UT: "/hello_exp", + UT: uri_1, Uri: "/hello", ElapsedTime: 32000, ExceptionInfo: "exp", diff --git a/collector-agent/agent/spanChunk.yaml b/collector-agent/agent/spanChunk.yaml new file mode 100644 index 000000000..3a429c3d3 --- /dev/null +++ b/collector-agent/agent/spanChunk.yaml @@ -0,0 +1,42 @@ +spanChunk +{ +version: 1 +transactionId { agentStartTime: 1603785846801 sequence: 4 } +spanId: -2310501016293025621 +endPoint: "localhost:38080" +spanEvent { depth: 1 endElapsed: 193 serviceType: 100 apiId: 1 } +spanEvent { sequence: 1 depth: 2 endElapsed: 193 serviceType: 9054 apiId: 1269 } +spanEvent { sequence: 2 depth: 3 endElapsed: 193 serviceType: 9054 apiId: 1266 } +spanEvent { sequence: 3 depth: 4 startElapsed: 7 endElapsed: 46 serviceType: 9053 apiId: 577 } +spanEvent { sequence: 4 depth: 5 startElapsed: 25 endElapsed: 9 serviceType: 9053 annotation { key: 48 value { stringValue: "naver.com:80" } } apiId: 1270 } s +panEvent { sequence: 5 startElapsed: 11 endElapsed: 8 serviceType: 9052 annotation { key: 40 value { stringValue: "/" } } annotation { key: 46 value { intValue: 301 } } annotation { key: 49 value { intBooleanIntBooleanValue { intValue2: 6 } } } apiId: 581 nextEvent { messageEvent { nextSpanId: -598520380655700791 destinationId: "naver.com" } } } +spanEvent { sequence: 6 depth: 4 startElapsed: 14 endElapsed: 14 serviceType: 9053 apiId: 577 } +spanEvent { sequence: 7 depth: 5 endElapsed: 9 serviceType: 9053 annotation { key: 48 value { stringValue: "www.naver.com:80" } } apiId: 1270 } +spanEvent { sequence: 8 startElapsed: 9 endElapsed: 5 serviceType: 9052 annotation { key: 40 value { stringValue: "/" } } annotation { key: 46 value { intValue: 302 } } annotation { key: 49 value { intBooleanIntBooleanValue { intValue2: 5 } } } apiId: 581 nextEvent { messageEvent { nextSpanId: 3587956703181255046 destinationId: "www.naver.com" } } } +spanEvent { sequence: 9 depth: 4 startElapsed: 6 endElapsed: 120 serviceType: 9053 apiId: 577 } +spanEvent { sequence: 10 depth: 5 endElapsed: 94 serviceType: 9053 annotation { key: 48 value { stringValue: "www.naver.com:443" } } apiId: 1270 } +spanEvent { sequence: 11 startElapsed: 94 endElapsed: 23 serviceType: 9052 annotation { key: 40 value { stringValue: "/" } } annotation { key: 46 value { intValue: 200 } } annotation { key: 49 value { intBooleanIntBooleanValue { intValue2: 23 } } } apiId: 581 nextEvent { messageEvent { nextSpanId: 395410527152755259 destinationId: "www.naver.com" } } } +applicationServiceType: 1010 +keyTime: 1603785892805 +localAsyncId { asyncId: 1 sequence: 1 } +} + +span +{ +version: 1 +transactionId { agentStartTime: 1603785846801 sequence: 4 } +spanId: -2310501016293025621 +parentSpanId: -1 +startTime: 1603785892765 +elapsed: 257 +apiId: 4 +serviceType: 1010 +acceptEvent { rpc: "/google/httpclient/apachehttp/executeAsync.pinpoint" endPoint: "localhost:38080" remoteAddr: "0:0:0:0:0:0:0:1" } +annotation { key: 46 value { intValue: 200 } } +spanEvent { depth: 1 startElapsed: 1 endElapsed: 256 serviceType: 1011 apiId: 3 } +spanEvent { sequence: 1 depth: 2 endElapsed: 256 serviceType: 5051 apiId: 5 } +spanEvent { sequence: 2 depth: 3 startElapsed: 2 endElapsed: 236 serviceType: 5071 apiId: 1006 } +spanEvent { sequence: 3 depth: 4 startElapsed: 30 endElapsed: 6 serviceType: 9054 apiId: 1267 asyncEvent: 1 } +applicationServiceType: 1010 +} + diff --git a/collector-agent/common/Defines.go b/collector-agent/common/Defines.go index 7ae5dcb98..2c37250a6 100644 --- a/collector-agent/common/Defines.go +++ b/collector-agent/common/Defines.go @@ -1,11 +1,19 @@ package common -const API_WEB_REQUEST = 100 -const API_DEFAULT = 0 +type Api_Type int const ( - META_Default_api = iota - META_Web_request_api = iota - META_String_api = iota - META_Sql_uid_api = iota + API_WEB_REQUEST Api_Type = 100 + API_DEFAULT Api_Type = 0 + API_INVOCATION Api_Type = 200 +) + +type Meta_Type int32 + +const ( + META_Default_api Meta_Type = iota + META_Web_request_api + META_String_api + META_Sql_uid_api + META_INVOCATION_API ) diff --git a/collector-agent/common/Utils.go b/collector-agent/common/Utils.go index 1788699cd..7e0fd24f3 100644 --- a/collector-agent/common/Utils.go +++ b/collector-agent/common/Utils.go @@ -2,14 +2,12 @@ package common import ( "context" - "errors" "fmt" "strconv" "strings" "time" v1 "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/pinpoint-grpc-idl-go/proto/v1" - "google.golang.org/grpc" "google.golang.org/grpc/metadata" ) @@ -38,42 +36,32 @@ func ParseDotFormatToTime(v string) (int64, error) { return sec*1000 + ms, nil } } - return 0, errors.New(fmt.Sprintf("input:%s is invalid", v)) + return 0, fmt.Errorf("input:%s is invalid", v) } -func WaitChannelEvent(doneCh chan bool, sec time.Duration) E_AGENT_STATUS { +func WaitEventsWithTime(ctx context.Context, dur time.Duration) E_AGENT_STATUS { select { - case <-doneCh: + case <-ctx.Done(): return E_AGENT_STOPPING - case <-time.After(sec * time.Second): + case <-time.After(dur): return E_AGENT_GOON } } -func BuildPinpointCtx(sec time.Duration, md metadata.MD) (ctx context.Context, cancel context.CancelFunc) { - if sec == -1 { +func BuildMdContextWithTimeout(dur time.Duration, md metadata.MD) (ctx context.Context, cancel context.CancelFunc) { + if dur == -1 { ctx = context.Background() //cancel = nil ctx = metadata.NewOutgoingContext(ctx, md) return ctx, nil } else { - ctx, cancel = context.WithTimeout(context.Background(), sec*time.Second) + ctx, cancel = context.WithTimeout(context.Background(), dur) ctx = metadata.NewOutgoingContext(ctx, md) return ctx, cancel } } -func CreateGrpcConnection(address string) (*grpc.ClientConn, error) { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*config.GrpcConTextTimeOut) - defer cancel() - conn, err := grpc.DialContext(ctx, address, GetDialOption()...) - if err != nil { - return nil, err - } - return conn, nil -} - func TypeV1_String_TransactionId(tid_s string) *v1.PTransactionId { tidFormat := strings.Split(tid_s, "^") if len(tidFormat) < 3 { diff --git a/collector-agent/common/config.go b/collector-agent/common/config.go index 8dca7988f..cb392dd21 100644 --- a/collector-agent/common/config.go +++ b/collector-agent/common/config.go @@ -1,26 +1,45 @@ package common import ( + "context" "fmt" + "io" "net" "os" + "path" + "strings" "time" v1 "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/pinpoint-grpc-idl-go/proto/v1" + "github.com/sirupsen/logrus" + prefixed "github.com/x-cray/logrus-prefixed-formatter" "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "gopkg.in/natefinch/lumberjack.v2" ) -type Config struct { - SocketType string - Address string - StatAddress string +type UserSetting struct { + RecvBufSize int // default is 4k + BindAddress string SpanAddress string AgentAddress string + StatAddress string + Container bool + LoggerLevel string + LoggerDir string + LogStdout bool + Profile bool +} + +func (u *UserSetting) String() string { + return fmt.Sprintf("{RecvBufSize:%v BindAddress:%v SpanAddress:%v AgentAddress:%v StatAddress:%v}", u.RecvBufSize, u.BindAddress, u.SpanAddress, u.AgentAddress, u.StatAddress) +} + +type Config struct { + Log *logrus.Logger + LogEntry *logrus.Entry + GrpcOption []grpc.DialOption - WebPorts int16 - LoggerLevel string - LoggerDir string - // tuning AgentChannelSize uint64 SpanStreamParallelismSize int32 @@ -30,35 +49,26 @@ type Config struct { SpanTimeWait time.Duration MetaDataTimeWait time.Duration GrpcConTextTimeOut time.Duration - // agent auto offline after xxxx - AgentFreeOnlineSurvivalTimeSec time.Duration - // agentInfo - HostName string - HostIp string - Pid int32 - StartTime int64 - ServerType int32 - Container bool + AgentRetireTime time.Duration + HostName string + HostIp string + Pid int32 + StartTime int64 + User *UserSetting } -var config = &Config{ - WebPorts: 80, - AgentChannelSize: 1000, - SpanStreamParallelismSize: 2, - AgentReTryTimeout: 10, - PingInterval: 300, - StatInterval: 5, - SpanTimeWait: 10, - MetaDataTimeWait: 10, - GrpcConTextTimeOut: 5, - AgentFreeOnlineSurvivalTimeSec: 1 * 60 * 60, // 1 hour - ServerType: 1700, // PHP - LoggerLevel: "DEBUG", - LoggerDir: "/tmp/", - StartTime: time.Now().Unix(), - Pid: int32(os.Getgid()), - HostName: getHostName(), - HostIp: lookupIpFromName(getHostName()), +func (c *Config) ParseServerAddress() (socket_type string, address string) { + raw_address := c.User.BindAddress + + if strings.HasPrefix(raw_address, "sock") { + // /tmp/pinpoint.sock + // a very loose checking + // assume a file + return "unix", address + } else { + // like 0.0.0.0:5689 + return "tcp", strings.Replace(raw_address, "@", ":", 1) + } } func getHostName() string { @@ -69,7 +79,7 @@ func getHostName() string { return name } -func lookupIpFromName(name string) string { +func lookupIpFromName() string { conn, err := net.Dial("udp", "8.8.8.8:80") if err == nil { defer conn.Close() @@ -79,55 +89,98 @@ func lookupIpFromName(name string) string { return "127.0.0.1" } -//var once sync.Once - -func GetConfig() *Config { - //once.Do( - // func() { - // //tuning - // config = &Config{ - // WebPorts: 80, - // AgentChannelSize: 1000, - // SpanStreamParallelismSize: 2, - // AgentReTryTimeout: 10, - // PingInterval: 300, - // StatInterval: 300, - // SpanTimeWaitSec: 10, - // MetaDataTimeWaitSec: 10, - // - // ServerType: 1700, // PHP - // LoggerLevel: "DEBUG", - // LoggerDir: "/tmp/", - // StartTime: time.Now().Unix(), - // Pid: int32(os.Getgid()), - // } - // }) +func CreateDefaultConfig() *Config { + config := &Config{ + AgentChannelSize: 1000, + SpanStreamParallelismSize: 2, + AgentReTryTimeout: 10 * time.Second, + PingInterval: 5 * time.Minute, + StatInterval: 5 * time.Second, + SpanTimeWait: 10 * time.Second, + MetaDataTimeWait: 10 * time.Second, + GrpcConTextTimeOut: 5 * time.Second, + AgentRetireTime: 1 * time.Hour, + StartTime: time.Now().Unix(), + Pid: int32(os.Getgid()), + HostName: getHostName(), + HostIp: lookupIpFromName(), + Log: logrus.New(), + } + config.GrpcOption = append(config.GrpcOption, + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithBlock()) + config.LogEntry = config.Log.WithField("id", "main") return config } -/** -WithInsecure,WithBlock -*/ -func GetDialOption() []grpc.DialOption { - var opts []grpc.DialOption - opts = append(opts, grpc.WithInsecure()) - opts = append(opts, grpc.WithBlock()) - return opts +func CreateTestConfig() *Config { + config := CreateDefaultConfig() + user := &UserSetting{ + AgentAddress: "dev-pinpoint:9991", + SpanAddress: "dev-pinpoint:9993", + StatAddress: "dev-pinpoint:9992", + LoggerLevel: "debug", + LogStdout: true, + RecvBufSize: 4 * 1024, + } + config.User = user + config.InitLogger() + return config } -func GetPBAgentInfo(serverType int32) *v1.PAgentInfo { +func (config *Config) CreateGrpcConnection(parent_ctx context.Context, address string) (*grpc.ClientConn, error) { + ctx, cancel := context.WithTimeout(parent_ctx, config.GrpcConTextTimeOut) + defer cancel() + conn, err := grpc.DialContext(ctx, address, config.GrpcOption...) + if err != nil { + return nil, err + } + return conn, nil +} + +func (config *Config) InitLogger() { + if level, err := logrus.ParseLevel(config.User.LoggerLevel); err == nil { + config.Log.SetLevel(level) + } + + var log_writers []io.Writer + + if _, err := os.Stat(config.User.LoggerDir); err == nil { + + logFile := path.Join(config.User.LoggerDir, "collector.log") + // bind logger on the file + logger := &lumberjack.Logger{ + Filename: logFile, + MaxSize: 50, + MaxBackups: 50, + } + + log_writers = append(log_writers, logger) + } + + if config.User.LogStdout { + log_writers = append(log_writers, os.Stdout) + } + + config.Log.SetOutput(io.MultiWriter(log_writers...)) + + config.Log.SetFormatter(&prefixed.TextFormatter{ + ForceColors: true, + TimestampFormat: "2006-01-02 15:04:05.999", + FullTimestamp: true, + ForceFormatting: true, + }) +} + +func GetPBAgentInfo(serverType int32, config *Config) *v1.PAgentInfo { agentInfo := &v1.PAgentInfo{ Hostname: config.HostName, Ip: config.HostIp, Pid: config.Pid, ServiceType: serverType, - Container: config.Container, + Container: config.User.Container, EndTimestamp: -1, } return agentInfo } - -func (self *Config) String() string { - return fmt.Sprintf("SocketType:%s Address:%s StatAddress:%s SpanAddress:%s AgentAddress%s WebPorts:%d LoggerLevel:%s LoggerDir:%s AgentChannelSize:%d SpanStreamParallelismSize:%d AgentReTryTimeout:%s PingInterval:%d StatInterval:%d SpanTimeWaitSec:%d MetaDataTimeWaitSec:%d Pid:%d StartTime:%d ServerType:%d Container:%t", self.SocketType, self.Address, self.StatAddress, self.SpanAddress, self.AgentAddress, self.WebPorts, self.LoggerLevel, self.LoggerDir, self.AgentChannelSize, self.SpanStreamParallelismSize, self.AgentReTryTimeout, self.PingInterval, self.StatInterval, self.SpanTimeWait, self.MetaDataTimeWait, self.Pid, self.StartTime, self.ServerType, self.Container) -} diff --git a/collector-agent/go.mod b/collector-agent/go.mod index ffaf3e479..3c3680c13 100644 --- a/collector-agent/go.mod +++ b/collector-agent/go.mod @@ -1,6 +1,6 @@ module github.com/pinpoint-apm/pinpoint-c-agent/collector-agent -go 1.18 +go 1.19 require ( github.com/golang/protobuf v1.5.3 diff --git a/collector-agent/server.go b/collector-agent/server.go index b3a3f01a7..e775c57f4 100644 --- a/collector-agent/server.go +++ b/collector-agent/server.go @@ -1,39 +1,108 @@ package main import ( - // _ "net/http/pprof" - "flag" + "fmt" + "net/http" + _ "net/http/pprof" + "os" + "runtime" + "strconv" + "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/common" "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/server" - log "github.com/sirupsen/logrus" ) var ( - server_recv_buf = flag.Int("RecvBufSize", server.RECV_BUF_SIZE_DEF, "Set recv buf; eg: -RecvBufSize=409600") + agent_address = flag.String("AgentAddress", "localhost:9991", "Set recv buf; eg: -AgentAddress=localhost:9991") + span_address = flag.String("SpanAddress", "localhost:9991", "Set recv buf; eg: -SpanAddress=localhost:9993") + stat_address = flag.String("StatAddress", "localhost:9991", "Set recv buf; eg: -StatAddress=localhost:9992") + bind_address = flag.String("host", "", "server bind host and port information; eg: -host=0.0.0.0@10000") + in_container = flag.Bool("container", false, "collector-agent run in a pod or PM; eg: -container=true") + log_dir = flag.String("LogDir", os.TempDir(), "Set logging output directory; eg: -LogDir=/tmp") + log_stdout = flag.Bool("LogStdout", true, "enable net/http/pprof") + log_level = flag.String("LogLevel", "debug", "Set logging output level(debug/info/warn/error); eg: -LogLevel=info") + server_recv_buf = flag.Int("RecvBufSize", 4096*100, "Set recv buf; eg: -RecvBufSize=409600") + enable_profile = flag.Bool("EnableProfile", false, "enable net/http/pprof") ) -func initServerSetting() { - if *server_recv_buf > server.RECV_BUF_SIZE_DEF { - server.Setting.RecvBufSize = *server_recv_buf +func parseConfig() *common.Config { + setting := &common.UserSetting{ + RecvBufSize: *server_recv_buf, + BindAddress: *bind_address, + SpanAddress: *span_address, + AgentAddress: *agent_address, + StatAddress: *stat_address, + Container: *in_container, + LoggerLevel: *log_level, + LogStdout: *log_stdout, + LoggerDir: *log_dir, + Profile: *enable_profile, + } + if ip, ok := os.LookupEnv("PP_COLLECTOR_AGENT_SPAN_IP"); ok { + if port, ok := os.LookupEnv("PP_COLLECTOR_AGENT_SPAN_PORT"); ok { + setting.SpanAddress = fmt.Sprintf("%s:%s", ip, port) + } + } + + if ip, ok := os.LookupEnv("PP_COLLECTOR_AGENT_STAT_IP"); ok { + if port, ok := os.LookupEnv("PP_COLLECTOR_AGENT_STAT_PORT"); ok { + setting.StatAddress = fmt.Sprintf("%s:%s", ip, port) + } + } + + if ip, ok := os.LookupEnv("PP_COLLECTOR_AGENT_AGENT_IP"); ok { + if port, ok := os.LookupEnv("PP_COLLECTOR_AGENT_AGENT_PORT"); ok { + setting.AgentAddress = fmt.Sprintf("%s:%s", ip, port) + } + } + + if in, ok := os.LookupEnv("PP_COLLECTOR_AGENT_ISDOCKER"); ok { + if b, err := strconv.ParseBool(in); err == nil { + setting.Container = b + } + } + + if v, ok := os.LookupEnv("PP_Log_Level"); ok { + setting.LoggerLevel = v + } + + if v, ok := os.LookupEnv("PP_LOG_DIR"); ok { + setting.LoggerDir = v + } + + if v, ok := os.LookupEnv("PP_ADDRESS"); ok { + setting.BindAddress = v } + + config := common.CreateDefaultConfig() + config.User = setting + config.InitLogger() + return config } func main() { flag.Parse() - initServerSetting() + config := parseConfig() + + if config.User.Profile { + go func() { + log.Println(http.ListenAndServe("0.0.0.0:8081", nil)) + runtime.SetBlockProfileRate(1) + }() + } + + if config.User.BindAddress == "" { + flag.Usage() + return + } - server.InitServerConfig() - spanServer := server.SpanServer{} - // disable performance profile - // go func() { - // log.Println(http.ListenAndServe("0.0.0.0:8081", nil)) - // runtime.SetBlockProfileRate(1) - // }() + config.Log.Infof("Config:{%v}", config) + server := server.CreateServer(parseConfig()) - if _, err := spanServer.Run(); err != nil { - log.Warn("SpanServer is exit ....") + if _, err := server.Run(); err != nil { + config.Log.Warn("SpanServer is exit") } } diff --git a/collector-agent/server/Server.go b/collector-agent/server/Server.go new file mode 100644 index 000000000..62dc0e7d6 --- /dev/null +++ b/collector-agent/server/Server.go @@ -0,0 +1,309 @@ +package server + +import ( + "encoding/binary" + "encoding/json" + "fmt" + "math" + "net" + "os" + "os/signal" + "strconv" + "sync" + "sync/atomic" + "syscall" + "time" + + "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/agent" + "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/common" + + "github.com/sirupsen/logrus" +) + +var Version = "v0.6.4" + +type Server struct { + listener net.Listener + agentRouter agent.I_PacketRouter + createTime int64 + uniqueIDCounter int64 + lastTime int64 + config *common.Config + log *logrus.Logger +} + +func CreateServer(config *common.Config) *Server { + return &Server{ + config: config, + log: config.Log, + agentRouter: agent.CreateAgentRouter(config), + createTime: time.Now().Unix(), + uniqueIDCounter: 0, + } +} + +type ServerInfo struct { + AppId string `json:"appid"` + AppName string `json:"appname"` + StartTime string `json:"time"` + Version string `json:"version"` +} + +type ServerUniqueId struct { + UID int64 `json:"uid"` +} + +const CLIENT_HEADER_SIZE = 8 + +func (s *Server) Run() (code int, err error) { + + var wg sync.WaitGroup + defer wg.Wait() + wg.Add(1) + + go func() { + defer wg.Done() + s.startListen() + }() + + sig := make(chan os.Signal, 1) + + signal.Notify(sig, + syscall.SIGHUP, + syscall.SIGINT, + syscall.SIGTERM, + syscall.SIGQUIT) + + for { + select { + case sig := <-sig: + s.log.Warnf("catch signal %s", sig) + s.log.Warn("Stopping listener ...") + s.listener.Close() + return 0, fmt.Errorf("SpanServer exit with signal %s", sig) + case <-time.After(s.config.AgentRetireTime): + s.agentRouter.Clean() + } + } +} + +func (server *Server) genUniqueId() *ServerUniqueId { + return &ServerUniqueId{ + UID: server.createTime + atomic.AddInt64(&server.uniqueIDCounter, 1), + } +} + +func (s *Server) parsePacket(con net.Conn, size, packetType uint32, body []byte) (err error) { + s.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: body} + + switch packetType { + case 1: //REQ_UPDATE_SPAN + err = s.agentRouter.DispatchPacket(&rawPacket) + if err != nil { + s.log.Warnf("dispatcher packet with an exception: %s", err) + return err + } + case 2: //REQ_UNIQUE_ID + uniqueBody, err := json.Marshal(s.genUniqueId()) + if err == nil { + err = s.respToClient(con, 2, uniqueBody) + } + s.log.Infof("get genUniqueId") + return err + default: + s.log.Warnf("unsupported type:%d", packetType) + } + + return nil +} + +func (s *Server) startListen() { + var wg sync.WaitGroup + + socket_type, address := s.config.ParseServerAddress() + s.log.Debugf("bind server on %v:%s", socket_type, address) + listener, err := net.Listen(socket_type, address) + if err != nil { + s.log.Errorf("bind %s:%s failed with %v", socket_type, address, err) + panic(err) + } + + s.listener = listener + + for { + conn, err := listener.Accept() + if err != nil { + s.log.Errorf("accepter failed with %s", err.Error()) + break + } + wg.Add(1) + go func() { + defer wg.Done() + s.handleClient(conn) + }() + } + +} + +func ParseHeader(buffer []byte) (packetLen, packetType uint32) { + + packetType = binary.BigEndian.Uint32(buffer[0:4]) + packetLen = binary.BigEndian.Uint32(buffer[4:8]) + return packetLen, packetType +} + +func (server *Server) 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 + } + bodyLen, Type := ParseHeader(buffer[start : start+total]) + if bodyLen > uint32(server.config.User.RecvBufSize) { + return 0, 0 + } + + // fetch packet + if total < int32(bodyLen+CLIENT_HEADER_SIZE) { + return 0, int32(bodyLen) + CLIENT_HEADER_SIZE - total + } + *packetType = int32(Type) + *packetLen = int32(bodyLen) + *body = buffer[start+CLIENT_HEADER_SIZE : start+CLIENT_HEADER_SIZE+int32(bodyLen)] + + return int32(bodyLen) + CLIENT_HEADER_SIZE, 0 +} + +func (s *Server) respToClient(con net.Conn, msgType uint32, msgBody []byte) error { + if len(msgBody) > math.MaxInt32 { + s.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 *Server) 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 (s *Server) handleClient(con net.Conn) { + defer con.Close() + // if err := con.Close(); err != nil { + // s.log.Warnf("close client met :%s", err) + // } + // }() + + s.log.Infof("client:%s is online", con.RemoteAddr()) + handshake, err := json.Marshal(s.genHello()) + if err != nil { + s.log.Warnf("generate handshake failed.reason:%s", err) + return + } + s.log.Infof("send handshake msg:%s", handshake) + //skip error checking,as con.Read does + s.respToClient(con, 0, handshake) + + // fetch data + clientInBuf := make([]byte, s.config.User.RecvBufSize) + inOffset := 0 + packetOffset := 0 + + for { + + size, err := con.Read(clientInBuf[inOffset:]) + + if err != nil { + s.log.Warnf("client:%s read error:%s", con.RemoteAddr(), err) + break + } + + if size > 0 { + inOffset += size + } else if size == 0 { + s.log.Infof("Connection:%s is closed by client. Reason: read size:%d in_offset:%d packet_offset:%d", con.RemoteAddr(), size, inOffset, packetOffset) + break + } + + ParseAgain: + + var body []byte = nil + var packetLen, packetType int32 + + token, needs := s.matchFullPacket(clientInBuf, int32(packetOffset), int32(inOffset-packetOffset), &packetLen, &packetType, &body) + if token == 0 { + if needs == 0 { + s.log.Error("needs cannot be 0") + break + } + + if s.config.User.RecvBufSize-inOffset < int(needs) { + // not enough space to hold income + if int(needs) > s.config.User.RecvBufSize/2 { + s.log.Errorf("packet overflow and overlap.Reason packet_offset:%d,in_offset:%d", packetOffset, inOffset) + break + } + unParsedSize := inOffset - packetOffset + copy(clientInBuf[0:unParsedSize], clientInBuf[packetOffset:inOffset]) + inOffset = unParsedSize + packetOffset = 0 + } + continue + } + + packetOffset += int(token) + + // gets a packet + err = s.parsePacket(con, uint32(packetLen), uint32(packetType), body) + if err != nil { + s.log.Warnf("parsePacket catches error:%s,client:%s", err, con.RemoteAddr()) + break + } + + if packetOffset == inOffset { + packetOffset = 0 + inOffset = 0 + s.log.Debug("ring buffer back to start") + continue + } + + goto ParseAgain + + } + + s.log.Infof("connection:%s is shutdown", con.RemoteAddr()) +} diff --git a/collector-agent/server/ServerEnv.go b/collector-agent/server/ServerEnv.go deleted file mode 100644 index 7bcad64d6..000000000 --- a/collector-agent/server/ServerEnv.go +++ /dev/null @@ -1,118 +0,0 @@ -package server - -import ( - "fmt" - "os" - "path" - "strconv" - "strings" - - "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/common" - - log "github.com/sirupsen/logrus" - prefixed "github.com/x-cray/logrus-prefixed-formatter" - "gopkg.in/natefinch/lumberjack.v2" -) - -/** -# pinpoint collector span ip -PP_COLLECTOR_AGENT_SPAN_IP=dev-pinpoint -# pinpoint collector span port -PP_COLLECTOR_AGENT_SPAN_PORT=9993 -# pinpoint collector agent IP -PP_COLLECTOR_AGENT_AGENT_IP=dev-pinpoint -# pinpoint collector agent port -PP_COLLECTOR_AGENT_AGENT_PORT=9991 -# pinpoint collector stat ip -PP_COLLECTOR_AGENT_STAT_IP=dev-pinpoint -# pinpoint collector stat port -PP_COLLECTOR_AGENT_STAT_PORT=9992 -# mark all agent a docker -PP_COLLECTOR_AGENT_ISDOCKER=true -PP_LOG_DIR=/tmp/ -PP_Log_Level=ERROR -# binds on -PP_ADDRESS=0.0.0.0@9999 -*/ - -func InitServerConfig() { - config := common.GetConfig() - - spanIp := os.Getenv("PP_COLLECTOR_AGENT_SPAN_IP") - spanPort := os.Getenv("PP_COLLECTOR_AGENT_SPAN_PORT") - config.SpanAddress = spanIp + ":" + spanPort - if config.SpanAddress == ":" { - panic("Invalid SpanAddress") - } - - statIp := os.Getenv("PP_COLLECTOR_AGENT_STAT_IP") - statPort := os.Getenv("PP_COLLECTOR_AGENT_STAT_PORT") - config.StatAddress = statIp + ":" + statPort - - if config.StatAddress == ":" { - panic("Invalid StatAddress") - } - - agentIp := os.Getenv("PP_COLLECTOR_AGENT_AGENT_IP") - agentPort := os.Getenv("PP_COLLECTOR_AGENT_AGENT_PORT") - config.AgentAddress = agentIp + ":" + agentPort - if config.AgentAddress == ":" { - panic("Invalid AgentAddress") - } - - inDocker := os.Getenv("PP_COLLECTOR_AGENT_ISDOCKER") - if b, err := strconv.ParseBool(inDocker); err == nil { - config.Container = b - } else { - config.Container = false - } - - logLevel := os.Getenv("PP_Log_Level") - config.LoggerLevel = logLevel - logDir := os.Getenv("PP_LOG_DIR") - config.LoggerDir = logDir - address := os.Getenv("PP_ADDRESS") - if len(address) == 0 { - panic("PP_ADDRESS invalid") - } - - if string(address[len(address)-4:]) == "sock" { - // a very loose checking - // assume a file - config.SocketType = "unix" - config.Address = address - } else { - config.Address = strings.Replace(address, "@", ":", 1) - config.SocketType = "tcp" - } - - // initialize logger - if level, err := log.ParseLevel(config.LoggerLevel); err == nil { - log.SetLevel(level) - } - - // if log dir exist use log file, if not keep loging on stdout - if _, err := os.Stat(config.LoggerDir); os.IsNotExist(err) { - log.SetOutput(os.Stdout) - log.Info(fmt.Sprintf("PP_LOG_DIR: '%s' not set or doesn't exist, falling back to stdout", config.LoggerDir)) - } else { - logFile := path.Join(config.LoggerDir, "collector.log") - // bind logger on the file - logger := &lumberjack.Logger{ - Filename: logFile, - MaxSize: 50, - MaxBackups: 50, - } - - log.SetOutput(logger) - } - - log.SetFormatter(&prefixed.TextFormatter{ - DisableColors: true, - TimestampFormat: "2006-01-02 15:04:05.999999999", - FullTimestamp: true, - ForceFormatting: true, - }) - - log.Info(config) -} diff --git a/collector-agent/server/SpanServer.go b/collector-agent/server/SpanServer.go deleted file mode 100644 index 9cdc7645e..000000000 --- a/collector-agent/server/SpanServer.go +++ /dev/null @@ -1,316 +0,0 @@ -package server - -import ( - "encoding/binary" - "encoding/json" - "fmt" - "math" - "net" - "os" - "os/signal" - "strconv" - "sync" - "sync/atomic" - "syscall" - "time" - - "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/agent" - "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/common" - - log "github.com/sirupsen/logrus" -) - -var Version = "v0.6.4" - -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"` -} - -type ServerUniqueId struct { - UID int64 `json:"uid"` -} - -const CLIENT_HEADER_SIZE = 8 - -func (server *SpanServer) init() { - server.quit = make(chan bool) - manager := &agent.AgentRouter{PingId: 1, - AgentMap: make(map[string]*agent.GrpcAgent), - Quit: server.quit, - WG: &server.wg, - } - - server.agentRouter = manager - server.createTime = time.Now().Unix() - server.index_st = 0 -} - -func (server *SpanServer) Run() (code int, err error) { - server.init() - - go server.startListen() - sig := make(chan os.Signal, 1) - - signal.Notify(sig, - syscall.SIGHUP, - syscall.SIGINT, - syscall.SIGTERM, - syscall.SIGQUIT) - - config := common.GetConfig() - - defer func() { - close(server.quit) - if err := server.listener.Close(); err != nil { - log.Warnf("close listener socket met:%s", err) - } - server.wg.Wait() - }() - - for { - select { - case sig := <-sig: - log.Warnf("catch 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) 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: body} - - switch packetType { - case 1: //REQ_UPDATE_SPAN - err = server.agentRouter.DispatchPacket(&rawPacket) - if err != nil { - 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("unsupported type:%d", packetType) - } - - return nil -} - -func (server *SpanServer) startListen() { - defer server.wg.Done() - server.wg.Add(1) - server.quit = make(chan bool) - config := common.GetConfig() - log.Debug("listen: ", config.SocketType, " address: ", config.Address) - listener, err := net.Listen(config.SocketType, config.Address) - if err != nil { - log.Errorf("bind %s:%s failed with %v", config.SocketType, config.Address, err.Error()) - panic(err) - } - server.listener = listener - - for { - conn, err := listener.Accept() - if err != nil { - select { - case <-server.quit: - return - default: - log.Errorf("accepter failed with %s", err.Error()) - } - } - go server.handleClient(conn) - } - -} - -func ParseHeader(buffer []byte) (packetLen, packetType uint32) { - - packetType = binary.BigEndian.Uint32(buffer[0:4]) - packetLen = binary.BigEndian.Uint32(buffer[4:8]) - return packetLen, packetType -} - -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 - } - bodyLen, Type := ParseHeader(buffer[start : start+total]) - if bodyLen > uint32(Setting.RecvBufSize) { - return 0, 0 - } - - // fetch packet - if total < int32(bodyLen+CLIENT_HEADER_SIZE) { - return 0, int32(bodyLen) + CLIENT_HEADER_SIZE - total - } - *packetType = int32(Type) - *packetLen = int32(bodyLen) - *body = buffer[start+CLIENT_HEADER_SIZE : start+CLIENT_HEADER_SIZE+int32(bodyLen)] - - 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 { - log.Warnf("close client met :%s", err) - } - }() - - log.Infof("client:%s is online", con.RemoteAddr()) - 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) - //skip error checking,as con.Read does - server.respToClient(con, 0, handshake) - - // fetch data - clientInBuf := make([]byte, Setting.RecvBufSize) - inOffset := 0 - packetOffset := 0 - - for { - - size, err := con.Read(clientInBuf[inOffset:]) - - if err != nil { - log.Warnf("client:%s read error:%s", con.RemoteAddr(), err) - break - } - - if size > 0 { - inOffset += size - } - - if size == 0 { - log.Infof("Connection:%s is closed by client. Reason: size:%d in_offset:%d packet_offset:%d", con.RemoteAddr(), size, inOffset, packetOffset) - break - } - - ParseAgain: - - var body []byte = nil - var packetLen, packetType int32 - - 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") - break - } - - if Setting.RecvBufSize-inOffset < int(needs) { - // not enough space to hold income - if int(needs) > Setting.RecvBufSize/2 { - log.Errorf("packet overflow and overlap.Reason packet_offset:%d,in_offset:%d", packetOffset, inOffset) - break - } - unParsedSize := inOffset - packetOffset - copy(clientInBuf[0:unParsedSize], clientInBuf[packetOffset:inOffset]) - inOffset = unParsedSize - packetOffset = 0 - } - continue - } - - packetOffset += int(token) - - // gets a packet - err = server.parsePacket(con, uint32(packetLen), uint32(packetType), body) - if err != nil { - log.Warnf("parsePacket catches error:%s,client:%s", err, con.RemoteAddr()) - break - } - - if packetOffset == inOffset { - packetOffset = 0 - inOffset = 0 - log.Debug("ring buffer back to start") - continue - } - - goto ParseAgain - - } - - log.Infof("connection:%s is shutdown", con.RemoteAddr()) - -} diff --git a/collector-agent/server/server_test.go b/collector-agent/server/server_test.go index 1032ebe62..c30bdda57 100644 --- a/collector-agent/server/server_test.go +++ b/collector-agent/server/server_test.go @@ -3,47 +3,30 @@ package server import ( "encoding/binary" "net" - "os" "strconv" "strings" "testing" "time" "github.com/pinpoint-apm/pinpoint-c-agent/collector-agent/common" - - log "github.com/sirupsen/logrus" ) -func launchJsonServer() *SpanServer { - config := common.GetConfig() - - config.SocketType = "tcp" - config.Address = "127.0.0.1:8789" - config.AgentAddress = "dev-pinpoint-01:9991" - config.StatAddress = "dev-pinpoint-01:9992" - config.SpanAddress = "dev-pinpoint-01:9993" - config.WebPorts = 80 - config.LoggerLevel = "DEBUG" - config.LoggerDir = "/tmp/" - - config.AgentChannelSize = 1000 - config.SpanStreamParallelismSize = 1 - config.AgentReTryTimeout = 10 - config.PingInterval = 5 - config.StatInterval = 5 - config.SpanTimeWait = 10 - config.MetaDataTimeWait = 10 - config.GrpcConTextTimeOut = 5 +func launchJsonServer() *Server { + config := common.CreateTestConfig() + + config.User.BindAddress = "127.0.0.1:8789" + config.User.AgentAddress = "dev-pinpoint-01:9991" + config.User.StatAddress = "dev-pinpoint-01:9992" + config.User.SpanAddress = "dev-pinpoint-01:9993" + config.HostName = "dev-pinpoint" - config.HostIp = "10.34.135.214" + config.HostIp = "10.10.10.10" config.Pid = 5689 config.StartTime = 13558755446548 - config.ServerType = 1700 - config.Container = false - js := SpanServer{} + js := CreateServer(config) - return &js + return js } func generateValidPacket(msg string) (buf []byte) { @@ -54,10 +37,10 @@ func generateValidPacket(msg string) (buf []byte) { return buf } -func generateUnvaalidPacket01() (buf []byte) { - buf = make([]byte, 8) - return buf -} +// func generateInvalidPacket01() (buf []byte) { +// buf = make([]byte, 8) +// return buf +// } func genUniqueIdBody() []byte { msg := make([]byte, 8) @@ -81,7 +64,6 @@ func generateInvalidPacket03() (buf []byte) { } func handleWrite(t *testing.T, conn net.Conn) { - defer conn.Close() conn.Write(genUniqueIdBody()) readId(t, conn) for i := 0; i < 5; i++ { @@ -92,7 +74,7 @@ func handleWrite(t *testing.T, conn net.Conn) { buffer := generateValidPacket(msg) _, e := conn.Write(buffer) if e != nil { - t.Error("Error to send message because of ", e.Error()) + t.Errorf("Error to send message because of %v", e) break } time.Sleep(100 * time.Millisecond) @@ -108,10 +90,7 @@ 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) @@ -126,38 +105,28 @@ func readId(t *testing.T, conn net.Conn) { if !strings.HasPrefix(id, "{\"uid\"") { t.Error(id) } + t.Log("read hello") } func TestJsonServer(t *testing.T) { js := launchJsonServer() - go js.Run() + go js.startListen() time.Sleep(2 * time.Second) conn, err := net.Dial("tcp", "127.0.0.1:8789") if err != nil { t.Error(err) } + defer conn.Close() + readHello(t, conn) handleWrite(t, conn) -} -func TestMain(m *testing.M) { - log.SetLevel(log.DebugLevel) - log.SetOutput(os.Stdout) - code := m.Run() - - os.Exit(code) } -func TestLoadConfig(t *testing.T) { - os.Setenv("PP_COLLECTOR_AGENT_SPAN_IP", "dev-pinpoint") - os.Setenv("PP_COLLECTOR_AGENT_SPAN_PORT", "9993") - os.Setenv("PP_COLLECTOR_AGENT_AGENT_IP", "dev-pinpoint") - os.Setenv("PP_COLLECTOR_AGENT_AGENT_PORT", "9991") - os.Setenv("PP_COLLECTOR_AGENT_STAT_IP", "dev-pinpoint") - os.Setenv("PP_COLLECTOR_AGENT_STAT_PORT", "9992") - os.Setenv("PP_COLLECTOR_AGENT_ISDOCKER", "true") - os.Setenv("PP_LOG_DIR", "/tmp/") - os.Setenv("PP_Log_Level", "ERROR") - os.Setenv("PP_ADDRESS", "0.0.0.0@9999") - InitServerConfig() -} +// func TestMain(m *testing.M) { +// log.SetLevel(log.DebugLevel) +// log.SetOutput(os.Stdout) +// code := m.Run() + +// os.Exit(code) +// } diff --git a/collector-agent/server/setting.go b/collector-agent/server/setting.go deleted file mode 100644 index afd6ffd83..000000000 --- a/collector-agent/server/setting.go +++ /dev/null @@ -1,11 +0,0 @@ -package server - -type ServerSetting struct { - RecvBufSize int // default is 4k -} - -const RECV_BUF_SIZE_DEF = 4096 * 100 - -var Setting = &ServerSetting{ - RecvBufSize: RECV_BUF_SIZE_DEF, -} diff --git a/collector-agent/start-collector-agent.sh b/collector-agent/start-collector-agent.sh index c8a5250ef..d52d9d2c0 100644 --- a/collector-agent/start-collector-agent.sh +++ b/collector-agent/start-collector-agent.sh @@ -1,14 +1,14 @@ #!/bin/bash -export PP_COLLECTOR_AGENT_SPAN_IP=dev-pinpoint -export PP_COLLECTOR_AGENT_SPAN_PORT=9993 -export PP_COLLECTOR_AGENT_AGENT_IP=dev-pinpoint -export PP_COLLECTOR_AGENT_AGENT_PORT=9991 -export PP_COLLECTOR_AGENT_STAT_IP=dev-pinpoint -export PP_COLLECTOR_AGENT_STAT_PORT=9992 -export PP_COLLECTOR_AGENT_ISDOCKER=false -# export PP_LOG_DIR=/tmp/ -export PP_Log_Level=DEBUG -export PP_ADDRESS=0.0.0.0@10000 -export GO_PATH=/home/pinpoint/go/bin -export PATH=$PATH:$GO_PATH -make && ./collector-agent \ No newline at end of file +# export PP_COLLECTOR_AGENT_SPAN_IP=dev-pinpoint +# export PP_COLLECTOR_AGENT_SPAN_PORT=9993 +# export PP_COLLECTOR_AGENT_AGENT_IP=dev-pinpoint +# export PP_COLLECTOR_AGENT_AGENT_PORT=9991 +# export PP_COLLECTOR_AGENT_STAT_IP=dev-pinpoint +# export PP_COLLECTOR_AGENT_STAT_PORT=9992 +# export PP_COLLECTOR_AGENT_ISDOCKER=false +# # export PP_LOG_DIR=/tmp/ +# export PP_Log_Level=DEBUG +# export PP_ADDRESS=0.0.0.0@10000 +# export GO_PATH=/home/pinpoint/go/bin +# export PATH=$PATH:$GO_PATH +make && ./collector-agent -AgentAddress=dev-pinpoint:9991 -SpanAddress=dev-pinpoint:9993 -StatAddress=dev-pinpoint:9992 -host=0.0.0.0@10000 \ No newline at end of file diff --git a/common/CHANGES.md b/common/CHANGES.md index c89ce6e47..96b3ebeee 100644 --- a/common/CHANGES.md +++ b/common/CHANGES.md @@ -1,3 +1,9 @@ +## v0.6.0 +- refactor span json protocol +- add async api +- data structure change: multiple map to list +- add `pinpoint_get_depth` + ## v0.5.3 2024-07-30 - support unittest in macos diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index ce5c5088c..b7fd5f2d6 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.13) -project(pinpoint VERSION 0.5.3 DESCRIPTION "pinpoint common library") +project(pinpoint VERSION 0.6.0 DESCRIPTION "pinpoint common library") set(CMAKE_CXX_STANDARD 11) @@ -8,10 +8,6 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") option(AGENT_WITH_PKGCONFIG_SUPPORT "Generate and install .pc files" OFF) -# 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) @@ -39,7 +35,7 @@ endif(CMAKE_COMPILER_IS_GNUCXX) add_subdirectory(jsoncpp) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/include) - +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/common.h.in ${CMAKE_CURRENT_SOURCE_DIR}/include/common.h @ONLY) if (WITH_TEST_CASE) include (CTest) enable_testing() diff --git a/common/LICENSE b/common/LICENSE new file mode 100644 index 000000000..980a15ac2 --- /dev/null +++ b/common/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. diff --git a/common/include/common.h b/common/include/common.h index 15b726bcc..da02eff0d 100644 --- a/common/include/common.h +++ b/common/include/common.h @@ -32,14 +32,6 @@ static const int RECONNECT_TIME_SEC = 5; 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 - // 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 { uint32_t type; @@ -59,6 +51,7 @@ typedef enum { E_OFFLINE = 0x1, E_TRACE_PASS = 0x2, E_TRACE_BLOCK = 0x4, + E_AGENT_INTERNAL_ERROR, } E_AGENT_STATUS; /** @@ -73,7 +66,7 @@ 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.5.3" +#define PINPOINT_C_AGENT_API_VERSION "0.6.0" /** * @brief change logs @@ -180,6 +173,32 @@ void pinpoint_add_clue(NodeID _id, const char* key, const char* value, E_NODE_LO */ void pinpoint_set_context_key(NodeID _id, const char* key, const char* value); +/** + * @brief treat current span as SpanChunk with async_node (pinpoint-c-agent, is only works on + * [PSpanChunk](https://github.com/pinpoint-apm/pinpoint-grpc-idl/blob/d5ea1a65548eb624c7ed1c441226742105c3a6bc/proto/v1/Span.proto#L106). + * async_node_id is generated by common like `generate_unique_id` + * @param id + * @param async_node_id + * @param node_sequence + */ +void pinpoint_set_async_ctx(NodeID id, int32_t async_node_id, int32_t node_sequence); + +/** + * @brief [tls] get sequence id from trace node(NodeID= id); root node, sequence id is 0 + * + * @param id + * @return int32_t if < 0, must have an error.(eg: NodeID not exist) + */ +int32_t pinpoint_get_sequence_id(NodeID id); + +/** + * @brief get depth for trace node + * + * @param id + * @return int32_t (-1: not a live trace node; 0 root trace; >0 it's depth) + */ +int32_t pinpoint_get_depth(NodeID id); + /** * @brief get string context * diff --git a/common/include/common.h.in b/common/include/common.h.in index 31b8f3949..da02eff0d 100644 --- a/common/include/common.h.in +++ b/common/include/common.h.in @@ -32,14 +32,6 @@ static const int RECONNECT_TIME_SEC = 5; 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 - // 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 { uint32_t type; @@ -59,6 +51,7 @@ typedef enum { E_OFFLINE = 0x1, E_TRACE_PASS = 0x2, E_TRACE_BLOCK = 0x4, + E_AGENT_INTERNAL_ERROR, } E_AGENT_STATUS; /** @@ -73,7 +66,7 @@ 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 "@PROJECT_VERSION@" +#define PINPOINT_C_AGENT_API_VERSION "0.6.0" /** * @brief change logs @@ -138,7 +131,7 @@ 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 span event + * the same as pinpoint_start_trace. BUT, end a span or a spanevent * 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 @@ -148,12 +141,12 @@ NodeID pinpoint_end_trace(NodeID); /** * check id->traceNode is root * @param - * @return 1: is root; 0: not root node;-1: nonexistent node + * @return 1: is root; 0: not root node;-1: A wrong id */ int pinpoint_trace_is_root(NodeID); /** - * force end current trace, only called when call stack leaked + * force end current trace, only called when callstack leaked * @return int 0 : means oK * -1: exception found, check the log */ @@ -180,6 +173,32 @@ void pinpoint_add_clue(NodeID _id, const char* key, const char* value, E_NODE_LO */ void pinpoint_set_context_key(NodeID _id, const char* key, const char* value); +/** + * @brief treat current span as SpanChunk with async_node (pinpoint-c-agent, is only works on + * [PSpanChunk](https://github.com/pinpoint-apm/pinpoint-grpc-idl/blob/d5ea1a65548eb624c7ed1c441226742105c3a6bc/proto/v1/Span.proto#L106). + * async_node_id is generated by common like `generate_unique_id` + * @param id + * @param async_node_id + * @param node_sequence + */ +void pinpoint_set_async_ctx(NodeID id, int32_t async_node_id, int32_t node_sequence); + +/** + * @brief [tls] get sequence id from trace node(NodeID= id); root node, sequence id is 0 + * + * @param id + * @return int32_t if < 0, must have an error.(eg: NodeID not exist) + */ +int32_t pinpoint_get_sequence_id(NodeID id); + +/** + * @brief get depth for trace node + * + * @param id + * @return int32_t (-1: not a live trace node; 0 root trace; >0 it's depth) + */ +int32_t pinpoint_get_depth(NodeID id); + /** * @brief get string context * diff --git a/common/readme.md b/common/readme.md index 2122e0afb..679613614 100644 --- a/common/readme.md +++ b/common/readme.md @@ -7,8 +7,3 @@ $ cmake -DWITH_TEST_CASE=1 -DWITH_CODECOVERAGE=1 -DCMAKE_BUILD_TYPE=Debug .. $ ./bin/TestCommon --gtest_filter=node.wakeTrace ``` -## Changes - -- 2023/11/23 - - support FetchContent #561 - diff --git a/common/src/ConnectionPool/SpanConnectionPool.h b/common/src/ConnectionPool/SpanConnectionPool.h index 85188bfbc..20f2741f9 100644 --- a/common/src/ConnectionPool/SpanConnectionPool.h +++ b/common/src/ConnectionPool/SpanConnectionPool.h @@ -68,7 +68,6 @@ class SpanConnectionPool { private: TransLayerPtr createConnection(const RouteMapValueVec& value_vec) { TransLayerPtr _connect(new TransLayer(this->co_host)); - using namespace std::placeholders; for (auto& value : value_vec) { _connect->RegPeerMsgCallback(value.first, value.second); diff --git a/common/src/ConnectionPool/TransLayer.cpp b/common/src/ConnectionPool/TransLayer.cpp index 6ae12d206..e479f8d8b 100644 --- a/common/src/ConnectionPool/TransLayer.cpp +++ b/common/src/ConnectionPool/TransLayer.cpp @@ -198,17 +198,13 @@ size_t TransLayer::PoolEventOnce(uint32_t timeout) { FD_ZERO(&wfds); FD_ZERO(&rfds); - // 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); - // } struct timeval tv = {timeout / 1000, (int)timeout % 1000}; @@ -223,13 +219,6 @@ size_t TransLayer::PoolEventOnce(uint32_t timeout) { goto ERR_NETWORK; } - if ((this->_state & S_WRITING) && FD_ISSET(fd, &wfds)) { - pp_trace("write event"); - if (_send_msg_to_collector() == -1) { - goto ERR_NETWORK; - } - } - if ((this->_state & S_READING) && FD_ISSET(fd, &rfds)) { pp_trace("read event"); if (recvByteStream() == -1) { @@ -237,6 +226,13 @@ size_t TransLayer::PoolEventOnce(uint32_t timeout) { goto ERR_NETWORK; } } + + if ((this->_state & S_WRITING) && FD_ISSET(fd, &wfds)) { + pp_trace("write event"); + if (_send_msg_to_collector() == -1) { + goto ERR_NETWORK; + } + } } // timeout return 0; diff --git a/common/src/ConnectionPool/TransLayer.h b/common/src/ConnectionPool/TransLayer.h index ad2b9f429..433e87596 100644 --- a/common/src/ConnectionPool/TransLayer.h +++ b/common/src/ConnectionPool/TransLayer.h @@ -40,7 +40,7 @@ using Cache::Chunks; const uint32_t _chunk_max_size = 10 * 1024 * 1024; // 10M const uint32_t _chunk_hold_size = 40 * 1024; // 40k -using MsgHandleFunc = std::function; +using MsgHandleFunc = std::function; using RouterMsgMap = std::map; using RouteMapValueType = RouterMsgMap::value_type; @@ -53,6 +53,7 @@ class TransLayer { c_fd(-1) {} void RegPeerMsgCallback(int type, MsgHandleFunc call_back) { msgRouteMap_[type] = call_back; } + void RegStatusChangedCallBack(std::function call_back) { statusChangedCallback_ = call_back; } @@ -149,7 +150,9 @@ class TransLayer { if (ret > 0) { int total = ret + next_size; int msg_offset = HandleMsgStream(in_buf, total); - if (msg_offset < total) { + if (msg_offset < 0) { // found fetal error + return -1; + } else if (msg_offset < total) { next_size = total - msg_offset; memcpy(in_buf, in_buf + msg_offset, next_size); } else { @@ -185,7 +188,10 @@ class TransLayer { uint32_t type = ntohl(header->type); auto has = msgRouteMap_.find(type); if (has != msgRouteMap_.end()) { - msgRouteMap_[type](type, buf + 8, len - 8); + int ret = has->second(type, buf + 8, len - 8); + if (ret == -1) { + return -1; + } } else { pp_trace("unsupported message type:%d from server", type); } diff --git a/common/src/ConnectionPool/test_trans_layer.cc b/common/src/ConnectionPool/test_trans_layer.cc index 38f1d3a46..6875f08b6 100644 --- a/common/src/ConnectionPool/test_trans_layer.cc +++ b/common/src/ConnectionPool/test_trans_layer.cc @@ -72,7 +72,7 @@ void fake_server() { close_socket(cfd); } -void handle_agent_info(int type, const char* buf, size_t len) { +int handle_agent_info(int type, const char* buf, size_t len) { printf("recv: %s", buf); EXPECT_EQ(type, RESPONSE_AGENT_INFO); Json::Value root; @@ -82,6 +82,7 @@ void handle_agent_info(int type, const char* buf, size_t len) { EXPECT_STREQ(root["id"].asCString(), "test-app"); EXPECT_STREQ(root["name"].asCString(), "test-name"); run = false; + return 0; } TEST(translayer, connect_remote) { diff --git a/common/src/Logging.cpp b/common/src/Logging.cpp index 32150d5c9..62b0aee8c 100644 --- a/common/src/Logging.cpp +++ b/common/src/Logging.cpp @@ -22,8 +22,8 @@ #include #include #include -inline int get_os_pid() { return syscall(SYS_gettid); } -inline long get_tid() { return getpid(); } +inline int get_os_pid() { return getpid(); } +inline long get_tid() { return syscall(SYS_gettid); } #endif #if defined(__APPLE__) @@ -48,7 +48,7 @@ static bool enable_trace_ = false; thread_local char buf[LOG_SIZE] = {0}; static void log_format_out(const char* format, va_list* args) { - int n = snprintf(buf, LOG_SIZE, "[pinpoint] [%d] [%ld]", get_os_pid(), get_tid()); + int n = snprintf(buf, LOG_SIZE, "[pinpoint] [%d:%ld]", get_os_pid(), get_tid()); vsnprintf(buf + n, LOG_SIZE - n - 1, format, *args); if (log_call_back_) { diff --git a/common/src/NodePool/PoolManager.cpp b/common/src/NodePool/PoolManager.cpp index 03cecc4cb..76e81588e 100644 --- a/common/src/NodePool/PoolManager.cpp +++ b/common/src/NodePool/PoolManager.cpp @@ -23,72 +23,91 @@ #include "PoolManager.h" #include "common.h" +#include "json/value.h" #include +#include #include -#ifndef UINT32_MAX -#define UINT32_MAX (0xfffffff) -#endif +#include + namespace PP { namespace NodePool { -void PoolManager::FreeNodeTree(NodeID nodeId) { - if (nodeId == E_INVALID_NODE || nodeId == E_ROOT_NODE) { +void PoolManager::FreeNodeTree(NodeID root) { + if (root == E_INVALID_NODE || root == E_ROOT_NODE) { return; } + for (NodeID next_id = ReturnNode(root); next_id != E_INVALID_NODE;) { + next_id = ReturnNode(next_id); + } +} - NodeID child_id, next_id; +void PoolManager::AppendToRootTrace(WrapperTraceNodePtr& root, TraceNode& newNode) { + std::lock_guard _safe(root->GetRootLock()); - if (ReturnNode(nodeId, child_id, next_id)) { - if (next_id != E_INVALID_NODE) { - FreeNodeTree(next_id); - } + if (newNode.root_id_ != E_INVALID_NODE) { + return; + } - if (child_id != E_INVALID_NODE) { - FreeNodeTree(child_id); - } + newNode.root_id_ = root->id_; + + NodeID last = root->GetLastNode(); + if (last != E_INVALID_NODE) { + WrapperTraceNodePtr lastNode = ReferNode(last); + lastNode->next_ = newNode.id_; + newNode.pre_trace_time_ = lastNode->trace_start_time_; + } else { + newNode.pre_trace_time_ = root->trace_start_time_; + } + + root->SetLastNode(newNode.id_); + + newNode.sequence_ = root->CreateNewSequence(); + + if (root->next_ == E_INVALID_NODE) { + root->next_ = newNode.id_; } } -bool PoolManager::ReturnNode(NodeID id, NodeID& child_id, NodeID& next_id) { + +NodeID PoolManager::ReturnNode(NodeID id) { + NodeID next = E_INVALID_NODE; 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)) { - return true; + if (this->returnNode(id, next, false)) { + return next; } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } pp_trace("[🐛]Restore node failed: [%d]; node restore forcefully", id); - return this->_restore(id, child_id, next_id, true); + this->returnNode(id, next, true); + return next; } -// avoiding `locking and waiting` -bool PoolManager::_restore(NodeID id, NodeID& child_id, NodeID& next_id, bool force) { - std::lock_guard _safe(this->_lock); +bool PoolManager::returnNode(NodeID id, NodeID& next, bool force) { int32_t index = (int32_t)id - 1; if (this->indexInUsedVec(index) == false) { pp_trace("%d not alive !!!", id); - child_id = E_INVALID_NODE; - next_id = E_INVALID_NODE; return true; } // check refcount TraceNode& node = this->getUsedNode(id); - if (node.checkZeroRef() == false && force == false) { - // DO NOT TOUCH THis Node + if (node.IsNotReference() == false && force == false) { + // DO NOT TOUCH this node return false; } else { this->usedNodeSet_[index] = false; - child_id = node.last_child_id_; - next_id = node.sibling_id_; this->_freeNodeList.push(index); + next = node.next_; + // xxx disable for CI + // pp_trace("returnNode node:%d next:%d", id, next); return true; } } 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"); } @@ -104,23 +123,19 @@ TraceNode& PoolManager::getUsedNode(NodeID id) { return this->nodeIndexVec[index / CELL_SIZE][index % CELL_SIZE]; } -TraceNode& PoolManager::getReadyNode() noexcept { // create a new node +TraceNode& PoolManager::getReadyNode() { // create a new node + if (this->_freeNodeList.empty()) { + if (maxId > POOL_MAX_NODES_LIMIT) { + throw std::out_of_range("node poll size limitation reached"); + } this->expandOnce(); } // as it holds a _lock, so no more _freeNodeList is empty int32_t index = this->_freeNodeList.top(); this->_freeNodeList.pop(); 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->getUsedNode(id); - } else { - return this->getReadyNode(); - } + return this->nodeIndexVec[index / CELL_SIZE][index % CELL_SIZE].Reset(NodeID(index + 1)); } void PoolManager::expandOnce() { @@ -138,29 +153,36 @@ void PoolManager::expandOnce() { // pp_trace("Node pool expanding is done! news size:%ld", this->nodeIndexVec.size() * CELL_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); - } +const Json::Value& PoolManager::EncodeTraceToJsonSpan(WrapperTraceNodePtr& root_node) { - if (node->last_child_id_ != E_INVALID_NODE) { - WrapperTraceNodePtr child = ReferNode(node->last_child_id_); - getRootNodeValue(child); + if (!root_node->IsRootNode()) { + pp_trace("current node:%d is not root", root_node->id_); + return root_node->GetConstValue(); } - if (node->checkOpt() == false) { - return empty; - } + for (NodeID next = root_node->next_; next != E_INVALID_NODE;) { + auto next_node = ReferNode(next); + next = next_node->next_; + + // XXX: if not end, force end + if (next_node->expired_time_ == -1) { + next_node->EndTrace(); + } + + // [ ] add skipped + // auto parent_node = ReferNode(next_node->parent_id_); + // if (next_node->ShouldSkip() || parent_node->ShouldSkip()) { + // next_node->SkipByParent(); + // continue; + // } - if (node->parent_id_ > E_ROOT_NODE) { - WrapperTraceNodePtr parent = ReferNode(node->parent_id_); - parent->appendNodeValue("calls", node->EncodeProtocol()); + root_node->AppendAnnotation("event", next_node->moveToSpan()); } - return node->EncodeProtocol(); + root_node->runUserOptionFunc(); + + return root_node->GetConstValue(); } } // namespace NodePool diff --git a/common/src/NodePool/PoolManager.h b/common/src/NodePool/PoolManager.h index 35ab1827f..289e46a31 100644 --- a/common/src/NodePool/PoolManager.h +++ b/common/src/NodePool/PoolManager.h @@ -32,72 +32,39 @@ class PoolManager { private: TraceNode& getUsedNode(NodeID id); - TraceNode& getReadyNode(void) noexcept; + TraceNode& getReadyNode(void); - TraceNode& _take(NodeID id); - - bool _restore(NodeID id, NodeID& child_id, NodeID& next_id, bool force); - - Json::Value& getRootNodeValue(WrapperTraceNodePtr& node); - - // void gatherChildrenValues(WrapperTraceNodePtr& parent, NodeID child_header); +protected: + virtual bool returnNode(NodeID id, NodeID& next, bool force); public: - /** - * @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 _safe(this->_lock); - return this->_take(id); - } + const Json::Value& EncodeTraceToJsonSpan(WrapperTraceNodePtr& node); - inline TraceNode& NewNode() { - std::lock_guard _safe(this->_lock); - return this->getReadyNode(); - } + virtual TraceNode& GetNode() { return this->getReadyNode(); } - inline WrapperTraceNodePtr ReferNode(NodeID id) { - std::lock_guard _safe(this->_lock); + virtual WrapperTraceNodePtr ReferNode(NodeID id) { TraceNode& e = this->getUsedNode(id); return WrapperTraceNodePtr(e); } - DEPRECATED("") inline WrapperTraceNodePtr GetWrapperNode(NodeID id = E_ROOT_NODE) { - std::lock_guard _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 ReturnNode(NodeID id, NodeID& child_id, NodeID& next_id); - - inline bool ReturnNode(const TraceNode& node) { - NodeID node1, node2; - return this->ReturnNode(node.getId(), node1, node2); - } + void AppendToRootTrace(WrapperTraceNodePtr& root, TraceNode& newNode); - uint32_t totalNodesCount() { - std::lock_guard _safe(this->_lock); - return (uint32_t)nodeIndexVec.size() * CELL_SIZE; - } + NodeID ReturnNode(NodeID id); - uint32_t freeNodesCount() { - std::lock_guard _safe(this->_lock); - return (uint32_t)this->_freeNodeList.size(); + virtual uint32_t totalNodesCount() { return (uint32_t)nodeIndexVec.size() * CELL_SIZE; } + + virtual uint32_t freeNodesCount() { return (uint32_t)this->_freeNodeList.size(); } + + bool NoNodesLeak() { + if (freeNodesCount() == totalNodesCount()) { + return true; + } else { + pp_trace("pool status: free:%u total:%u", freeNodesCount(), totalNodesCount()); + return false; + } } - void foreachAliveNode(std::function func) { - std::lock_guard _safe(this->_lock); + virtual void foreachAliveNode(std::function func) { for (int32_t index = 0; index < this->maxId; index++) { if (this->indexInUsedVec(index)) { func(this->getUsedNode((NodeID)(index + 1))); @@ -105,19 +72,6 @@ class PoolManager { } } - 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() { @@ -135,10 +89,7 @@ class PoolManager { } #ifdef COMMON_DEBUG - inline bool NoNodeLeak() { - std::lock_guard _safe(this->_lock); - return this->_freeNodeList.size() == nodeIndexVec.size() * CELL_SIZE; - } + inline bool NoNodeLeak() { return this->_freeNodeList.size() == nodeIndexVec.size() * CELL_SIZE; } #endif virtual ~PoolManager() {} @@ -162,15 +113,52 @@ class PoolManager { void expandOnce(); private: - std::mutex _lock; - // std::set _aliveNodeSet; + // std::mutex _lock; std::vector usedNodeSet_; std::vector readyNodeSet_; int32_t maxId; std::stack _freeNodeList; static const int CELL_SIZE = 128; + static const int POOL_MAX_NODES_LIMIT = CELL_SIZE * 100; std::vector> nodeIndexVec; }; + +class ThreadSafePoolManager : public PoolManager { +public: + void foreachAliveNode(std::function func) override { + std::lock_guard _safe(this->_lock); + PoolManager::foreachAliveNode(func); + } + uint32_t freeNodesCount() override { + std::lock_guard _safe(this->_lock); + return PoolManager::freeNodesCount(); + } + + uint32_t totalNodesCount() override { + std::lock_guard _safe(this->_lock); + return PoolManager::totalNodesCount(); + } + + WrapperTraceNodePtr ReferNode(NodeID id) override { + std::lock_guard _safe(this->_lock); + return PoolManager::ReferNode(id); + } + + TraceNode& GetNode() override { + std::lock_guard _safe(this->_lock); + return PoolManager::GetNode(); + } + + // private: + bool returnNode(NodeID id, NodeID& next, bool force) override { + std::lock_guard _safe(this->_lock); + return PoolManager::returnNode(id, next, force); + } + +private: + std::mutex _lock; +}; + } // 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 50317f7d5..210db1222 100644 --- a/common/src/NodePool/TraceNode.cpp +++ b/common/src/NodePool/TraceNode.cpp @@ -21,121 +21,108 @@ */ #include "TraceNode.h" +#include "common.h" #include "header.h" +#include "json/value.h" +#include +#include + namespace PP { namespace NodePool { -TraceNode::~TraceNode() {} - -void TraceNode::clearAttach() { - // empty the json value - if (!this->_value.empty()) - this->_value.clear(); // Json::Value(); - - if (!this->context_.empty()) - this->context_.clear(); - - if (!this->_endTraceCallback.empty()) - this->_endTraceCallback.clear(); -} -void TraceNode::initId(const NodeID& id) { this->id_ = id; } +TraceNode& TraceNode::Reset(NodeID id) { + id_ = id; + root_id_ = parent_id_ = next_ = E_INVALID_NODE; -void TraceNode::AddChildTraceNode(WrapperTraceNodePtr& child) { - std::lock_guard _safe(this->mlock); - assert(id_ != child->id_); + pre_trace_time_ = 0; + trace_start_time_ = 0; + expired_time_ = -1; + reference_count_ = 0; + root_node_extra_ptr_ = nullptr; - if (this->last_child_id_ != E_INVALID_NODE) { - child->sibling_id_ = this->last_child_id_; + if (!this->user_optional_setting_func_.empty()) { + this->user_optional_setting_func_.clear(); } - this->last_child_id_ = child->id_; + this->value_.clear(); + set_exp_ = false; - 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; + return *this; } -void TraceNode::AddChildTraceNode(TraceNode& child) { - std::lock_guard _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::StartTrace() { trace_start_time_ = get_unix_time_ms(); } -void TraceNode::EndTimer() { - uint64_t end_time = get_unix_time_ms(); - this->cumulative_time += (end_time - this->start_time); -} +void TraceNode::EndTrace() { + expired_time_ = (get_unix_time_ms() - trace_start_time_); -void TraceNode::WakeUpTimer() { this->start_time = get_unix_time_ms(); } + this->AddAnnotation(":E", expired_time_); + this->AddAnnotation(":S", this->trace_start_time_ - this->pre_trace_time_); -void TraceNode::EndSpan() { - this->AddTraceDetail(":E", this->cumulative_time); - this->AddTraceDetail(":S", this->start_time); if (this->set_exp_) { - this->AddTraceDetail("EA", 1); + this->AddAnnotation("EA", 1); } -} -void TraceNode::EndSpanEvent() { - this->AddTraceDetail(":E", this->cumulative_time); - this->AddTraceDetail(":S", this->start_time - this->parent_start_time); + if (root_node_extra_ptr_ == nullptr) { // not root(SpanEvent) + AddAnnotation(":seq", sequence_); + AddAnnotation(":depth", depth_); + } } -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::BindParentTrace(WrapperTraceNodePtr& parent_ptr) { BindParentTrace(*parent_ptr); } + +void TraceNode::BindParentTrace(TraceNode& parent) { + parent_id_ = parent.id_; + depth_ = parent.depth_ + 1; } -void TraceNode::parseOpt(std::string key, std::string value) { +void TraceNode::parseUserOption(std::string key, std::string value) { 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:%" PRIu64 " cumulative_time:%" PRIu64 "", this->id_, - min, this->cumulative_time); - if ((int64_t)this->cumulative_time >= min) + if ((int64_t)this->expired_time_ >= min) { return true; - return false; + } else { + pp_trace("node:$d skipped due to `TraceMinTimeMs`", id_); + this->skipped_ = true; + return false; + } }; - this->_endTraceCallback.push_back(cb); + + this->user_optional_setting_func_.push_back(cb); } else if (key == "TraceOnlyException") { - auto cb = [=]() -> bool { return this->set_exp_; }; + auto cb = [=]() -> bool { + pp_trace("node:$d skipped due to `TraceOnlyException`", id_); + this->skipped_ = !this->set_exp_; + return this->set_exp_; + }; - this->_endTraceCallback.push_back(cb); + this->user_optional_setting_func_.push_back(cb); } } -bool TraceNode::checkOpt() { +bool TraceNode::runUserOptionFunc() { bool ret = true; - for (auto& cb : this->_endTraceCallback) { + for (auto& cb : this->user_optional_setting_func_) { if ((ret = cb()) == true) return ret; } return ret; } -void TraceNode::setOpt(const char* opt, va_list* args) { +void TraceNode::setNodeUserOption(const char* opt, va_list* args) { const char* var = opt; while (var != nullptr) { const char* delimit = strchr(var, ':'); if (delimit == nullptr) { - this->parseOpt(std::string(var), ""); + // key:value format + this->parseUserOption(std::string(var), ""); } else { + // command format std::string key(var, delimit - var); std::string value(delimit + 1); - this->parseOpt(key, value); + this->parseUserOption(key, value); } var = va_arg(*args, const char*); } diff --git a/common/src/NodePool/TraceNode.h b/common/src/NodePool/TraceNode.h index ce68b0408..7e02aaffa 100644 --- a/common/src/NodePool/TraceNode.h +++ b/common/src/NodePool/TraceNode.h @@ -25,12 +25,16 @@ #include "common.h" #include "Context/ContextType.h" #include "json/json.h" +#include "json/value.h" #include +#include +#include #include #include #include #include #include +#include #include #include #include @@ -43,94 +47,113 @@ using Context::LongContextType; using Context::StringContextType; class WrapperTraceNodePtr; const static int MAX_SUB_TRACE_NODES_LIMIT = 2048; -typedef std::shared_ptr _ContextType_; -using EndTraceCallBackFunc = std::function; -using EndTraceCallBackFuncVec = std::vector; +typedef std::shared_ptr ContextType_Ptr; + +using UserOptionalSettingFunc = std::function; +using UserOptionalSettingFunc_Vec = std::vector; +class WrapperTraceNodePtr; +using Root_Lock_t = std::mutex; class TraceNode { + +private: + using ContextMap_t = std::map; + struct RootTraceNodeExtra { + Root_Lock_t lock; + NodeID last; + NodeID next; + // uint64_t fellows_limit; + E_AGENT_STATUS status; + std::atomic sequence; + ContextMap_t context_map; + RootTraceNodeExtra() { + last = E_INVALID_NODE; + next = E_INVALID_NODE; + status = E_TRACE_PASS; + sequence = 0; + } + ~RootTraceNodeExtra() { context_map.clear(); } + int32_t createNewSequence() { return sequence++; } + }; + + std::unique_ptr root_node_extra_ptr_ = {nullptr}; + +public: + Root_Lock_t& GetRootLock() { return root_node_extra_ptr_->lock; } + + void UpgradeToRootNode(int agent_type) { + root_node_extra_ptr_ = std::unique_ptr(new RootTraceNodeExtra()); + root_id_ = id_; + parent_id_ = id_; + next_ = E_INVALID_NODE; + depth_ = 0; + sequence_ = 0; + AddAnnotation(":FT", agent_type); + } + + int32_t CreateNewSequence() { return root_node_extra_ptr_->createNewSequence(); } + + NodeID GetLastNode() { return root_node_extra_ptr_->last; } + + void SetLastNode(NodeID last) { root_node_extra_ptr_->last = last; } + + void SetStatus(E_AGENT_STATUS status) { root_node_extra_ptr_->status = status; } + + E_AGENT_STATUS GetStatus() { return root_node_extra_ptr_->status; } + public: - /** 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 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; - uint64_t limit; - uint64_t cumulative_time; - uint64_t root_start_time; - uint64_t parent_start_time; - bool set_exp_; + NodeID root_id_ = {E_INVALID_NODE}; + NodeID parent_id_ = {E_INVALID_NODE}; + NodeID id_ = {E_INVALID_NODE}; + NodeID next_ = {E_INVALID_NODE}; + + int32_t depth_ = {1}; + int32_t sequence_ = {-1}; + uint64_t trace_start_time_ = {0}; + uint64_t pre_trace_time_ = {0}; + + // the naming from pinpoint protocol + int64_t expired_time_ = {-1}; + bool set_exp_ = {false}; public: - void StartTimer(); - void EndTimer(); + void StartTrace(); - DEPRECATED("") void WakeUpTimer(); + void BindParentTrace(WrapperTraceNodePtr& node_ptr); + void BindParentTrace(TraceNode&); - void EndSpanEvent(); - void EndSpan(); + void EndTrace(); public: - void AddChildTraceNode(TraceNode& child); - DEPRECATED("") void AddChildTraceNode(WrapperTraceNodePtr& child); + void AddSubTraceNode(WrapperTraceNodePtr& root, TraceNode& sub_node); inline bool IsRootNode() const { return this->root_id_ == id_; } public: - TraceNode() { - this->id_ = E_INVALID_NODE; - this->root_id_ = E_INVALID_NODE; - this->resetRelative(); - this->resetStatus(); - this->ref_count_ = 0; - this->font_type_ = 0; - error_.set = false; - } + TraceNode() {} - virtual ~TraceNode(); + virtual ~TraceNode() = default; - TraceNode& reset(NodeID id) { - std::lock_guard _safe(this->mlock); - this->clearAttach(); - this->initId(id); - this->resetStatus(); - this->resetRelative(); - this->ref_count_ = 0; - return *this; - } + TraceNode& Reset(NodeID id); NodeID getId() const { return this->id_; } void getContext(const char* key, std::string& value) { - std::lock_guard _safe(this->mlock); - _ContextType_& ctx = this->context_.at(key); + ContextType_Ptr& ctx = this->context_map_.at(key); value = ctx->asStringValue(); } void getContext(const char* key, long& value) { - std::lock_guard _safe(this->mlock); - _ContextType_& ctx = this->context_.at(key); + ContextType_Ptr& ctx = this->context_map_.at(key); value = ctx->asLongValue(); } void setContext(const char* key, const char* buf) { - std::lock_guard _safe(this->mlock); - _ContextType_ context(std::make_shared(buf)); - this->context_[key] = context; + ContextType_Ptr context(std::make_shared(buf)); + this->context_map_[key] = context; } void setContext(const char* key, long l) { - std::lock_guard _safe(this->mlock); - _ContextType_ context(std::make_shared(l)); - this->context_[key] = context; + ContextType_Ptr context(std::make_shared(l)); + this->context_map_[key] = context; } public: @@ -142,8 +165,6 @@ class TraceNode { bool operator!=(TraceNode const& _node) const { return this->id_ != _node.id_; } private: - int font_type_; - struct Error { std::string message; std::string file_name; @@ -152,8 +173,6 @@ class TraceNode { } 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); @@ -162,125 +181,68 @@ class TraceNode { } public: - void AddTraceDetail(const char* key, const char* v) { - std::lock_guard _safe(this->mlock); - this->_value[key] = v; - } + void AddAnnotation(const char* key, const char* v) { value_[key] = v; } - void AddTraceDetail(const char* key, int v) { - std::lock_guard _safe(this->mlock); - this->_value[key] = v; - } + void AddAnnotation(const char* key, int v) { value_[key] = v; } - void AddTraceDetail(const char* key, uint64_t v) { - std::lock_guard _safe(this->mlock); - this->_value[key] = v; - } + void AddAnnotation(const char* key, uint64_t v) { value_[key] = v; } + void AddAnnotation(const char* key, int64_t v) { value_[key] = v; } - void AddTraceDetail(const char* key, const Json::Value& v) { - std::lock_guard _safe(this->mlock); - this->_value[key] = v; - } + void AddAnnotation(const char* key, const Json::Value& v) { value_[key] = v; } - void appendNodeValue(const char* key, Json::Value v) { - std::lock_guard _safe(this->mlock); - this->_value[key].append(v); - } + void AppendAnnotation(const char* key, Json::Value&& v) { value_[key].append(v); } - void appendNodeValue(const char* key, const char* v) { - std::lock_guard _safe(this->mlock); - this->_value[key].append(v); - } + void AppendAnnotation(const char* key, const char* v) { value_[key].append(v); } public: - void setOpt(const char* opt, va_list* args); - bool checkOpt(); + void setNodeUserOption(const char* opt, va_list* args); + bool runUserOptionFunc(); private: - void parseOpt(std::string key, std::string value); - - void clearAttach(); + void parseUserOption(std::string key, std::string value); - void initId(const NodeID& id); - - inline void resetRelative() { - 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; +private: + friend WrapperTraceNodePtr; + int addReference() { + reference_count_++; + return reference_count_.load(); } - inline void resetStatus() { - this->fetal_error_time = 0; - this->root_start_time = 0; - this->parent_start_time = 0; - this->start_time = 0; - this->limit = E_TRACE_PASS; - this->cumulative_time = 0; - this->set_exp_ = false; - error_.set = false; + int decReference() { + reference_count_--; + return reference_count_.load(); } public: - // changes: expose _lock - std::mutex mlock; - -public: - int addRef() { - ref_count_++; - return ref_count_.load(); - } - - int rmRef() { - ref_count_--; - return ref_count_.load(); - } - - bool checkZeroRef() { return ref_count_.load() == 0; } + bool IsNotReference() { return reference_count_.load() == 0; } public: std::string ToString() { - std::lock_guard _safe(this->mlock); + // TODO char pbuf[1024] = {0}; - int len = - snprintf(pbuf, 1024, - "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:%zu,_endTraceCallback:%zu \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()); + int len = snprintf(pbuf, 1024, "TODO ..."); return std::string(pbuf, len); } + const Json::Value& GetConstValue() { return value_; } + private: - std::atomic ref_count_; - int _subTraceNodeMaxSize; + std::atomic reference_count_; public: - // note: not tls, not a force limitation - inline void updateRootSubTraceSize() { - if (this->_subTraceNodeMaxSize < 0) { - throw std::out_of_range("current span reached max sub node limitation"); - } else { - this->_subTraceNodeMaxSize--; - } - } + Json::Value&& moveToSpan() { return std::move(value_); } -public: - Json::Value& EncodeProtocol() { return _value; } +private: + Json::Value value_; + std::map context_map_; + UserOptionalSettingFunc_Vec user_optional_setting_func_; private: - Json::Value _value; - std::map context_; - EndTraceCallBackFuncVec _endTraceCallback; + bool skipped_ = {false}; + +public: + bool ShouldSkip() { return skipped_; } + void SkipByParent() { skipped_ = true; } }; class WrapperTraceNodePtr { @@ -290,14 +252,15 @@ class WrapperTraceNodePtr { WrapperTraceNodePtr(WrapperTraceNodePtr& other) = delete; WrapperTraceNodePtr(WrapperTraceNodePtr&& other) : traceNode_(other.traceNode_) { - traceNode_.addRef(); + traceNode_.addReference(); } WrapperTraceNodePtr& operator=(const WrapperTraceNodePtr& other) = delete; - WrapperTraceNodePtr(TraceNode& node) : traceNode_(node) { traceNode_.addRef(); } + WrapperTraceNodePtr(TraceNode& node) : traceNode_(node) { traceNode_.addReference(); } TraceNode* operator->() { return &traceNode_; } - ~WrapperTraceNodePtr() { traceNode_.rmRef(); } + TraceNode& operator*() { return traceNode_; } + ~WrapperTraceNodePtr() { traceNode_.decReference(); } private: TraceNode& traceNode_; diff --git a/common/src/NodePool/test_node.cc b/common/src/NodePool/test_node.cc index 28d89ffec..ac1982355 100644 --- a/common/src/NodePool/test_node.cc +++ b/common/src/NodePool/test_node.cc @@ -2,6 +2,7 @@ #include "json/value.h" #include #include "header.h" +#define COMMON_DEBUG #include "NodePool/PoolManager.h" #include #include @@ -12,151 +13,42 @@ #include using PP::NodePool::PoolManager; +using PP::NodePool::ThreadSafePoolManager; using PP::NodePool::TraceNode; using PP::NodePool::WrapperTraceNodePtr; using namespace testing; namespace Json = AliasJson; -PoolManager nodePool_; -std::mutex cv_m; -std::condition_variable cv; -NodeID rootId = E_ROOT_NODE; - -// note: as it known, there may leak some node -void func() { - std::unique_lock lk(cv_m); - cv.wait(lk); - pinpoint_add_clues(rootId, "xxxx", "bbbbbbss", E_LOC_CURRENT); - pinpoint_add_clue(rootId, "xxx", "bbbbbb", E_LOC_CURRENT); - for (int i = 0; i < 100; ++i) { - rootId = pinpoint_start_trace(rootId); - pinpoint_set_context_key(rootId, "xxxx", "bbbbbb"); - std::this_thread::yield(); - 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); - std::this_thread::yield(); - rootId = pinpoint_end_trace(rootId); - std::this_thread::yield(); - } - pinpoint_add_clues(rootId, "xxxx", "bbbbbbss", E_LOC_CURRENT); - pinpoint_add_clue(rootId, "xxx", "bbbbbb", E_LOC_CURRENT); -} - -TEST(node, multipleThread) { - // no crash, works fine - NodeID root = pinpoint_start_trace(E_ROOT_NODE); - - std::vector threads; - for (int i = 0; i < 10; i++) { - threads.push_back(std::thread(func)); - } - - sleep(2); - cv.notify_all(); - - for (int i = 0; i < 10; i++) { - threads[i].join(); - } - pinpoint_end_trace(root); - pinpoint_end_trace(root); - // EXPECT_TRUE(PoolManager::getInstance().NoNodeLeak()); -} - -void test_opt(TraceNode& node, const char* opt, ...) { +static void test_opt(TraceNode& node, const char* opt, ...) { va_list args; va_start(args, opt); - node.setOpt(opt, &args); + node.setNodeUserOption(opt, &args); va_end(args); } -TEST(node, opt) { - - TraceNode& node = nodePool_.Take(); +TEST(NodePool, opt) { + PoolManager nodePool_; + TraceNode& node = nodePool_.GetNode(); test_opt(node, "TraceMinTimeMs:23", "TraceOnlyException", nullptr); - node.cumulative_time = 22; - EXPECT_FALSE(node.checkOpt()); - node.cumulative_time = 23; - EXPECT_TRUE(node.checkOpt()); + node.expired_time_ = 22; + EXPECT_FALSE(node.runUserOptionFunc()); + node.expired_time_ = 23; + EXPECT_TRUE(node.runUserOptionFunc()); - node.cumulative_time = 0; + node.expired_time_ = 0; node.set_exp_ = true; - EXPECT_TRUE(node.checkOpt()); + EXPECT_TRUE(node.runUserOptionFunc()); node.set_exp_ = false; - EXPECT_FALSE(node.checkOpt()); - - nodePool_.ReturnNode(node); - // EXPECT_TRUE(PoolManager::getInstance().NoNodeLeak()); -} + EXPECT_FALSE(node.runUserOptionFunc()); -static std::string span; -void capture(const char* msg) { - pp_trace("capture:%s", msg); - span = std::string(msg); + nodePool_.ReturnNode(node.id_); + EXPECT_TRUE(nodePool_.NoNodeLeak()); } -//./bin/TestCommon --gtest_filter=node.pinpoint_start_traceV1 -TEST(node, pinpoint_start_traceV1) { - 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); - child1 = pinpoint_start_traceV1(root, "TraceMinTimeMs:23", nullptr); - pinpoint_add_clue(child1, "name", "Take1sec", E_LOC_CURRENT); - sleep(1); - pinpoint_end_trace(child1); - check_tracelimit(-1); - check_tracelimit(0); - check_tracelimit(time(nullptr)); - child1 = pinpoint_start_traceV1(root, "TraceOnlyException", nullptr); - pinpoint_add_clue(child1, "name", "Exception", E_LOC_CURRENT); - pinpoint_add_exception(child1, "xxxxxxxxx"); - pinpoint_end_trace(child1); - child1 = pinpoint_start_traceV1(root, "TraceMinTimeMs:2000", nullptr); - pinpoint_add_clue(child1, "name", "TraceMinTimeMs:2000", E_LOC_CURRENT); - sleep(1); - - { - NodeID child = pinpoint_start_traceV1(child1, "TraceMinTimeMs:23", nullptr); - pinpoint_add_clue(child1, "name", "childFromTraceMinTimeMs:23-1", E_LOC_CURRENT); - pinpoint_end_trace(child); - child = pinpoint_start_traceV1(child1, "TraceMinTimeMs:23", nullptr); - pinpoint_add_clue(child1, "name", "childFromTraceMinTimeMs:23-2", E_LOC_CURRENT); - pinpoint_end_trace(child); - child = pinpoint_start_traceV1(child1, "TraceMinTimeMs:23", nullptr); - pinpoint_add_clue(child1, "name", "childFromTraceMinTimeMs:23-3", E_LOC_CURRENT); - pinpoint_end_trace(child); - } - - pinpoint_end_trace(child1); - - child1 = pinpoint_start_traceV1(root, "TraceOnlyException", nullptr); - pinpoint_add_clue(child1, "name", "NoException", E_LOC_CURRENT); - pinpoint_end_trace(child1); - - child1 = pinpoint_start_traceV1(root, "TraceMinTimeMs:-23", nullptr); - pinpoint_add_clue(child1, "name", "TraceMinTimeMs:-23", E_LOC_CURRENT); - pinpoint_end_trace(child1); - - pinpoint_end_trace(root); - 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); - EXPECT_TRUE(span.find("NoException") == span.npos); - - EXPECT_TRUE(span.find("childFromTraceMinTimeMs:23-3") == span.npos); - EXPECT_TRUE(span.find("childFromTraceMinTimeMs:23-2") == span.npos); -} - -TEST(node, leak_node) { +TEST(NodePool, leak_node) { + PoolManager nodePool_; auto count = nodePool_.freeNodesCount(); NodeID root, child1, child2; root = pinpoint_start_trace(E_ROOT_NODE); @@ -171,63 +63,8 @@ TEST(node, leak_node) { EXPECT_EQ(count, nodePool_.freeNodesCount()); show_status(); } -std::set 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) { +TEST(NodePool, tons_of_nodes_01) { pinpoint_set_agent("tcp:127.0.0.1:9999", 7000, -1, 7000); // auto count = usedNode(); NodeID root = pinpoint_start_trace(E_ROOT_NODE); @@ -241,51 +78,17 @@ TEST(node, tons_of_nodes_01) { root = pinpoint_start_trace(E_ROOT_NODE); NodeID child1 = root; - for (int i = 0; i < 1000; i++) { + for (int i = 0; i < 3000; i++) { NodeID child = pinpoint_start_trace(child1); - mark_current_trace_status(root, E_OFFLINE); + change_trace_status(root, E_OFFLINE); pinpoint_end_trace(child); child1 = child; } - mark_current_trace_status(root, E_TRACE_BLOCK); + change_trace_status(root, E_TRACE_BLOCK); pinpoint_end_trace(root); } -// 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) { + +TEST(NodePool, tons_of_nodes_1k) { NodeID root = pinpoint_start_trace(E_ROOT_NODE); NodeID next = root; for (int i = 0; i < 1000; i++) { @@ -301,7 +104,7 @@ TEST(node, tons_of_nodes_1k) { show_status(); } -TEST(node, tons_of_nodes_leak) { +TEST(NodePool, tons_of_nodes_leak) { NodeID root, child_1, child_2; root = pinpoint_start_trace(E_ROOT_NODE); @@ -314,7 +117,7 @@ TEST(node, tons_of_nodes_leak) { pinpoint_end_trace(child_1); } -TEST(node, tons_of_nodes_free_all) { +TEST(NodePool, tons_of_nodes_free_all) { NodeID root, child_1, child_2; root = pinpoint_start_trace(E_ROOT_NODE); @@ -326,18 +129,23 @@ TEST(node, tons_of_nodes_free_all) { pinpoint_end_trace(root); pinpoint_end_trace(child_1); } -//./bin/TestCommon --gtest_filter=node.free_when_add -TEST(node, free_when_add) { +//./bin/TestCommon --gtest_filter=NodePool.free_when_add +TEST(NodePool, free_when_add) { + ThreadSafePoolManager nodePool_; auto getUsedNode = [&]() { return nodePool_.totalNodesCount() - nodePool_.freeNodesCount(); }; auto usedNode = getUsedNode(); NodeID root; auto make_it_busy = [&]() { - 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); + auto& w_root = nodePool_.GetNode(); + root = w_root.id_; + auto& w_child = nodePool_.GetNode(); + + WrapperTraceNodePtr parent_ptr = w_root; + w_child.BindParentTrace(parent_ptr); + + w_child.AddAnnotation("E_ROOT_NODE", 234); std::this_thread::sleep_for(std::chrono::seconds(2)); + nodePool_.ReturnNode(w_child.id_); }; std::thread t(make_it_busy); std::this_thread::sleep_for(std::chrono::seconds(1)); @@ -346,14 +154,14 @@ TEST(node, free_when_add) { 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); + pp_trace("it takes: %ld to free ", (long)end); t.join(); EXPECT_EQ(usedNode, getUsedNode()); EXPECT_TRUE(end >= 100); } //./bin/TestCommon --gtest_filter=node.orphan_node -TEST(node, orphan_node) { +TEST(NodePool, orphan_node) { NodeID root, child_1, orphan; root = pinpoint_start_trace(E_ROOT_NODE); child_1 = pinpoint_start_trace(root); @@ -370,7 +178,7 @@ TEST(node, orphan_node) { pinpoint_end_trace(root); } //./bin/TestCommon --gtest_filter=node.orphan_node_01 -TEST(node, orphan_node_01) { +TEST(NodePool, orphan_node_01) { pinpoint_set_agent("tcp:127.0.0.1:9999", 7000, -1, 7000); NodeID root, child_1, orphan; root = pinpoint_start_trace(E_ROOT_NODE); @@ -382,7 +190,7 @@ TEST(node, orphan_node_01) { pinpoint_end_trace(orphan); } //./bin/TestCommon --gtest_filter=node.orphan_root_parent_end -TEST(node, orphan_parent_root_end) { +TEST(NodePool, orphan_parent_root_end) { pinpoint_set_agent("tcp:127.0.0.1:9999", 7000, -1, 7000); NodeID root, child_1, orphan; root = pinpoint_start_trace(E_ROOT_NODE); @@ -394,7 +202,7 @@ TEST(node, orphan_parent_root_end) { pinpoint_end_trace(orphan); } -TEST(node, orphan_root_parent_end) { +TEST(NodePool, orphan_root_parent_end) { pinpoint_set_agent("tcp:127.0.0.1:9999", 7000, -1, 7000); NodeID root, child_1, orphan; root = pinpoint_start_trace(E_ROOT_NODE); @@ -405,8 +213,9 @@ TEST(node, orphan_root_parent_end) { pinpoint_end_trace(orphan); } + // ./bin/TestCommon --gtest_filter=node.end_trace_in_mt -TEST(node, end_trace_in_mt) { +TEST(NodePool, end_trace_in_mt) { pinpoint_set_agent("tcp:127.0.0.1:9999", 7000, -1, 7000); NodeID root = pinpoint_start_trace(E_ROOT_NODE); NodeID next = root; @@ -438,16 +247,97 @@ TEST(node, end_trace_in_mt) { for (auto& thread : threads) thread.join(); } -// ./bin/TestCommon --gtest_filter=node.max_sub_nodes -TEST(node, max_sub_nodes) { + +// ./bin/TestCommon --gtest_filter=NodePool.max_sub_nodes +TEST(NodePool, max_sub_nodes) { 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); if (next == E_INVALID_NODE) { + pp_trace(" pinpoint_start_trace return E_INVALID_NODE "); break; } pinpoint_end_trace(next); } pinpoint_end_trace(root); +} + +TEST(NodePool, get_and_give_back) { + PoolManager pool; + // new + TraceNode& _node = pool.GetNode(); + void* p = &_node; + NodeID id = _node.getId(); + NodeID next; + // give back + next = pool.ReturnNode(id); + EXPECT_EQ(next, E_INVALID_NODE); + TraceNode& _node_01 = pool.GetNode(); + + TraceNode& new_node = pool.GetNode(); + NodeID new_id = new_node.id_; + + auto ref_node = pool.ReferNode(new_id); + EXPECT_EQ(ref_node->id_, new_node.id_); + + next = pool.ReturnNode(new_id); + EXPECT_THROW(pool.ReferNode(new_id), std::out_of_range); + + // ref current + auto ref_new_node = pool.ReferNode(_node_01.getId()); + + EXPECT_EQ(p, &_node); + // reuse the same id + EXPECT_EQ(id, _node.getId()); + EXPECT_THROW(pool.ReferNode(NodeID(100)), std::out_of_range); + EXPECT_THROW(pool.ReferNode(NodeID(10000)), std::out_of_range); +} + +static ThreadSafePoolManager thread_safe_pool; + +void test_node_pool(bool& result) { + NodeID it = E_INVALID_NODE; + for (int i = 0; i < 1000; i++) { + TraceNode& _node = thread_safe_pool.GetNode(); + usleep(1000); + if (_node.getId() == it) { + result = false; + return; + } + thread_safe_pool.ReturnNode(_node.id_); + } + result = true; +} + +// ./bin/TestCommon --gtest_filter=NodePool.get_and_give_back_tls +TEST(NodePool, 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)); + + t1.join(); + t2.join(); + EXPECT_TRUE(rth1); + EXPECT_TRUE(rth2); +} + +// ./bin/TestCommon --gtest_filter=NodePool.double_append +TEST(NodePool, double_append) { + PoolManager pool; + NodeID root_id; + { + auto& root = pool.GetNode(); + root.UpgradeToRootNode(1500); + root_id = root.id_; + auto& child_0 = pool.GetNode(); + + child_0.BindParentTrace(root); + PP::NodePool::WrapperTraceNodePtr root_ptr(root); + pool.AppendToRootTrace(root_ptr, child_0); + pool.AppendToRootTrace(root_ptr, child_0); + pool.AppendToRootTrace(root_ptr, root); + } + pool.FreeNodeTree(root_id); + EXPECT_TRUE(pool.NoNodesLeak()); } \ No newline at end of file diff --git a/common/src/NodePool/test_node_pool.cc b/common/src/NodePool/test_node_pool.cc deleted file mode 100644 index e4265121f..000000000 --- a/common/src/NodePool/test_node_pool.cc +++ /dev/null @@ -1,71 +0,0 @@ -#include "NodePool/TraceNode.h" -#include "PoolManager.h" -#include "common.h" -#include "header.h" -#include -#include - -using namespace testing; -using PP::NodePool::PoolManager; -using PP::NodePool::TraceNode; - -TEST(poolManger, get_and_give_back) { - PoolManager pool; - // new - TraceNode& _node = pool.Take(); - void* p = &_node; - NodeID id = _node.getId(); - NodeID child, next; - // give back - pool.ReturnNode(id, child, next); - EXPECT_EQ(child, E_INVALID_NODE); - EXPECT_EQ(next, E_INVALID_NODE); - 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()); - - EXPECT_EQ(p, &_node); - EXPECT_EQ(ref_new_node, _node); - // reuse the same id - EXPECT_EQ(id, _node.getId()); - EXPECT_THROW(pool.Take(NodeID(100)), std::out_of_range); - EXPECT_THROW(pool.Take(NodeID(10000)), std::out_of_range); -} - -static PoolManager g_pool; - -void test_node_pool(bool& result) { - NodeID it = E_INVALID_NODE; - for (int i = 0; i < 1000; i++) { - TraceNode& _node = g_pool.Take(); - usleep(1000); - if (_node.getId() == it) { - result = false; - return; - } - g_pool.ReturnNode(_node); - // g_pool.freeNode(_node.getId()); - } - result = true; -} - -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)); - - t1.join(); - t2.join(); - EXPECT_TRUE(rth1); - EXPECT_TRUE(rth2); -} diff --git a/common/src/common.cpp b/common/src/common.cpp index a2fddd03b..cdbae6147 100644 --- a/common/src/common.cpp +++ b/common/src/common.cpp @@ -18,11 +18,13 @@ // #include "common.h" +#include "json/value.h" #include #include #include #include #include +#include #include #include #include @@ -37,13 +39,13 @@ using std::chrono::milliseconds; using std::chrono::system_clock; using std::chrono::time_point; using std::chrono::time_point_cast; - namespace PP { namespace Json = AliasJson; using Cache::NodeTreeWriter; using ConnectionPool::TransLayerPtr; using NodePool::TraceNode; using NodePool::WrapperTraceNodePtr; +using PoolManger_ptr = std::unique_ptr; typedef struct { int agent_type; @@ -64,6 +66,7 @@ class Agent { std::placeholders::_2, std::placeholders::_3)}}) { statePtr_ = std::unique_ptr(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_); } @@ -86,9 +89,12 @@ class Agent { // 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); + + void SendSpanTrace(NodeID root_id, int timeout) { + WrapperTraceNodePtr root = local_nodePool_ptr->ReferNode(root_id); + const Json::Value& value_ptr = local_nodePool_ptr->EncodeTraceToJsonSpan(root); + + std::string spanStr = node_tree_to_string(value_ptr); pp_trace("this span:(%s)", spanStr.c_str()); TrySendSpan(spanStr, timeout); if (unlikely(rawSpanHandler_ != nullptr)) { @@ -96,9 +102,9 @@ class Agent { } } - void HandleHelloMsg(int type, const char* buf, size_t len) { + int HandleHelloMsg(int type, const char* buf, size_t len) { if (statePtr_->IsReady()) { - return; + return 0; } Json::Value root; @@ -113,105 +119,114 @@ class Agent { if (root["version"] || root["version"].isString()) { std::string version = root["version"].asString(); - std::string lowest_version = "v0.5.0"; + std::string lowest_version = "v0.6.0"; + pp_trace("collector information: version:%s", version.c_str()); if (version < lowest_version) { pp_trace("collector-agent should be >=v0.5.0, please upgrade it"); - return; + return -1; } } if (root["time"] && root["time"].isString()) { statePtr_->SetStartTime(std::stoll(root["time"].asString())); } + return 0; } public: - NodeID StartTrace(NodeID id, const char* opt = nullptr, va_list* args = nullptr) { - if (id <= E_INVALID_NODE) { + NodeID StartTrace(NodeID parent_id, const char* opt = nullptr, va_list* args = nullptr) { + if (parent_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_); + } else if (parent_id == E_ROOT_NODE) { + TraceNode& trace = local_nodePool_ptr->GetNode(); + trace.UpgradeToRootNode(agent_type_); + trace.StartTrace(); return trace.id_; } else { - WrapperTraceNodePtr parent = nodePool_.ReferNode(id); - + WrapperTraceNodePtr parent = local_nodePool_ptr->ReferNode(parent_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 + WrapperTraceNodePtr root = local_nodePool_ptr->ReferNode(parent->root_id_); + + TraceNode& trace = local_nodePool_ptr->GetNode(); + + trace.StartTrace(); + + trace.BindParentTrace(parent); + + local_nodePool_ptr->AppendToRootTrace(root, trace); + if (opt != nullptr) { - new_trace.setOpt(opt, args); + trace.setNodeUserOption(opt, args); } - return new_trace.id_; + return trace.id_; } } - NodeID EndTrace(NodeID ID, int timeout = 0) { + + 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(); + WrapperTraceNodePtr w_trace = local_nodePool_ptr->ReferNode(id); + if (!w_trace->IsRootNode()) { + w_trace->EndTrace(); + return w_trace->parent_id_; + } else { + if (w_trace->GetStatus() == E_TRACE_PASS) { + w_trace->EndTrace(); if (timeout == 0) { timeout = span_timeout_; } - SendSpanTrace(ID, timeout); - } else if (w_trace->limit & E_TRACE_BLOCK) { + SendSpanTrace(id, timeout); + } else if (w_trace->GetStatus() == 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=%" PRIu64 "", w_trace->getId(), - w_trace->limit); + pp_trace("current [%d] span dropped,due to limit=%u", w_trace->getId(), + w_trace->GetStatus()); } - } 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); + // dealloc w_trace by scope + local_nodePool_ptr->FreeNodeTree(id); return E_ROOT_NODE; } bool IsRootTrace(NodeID id) { - WrapperTraceNodePtr w_node = nodePool_.ReferNode(id); + WrapperTraceNodePtr w_node = local_nodePool_ptr->ReferNode(id); return w_node->IsRootNode(); } + + int32_t GetDepth(NodeID id) { + WrapperTraceNodePtr w_node = local_nodePool_ptr->ReferNode(id); + return w_node->depth_; + } + 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; + WrapperTraceNodePtr w_node = local_nodePool_ptr->ReferNode(id); + WrapperTraceNodePtr w_root = local_nodePool_ptr->ReferNode(w_node->root_id_); + E_AGENT_STATUS older = w_root->GetStatus(); + pp_trace("change current [%d] status, before:%lld,now:%d", w_root->getId(), older, status); + w_root->SetStatus(static_cast(status)); + return older; } + void AnnotateTrace_V1(NodeID id, const char* key, const char* value, E_NODE_LOC flag) { NotInternalKey(key); WrapperTraceNodePtr w_node = GetWrapperTraceNode(id, flag); - w_node->AddTraceDetail(key, value); - pp_trace(" [%d] add clue key:%s value:%s", id, key, value); + w_node->AddAnnotation(key, value); + pp_trace(" [%d] add anno_v1 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); + std::string ann_value = ""; + ann_value += key; + ann_value += ':'; + ann_value += value; + + w_node->AppendAnnotation("anno", ann_value.c_str()); + pp_trace(" [%d] add anno_v2 %s:%s", id, key, value); } void AnnotateErrorTrace(NodeID id, const char* msg, const char* error_filename, uint32_t error_lineno) { @@ -220,7 +235,7 @@ class Agent { eMsg["msg"] = msg; eMsg["file"] = error_filename; eMsg["line"] = error_lineno; - w_root->AddTraceDetail("ERR", eMsg); + w_root->AddAnnotation("ERR", eMsg); } void AnnotateExceptionTrace(NodeID id, const char* exception) { @@ -232,8 +247,8 @@ class Agent { exp["M"] = exception; // TODO not support class exp["C"] = "class"; - exp[":S"] = get_unix_time_ms() - w_root->start_time; - w_node->AddTraceDetail("EXP_V2", exp); + exp[":S"] = get_unix_time_ms() - w_root->trace_start_time_; + w_node->AddAnnotation("EXP_V2", exp); pp_trace(" [%d] add exp value:%s", id, exception); } @@ -241,6 +256,14 @@ class Agent { WrapperTraceNodePtr w_node = GetWrapperTraceNode(id, E_LOC_ROOT); w_node->setContext(key, value); } + + int32_t GetSequenceId(NodeID id) { + // get node + WrapperTraceNodePtr node_ptr = GetWrapperTraceNode(id, E_LOC_CURRENT); + // return newSequence + return node_ptr->sequence_; + } + int GetTraceContext(NodeID id, const char* key, char* pbuf, int buf_size) { WrapperTraceNodePtr w_node = GetWrapperTraceNode(id, E_LOC_ROOT); std::string value; @@ -265,10 +288,20 @@ class Agent { using SpanHandler = void (*)(const char*); void RegisterRawSpanHandler(SpanHandler user_handler) { rawSpanHandler_ = user_handler; } - std::string GetNodePoolStatus() { return nodePool_.Status(); } + void SetAsyncContext(NodeID id, int32_t async_node_id, int32_t node_sequence) { + WrapperTraceNodePtr w_node = GetWrapperTraceNode(id, E_LOC_ROOT); + Json::Value async_value; + async_value["id"] = async_node_id; + async_value["seq"] = node_sequence; + w_node->AddAnnotation("asy", async_value); + pp_trace("mark current node:%d as async call with async_id:%d sequence:%d", id, async_node_id, + node_sequence); + } + + std::string GetNodePoolStatus() { return local_nodePool_ptr->Status(); } void DebugNodeId(NodeID id) { try { - WrapperTraceNodePtr w_node = nodePool_.ReferNode(id); + WrapperTraceNodePtr w_node = local_nodePool_ptr->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()); @@ -288,9 +321,9 @@ class Agent { 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); + WrapperTraceNodePtr w_node = local_nodePool_ptr->ReferNode(id); if (flag == E_LOC_ROOT) { - return nodePool_.ReferNode(w_node->root_id_); + return local_nodePool_ptr->ReferNode(w_node->root_id_); } else { return w_node; } @@ -300,20 +333,28 @@ class Agent { int span_timeout_; int agent_type_; ConnectionPool::SpanConnectionPool connection_pool_; - NodePool::PoolManager nodePool_; StatePtr statePtr_; SpanHandler rawSpanHandler_ = {nullptr}; Json::CharReaderBuilder builder; + NodeTreeWriter _writer; +#ifndef PINPOINT_MT + static thread_local PoolManger_ptr local_nodePool_ptr; +#else + PoolManger_ptr local_nodePool_ptr = {PoolManger_ptr(new NodePool::ThreadSafePoolManager())}; +#endif public: static thread_local NodeID per_thread_current_id; - NodeTreeWriter _writer; }; thread_local NodeID Agent::per_thread_current_id = E_ROOT_NODE; +#ifndef PINPOINT_MT +thread_local PoolManger_ptr Agent::local_nodePool_ptr = PoolManger_ptr(new NodePool::PoolManager()); +#endif + using AgentPtr = std::unique_ptr; -AgentPtr _agentPtr = {nullptr}; +static AgentPtr _agentPtr = {nullptr}; } // namespace PP @@ -349,7 +390,7 @@ NodeID pinpoint_start_traceV1(NodeID parentId, const char* opt, ...) { va_list args; va_start(args, opt); NodeID child = _agentPtr->StartTrace(parentId, opt, &args); - pp_trace(" [%d] pinpoint_start child [%d]", parentId, child); + pp_trace(" [%d] pinpoint_start child [%d]", parentId, child); va_end(args); return child; } catch (const std::out_of_range& ex) { @@ -410,6 +451,22 @@ int pinpoint_trace_is_root(NodeID id) { return -1; } +int32_t pinpoint_get_depth(NodeID id) { + if (_agentPtr) { + try { + if (id == E_ROOT_NODE) { + return -1; + } + return _agentPtr->GetDepth(id); + } 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; +} + int pinpoint_force_end_trace(NodeID id, int32_t timeout) { if (_agentPtr) { try { @@ -510,7 +567,7 @@ uint64_t change_trace_status(NodeID id, int status) { } 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); + pp_trace(" %s [%d] failed with unknown reason", __func__, id); } } return 0; @@ -586,4 +643,35 @@ uint64_t get_unix_time_ms() { std::chrono::time_point now = std::chrono::system_clock::now(); time_point current = time_point_cast(now); return current.time_since_epoch().count(); +} + +int32_t pinpoint_get_sequence_id(NodeID node) { + if (_agentPtr) { + try { + return _agentPtr->GetSequenceId(node); + } catch (const std::out_of_range& ex) { + pp_trace(" %s [%d] pinpoint_get_sequence: failed with out_of_range: %s", __func__, node, + ex.what()); + } catch (const std::runtime_error& ex) { + pp_trace(" %s [%d] pinpoint_get_sequence: failed with runtime_error: %s", __func__, node, + ex.what()); + } catch (const std::exception& ex) { + pp_trace(" %s [%d] pinpoint_get_sequence: failed with %s", __func__, node, ex.what()); + } + } + return -1; +} + +void pinpoint_set_async_ctx(NodeID id, int32_t async_node_id, int32_t node_sequence) { + if (_agentPtr) { + try { + _agentPtr->SetAsyncContext(id, async_node_id, node_sequence); + } 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 unknown reason", __func__, id); + } + } } \ No newline at end of file diff --git a/common/src/test_common.cc b/common/src/test_common.cc index 34b6ab6cc..7ab09373c 100644 --- a/common/src/test_common.cc +++ b/common/src/test_common.cc @@ -1,13 +1,17 @@ #include "gtest/gtest.h" // #include // #include + #include #include #include "common.h" #include "json/value.h" +#include "json/reader.h" using namespace testing; std::string ouputMsg; +namespace Json = AliasJson; + void cc_log_error_cb(const char* msg) { ouputMsg = msg; } TEST(common, uid_all_in_one) { @@ -23,18 +27,21 @@ TEST(common, uid_all_in_one) { TEST(common, start_end_trace) { register_span_handler(cc_log_error_cb); + EXPECT_EQ(pinpoint_get_depth(E_ROOT_NODE), -1); NodeID id = pinpoint_start_trace(E_ROOT_NODE); - mark_current_trace_status(id, E_OFFLINE); + EXPECT_EQ(pinpoint_get_depth(id), 0); + change_trace_status(id, E_OFFLINE); EXPECT_EQ(pinpoint_trace_is_root(id), 1); id = pinpoint_start_trace(id); + EXPECT_EQ(pinpoint_get_depth(id), 1); EXPECT_EQ(pinpoint_trace_is_root(id), 0); - mark_current_trace_status(id, E_OFFLINE); + change_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); + EXPECT_EQ(pinpoint_get_depth(id), 2); + change_trace_status(id, E_TRACE_PASS); catch_error(id, "sdfasfas", "fsafdsfasd", 234); id = pinpoint_end_trace(id); @@ -42,8 +49,8 @@ TEST(common, start_end_trace) { id = pinpoint_end_trace(id); EXPECT_EQ(id, 0); - mark_current_trace_status(-1024, E_TRACE_BLOCK); - mark_current_trace_status(1024, E_TRACE_BLOCK); + change_trace_status(-1024, E_TRACE_BLOCK); + change_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); @@ -187,4 +194,231 @@ TEST(common, none_utf8) { AliasJson::Value value; value["a"] = "ä\xA9ü"; pp_trace("%s ", value.toStyledString().c_str()); +} + +static std::string span; +static void capture(const char* msg) { + pp_trace("capture:%s", msg); + span = std::string(msg); +} + +//./bin/TestCommon --gtest_filter=common.pinpoint_start_traceV1 +TEST(common, pinpoint_start_traceV1) { + 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); + child1 = pinpoint_start_traceV1(root, "TraceMinTimeMs:23", nullptr); + pinpoint_add_clue(child1, "name", "Take1sec", E_LOC_CURRENT); + std::this_thread::sleep_for(std::chrono::seconds(1)); + pinpoint_end_trace(child1); + check_trace_limit(-1); + check_trace_limit(0); + check_trace_limit(time(nullptr)); + child1 = pinpoint_start_traceV1(root, "TraceOnlyException", nullptr); + pinpoint_add_clue(child1, "name", "Exception", E_LOC_CURRENT); + pinpoint_add_exception(child1, "xxxxxxxxx"); + pinpoint_end_trace(child1); + + child1 = pinpoint_start_traceV1(root, "TraceMinTimeMs:2000", nullptr); + pinpoint_add_clue(child1, "name", "TraceMinTimeMs:2000", E_LOC_CURRENT); + std::this_thread::sleep_for(std::chrono::seconds(1)); + + // [ ] optional setting not ready + // { + // NodeID child = pinpoint_start_traceV1(child1, "TraceMinTimeMs:23", nullptr); + // pinpoint_add_clue(child, "name", "childFromTraceMinTimeMs:23-1", E_LOC_CURRENT); + // pinpoint_end_trace(child); + + // child = pinpoint_start_traceV1(child1, "TraceMinTimeMs:23", nullptr); + // pinpoint_add_clue(child, "name", "childFromTraceMinTimeMs:23-2", E_LOC_CURRENT); + // pinpoint_end_trace(child); + + // child = pinpoint_start_traceV1(child1, "TraceMinTimeMs:23", nullptr); + // pinpoint_add_clue(child, "name", "childFromTraceMinTimeMs:23-3", E_LOC_CURRENT); + + // pinpoint_end_trace(child); + // } + + pinpoint_end_trace(child1); + + child1 = pinpoint_start_traceV1(root, "TraceOnlyException", nullptr); + pinpoint_add_clue(child1, "name", "NoException", E_LOC_CURRENT); + pinpoint_end_trace(child1); + + child1 = pinpoint_start_traceV1(root, "TraceMinTimeMs:-23", nullptr); + pinpoint_add_clue(child1, "name", "TraceMinTimeMs:-23", E_LOC_CURRENT); + pinpoint_end_trace(child1); + + pinpoint_end_trace(root); + // 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); + // EXPECT_TRUE(span.find("NoException") == span.npos); + + // EXPECT_TRUE(span.find("childFromTraceMinTimeMs:23-3") == span.npos); + // EXPECT_TRUE(span.find("childFromTraceMinTimeMs:23-2") == span.npos); +} + +std::set removed_keys = {":E", ":S"}; +static void removeKeys(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 == "event") { + for (long i = 0; i < v[*iter].size(); i++) { + removeKeys(v["event"][(int)i]); + } + } + } + + return; +} + +static bool check_span_order(std::string& i1, std::string& i2) { + Json::Value v_i1, v_i2; + Json::Reader reader; + reader.parse(i1, v_i1, true); + reader.parse(i2, v_i2, true); + removeKeys(v_i1); + removeKeys(v_i2); + pp_trace("v_i1\r\n%s", v_i1.toStyledString().c_str()); + pp_trace("v_i2\r\n%s", v_i2.toStyledString().c_str()); + return v_i1.toStyledString() == v_i2.toStyledString(); +} + +TEST(common, call_order) { + span.clear(); + 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->root", E_LOC_CURRENT); + child2 = pinpoint_start_trace(child1); + pinpoint_add_clue(child2, "name:", "child2->child1", E_LOC_CURRENT); + child2 = pinpoint_start_trace(child1); + pinpoint_add_clue(child2, "name:", "child3->child1", E_LOC_CURRENT); + pinpoint_end_trace(child2); + child2 = pinpoint_start_trace(child1); + pinpoint_add_clue(child2, "name:", "child4->child1", E_LOC_CURRENT); + pinpoint_end_trace(child2); + child2 = pinpoint_start_trace(child1); + pinpoint_add_clue(child2, "name:", "child5->child1", E_LOC_CURRENT); + child2 = pinpoint_start_trace(child2); + pinpoint_add_clue(child2, "name:", "child6->child5", E_LOC_CURRENT); + + pinpoint_end_trace(child2); + pinpoint_end_trace(child1); + pinpoint_end_trace(root); + + std::string exp = + R"({":FT":7000,"event":[{":E":0,":S":0,":depth":1,":seq":0,"name:":"child1->root"},{":E":0,":S":0,":depth":2,":seq":1,"name:":"child2->child1"},{":E":0,":S":0,":depth":2,":seq":2,"name:":"child3->child1"},{":E":0,":S":0,":depth":2,":seq":3,"name:":"child4->child1"},{":E":0,":S":0,":depth":2,":seq":4,"name:":"child5->child1"},{":E":0,":S":0,":depth":3,":seq":5,"name:":"child6->child5"}],"name:":"root"})"; + printf("\n%s\n", span.c_str()); + EXPECT_TRUE(check_span_order(span, exp)); +} +std::mutex cv_m; +std::condition_variable cv; +NodeID rootId = E_ROOT_NODE; +// note: as it known, there may leak some nodes +static void func() { + std::unique_lock lk(cv_m); + cv.wait(lk); + pinpoint_add_clues(rootId, "xxxx", "bbbbbbss", E_LOC_CURRENT); + pinpoint_add_clue(rootId, "xxx", "bbbbbb", E_LOC_CURRENT); + for (int i = 0; i < 100; ++i) { + rootId = pinpoint_start_trace(rootId); + pinpoint_set_context_key(rootId, "xxxx", "bbbbbb"); + std::this_thread::yield(); + 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); + std::this_thread::yield(); + rootId = pinpoint_end_trace(rootId); + std::this_thread::yield(); + } + pinpoint_add_clues(rootId, "xxxx", "bbbbbbss", E_LOC_CURRENT); + pinpoint_add_clue(rootId, "xxx", "bbbbbb", E_LOC_CURRENT); +} + +TEST(common, multipleThread) { + // no crash, works fine + NodeID root = pinpoint_start_trace(E_ROOT_NODE); + + std::vector threads; + + for (int i = 0; i < 10; i++) { + threads.push_back(std::thread(func)); + } + + std::this_thread::sleep_for(std::chrono::seconds(2)); + cv.notify_all(); + + for (int i = 0; i < 10; i++) { + threads[i].join(); + } + pinpoint_end_trace(root); + pinpoint_end_trace(root); + // EXPECT_TRUE(PoolManager::getInstance().NoNodeLeak()); +} + +TEST(common, sequenceId) { + NodeID root = pinpoint_start_trace(E_ROOT_NODE); + NodeID child_01 = pinpoint_start_trace(root); + NodeID child_02 = pinpoint_start_trace(child_01); + EXPECT_EQ(pinpoint_get_sequence_id(child_01), 0); + EXPECT_EQ(pinpoint_get_sequence_id(child_02), 1); + EXPECT_EQ(pinpoint_get_sequence_id(root), 0); + NodeID child_03 = pinpoint_start_trace(child_02); + EXPECT_EQ(pinpoint_get_sequence_id(child_03), 2); + pinpoint_end_trace(root); + EXPECT_EQ(pinpoint_get_sequence_id(child_03), -1); + show_status(); +} + +static void simple_call() { + NodeID root = pinpoint_start_trace(E_ROOT_NODE); + NodeID child_01 = pinpoint_start_trace(root); + NodeID child_02 = pinpoint_start_trace(child_01); + EXPECT_EQ(pinpoint_get_sequence_id(child_01), 0); + EXPECT_EQ(pinpoint_get_sequence_id(child_02), 1); + EXPECT_EQ(pinpoint_get_sequence_id(root), 0); + NodeID child_03 = pinpoint_start_trace(child_02); + EXPECT_EQ(pinpoint_get_sequence_id(child_03), 2); + pinpoint_end_trace(root); + + show_status(); +} + +TEST(common, thread) { + std::thread t1(simple_call); + std::thread t2(simple_call); + std::thread t3(simple_call); + t1.join(); + t2.join(); + t3.join(); +} + +TEST(common, async_ctx) { + NodeID root = pinpoint_start_trace(E_ROOT_NODE); + NodeID child_01 = pinpoint_start_trace(root); + NodeID child_02 = pinpoint_start_trace(child_01); + EXPECT_EQ(pinpoint_get_sequence_id(child_01), 0); + EXPECT_EQ(pinpoint_get_sequence_id(child_02), 1); + EXPECT_EQ(pinpoint_get_sequence_id(root), 0); + NodeID child_03 = pinpoint_start_trace(child_02); + EXPECT_EQ(pinpoint_get_sequence_id(child_03), 2); + + pinpoint_set_async_ctx(root, 256, 0); + pinpoint_end_trace(root); + pinpoint_set_async_ctx(1024, 256, 0); } \ No newline at end of file diff --git a/common/src/test_util.cc b/common/src/test_util.cc index 88ab51caa..2ece7446c 100644 --- a/common/src/test_util.cc +++ b/common/src/test_util.cc @@ -74,17 +74,14 @@ TEST(util, variadic_func_str) { 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(); + TraceNode& n1 = node_pool.GetNode(); + TraceNode& n2 = node_pool.GetNode(); + TraceNode& n3 = node_pool.GetNode(); + TraceNode& n4 = node_pool.GetNode(); 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(); @@ -115,7 +112,7 @@ TEST(util, mergeTraceNodeTree_1) { EXPECT_TRUE(span.find("id1") != span.npos); EXPECT_TRUE(span.find("id2") != span.npos); EXPECT_TRUE(span.find("id3") != span.npos); - EXPECT_TRUE(span.find("calls") != span.npos); + EXPECT_TRUE(span.find("event") != span.npos); } TEST(util, logger) { diff --git a/common/test/test_main.cpp b/common/test/test_main.cpp index dfc16dd46..570ce3d6e 100644 --- a/common/test/test_main.cpp +++ b/common/test/test_main.cpp @@ -2,7 +2,7 @@ // #include #include -int main(int argc, char const* argv[]) { +int main(int, char const*[]) { 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); diff --git a/php_pinpoint_php.h b/php_pinpoint_php.h index 6a5b66943..937d194c1 100644 --- a/php_pinpoint_php.h +++ b/php_pinpoint_php.h @@ -93,10 +93,11 @@ PHP_FUNCTION(_pinpoint_start_time); PHP_FUNCTION(_pinpoint_set_context); PHP_FUNCTION(_pinpoint_get_context); PHP_FUNCTION(_pinpoint_mark_as_error); -// DEPRECATED("pinpoint_get_func_ref_args only used for compatiblity") -// PHP_FUNCTION(pinpoint_get_func_ref_args); PHP_FUNCTION(pinpoint_status); +PHP_FUNCTION(_pinpoint_get_sequence_id); +PHP_FUNCTION(_pinpoint_set_async_ctx); PHP_FUNCTION(_pinpoint_join_cut); +PHP_FUNCTION(_pinpoint_get_trace_depth); PHP_MINIT_FUNCTION(pinpoint_php); PHP_MSHUTDOWN_FUNCTION(pinpoint_php); diff --git a/pinpoint_php.cpp b/pinpoint_php.cpp index 6276293c8..600b516d5 100644 --- a/pinpoint_php.cpp +++ b/pinpoint_php.cpp @@ -67,7 +67,7 @@ ZEND_GET_MODULE(pinpoint_php) #endif ZEND_DECLARE_MODULE_GLOBALS(pinpoint_php); -//static void pinpoint_log(char *msg); +// static void pinpoint_log(char *msg); // clang-format off /* {{{ PHP_INI @@ -138,6 +138,17 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_add_id_value, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, nodeid) ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_get_seqid_id, 0, 0, 1) +ZEND_ARG_INFO(0, nodeid) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_set_async_id, 0, 0, 3) +ZEND_ARG_INFO(0, async_node) +ZEND_ARG_INFO(0, sequence) +ZEND_ARG_INFO(0, nodeid) +ZEND_END_ARG_INFO() + // php5 needs (0,0,0) ZEND_BEGIN_ARG_INFO_EX(arginfo_none, 0, 0, 0) ZEND_END_ARG_INFO() @@ -149,11 +160,11 @@ ZEND_END_ARG_INFO() 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_get_trace_depth, arginfo_add_id) PHP_FE(_pinpoint_unique_id, arginfo_none) PHP_FE(pinpoint_get_this, arginfo_none) PHP_FE(pinpoint_get_caller_arg,arginfo_add_arg_index) 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) @@ -163,6 +174,8 @@ const zend_function_entry pinpoint_php_functions[] = { PHP_FE(_pinpoint_add_clue, arginfo_add_id_key_value_flag) PHP_FE(_pinpoint_add_clues, arginfo_add_id_key_value_flag) PHP_FE(_pinpoint_join_cut,arginfo_add_join_cb_cb_cb) + PHP_FE(_pinpoint_get_sequence_id,arginfo_get_seqid_id) + PHP_FE(_pinpoint_set_async_ctx,arginfo_set_async_id) PHP_FE_END /* Must be the last line in pinpioint_php_functions[] */ }; /* }}} */ @@ -223,6 +236,24 @@ PHP_FUNCTION(_pinpoint_drop_trace) { RETURN_TRUE; } +PHP_FUNCTION(_pinpoint_get_trace_depth) { + NodeID id = E_INVALID_NODE; + +#if PHP_VERSION_ID < 70000 + long _id = -1; + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &_id); +#else + zend_long _id = -1; + zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &_id); +#endif + if (_id == -1) { + id = pinpoint_get_per_thread_id(); + } else { + id = (NodeID)_id; + } + RETURN_LONG(pinpoint_get_depth(id)); +} + PHP_FUNCTION(pinpoint_get_this) { if (EX(prev_execute_data) && EX(prev_execute_data)->prev_execute_data) { zval *self = &EX(prev_execute_data)->prev_execute_data->This; @@ -771,9 +802,9 @@ static void replace_ex_caller_parameters(zval *argv) { uint32_t size = zend_array_count(Z_ARRVAL_P(argv)); pp_trace("argv size:%d", size); uint32_t param_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data)); - if (size != param_count) { + if (size < param_count) { pp_trace( - "error: replace_ex_caller_parameters return `size` does not matched"); + "error: replace_ex_caller_parameters return `size` does not match"); return; } @@ -781,12 +812,11 @@ static void replace_ex_caller_parameters(zval *argv) { zval *ex_param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1); // check old and new - while (i < size) { + while (i < param_count) { zval *val = zend_array_index(argv, i + 1); if (Z_TYPE_P(ex_param_ptr) != Z_TYPE_P(val)) { pp_trace("error: replace_ex_caller_parameters return `type` does not " - "matched " - "expected:%d give:%d", + "match expected:%d give:%d", Z_TYPE_P(ex_param_ptr), Z_TYPE_P(val)); return; } @@ -796,7 +826,7 @@ static void replace_ex_caller_parameters(zval *argv) { i = 0; ex_param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1); - while (i < size) { + while (i < param_count) { zval *val = zend_array_index(argv, i + 1); if (Z_TYPE_P(val) == IS_ARRAY) { @@ -1204,6 +1234,54 @@ PHP_MINIT_FUNCTION(pinpoint_php) { } /* }}} */ +PHP_FUNCTION(_pinpoint_get_sequence_id) { + NodeID id = E_ROOT_NODE; + long sequence = E_ROOT_NODE; + +#if PHP_VERSION_ID < 70000 + long _id = -1; + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &_id); +#else + zend_long _id = -1; + zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &_id); +#endif + if (_id == -1) { + id = pinpoint_get_per_thread_id(); + sequence = pinpoint_get_sequence_id(id); + RETURN_LONG((long)sequence); + } else { + id = (NodeID)_id; + sequence = pinpoint_get_sequence_id(id); + RETURN_LONG((long)sequence); + } +} + +PHP_FUNCTION(_pinpoint_set_async_ctx) { + NodeID id = E_ROOT_NODE; + +#if PHP_VERSION_ID < 70000 + long _id = -1; + long async_node_id = -1; + long node_sequence = -1; + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &_id, &async_node_id, + &node_sequence); +#else + zend_long _id = -1; + zend_long async_node_id = -1; + zend_long node_sequence = -1; + zend_parse_parameters(ZEND_NUM_ARGS(), "lll", &_id, &async_node_id, + &node_sequence); +#endif + + if (_id == -1) { + id = pinpoint_get_per_thread_id(); + pinpoint_set_async_ctx(id, (int32_t)async_node_id, (int32_t)node_sequence); + } else { + id = (NodeID)_id; + pinpoint_set_async_ctx(id, (int32_t)async_node_id, (int32_t)node_sequence); + } +} + /* {{{ PHP_MSHUTDOWN_FUNCTION */ PHP_MSHUTDOWN_FUNCTION(pinpoint_php) { @@ -1262,7 +1340,8 @@ PHP_RSHUTDOWN_FUNCTION(pinpoint_php) { PHP_MINFO_FUNCTION(pinpoint_php) { php_info_print_table_start(); php_info_print_table_header(2, "pinpoint_php support", "enabled"); - php_info_print_table_header(2, "pinpoint_php extension version", PHP_PINPOINT_PHP_VERSION); + php_info_print_table_header(2, "pinpoint_php extension version", + PHP_PINPOINT_PHP_VERSION); php_info_print_table_end(); // /* Remove comments if you have entries in php.ini diff --git a/plugins/PY/pinpointPy/__init__.py b/plugins/PY/pinpointPy/__init__.py index 45054d661..2c4b2b446 100644 --- a/plugins/PY/pinpointPy/__init__.py +++ b/plugins/PY/pinpointPy/__init__.py @@ -31,5 +31,5 @@ def use_thread_local_context(): __all__ = ['monkey_patch_for_pinpoint', 'use_thread_local_context' 'set_agent', 'app_id', 'app_name', 'gen_tid', 'get_logger', 'PinTransaction', 'GenPinHeader', 'PinHeader'] -__version__ = "1.3.1" +__version__ = "1.3.2" __author__ = 'liu.mingyi@navercorp.com' diff --git a/plugins/PY/pinpointPy/pinpoint.py b/plugins/PY/pinpointPy/pinpoint.py index 2df13db13..752c33c13 100644 --- a/plugins/PY/pinpointPy/pinpoint.py +++ b/plugins/PY/pinpointPy/pinpoint.py @@ -21,6 +21,8 @@ import random import logging import _pinpointPy +import warnings + __app_id = 'app_id_str' __app_name = 'app_name_str' @@ -104,9 +106,15 @@ def gen_sid() -> str: def trace_has_root(trace_id=-1): + warnings.warn( + "deprecated try to use `is_root_trace`", DeprecationWarning) return _pinpointPy.trace_has_root(trace_id) +def is_root_trace(trace_id=-1): + return _pinpointPy.is_root_trace(trace_id) + + def mark_as_error(message: str, filename: str = '', line: int = 0, trace_id: int = -1): _pinpointPy.mark_as_error(message, filename, line, trace_id) diff --git a/setup.py b/setup.py index 496731062..cef58be23 100644 --- a/setup.py +++ b/setup.py @@ -39,7 +39,7 @@ Path(cwd, './common/src')] setup(name='pinpointPy', - version="1.3.1", # don't forget update __version__ in pinpointPy/__init__.py + version="1.3.2", # 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', @@ -61,6 +61,8 @@ """ # Changed +## 1.3.2 [not released] +- add new API `is_root_trace` ## 1.3.1 - fix bug https://github.com/pinpoint-apm/pinpoint-c-agent/issues/626 ## 1.3.0 diff --git a/src/CPP/CMakeLists.txt b/src/CPP/CMakeLists.txt index 841061aba..971c9a624 100644 --- a/src/CPP/CMakeLists.txt +++ b/src/CPP/CMakeLists.txt @@ -3,15 +3,15 @@ project(common) set(CMAKE_CXX_STANDARD 11) include(FetchContent) -FetchContent_Declare( - pinpoint - GIT_REPOSITORY https://github.com/pinpoint-apm/pinpoint-c-agent.git - # GIT_TAG 74bc39d813d664cb56b78b1506d91932c8131396 - # not recommended, please use hash key like `74bc39d813d664cb56b78b1506d91932c8131396`or tag name - GIT_TAG v0.5.0 -) +# FetchContent_Declare( +# pinpoint +# GIT_REPOSITORY https://github.com/pinpoint-apm/pinpoint-c-agent.git +# # GIT_TAG 74bc39d813d664cb56b78b1506d91932c8131396 +# # not recommended, please use hash key like `74bc39d813d664cb56b78b1506d91932c8131396`or tag name +# GIT_TAG v0.5.0 +# ) -# FetchContent_Declare(pinpoint SOURCE_DIR ${PROJECT_SOURCE_DIR}/../../) +FetchContent_Declare(pinpoint SOURCE_DIR ${PROJECT_SOURCE_DIR}/../../) FetchContent_GetProperties(pinpoint) if (NOT pinpoint_POPULATED) @@ -24,10 +24,10 @@ 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) +if(UNIX) + target_link_libraries(test_pinpoint_cpp PRIVATE pthread pinpoint_common_static rt) + target_link_libraries(test_pinpoint_c PRIVATE pthread 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 ) + 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/CPP/pinpoint_define.h b/src/CPP/pinpoint_define.h index 1d0258cfd..f1fdef638 100644 --- a/src/CPP/pinpoint_define.h +++ b/src/CPP/pinpoint_define.h @@ -14,8 +14,9 @@ // the License. //////////////////////////////////////////////////////////////////////////////// -const static char* PP_PHP_ARGS = "-1"; -const static int PP_PHP_RETURN = 14; +const static char *PP_ARGS = "-1"; +const static char *PP_ASYNC_CALL_ID = "asyId"; +const static int PP_RETURN = 14; const static int PP_PROXY_HTTP_HEADER = 300; const static int PP_SQL_ID = 20; const static int PP_SQL = 21; @@ -23,56 +24,57 @@ const static int PP_SQL_METADATA = 22; const static int PP_SQL_PARAM = 23; const static int PP_SQL_BINDVALUE = 24; const static int PP_STRING_ID = 30; -const static char* PP_HTTP_URL = "40"; +const static char *PP_HTTP_URL = "40"; const static int PP_HTTP_PARAM = 41; const static int PP_HTTP_PARAM_ENTITY = 42; const static int PP_HTTP_COOKIE = 45; -const static char* PP_HTTP_STATUS_CODE = "46"; +const static char *PP_HTTP_STATUS_CODE = "46"; const static int PP_HTTP_INTERNAL_DISPLAY = 48; const static int PP_HTTP_IO = 49; const static int PP_MESSAGE_QUEUE_URI = 100; const static int PP_KAFKA_TOPIC = 140; -const static char* PP_SQL_FORMAT = "SQL"; -const static char* PP_C_CPP = "1300"; -const static char* PP_C_CPP_METHOD = "1301"; -const static char* PP_MYSQL = "2101"; -const static char* PP_KAFKA = "8660"; -const static char* PP_REDIS = "8200"; -const static char* PP_REDIS_REDISSON = "8203"; -const static char* PP_REDIS_REDISSON_INTERNAL = "8204"; -const static char* PP_MEMCACHED = "8050"; -const static char* PP_C_CPP_REMOTE_METHOD = "9800"; +const static char *PP_SQL_FORMAT = "SQL"; +const static char *PP_C_CPP = "1300"; +const static char *PP_C_CPP_METHOD = "1301"; +const static char *PP_INVOCATION_CALL_TYPE = "100"; +const static char *PP_MYSQL = "2101"; +const static char *PP_KAFKA = "8660"; +const static char *PP_REDIS = "8200"; +const static char *PP_REDIS_REDISSON = "8203"; +const static char *PP_REDIS_REDISSON_INTERNAL = "8204"; +const static char *PP_MEMCACHED = "8050"; +const static char *PP_C_CPP_REMOTE_METHOD = "9800"; -const static char* PP_HEADER_NGINX_PROXY = "Pinpoint-ProxyNginx"; -const static char* PP_HEADER_APACHE_PROXY = "HTTP_PINPOINT_PROXYAPACHE"; -const static char* PP_HEADER_SAMPLED = "HTTP_PINPOINT_SAMPLED"; -const static char* PP_HEADER_PINPOINT_HOST = "HTTP_PINPOINT_HOST"; -const static char* PP_HEADER_PAPPTYPE = "HTTP_PINPOINT_PAPPTYPE"; -const static char* PP_HEADER_PAPPNAME = "HTTP_PINPOINT_PAPPNAME"; -const static char* PP_HEADER_TRACEID = "HTTP_PINPOINT_TRACEID"; -const static char* PP_HEADER_SPANID = "HTTP_PINPOINT_SPANID"; -const static char* PP_HEADER_PSPANID = "HTTP_PINPOINT_PSPANID"; +const static char *PP_HEADER_NGINX_PROXY = "Pinpoint-ProxyNginx"; +const static char *PP_HEADER_APACHE_PROXY = "HTTP_PINPOINT_PROXYAPACHE"; +const static char *PP_HEADER_SAMPLED = "HTTP_PINPOINT_SAMPLED"; +const static char *PP_HEADER_PINPOINT_HOST = "HTTP_PINPOINT_HOST"; +const static char *PP_HEADER_PAPPTYPE = "HTTP_PINPOINT_PAPPTYPE"; +const static char *PP_HEADER_PAPPNAME = "HTTP_PINPOINT_PAPPNAME"; +const static char *PP_HEADER_TRACEID = "HTTP_PINPOINT_TRACEID"; +const static char *PP_HEADER_SPANID = "HTTP_PINPOINT_SPANID"; +const static char *PP_HEADER_PSPANID = "HTTP_PINPOINT_PSPANID"; -const static char* PP_SERVER_TYPE = "stp"; -const static char* PP_NEXT_SPAN_ID = "nsid"; -const static char* PP_DESTINATION = "dst"; -const static char* PP_INTERCEPTOR_NAME = "name"; -const static char* PP_ADD_EXCEPTION = "EXP"; +const static char *PP_SERVER_TYPE = "stp"; +const static char *PP_NEXT_SPAN_ID = "nsid"; +const static char *PP_DESTINATION = "dst"; +const static char *PP_INTERCEPTOR_NAME = "name"; +const static char *PP_ADD_EXCEPTION = "EXP"; const static int PP_ROOT_LOC = 1; -const static char* PP_REQ_URI = "uri"; -const static char* PP_REQ_CLIENT = "client"; -const static char* PP_REQ_SERVER = "server"; -const static char* PP_APP_NAME = "appname"; -const static char* PP_APP_ID = "appid"; -const static char* PP_UT = "UT"; -const static char* PP_PARENT_SPAN_ID = "psid"; -const static char* PP_PARENT_NAME = "pname"; -const static char* PP_PARENT_TYPE = "ptype"; -const static char* PP_PARENT_HOST = "Ah"; -const static char* PP_NGINX_PROXY = "NP"; -const static char* PP_APACHE_PROXY = "AP"; -const static char* PP_TRANSCATION_ID = "tid"; -const static char* PP_SPAN_ID = "sid"; -const static char* PP_NOT_SAMPLED = "s0"; -const static char* PP_SAMPLED = "s1"; +const static char *PP_REQ_URI = "uri"; +const static char *PP_REQ_CLIENT = "client"; +const static char *PP_REQ_SERVER = "server"; +const static char *PP_APP_NAME = "appname"; +const static char *PP_APP_ID = "appid"; +const static char *PP_UT = "UT"; +const static char *PP_PARENT_SPAN_ID = "psid"; +const static char *PP_PARENT_NAME = "pname"; +const static char *PP_PARENT_TYPE = "ptype"; +const static char *PP_PARENT_HOST = "Ah"; +const static char *PP_NGINX_PROXY = "NP"; +const static char *PP_APACHE_PROXY = "AP"; +const static char *PP_TRANSCATION_ID = "tid"; +const static char *PP_SPAN_ID = "sid"; +const static char *PP_NOT_SAMPLED = "s0"; +const static char *PP_SAMPLED = "s1"; diff --git a/src/CPP/test_pinpoint.c b/src/CPP/test_pinpoint.c index c1d74f8e4..d944e6416 100644 --- a/src/CPP/test_pinpoint.c +++ b/src/CPP/test_pinpoint.c @@ -26,7 +26,7 @@ #elif defined(__linux__) || defined(__APPLE__) #include #endif -int32_t id = 0; +int32_t local_node_id = 0; const char* app_id = "c_test_app"; const char* app_name = "c_test_name"; @@ -48,64 +48,70 @@ void random_sleep() { } 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_SERVER_TYPE, PP_C_CPP_REMOTE_METHOD, E_LOC_CURRENT); + local_node_id = pinpoint_start_trace(local_node_id); + pinpoint_add_clue(local_node_id, PP_INTERCEPTOR_NAME, "httpclient", E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_DESTINATION, "www.pinpoint-wonderful.com", E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_SERVER_TYPE, PP_C_CPP_REMOTE_METHOD, E_LOC_CURRENT); char* sid = get_sid(); - pinpoint_add_clue(id, PP_NEXT_SPAN_ID, sid, E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_NEXT_SPAN_ID, sid, E_LOC_CURRENT); free(sid); - 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); + pinpoint_add_clues(local_node_id, PP_HTTP_URL, "/support/c-cpp-php-python", E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_ADD_EXCEPTION, "test this exception", E_LOC_CURRENT); + pinpoint_add_clues(local_node_id, PP_HTTP_STATUS_CODE, "300", E_LOC_CURRENT); random_sleep(); - id = pinpoint_end_trace(id); + local_node_id = pinpoint_end_trace(local_node_id); +} + +static void test_async() { + // todo ... + // goto test_pinpoint.cpp test_async } void test_mysql() { - id = pinpoint_start_trace(id); - pinpoint_add_clue(id, PP_INTERCEPTOR_NAME, "mysql::excute", E_LOC_CURRENT); - pinpoint_add_clue(id, PP_SERVER_TYPE, PP_MYSQL, E_LOC_CURRENT); - pinpoint_add_clue(id, PP_SQL_FORMAT, "select 1*3;", E_LOC_CURRENT); - pinpoint_add_clue(id, PP_DESTINATION, "localhost:3307", E_LOC_CURRENT); + local_node_id = pinpoint_start_trace(local_node_id); + pinpoint_add_clue(local_node_id, PP_INTERCEPTOR_NAME, "mysql::excute", E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_SERVER_TYPE, PP_MYSQL, E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_SQL_FORMAT, "select 1*3;", E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_DESTINATION, "localhost:3307", E_LOC_CURRENT); random_sleep(); - id = pinpoint_end_trace(id); + local_node_id = pinpoint_end_trace(local_node_id); } void test_func() { - id = pinpoint_start_trace(id); - pinpoint_add_clue(id, PP_INTERCEPTOR_NAME, "test_func", E_LOC_CURRENT); - pinpoint_add_clue(id, PP_SERVER_TYPE, PP_C_CPP_METHOD, E_LOC_CURRENT); - pinpoint_add_clues(id, PP_PHP_ARGS, "I'm the parameters", E_LOC_CURRENT); + local_node_id = pinpoint_start_trace(local_node_id); + pinpoint_add_clue(local_node_id, PP_INTERCEPTOR_NAME, "test_func", E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_SERVER_TYPE, PP_C_CPP_METHOD, E_LOC_CURRENT); + pinpoint_add_clues(local_node_id, PP_ARGS, "I'm the parameters", E_LOC_CURRENT); random_sleep(); - id = pinpoint_end_trace(id); + local_node_id = pinpoint_end_trace(local_node_id); } void test_req() { - id = pinpoint_start_trace(id); - pinpoint_add_clue(id, PP_REQ_URI, "test_url", E_LOC_CURRENT); - pinpoint_add_clue(id, PP_REQ_CLIENT, "127.0.0.1", E_LOC_CURRENT); - pinpoint_add_clue(id, PP_REQ_SERVER, "HTTP_HOST", E_LOC_CURRENT); - pinpoint_add_clue(id, PP_SERVER_TYPE, PP_C_CPP, E_LOC_CURRENT); - pinpoint_add_clue(id, PP_INTERCEPTOR_NAME, "C_CPP Request", E_LOC_CURRENT); - pinpoint_add_clue(id, PP_APP_NAME, app_name, E_LOC_CURRENT); - pinpoint_add_clue(id, PP_APP_ID, app_id, E_LOC_CURRENT); + local_node_id = pinpoint_start_trace(local_node_id); + pinpoint_add_clue(local_node_id, PP_REQ_URI, "test_url", E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_REQ_CLIENT, "127.0.0.1", E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_REQ_SERVER, "HTTP_HOST", E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_SERVER_TYPE, PP_C_CPP, E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_INTERCEPTOR_NAME, "C_CPP Request", E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_APP_NAME, app_name, E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_APP_ID, app_id, E_LOC_CURRENT); char ut[64] = {0}; snprintf(ut, 64, "/user/?/add/%d", rand() % 10); - pinpoint_add_clue(id, PP_UT, ut, E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_UT, ut, E_LOC_CURRENT); random_sleep(); test_func(); test_mysql(); test_httpclient(); + test_async(); char* tid = get_tid(); char* sid = get_sid(); - pinpoint_add_clue(id, PP_TRANSCATION_ID, tid, E_LOC_CURRENT); - pinpoint_add_clue(id, PP_SPAN_ID, sid, E_LOC_CURRENT); - pinpoint_add_clues(id, PP_HTTP_STATUS_CODE, "200", E_LOC_CURRENT); - id = pinpoint_end_trace(id); + pinpoint_add_clue(local_node_id, PP_TRANSCATION_ID, tid, E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_SPAN_ID, sid, E_LOC_CURRENT); + pinpoint_add_clues(local_node_id, PP_HTTP_STATUS_CODE, "200", E_LOC_CURRENT); + local_node_id = pinpoint_end_trace(local_node_id); check_tracelimit(-1); free(tid); free(sid); diff --git a/src/CPP/test_pinpoint.cpp b/src/CPP/test_pinpoint.cpp index 4e67556d8..2f89247bd 100644 --- a/src/CPP/test_pinpoint.cpp +++ b/src/CPP/test_pinpoint.cpp @@ -17,13 +17,17 @@ #include "common.h" #include "pinpoint_define.h" #include +#include +#include +#include +#include #include #include #include #include #include -thread_local NodeID id = E_ROOT_NODE; +thread_local NodeID local_node_id = E_ROOT_NODE; const char *app_id = "cd.dev.test.cpp"; const char *app_name = "cd.dev.test.cpp"; @@ -35,65 +39,126 @@ std::string get_tid() { std::to_string(generate_unique_id()); } +std::string span_id_ = get_sid(); +std::string transcation_id_ = get_tid(); + void random_sleep() { int32_t delay = rand() % 100; 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", + local_node_id = pinpoint_start_trace(local_node_id); + pinpoint_add_clue(local_node_id, PP_INTERCEPTOR_NAME, "httpclient", + E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_DESTINATION, "www.pinpoint-wonderful.com", + E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_SERVER_TYPE, PP_C_CPP_REMOTE_METHOD, + E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_NEXT_SPAN_ID, get_sid().c_str(), 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", + pinpoint_add_clues(local_node_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); + pinpoint_add_clue(local_node_id, PP_ADD_EXCEPTION, "test this exception", + E_LOC_CURRENT); + pinpoint_add_clues(local_node_id, PP_HTTP_STATUS_CODE, "300", E_LOC_CURRENT); random_sleep(); - id = pinpoint_end_trace(id); + local_node_id = pinpoint_end_trace(local_node_id); } void test_mysql() { - id = pinpoint_start_trace(id); - pinpoint_add_clue(id, PP_INTERCEPTOR_NAME, "mysql::excute", E_LOC_CURRENT); - pinpoint_add_clue(id, PP_SERVER_TYPE, PP_MYSQL, E_LOC_CURRENT); - pinpoint_add_clue(id, PP_SQL_FORMAT, "select 1*3;", E_LOC_CURRENT); - pinpoint_add_clue(id, PP_DESTINATION, "localhost:3307", E_LOC_CURRENT); + local_node_id = pinpoint_start_trace(local_node_id); + pinpoint_add_clue(local_node_id, PP_INTERCEPTOR_NAME, "mysql::excute", + E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_SERVER_TYPE, PP_MYSQL, E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_SQL_FORMAT, "select 1*3;", E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_DESTINATION, "localhost:3307", + E_LOC_CURRENT); random_sleep(); - id = pinpoint_end_trace(id); + local_node_id = pinpoint_end_trace(local_node_id); } void test_func() { - id = pinpoint_start_trace(id); - pinpoint_add_clue(id, PP_INTERCEPTOR_NAME, "test_func", E_LOC_CURRENT); - pinpoint_add_clue(id, PP_SERVER_TYPE, PP_C_CPP_METHOD, E_LOC_CURRENT); - pinpoint_add_clues(id, PP_PHP_ARGS, "I'm the parameters", E_LOC_CURRENT); + local_node_id = pinpoint_start_trace(local_node_id); + pinpoint_add_clue(local_node_id, PP_INTERCEPTOR_NAME, "test_func", + E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_SERVER_TYPE, PP_C_CPP_METHOD, + E_LOC_CURRENT); + pinpoint_add_clues(local_node_id, PP_ARGS, "I'm the parameters", + E_LOC_CURRENT); random_sleep(); - id = pinpoint_end_trace(id); + local_node_id = pinpoint_end_trace(local_node_id); } void test_kafka() { - id = pinpoint_start_trace(id); - pinpoint_add_clue(id, "name", "kafka", E_LOC_CURRENT); - pinpoint_add_clue(id, "stp", PP_KAFKA, E_LOC_CURRENT); - pinpoint_add_clues(id, "140", "xxxxx", E_LOC_CURRENT); - pinpoint_add_clue(id, "dst", "xxxx", E_LOC_CURRENT); - id = pinpoint_end_trace(id); + local_node_id = pinpoint_start_trace(local_node_id); + pinpoint_add_clue(local_node_id, "name", "kafka", E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, "stp", PP_KAFKA, E_LOC_CURRENT); + pinpoint_add_clues(local_node_id, "140", "xxxxx", E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, "dst", "xxxx", E_LOC_CURRENT); + local_node_id = pinpoint_end_trace(local_node_id); +} + +static void test_async() { + local_node_id = pinpoint_start_trace(local_node_id); + + pinpoint_add_clue(local_node_id, PP_INTERCEPTOR_NAME, "test_async", + E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_SERVER_TYPE, PP_INVOCATION_CALL_TYPE, + E_LOC_CURRENT); + + // generate async_id + char async_id_str[32] = {0}; + int32_t async_id = random() % 99999; + sprintf(async_id_str, "%d", async_id); + pinpoint_add_clue(local_node_id, PP_ASYNC_CALL_ID, async_id_str, + E_LOC_CURRENT); + // get sequence + int32_t sequence_id = pinpoint_get_sequence_id(local_node_id); + + auto pinpoint_invocation_wrap_func = + [=](std::function user_func) { + local_node_id = pinpoint_start_trace(local_node_id); + pinpoint_add_clue(local_node_id, PP_APP_NAME, "cpp_app", E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_APP_ID, "CPP_APP", E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_TRANSCATION_ID, + transcation_id_.c_str(), E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_SPAN_ID, span_id_.c_str(), + E_LOC_CURRENT); + + pinpoint_add_clue(local_node_id, PP_SERVER_TYPE, PP_C_CPP_METHOD, + E_LOC_CURRENT); + pinpoint_set_async_ctx(local_node_id, async_id, sequence_id); + + user_func(); + + local_node_id = pinpoint_end_trace(local_node_id); + }; + // test_func is the target function + // while, you can use std::bind magic supporting any kind of function + // eg: std::bind(func,"a",3,4) ; + // std::bind(&MyClass::print, &obj, "bbc"); + // more question: https://en.cppreference.com/w/cpp/utility/functional/bind + // or `dl_cd_pinpoint@navercorp.com` + std::thread async_call(pinpoint_invocation_wrap_func, test_func); + + local_node_id = pinpoint_end_trace(local_node_id); + // joins async_call thread after local_node_id stopped + async_call.join(); } void test_req() { - id = pinpoint_start_trace(id); - pinpoint_add_clue(id, PP_REQ_URI, "test_url", E_LOC_CURRENT); - pinpoint_add_clue(id, PP_REQ_CLIENT, "127.0.0.1", E_LOC_CURRENT); - pinpoint_add_clue(id, PP_REQ_SERVER, "HTTP_HOST", E_LOC_CURRENT); - pinpoint_add_clue(id, PP_SERVER_TYPE, PP_C_CPP, E_LOC_CURRENT); - pinpoint_add_clue(id, PP_INTERCEPTOR_NAME, "C_CPP Request", E_LOC_CURRENT); - pinpoint_add_clue(id, PP_APP_NAME, "cpp_app", E_LOC_CURRENT); - pinpoint_add_clue(id, PP_APP_ID, "CPP_APP", E_LOC_CURRENT); + local_node_id = pinpoint_start_trace(local_node_id); + pinpoint_add_clue(local_node_id, PP_REQ_URI, "test_url", E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_REQ_CLIENT, "127.0.0.1", E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_REQ_SERVER, "HTTP_HOST", E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_SERVER_TYPE, PP_C_CPP, E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_INTERCEPTOR_NAME, "C_CPP Request", + E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_APP_NAME, "cpp_app", E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_APP_ID, "CPP_APP", E_LOC_CURRENT); random_sleep(); @@ -101,15 +166,20 @@ void test_req() { test_mysql(); test_httpclient(); test_kafka(); - pinpoint_add_clue(id, PP_TRANSCATION_ID, get_tid().c_str(), E_LOC_CURRENT); - pinpoint_add_clue(id, PP_SPAN_ID, get_sid().c_str(), E_LOC_CURRENT); - pinpoint_add_clues(id, PP_HTTP_STATUS_CODE, "200", E_LOC_CURRENT); - catch_error(id, "msg", __FILE__, 100); - id = pinpoint_end_trace(id); + // make a asynchronous (by thread) call + test_async(); + + pinpoint_add_clue(local_node_id, PP_TRANSCATION_ID, transcation_id_.c_str(), + E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_SPAN_ID, span_id_.c_str(), E_LOC_CURRENT); + + pinpoint_add_clues(local_node_id, PP_HTTP_STATUS_CODE, "200", E_LOC_CURRENT); + catch_error(local_node_id, "msg", __FILE__, 100); + local_node_id = pinpoint_end_trace(local_node_id); } int main(int argc, char const *argv[]) { - pinpoint_set_agent("tcp:127.0.0.1:9999", 0, -1, 1300); + pinpoint_set_agent("tcp:127.0.0.1:10000", 10, -1, 1300); register_logging_cb(nullptr, 1); srand(time(nullptr)); int i = 0; diff --git a/src/PY/_pinpoint_py.cpp b/src/PY/_pinpoint_py.cpp index 9bb7364a7..8991949f5 100644 --- a/src/PY/_pinpoint_py.cpp +++ b/src/PY/_pinpoint_py.cpp @@ -196,10 +196,26 @@ static PyObject *py_generate_unique_id(PyObject *self, return Py_BuildValue("l", ret); } +static PyObject *py_is_root_trace(PyObject *self, PyObject *args) { + int id = -1; + if (!PyArg_ParseTuple(args, "|i", &id)) { + return Py_BuildValue("O", Py_False); + } + if (id == E_INVALID_NODE) { + id = pinpoint_get_per_thread_id(); + } + 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_trace_has_root(PyObject *self, PyObject *args) { int id = -1; if (!PyArg_ParseTuple(args, "|i", &id)) { - return NULL; + return Py_BuildValue("O", Py_False); } if (id == E_INVALID_NODE) { id = pinpoint_get_per_thread_id(); @@ -324,7 +340,12 @@ static PyMethodDef PinpointMethods[] = { "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 " + "warning use `is_root_trace` " + "def trace_has_root(int id=-1)-> bool # check current whether have a " + "root. \n True: \nFalse: " + "\n Note: If the id is invalid, return false"}, + {"is_root_trace", py_is_root_trace, METH_VARARGS, + "def is_root_trace(int id=-1)-> bool # 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, diff --git a/src/PY/test/testPinpoint.py b/src/PY/test/testPinpoint.py index 79f7f951e..d29ef8f8b 100644 --- a/src/PY/test/testPinpoint.py +++ b/src/PY/test/testPinpoint.py @@ -30,10 +30,13 @@ def test_encode(self): def test_trace_life(self): self.assertFalse(_pinpointPy.trace_has_root()) + self.assertFalse(_pinpointPy.is_root_trace()) _pinpointPy.start_trace() self.assertTrue(_pinpointPy.trace_has_root()) + self.assertTrue(_pinpointPy.is_root_trace()) _pinpointPy.start_trace() self.assertTrue(_pinpointPy.trace_has_root()) + self.assertFalse(_pinpointPy.is_root_trace()) _pinpointPy.start_trace() _pinpointPy.start_trace() @@ -52,6 +55,7 @@ def test_trace_life(self): _pinpointPy.end_trace() _pinpointPy.force_flush_trace(10) self.assertFalse(_pinpointPy.trace_has_root()) + self.assertFalse(_pinpointPy.is_root_trace()) def test_set_collector_host(self): self.assertTrue(_pinpointPy.set_agent( diff --git a/src/PY/test/testUnderThreadMode.py b/src/PY/test/testUnderThreadMode.py index be4d21849..a60e8d2a1 100644 --- a/src/PY/test/testUnderThreadMode.py +++ b/src/PY/test/testUnderThreadMode.py @@ -19,8 +19,10 @@ def _test_api_flow(self): while self.thread_running: self.assertFalse(_pinpointPy.trace_has_root()) + self.assertFalse(_pinpointPy.is_root_trace()) _pinpointPy.start_trace() self.assertTrue(_pinpointPy.trace_has_root()) + self.assertTrue(_pinpointPy.is_root_trace()) _pinpointPy.set_context_key('sid', '12345678') _pinpointPy.add_clue("key", "value3") _pinpointPy.add_clues("key", "value3") @@ -33,6 +35,7 @@ def _test_api_flow(self): value = _pinpointPy.get_context_key('sid') self.assertFalse(value) self.assertFalse(_pinpointPy.trace_has_root()) + self.assertFalse(_pinpointPy.is_root_trace()) def test_thread_safe(self): thread1 = Thread(target=self._test_api_flow) diff --git a/testapps/.dockerignore b/testapps/.dockerignore index 4916fbd92..672a400a8 100644 --- a/testapps/.dockerignore +++ b/testapps/.dockerignore @@ -1,3 +1,5 @@ **/venv/ **/env/ -**/__pycache__ \ No newline at end of file +**/__pycache__ +**/build/ +.cache \ No newline at end of file diff --git a/testapps/SimplePHP/kafka_consumer.php b/testapps/SimplePHP/kafka_consumer.php new file mode 100644 index 000000000..2275e0432 --- /dev/null +++ b/testapps/SimplePHP/kafka_consumer.php @@ -0,0 +1,57 @@ +addJoinPoint('handle_message_in_kafka', \Pinpoint\Plugins\Common\CommonPlugin::class); + $ar[] = $classHandler; + return $ar; + } +} + + +define('APPLICATION_NAME', 'cd.dev.test.php'); // your application name +define('APPLICATION_ID', 'cd.dev.test.run'); // your application id +define("PP_ENABLE_EXPERIMENTAL_FEATURE", true); +define('PP_REQ_PLUGINS', ConsumerPlugins::class); +require_once __DIR__ . '/vendor/pinpoint-apm/pinpoint-php-aop/auto_pinpointed.php'; + + +// https://arnaud.le-blanc.net/php-rdkafka-doc/phpdoc/rdkafka.examples-high-level-consumer.html +$conf = new RdKafka\Conf(); + +$conf->set('group.id', 'myConsumerGroup'); + +// Initial list of Kafka brokers +$conf->set('metadata.broker.list', 'dev-kafka:9092'); +// $conf->set('auto.offset.reset', 'earliest'); +$consumer = new RdKafka\KafkaConsumer($conf); + +// Subscribe to topic 'test' +$consumer->subscribe(['test']); + +while (true) { + $message = $consumer->consume(120 * 1000); + switch ($message->err) { + case RD_KAFKA_RESP_ERR_NO_ERROR: + + $handler = new SimplePHP\MessageHandler(); + $handler->handle_message_in_kafka($message); + break; + case RD_KAFKA_RESP_ERR__PARTITION_EOF: + echo "No more messages; will wait for more\n"; + break; + case RD_KAFKA_RESP_ERR__TIMED_OUT: + echo "Timed out\n"; + break; + default: + throw new \Exception($message->errstr(), $message->err); + break; + } +} diff --git a/testapps/SimplePHP/php.ini b/testapps/SimplePHP/php.ini index 25c8523b2..a4e030d99 100644 --- a/testapps/SimplePHP/php.ini +++ b/testapps/SimplePHP/php.ini @@ -17,3 +17,6 @@ log_errors= On extension=apcu.so apc.enabled=1 apc.enable_cli=1 + +[kafka] +extension=rdkafka.so \ No newline at end of file diff --git a/testapps/SimplePHP/run.php b/testapps/SimplePHP/run.php index 381e7196c..5977e001c 100644 --- a/testapps/SimplePHP/run.php +++ b/testapps/SimplePHP/run.php @@ -198,7 +198,6 @@ function call_apc() apcu_add('foo', $bar); var_dump(apcu_fetch('foo')); - apcu_store('cas', 2); apcu_cas("cas", 1, 2); apcu_cas("cas", 2, 1); @@ -207,6 +206,39 @@ function call_apc() apcu_clear_cache(); } +function produce_msg_kafka() +{ + $conf = new RdKafka\Conf(); + // $conf->set('log_level', (string) LOG_DEBUG); + // $conf->set('debug', 'all'); + $conf->set('metadata.broker.list', 'dev-kafka:9092'); + $producer = new RdKafka\Producer($conf); + $producer->addBrokers("dev-kafka:9092"); + + $topic = $producer->newTopic("test"); + $headers = [ + "a" => 1, + "b" => "xxxx" + ]; + + for ($i = 0; $i < 2; $i++) { + $topic->produce(RD_KAFKA_PARTITION_UA, 0, "I'm Message $i", "key"); + $topic->producev(RD_KAFKA_PARTITION_UA, 0, "I'm Message $i", "key", $headers); + $producer->poll(0); + } + + for ($flushRetries = 0; $flushRetries < 10; $flushRetries++) { + $result = $producer->flush(10000); + if (RD_KAFKA_RESP_ERR_NO_ERROR === $result) { + break; + } + } + + if (RD_KAFKA_RESP_ERR_NO_ERROR !== $result) { + throw new \RuntimeException('Was unable to flush, messages might be lost!'); + } +} + function main() { call_mysql(); @@ -217,6 +249,7 @@ function main() call_redis(); call_memcached(); call_apc(); + produce_msg_kafka(); } main(); diff --git a/testapps/SimplePHP/run_all.sh b/testapps/SimplePHP/run_all.sh new file mode 100644 index 000000000..c9e6a2e88 --- /dev/null +++ b/testapps/SimplePHP/run_all.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +php kafka_consumer.php & + +php /workspace/run.php + +sleep 10s \ No newline at end of file diff --git a/testapps/SimplePHP/simplephp.dockerfile b/testapps/SimplePHP/simplephp.dockerfile index e2599efa0..76bd52e33 100644 --- a/testapps/SimplePHP/simplephp.dockerfile +++ b/testapps/SimplePHP/simplephp.dockerfile @@ -1,18 +1,17 @@ -FROM ubuntu:20.04 -ENV TZ=Asia/Shanghai -ENV LC_CTYPE=en_US.UTF-8 +# FROM ubuntu:20.04 +FROM php:7.4-fpm WORKDIR /workspace -RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone -RUN DEBIAN_FRONTEND="noninteractive" apt update && apt-get install -y build-essential git php7.4 php7.4-dev php7.4-curl php7.4-mysql libmemcached-dev zlib1g-dev libssl-dev pkg-config -COPY testapps/SimplePHP/php.ini /etc/php/7.4/cli/php.ini +RUN DEBIAN_FRONTEND="noninteractive" apt update && apt-get install -y libmemcached-dev zlib1g-dev libssl-dev pkg-config librdkafka-dev libzip-dev zip +COPY testapps/SimplePHP/php.ini /usr/local/etc/php/conf.d/ COPY testapps/SimplePHP/src /workspace/src COPY testapps/SimplePHP/composer-real.json /workspace/composer.json COPY testapps/SimplePHP/run.php /workspace/run.php -RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer -RUN git clone --recurse-submodules --depth 1 --branch 1.18.1 https://github.com/mongodb/mongo-php-driver.git && cd mongo-php-driver && phpize && ./configure && make -j && make install -RUN cd /tmp/ && git clone https://github.com/phpredis/phpredis.git && cd phpredis && git checkout 6.0.2 && phpize && ./configure && make install -RUN cd /tmp/ && git clone https://github.com/php-memcached-dev/php-memcached.git && cd php-memcached && phpize && ./configure && make install -RUN cd /tmp/ && git clone https://github.com/krakjoe/apcu.git && cd apcu && phpize && ./configure && make install +COPY testapps/SimplePHP/kafka_consumer.php /workspace/kafka_consumer.php +COPY testapps/SimplePHP/run_all.sh /workspace/run_all.sh + +RUN docker-php-ext-install zip mysqli pdo pdo_mysql && docker-php-ext-enable pdo_mysql +RUN pecl channel-update pecl.php.net && printf "\n" | pecl install rdkafka mongodb redis memcached apcu + COPY config.m4 /pinpoint-c-agent/config.m4 COPY pinpoint_php.cpp /pinpoint-c-agent/pinpoint_php.cpp COPY php_pinpoint_php.h /pinpoint-c-agent/php_pinpoint_php.h @@ -20,7 +19,8 @@ COPY common /pinpoint-c-agent/common COPY tests /pinpoint-c-agent/tests RUN cd /pinpoint-c-agent/ && phpize && ./configure && make && make install +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer -RUN COMPOSER_ALLOW_SUPERUSER=1 composer require pinpoint-apm/pinpoint-php-aop:^3.0.2 +RUN COMPOSER_ALLOW_SUPERUSER=1 composer require pinpoint-apm/pinpoint-php-aop:dev-feat-async-rdkafka -CMD [ "php" ,"/workspace/run.php" ] +CMD [ "sh" ,"/workspace/run_all.sh" ] diff --git a/testapps/SimplePHP/src/MessageHandler.php b/testapps/SimplePHP/src/MessageHandler.php new file mode 100644 index 000000000..975c579b0 --- /dev/null +++ b/testapps/SimplePHP/src/MessageHandler.php @@ -0,0 +1,11 @@ +topic_name $message->partition\n"; + } + +} diff --git a/testapps/compose.yaml b/testapps/compose.yaml index e88608092..c9fb151d0 100644 --- a/testapps/compose.yaml +++ b/testapps/compose.yaml @@ -16,20 +16,32 @@ services: limits: cpus: "1" healthcheck: - test: - [ - "CMD", - "mysqladmin", - "-uroot", - "-ppassword", - "ping", - "-h", - "localhost" - ] + test: [ "CMD", "mysqladmin", "-uroot", "-ppassword", "ping", "-h", "localhost" ] interval: 15s timeout: 10s retries: 10 + dev-kafka: + image: apache/kafka:3.8.0 + container_name: broker + environment: + KAFKA_NODE_ID: 1 + KAFKA_PROCESS_ROLES: broker,controller + KAFKA_LISTENERS: PLAINTEXT://:9092,CONTROLLER://:9093 + KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://dev-kafka:9092 + KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT + KAFKA_CONTROLLER_QUORUM_VOTERS: 1@localhost:9093 + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 + KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 + KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0 + # KAFKA_NUM_PARTITIONS: 3 + KAFKA_CREATE_TOPICS: "test-topic:1:1" + ports: + - 9092:9092 + - 9093:9093 + dev-mariadb: image: mariadb environment: @@ -43,14 +55,7 @@ services: ports: - "3307:3307" healthcheck: - test: - [ - "CMD", - "healthcheck.sh", - "--su-mysql", - "--connect", - "--innodb_initialized" - ] + test: [ "CMD", "healthcheck.sh", "--su-mysql", "--connect", "--innodb_initialized" ] start_period: 1m interval: 1m timeout: 5s @@ -64,12 +69,7 @@ services: volumes: - ..:/workspace:cached # todo load all data - entrypoint: - [ - "bash", - "-c", - "cd /workspace/testapps/ && sh load_sample_db.sh" - ] + entrypoint: [ "bash", "-c", "cd /workspace/testapps/ && sh load_sample_db.sh" ] redis: image: redis:alpine @@ -290,6 +290,8 @@ services: condition: service_healthy dev-collector: condition: service_started + dev-kafka: + condition: service_started restart: always build: @@ -488,7 +490,6 @@ services: dev-mysql-setup: condition: service_completed_successfully - thinkphp8: build: dockerfile: testapps/thinkphp-php/thinkphp.dockerfile @@ -524,3 +525,17 @@ services: test: curl -f http://localhost:8000/ interval: 5s timeout: 1s + + cpp-httplib: + build: + dockerfile: testapps/cpp/cpp.dockerfile + context: ../ + ports: + - 8203:8080 + healthcheck: + test: curl -f http://localhost:8080/create_async_task + interval: 30s + timeout: 10s + depends_on: + dev-collector: + condition: service_started diff --git a/testapps/cpp/CMakeLists.txt b/testapps/cpp/CMakeLists.txt new file mode 100644 index 000000000..3cfb244f6 --- /dev/null +++ b/testapps/cpp/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.15) +project(pinpoint_http_test_server) +set(CMAKE_CXX_STANDARD 11) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +include(FetchContent) + +FetchContent_Declare( + pinpoint + URL https://github.com/eeliu/pinpoint-c-agent/releases/download/v0.2.33/pinpoint-common.tar.gz +) + +FetchContent_Declare( + httplib + URL https://github.com/yhirose/cpp-httplib/archive/refs/tags/v0.18.0.tar.gz +) + +FetchContent_MakeAvailable(httplib pinpoint) + + +add_executable(server server.cpp) + +target_link_libraries(server PRIVATE pthread pinpoint_common_static httplib rt) \ No newline at end of file diff --git a/testapps/cpp/cpp.dockerfile b/testapps/cpp/cpp.dockerfile new file mode 100644 index 000000000..51a91d36d --- /dev/null +++ b/testapps/cpp/cpp.dockerfile @@ -0,0 +1,10 @@ +FROM gcc:10 + +RUN apt update && apt install -y cmake +COPY testapps/cpp/ /apps +WORKDIR /apps +RUN mkdir -p build && cd build && cmake .. && make + +EXPOSE 8080 + +ENTRYPOINT [ "build/server" ] \ No newline at end of file diff --git a/testapps/cpp/image.png b/testapps/cpp/image.png new file mode 100644 index 0000000000000000000000000000000000000000..2f696772ade08a906c7b24077370c0ac318e577d GIT binary patch literal 81549 zcmb@ucR1YL);FF+LW&_p^cEzD&geA}y_2XxM9*NN_dx`aVD!$2E?V?XkZ7Zq84Mn!VTBYkl^2uk~4bO}MtE65uxN?JHNV092G; z=w7)(9DU`=HO`yFgeQ4LzThiYn6Ie3c=pok>ShZlLLZs3ZS;Kqs(ov}9}SxtD-);d zU|7YO^-S-Gx=;2fq-`z_=%o!X982Kt2YUU&Poyg(Jx-mB#HJ)`-y3X3rzh1hX0B&= zu9)|==mk6xf?*SFmo<}o`^7UVJ2PE8GSr3ejPXfty~6N}>TS4!rlmage7LFSsePK% zE6Od}{kKw03XG?Tb(c}T`MoW&8GJ)hC>~eFvtql~?d~gZM4E^I4cs(iu7SKHZeBT> zf>>m8e8NTWJ_3FGMu(+rmxg`nXAYTRgFWdUwQRr(O{dL-u&v9+q{Lpm#V8V__?k2y zpLF!A+Fh=sI{$q{(jEfF+e7CoBiuI21igOGj0yi7(d?=jIy;-jk5KE zJ*CZ~oZGNYYq@lmYah8Kw4qgk=7Y^PKm4glctUF}c+rU|f6`HR zZZ|<=DW}RS&8l0EcEYO(Gq-3<62&e%tnDT2q0c-ogZ=Q5vat`CV7CRE=3%0}br(nY zek~*x7CQ3XCo0oq9evyt$r;Pf%&>|hRX`iENh)S=!3=qh^g9A6UWl{cGyQ)EeelaM z!G-s<@(yXc4Skqhm=4jzsqc3f$xjYo1;=uioKp5P!G5KFFi@3(dCOTdnZ)p zsn;Qg69z5^abHHyyPPav=*q{IF-iOD3_@q3WjDonv|7A>P)Cn{%58f~s*L!Ntr&M~ zp881PD33;YlvJ>B`>5Dln3$zyaG7U2kM`T9`^1l&T~yxeHZKM_;uwh(e%&xX>mG@u zjak^OpTEs8_Wm8)D5wiykGPpnTnxm-`T`J-h6}F`rqjflUN#zxzt5F5mG#BF&anw| zlm9hR0WT920vQZZ+0Aww~;XKI$zoz>-Y8!9RRJK@=-ouZ~S%ZU3cYwQ&u7$Id03QJM9;5)&=# za(vGOnkgw6d9^qHXfBVaJ;B1yA{dTRm|?D8dDsm4~Iq~$IU|+^;q7H(dQ4CO?R1#6OHzoqO2!X;(F}8 z*TOQdu61t=;;G2?`D<3HHPl}vI+N!nU5aru$x5)B`!AVlMk=!gFvbZ{m8JagJ~_uP z;F9)mnQ@iBCuW206;Tt#cHKKl)gkKJDOicDP?G*w;@nG{R&rIP(}+kX)gX!%R1y}` z5_L!_7!EzJBIW{EN_%Yzmp*&qG!xF`nKLei+mgJyIVx63s_bOukSjLL}49v`+TY=kv~7juKcNqgAk)5~tpOTLrxOO)hNNCN1Cd}A5@ zAUU+?=Rf?T%kMr-Au!gXk@4hcZr}Z6_raI5wRKe>^T{p*YciI5PW5H+D@p#z*yJqF z5$`UkOc49vV$)I?SS!xAKr^msE0y;SRjzuNXrl=w1n)E?WWPr-;4G_FZ1r$4vXJPG{nqRqPCOOr{y$05m_67BhM1edLx zAad0H22(PRD`dBd-_&y;v5p>E#Gqx!E7N^h`AEdy{PFl>mwkkz_lDL=-gfZV=wX;F zjaH5=62cJ-GXq2@+Z*W8#fEx&U^RtmX3vsjqP@#EdHaZZyNbK+N7Obll!F=%0m^QG@h`?&P>pdE9RAalr(ay zE)?cv49xU08y#f0IQU?3SF~{LVJ9h{ntCt zj_umH=pg*kd-K-^MK%z(s!1rL^15UEi6oZEHIeIpPMHb0NvCWSQoVWdY7cyYy=1$* z;A?Y)5FGdPM6}hJ)kbQU58}SPzC$PJDa|Z|CtkF9^NDjL(5=ec$3}|dXwEW{j$m6E zev`yzTWQ;a1=dRNl0(Wm-TPLLOF!?m$>i&ykCFVj?QLRwCQ1E?_J|)jT?sIcK2Ue| z*mTAWzj^-j#@u1x0sUy45UKJL8lt`F2eM!C4+}E(MtMa`Y2UvED0gnVt2PP8uGK-e zQl4P79HLnTx_N1^Nsna@BkkWs;D1pztUs>Hz61xHBsffaDrOq)Kii39J)euAjqzX< z=Mt5L)~ls}(8p(YT-7`4(Tb^c>;B%(D1iodRNA%j>|2io|J~{FUq&nhT?=TG;l7+- z{gxf6jFy<;a+IwcL!7{mJ(ejv-33ETjeFA>B-n)*F9HU%kSD=%IrpfW+)YHVCx(od z=lFZU!ynLKAx6dWW=}&L1CxlXsX;lb^fE2<;B}-tW`X?AJ@-yQu0YP+?EY@tS3YO9 z)}+GjO^S-Rf}U!b?HgZy|9ZHe(ZMOmxqIGjycD_dJgf5h=*BN6qvUTV?|tS~244fm#)(?IE_s$^bTb$E<=~=gSsbG2 z6JRM{^--?su5vk*5r&@+nU_As-Q1(Z^+36pYPXfOi(SS;tzjFQp_4Em9U#Mg#AuX) z`gG97xRpRIgMTqS+7d;t#fnLYuQV-SRDShUE%$EW)gZpMQ&mlXdBUqS@}38L=K^o( zT>uKZ?ttQz)dpIUfIrV@ZPsh;S;PL(ra$zMenP{c6Yo8w)dNm7jJ?u@ZvvkL9r%3p zL4uR>X*Dv^_yM-0Wv6m8J_yix)kfs4keBkzA#%ses8*{t*Ya?p7i&d_9sWIEH=-;! zm%eR&kdwc!TuQZet`XfsvyJsMwsdGy&@_PddlnJnQ_zT>lQ{qa{G5b zjelV_aSFH>)wwypJ5=$==y_Jk&HBTRWv*#YyV+08{fQDDW3D+XQd&z8Ps zs`q?!&G>K5Nbsov-lILuq$=`PO<32w-fiOUbID2Tg?%D}nJ9W$@ho&befG#-p z4MN5y)*81^&c_jU)E9pSU0InobIEV&foo^N(454%IPidQAgTHG31@ z%8hQIM6c)-v~URprIQ8uJc>TO%c2!v*|{n&x3TmMKiW2L!Z-Dp;Vwr;;DjGAlmOIF z!s@2blfSti4YU2>#8a_;n}>%?84Q`s<_X3f0@ni#+a|`luwY@g`+}LV)vo`^BSe za-Jm5@{G?`UwL-81@$IQ%oM}jB||c#A;yp%3Xgly4svf;ZWemm9rqQUS#&FnHaHcW z5Ej(w2E6z9hwvW@qEKV@XHM~{dNmyAW@hHo(bzzhM%*EvC2%traVLZ2@h|FloZNOG zJ|BiCh~K9TzFze4huC#prss=m;Bow?BYH8U zvH=ct)K0u>$8v4$kj0>+x*-iE9L3~aDoCb>ER9M;mKVsoS)jzcNu6pRr zI@8L)%VLY{?P%RUOjQ}Z5%l?PPYD%gC^LZ0kEpBd(U(k^howP`)%{!7-)S-L-hCby zKZm9+my$fU-&DB4$2y)cO~t`k$Vk|h_pp2m2GGnn1p4RD8@g))a?CAe6kDvS;srE@ zF=6`b(fWMZ{z@OT9X2Wb#UI`CdG6`Z;Gui5{a|BJ7UriX0`*Jx!Lmq4m$2VwR4xKe z-TG&+&T@T}BsM0E$3M#!pfpG~zjXv~*YkD2|}wTiI2bGvo{mTf_~-EOnv4^hY$xQ4N3Ps)Ch-2{pS*|mI62|p0s z66?SI35Ge~c@|)4`SuoJ-n&Iq&uS~XEX)FThilx={9-4tXwx7V9~g?l+~; zJ6_Ba=FYJ!e{pR6F<4vXYBv$*vPHE^x}#KdUx5}WkJcNjgZ!P~tF&@NrG-I>+k_1L zpDy^91+1sbrTI{;9Yr+ftvFIRq0TwgFhOn~z|0fgSL3AqPAvCTp^#bf^P&y6Mv46@ zR0Sv2K};xb_ICbvE=rO4NB>shKZVP&-u>jwoaaTWAQhjE@nRN!eiEzrcM^d?g(SND z`y30-xpOLI1Oo-{1!qE2I?C)8)BjrBmFw$iftaA&IR%9?GqK0$?Rh%oL(}G5vVRu} z|4WWZq4mRy*&7X%;F*Fy!}wD$GQ~3yVu9UiaiYH&3A_?io827sn*6a;G;Nlb3d`U4 zo+DE(4T9u2;NEL>%~i}>g*0KgcjcaDirD^(I{)rt5Ha&_Z|0WY0rYv zl_j(k@-!d&~!WP<%B|JHuAL2|Vuv46$005wu9TxQul-XSY zWL*UY5)WS?KDPbzv;TF1z;{_1EniwMJBmIf>C|Jf zb*LEYZO#;g>vNg&13ht$<9o8ye-Sahw9&lgt=vd3 zgg2m7po^UNKUm@wTDxn2#UnW%3x2_Y3{C%nwqk?wzJZ~(-y}qTY0&@H1Q<>{Jq}lv zj@aaDb;KQocC(^d3L>uBZz3G$|I;bLh|f4T7v>b^UV0$lJ(|`@wJ*upeh$;W&7$X2 z`VX{_6Xq`?iQQGMWK`xjEf;*AK9MF8x)VR)MIRY03T}WCs-AIQMxi7m{co%T-F# zm($vpGrFYa7Y~-U3-lmn(5xmyEuew7YbQ`W1P7rita+rO3prlKhnI0gx=F8-9OlFv zs2Y!e1ZcDT<@tWChJ0WBHE{*2==Kf}H4nHiMQGJm}X%PeYSEr$SK!EJAuu0mm`pMUS zSmVaOvqlD(ImGPGeE#ti_RZ9W@6*FQKyElMf0+`iKqm33@^FtA?YtPR{Y!${UuP93 zc-P8WJnUurxQLG1p&lhtfR}MhhgGe8p?@lEGt27K*QigMmGR8?L1~M~(AaA3QA^I; z+eBJi?(d+FcI?L0ugkwLuPWc(eU3QfkK{UowE+k)42dszcHCZ$a8KT_ z1x25x4CGTbewA7;mU{Q~YFRk(x6-TAG(dgF$X^(+9v`dai@l`wT3LTnKS`My27BJqm)YXm!AK+bYpq$bN&Aru+{HwY5gyry|PINkT zxeYRIYIq$p@gL-nYU?HYtkknY*x@UYcqRV?CE*Q5XFWvC=oKvKbebLZ2BWfU&ko^@ zfXP(ypd)8{Avu!05u&8(k;${p;gLK=?m_wPKSchM|HPWT<%fnIlnUb!_ z#VXTAs$4s7pY|mL4UC=?Yudx69$~8_mSRMs z)T|$o!%x{In~x7^2f@1+C_$eEf1|3y`q!KSRSP+O@L zQb3TKUvlB7yv-~H^2oH!?6PEl+AjEfN7Gx_@xh1l-obQ93a7_38Q{J-5XQCP`=z5% z6<*4b4Z{r7wgkk_K>F9?#X-29;mPAe>6&tCN!AV6TI{c;@`QpQkgwHlvvuW#diWYg zTtM%cszZRDQDSV^h+gGdP_uFyg0O;GWv$o9o11~)G$9@ zw4qV|0=BE_Pias`kWaZ)afdiJtWXq}-|5aCQeG~ReUek>^u+}6Dj>?DdhF3@|BHQa znd7#`VZ*@Qk@fekX}+4*dx=V4SCsS2n$}k)RMLzO{qk!(H@U#{L~Wn<;Hbfm?sx0<_0rvlA6&Z0op(?2u$BAl6_{U}vBk%T z*Y1p|nFA|i9`EUXzGvOwf~lnsC^pIG^QyA4G?ESvsUC0bSmq3#Im9H|%K2EG3*;a% zgb_kE9x6lg&rh1UeepilU9=$nj==Z=^_zOidi3&4C&JqA@HVHbAWH?PWGpdT8whrHiP~eM7squkhvjI~zd!G=!7^VnW%!9$ipt z&f5sk$vnMg>bv6Qs33ziot#d~neC-AsIWGD+NO&_za6vfWS<@#OIwPWGOe`9l6bx8 z-fgnHvQn_WvmuDtH8VQ)Iu7)22E{|p;?MRMoQ&!@&%Z{3UMjyPBGOgCKL22ua_%K? zN;@;oHD>G4lP=8EGcpf%@w?op{7o|?x0>jFG9<8Y6j>pWY$IoUP+zeH>3CwND==k13`x-;#@O|Uvj2E!{C8##~R*?ySynf#qu^%bC1borymjaLvQEM z_R}K4r7{k@c_J=_YjHMSbg)@8+?;nH&}u=$d#rDhPhe2up>oTer=|5Fn<)9o%S!~}yRkmOAThBpKF97rT;odmGA30U=DIU4$yB_BWT0B4&oRF@2Q4- zRP&AT);A#zm0Op{DER5p1w>;Aq4%oQnWIJO8;|Y+Uzvjo68fAt7mm*>s2Uqv>L>G_ zRDbjvef|0=lBD3Gb#9=t6`uCgF7cK*@_B()?#8H%JG0b_ohg*l>hfhk6^2WfPOlIpE?g`V0r~Oz8kW)Gq${WWh`OEI^w!YD-x$9tY*i#XJ zH{^WHfB(^13TnxI>j1S!;3TZ^c827kGJfL2UFinqNd-0%W~wx&^!wr^)Ajm{2>h^- z>0W$Fql8Fa&Hfd1t#k~2$^^N%+C|kVc50TWM95c`$)oqzK?m{~0!!9YjLo|Y>#A@R z56IIL+ThM^#DqEQV%mSPMVEuTyy5S~u z;oPN6y?$FuNfp@cd{2i&%o7HPY_1tdqUL3Z#sEE$L4!sO_5s|mr6bE=ALo?~OsSg{ zT`L-M{xxz=FuYMqNv=E+br7Up*%>c&RWF_UuCR^X5PZWwK}RJ(-)d z(yppe_%Rfz<9Y(l=pqt^wjZ4OP5u6Dh7I$TD%l9VBPC)p$m=_E5|49o3am;s1B8mz zC<_9Xa>x}lz;yr5yXy*u608MjmPim=E6D|k*<1RqN5>wCb)#QlG6FG?$8|r8W zrZR8{x#QtG23z^MW_kmc|Np^XSy1VsLqOhVY zo0_eAPe-XhXVl!~r0;EprsWnYeoMX#{Yf*?@xs8=$%SYje5-*!ENiIWT1yp?U9F1rr3piub0Vr4;^FNv2-T>yK8ko zX-b**ZrQ$|52lecbuI1Omz!>Tf12cV(pMg?TvGsR=Oa9D+52b-iFTxsEF42lZQp>! z3b(CC|M)VHTQ%laH@;|*ruobfplo#NR$ZWH05wZ&0X25wXMd_$k4QBgRpp$1w_O%A zazCz&n5*YL-#EYrPMJA-pWNl`Yc^!`KD1sBv&;=Q?qQ+h3`ICv3|+qHz&rXw&L;0v(5C4L&^x$ zO6F)(Fmvj022*+rSI+cu>(&6ma&%$b*|TYwy1vix-H)i1=S7&S$GO$w8uO7+sO4f6rbUo&sNs!^4iMPY)U3EG?8bvTkT%odJp*TxkH{yMb}=o zsxcx&_iQ}-I-$O10EvXzx0itGw?f7*6$G+}NhH!DebY0pF+00DTR=;U=ICgMo5uuNtW7TnBnhjBZW<}~qbR@-r;+^I*-paIs!s-lI?YDcp1Q=ES9SpXTW5$w8J!cT3H`|i`o^2 zd)Nnk7RfN!<+ZoJ8|Gd4`QFYYTEQ@pD+B&-^JTF9@4T4SXX~buBxaNPo|jIYHHLn? zF5fv2o`ic^2u(!4;ND+{kBcG;8MyfBN@fo`4oAE-?-jvzowd|WDkN;nR#xZyPdr(u z_4jBAAgi|_fNadk+oG&@q!eU5A9u0BTp}8s0bpBwkX~V}FB`i%qgGJ&*$?GvXGr{t zX}4Mo)r;$)A?og{8zlgYH{Sx+y-wrzZuE)PN3t*WwhP!|8uN+X`nUbf%DH?R88L@i z60q?eyW#~$-DShm#3L62KW=;J^e5R7saV=IM&%n)QLW`>s)M`DjLH(L{9}l~Hh^>TS^CYO(3)#UjdOM(T>Qle!Rb(Qa79 zya-XU;s{{vMR8;n0StAER|GEjJEufM8!zIYK}_mfM7M$tvYU&UJaN*A2`LTUWOEb- z3@4&P#pE{>vvUPhI>nKi5o*JhtgA6Vkwi^3N7<6@kd$jYzlP~o-)uILZlSr=B%5;m zaks$|Wd1oQe?z*aFn-Y%`=e{q#IyC>O0r%inZ~)HxuU^P(hcc^jiBm-Bk<=7AVb+z zm7{Z~3A%@L_{2WG-!h+(DUpv4_En(4^nu)>li zqf0c={b^@KvFQ1S=Asv8=yU%-Ab z3prSO&+iR&SP^AT!M{qHPZ?0RFvxzA?Vi(&1J<>=ss2pKsPw86O|X&zY*pRyY+x9SgWwWnJ zi>`Fp9JT16SZ&6tQYFmyF-pliE~d6ahHF2fs~3l&AyTUTtuDLno1V~-;Mxab|BZZo z=29o*E>os$O4eGVJ{@qF?M95Y8geRjku^9XyotwT^q4-EledzLb}vgRkNJEydN&Du z47<7(QDVB-GM@`>iI;47we@+lZL0Z(*J~1VXSWr0K~pH~_(lfhVE<)P2P|%e4k(+q zAC9i)-d?A;h3lN$CDW7i7XC1>8T+dH?U?FM$%}E$%?{D(N-%9p(d}v2)TZ0!Q(Vjaj zdXw(GqZh}Aw@oEwc#G(T4oK91zwNUoajXR5%-!>Zx50(0o7%MCphEA`#*e5M0%gaW zF^^+cFKPs(lT~@n>68(ltN_XhB8)|$pO=yx0{k&ykRv-ernh`?HMUOhWbdrmM|TiR zabHI^T;_LprzHJM6g}7Kj2o?X%iuPu)*1S41GxF$bjmiWv2=CT2k}UK*_zoj8Gauq zmH*@#4Uw>>?QO~Pu2M*FZ6CSh{+`fD=3(V#ME^*Dy3g_{x|P;TDB0$n+d(S*L>O=#&8s7nC5BYs**P-j?)K*UmX?J{?VZjVs&Q zYYjT=f{d)N$+P2nQV*N@JrOgN9?0%uXuCRRj1NT{m=q;E#;4HHm48uwuUqvn=>*Sq{ ziQfZ9hv1|NYq+3(IVbX#uVzYJM$wUTNRhl{cW(D(RH5j_pi}W4U33{7w<4KqS|G2F zX=+_PY)4h9bo;GVvk_;K#QIPq9K&tpzByc7D&?>&AY}DzdorP=L>n|2AZz>$Sso+~ zuA4#I(bi5kGrr+(xG`d8bcuk60F*6lt^5l-oqkeNZXc_OFwZ6moO{GwJ_2W)g4;iv zX5JBa&Zn|kIxe?Z#&m;}@ar@3uY>FHA!#CEV3D~-9s^u?Lf9cu=5pk;Uob*{LCcH_ zHP`tdvyAw&BbtSGW0~i&!x51XR2K{_kZnHmH%i-)bD1M^KgHZR2Y)_a{SJxu-zBj< zYwc^vY${u#MMXub&G=PmO3M)~f&RoC^DHIEi+?OXFKUEbWhm$3rKN;Zz+v=j0mqL9 zL%}DASrRZ}pMQYJ{@CAWRqN5rgRQ?AdRTslKqKjhR#yf0WvO*jklYW>Ier@Bwt^rOxRkR@goqqIXS7cR;jn% z@~XgPP7mWYN{|w)#@gS#c#I%qKW!!XvaQb%^as)c-_E`Z@yYIgXB8aCEbzzN1L4f$ za=^z&rB$!!Mx1??rL8{7kAKgf=0EC?@ShYiiG0*P@dczjY+r^p9pM=h-pqkpO&~eq$xd>g(V|_`yM`HG%=jn~G_DQP zCCJ0j2YAZPU=AA)8u7NkwmxdM4EHuW!G|(3S5O{6+N>07tH_H z=yEMO<_`c0Fbmh_Z`734xHRt73c1Uc?VvotC61Api~1KZ$*BE^*57c$ebz|xi6U8%k1ggqbTSG5)WCOYqKC4vlU`{z?&?1!wfTy8hG zfWw9aMiEr9mkrS|JIoC-u3=hEW6ju33#(e%tN&hOFdfPMvay!&{BVD7HEzgY$-<-b z_;K^{fNAn+upB4mts}YLe zQhj%1@(eYA4f+{KGGCWP{0$LP%?#IHz20NFMC|;%L`H48Ze2*Ro8L(vFkW&#TvrEM z>pNRkcA7&H$Vu_9OM z`hq@pwg*Wz2UkIaGRU4?AP$hRIC9HkSS6L%PPT7MVRi@PO*G1Bgqm8@cqCdSpYPes zou=8{3P)v=W5?G0i#LnYPQ!5#kK*M{eAHw{RK#fuUrTn@XQ#W^<+%oPZW69& zy;FbcVT44>y}dFv3VvIotKhM3+z|DVjBs^X!bgs%hCu0>VBvv2ax}nie@f;(`;9Dg zZ+keZ@h87+%=#x8od-`k=0N)l6Ub zI2@jNL7>b5r5f>wdd+?NNL)^{Ua<&Ofy+C9ilalxs& zakft`MA3WPnCVXkl^*^$9FZ3W%1H*7efwJc+*wgN`nDJCW2xA)qV0F{K`%Mv>2vOX z{p(ulf7LRj0Mz8UZQd6jFB#atDXsp`o6koc6X)*TzH+sb{6DC_6^a6YixeJ*#4!ij z6$I+=|5CaA??Pi%kj-cySWb0cZq&a_DHh{hJtK(|g=^hpRDSu%=G)!H8`3#{t9Lz* z7xQd3i}t;L&iYqFe*aPbjTn!!Yt9Q5m_N&#?IODMtl`632I;@A_S*RYay2b%3(DYC zFNsF~XO-$H!o^oi&yjW|qtckJRCJl?(@z)=+KImos z2lZz;P4e7fOwazyN>ul*+yY)p-Qv?@30&+wH1y>2o_yNafU+NUBwa?7S6xP~{S%)*VTvt0kp7Za3SlviGUBW)%r8e|^ z(fjd~yXhW)?Ws<&0n45i!{1|gOztW<+lI5-^NX%sF~LmbK@noMrwUcCKI``lRm81W zq37e;x6cxEgtXQg)L7eFS=k5qJ?-NLOs7?8*~<@f{=%kNK)@nS?z1n45g!|=a$bnv^_d56(OosQJ6H9VN+A{bkLEd9Xr~i*fUC>KJ~OzuEJ~%0!Mq zN-;hU6Lz==wS;D^t+cZTYvN|!mL1DC^sGj$F6-VXy%^uB=&lVxdK_te&cH}-%5q7| zrm`HBO3;N53125IISp4o)q#=Lvk0CXjNO-A4sB|cXH1h)m;u_)I5jSG&wxlQ#zr&4 z+>MhRwZiDxWqHzA*8o#_<|vFc{OjGi=iWf|^GfwD0Z7VEnhIga`4Lx(d*gPXl+3X934t!a)P>Uig!;= z*FD}&qve2&A3m))ih$C7bIfU_Dj}IhTgxyB`KRrd2#g{_hHkg)-;u6!fr{_`${f>h z!4F;YKM+1L?DLmfxcC8pxdbfCb=NyWrVW1p(wbMC_frOitIWfzBA2*$cmS`+*Pyo% z@_m)=UHUijze_&qs;{2m9V@8j8VFnz)s*!yX2k1M-z$qa_E3geE{+hxMe_4UssX9? zt0g*Y_;h9s2*wd}8wUzr5KTSe@shx48<5yrFwR!julPo;kL?+jJm}X1tLH+d8BOj6 zyoZIkdn6AO(_1E+v0}d(A!?vUDq3%{_RC@r?Noi1i-yLXriJRG9aVgGXIhyJ(e`qq z_Sg%^)?4xSZraPzRh7y_v5D@5-UcfPCa_PSpX-Lg)j3#2Grb#1k{1+D1E zKwc5ZCeI-VW6Xq-xe#9jYK6^AA{h4ygGlPN9NH(Y#ojd2gyt@tuG~kH?XBbs2~vJ~ z*D(=k&*XrP^@&PC;~`csn1u7g;i9gz=5oTaiw2m%A6IB@&=#f;zuO3MlWrO*wIaGF z64AS1?H)TXUh6#O3QNo!Cs7lL04v{?co@KJMfdh$BT6Ulrfh2F*&4vhT4b)b{)6iW zw}=Ne>D6grZ=KA7y`*JEnvHCFL80?*-&01P-Pm1k5btBV2`=x|gu=$&NRHW^zt&*U$&S(u--EJ4=P(pI)T(;Fx*%92)%iu~ZgKR0)M zpSITw1Of7#ye+xz*-DeQ%2;(Z@6eaYoX*FD-mI~3}}uR zn@*Inm=XLE<_WEt_R*v)HAD*!z4NPpTS>-lKA7bXSr78KmyqVX=J>ch@TW{f`QqkNWt>j+;f<8vVP|7~`J?jpguG#aI9VBZ}!m+(Oy};`$ zr%vD7O>Qm&ZlInijLm00FdEu?zfgif(FRP*Y&R~`I?Ze~GW6tOtGWd-ntL~sIpH__ zZKmahej!>*?^)mbNM5#-o8q4$de@#&xyuXaSwT;G%(mbBX-@a}o%cstGV~K6>s2}f zjdSBXJ;P9N?yAg&Dg#;WOQzlPZ)5MxcPR7MheF*W>%)OI>0tCig){eLj9;;muzf^o zt5XI@anGS+3aGg8{s-Uvu7IYoaK16X+_J`yCz2ttUHHCtfzywCci`RaZdU7U1XEq6 z)y$R0_>^n@26xQ`)!6_y@cjtRf}3%H3@2fCXnRV7vUpT##cQ#ZaQ;CnLs#x%$6TjG zDPFRam0>q42fJ?QR{bISXw_3VkqR70@2hC;+c`K4N?cy#NUS&j4=#~p#^sq+Q6?)E3&Ck8+ALeyE;*gV)ss!i-_j-sZF3o+w;-^ zlayYErY+D-b@8o6liKMm1sGF^qXI(Q2XY|gn8Y$f_kqfKRz%b<|DIW=mfEn=Ms23$ z7)6Wbdo#A?G$s_;DQryp+)A2jOpKceV2d<0Roe2Naq~uwd$9OD$+54o{$1v40boU4 zH1P$dfesW-^PK@sPP9g_B zeO`Js;AcWNR%iDR^-zv{cTN|p@KaL;2DS9r zIrQw6yiJyYR%w=~$4#X0Co~9|`iSPc^3v%)d{z^!3m*yDkTDwioEz-$3vn=k1CGCI zVJgWl7yQ$B@RJu2GMuAHUEQVa;v$3mvx=bh-N}m{`SG3P^>P28J_o!vpBwkMJ2e%) z(&$AWa5y^j$SvN1=&iByVDDJ%;;jdqm!-_%+Q4!=W=qCtpq8}OLrxBqs zSO1w3>5cor*9=jljuh(Rk?L-Mtk<*z6=MBjS047{bgj63m?vsl6~_qLe|nbN>HJ}o zPLw&LNsNUFK*sJAzarZ-s_vP@-4qX0nzK^z&05cRFwsyD^TW3%!1otfXtiIbrN@=~ z6Yqc#mk9mbt?toxKu7deC3)<*+Y8_dnf5G5QJDIjkmE2_Q>{sB1+HVR{>I7S*xTtm zF9zVs#fvRCsKlil?(=-5;Q&waHzc|f@J7-oIC$uZVT-u@*8otV1 zGZc|`Yd|=DnPo|BO2=aY5l92CKN9X0>8>^Ppm_(Rtkp&tV*T#685ro|uQT{ITBi#S zs<&z|B{n3wi!C2^C7a1ohmPzz`Jk!S)GRT!50Yq#^Pyjb3PiOAK=Y7sjp71Ka_ET8 zmWZfsexk`&k-%LYr&-89g0v{Uhj8;AdA|UfIdWNIecxqx;BRjW-Fw#R zC>aBysU3LIvelAchU^X4I*r|EbfT#uGXZJ?057DXOGY@>!YO>{y&2U!e6yUSqjgCX z1w3EgSPykY@;HpGJ|>=xT6xwi@J00VZu_${ugx<%+Sm-U125IQPv(4|WNDHHEbG;8 z#nG5&f(m|8<#uPnNFOW;wD)a9oU#z#SPAXHrr$?aAT90Tl8(0}31`=!uT5UMl&e7Z zj|MrTu0B={%PLv#%od2-@H|20n3LF@cvpw-4>i7QI~Tgot*f{fZg|*_(vw9rSBIif zmw(FfCkCXo6?SJY_tI8nXF}(N(?wxG>9_!vqlOhL)39^#0~0x+9gs4l$i3-@#uvnF zKV6=edGabu*Xek)qu%&)_Zp*R%Ohc`YHU2yl7S;2x0Y$7B4%B{js!D5i|aKl_h<~4 zt#ZnRGIj1+54Zk=>!#$#TTq*;($~^&dVAO(Ny6pi8~L!)nugo+--JR3Z!+ccNZ?er z$j8i94S#fL+}TJm{t{p0@>KhxPk%~C=JUIn*8`6aOLoJ2$QQJV!>)hFKICwr=+yJj8gbvt7Wz;I^|3<+R%?xYswiS zpA>&BrPY`@6X_Z==xR(#EXNzY#y2voN>L6XsKC+hHgwgCX^<*#-rLabHt;Vkq=XJB@A-A$Lb(kyTeCl&pyg(|iDbci9 z9(0J+l3s|hV*YlGMaZ;bU(tcf(^%84;}I{1)_v5k^Kld1?=LPsezUqMl%dp2pN_Fu;*D2g z2RI{Sf|XOOoGk(tf>0-1u->>?K6v&o(Cv#0C(WevHo;UeS#DXaHe<5+-%rQgUXVa& zC=m@l2`9n4LiM% z6~5+sX7~DcwC#(9_Zu~O$j@Y!_?&9UIHRSw6HLCvanMJtVVTpQZ3r4sfu%+}ZfwfP z4vvfT17I@5+3I`oDj^;9))Wy;vwIie2PL<++gZ+`k~W!}EyolQGy`8WElxtona@dL z+iQSK-)<>MifDMyJJk7~dn4bE*>z9QCe3dDqEZ2~F@n`gF>iz}YNl(E)qJGulVVHM zv^<&tF)sW|Si8;@_;I0F{$qRoJhG4Oitvx8W@i4-8f$w?-vF2|xzqN&54NT;wG;N} zN*oC`)19qYgFmBXpD9KbnVH`12sd^3)t zF5aW(?v29&eJvI6jJ=$*VL8mZAG>mWE6!HU@#8|hmlksGW;zNMbUg-2gI3c-=h7s5 z>m0jmvvxm%0g+5HMO+Nm!@y*DEw|#O3gS23lhOZ+tUzK~9ik9MS}F;|C-27t<0JY= zxvvtYtA@p{te4dc1afFxmFTe#GvL!oDUg{u`YyQiC)|C+tVTF1*g*K~1YcHA*Z3d2Bs4-` z%~vgs&`}a;wDZ!i5AYulsXe1|Y3H>%2nu%$wma}+edW(zkm{hnWi+z{grnyPH?Jd` z*Vad+pi-TqO4-D0|7dyrH~(kx&u+TZFgX;OyGD`a5~Wyym10yL2o6sFcWqk#9PvjB zoEM{Vn;tX=y69^o{+kbrQ`$quU@mI6@C=N~$~XV6vy3h%f^#$5Ohtt+_x)$d{O=$U zm1w5F?wvEvko!!cyXw8@&31xn?T+zzN&{t+iZ(WtTx9x7aY0WWM~@M>TCu(6m`y^9 zj&Kog59MFCvhk?@LE4un>3q#&bcLcE2?|;qM!WyDf~m2Agl@t>FFnLmUPd2pD?`R8 z8Ii8u`UmxAe`S8=;g0JrzRbU*6L#d@Sxo$`lvF|!VEhnf)mLp-?%g|uXz{<+%9zlU zcgXg%S<0q0-~idC#!KimToS&1<*!GjMg*pG4Eo_$J#~h%pX0|Tt)P~2?*tX18UA`4 zL0TxG#SVDNF}uGCJHuSMsq-_}G>2aK>)uAWxO+c{ih6IyZ~hJLf?RG9fY+6?ntWE% zG=5m^*n~D;2zu#s@BQC4rt)3uB3v68*jL9z**$Md2nK1P&cdXJ~3eqAV-MLGPf^>s4NJ%Rxtstx!VtJ7Lj+-%?`$b-3peRDA83$KKg$pEtI)5Qf}us5D;v?@unCTaUCK%X)H=Xea*f z_b3r_3iun=N?8e$21X=9TJ@&SvLLmbSt17UWizUy_rujNxQiQn*&M2vfU?vAAl9$m zTLCjFOpM;)4Y8d#bqmJT*ti*e=dy7WZoyXkU7onC*8NykHO`k|!jp?`lOh-gGgTm+et`OxsoIC+l0{%RoH!pXtsIW#durC&fYPoYHBV zgO;n^NV%n3SpQI8nLDvM_nx)*J?WgI<+$wSJTZYBFcta4!FlG*=+_tp`)}lKT&4>5 zf2q*1a<)doKbG1qSOb)E%jci&fh*K<@j3FBs{ZwBl~c_N7V_z`BYM{fa~`N+=v=tm z|Jy8AFbVwmPdEF$LkZ!Z;ccHBpoqEFR~VgHovfGGDGN-@mp4S#l;hkB+8s7FJ}BINwID{zRWE5$k1kBbnXb&sfNoU_yG|=xQ@j7 zttb{=rIXVKSi(N@*HhDrQhS9)Z=puk5Pbmu8D2#v$!i;>G#sRg5AQh9wysQH&X#i zDMTpgm>-B}j*k_ry8xxb#FrWOC3>|=U^6@`pOzzyN>(IV!1?VR0pr>)2(a}R1bDg` zz3iW3sNg|MNB4XA(e~M316dsEU(FKFPqX8GZM%P>6P%jgYpJCz*R1rN4km03Ui`zQ zs>9U?$&cPqQy7cHC>UdWC6pcFd2 zjP+E%<}afY#q@ho>n4GL`H#{Cd(aC}%X-jOmFr(NObIxXeWPBcZM_w%;I8Ro>fe)z zSlq|7J!)j=eZByipIG%C${ifZ1p#|DMj!U@_tPl>Um?uVVm3ow`>ip!f*nE|wF~ar z=2d{w7HAJV`ifO>Z5;c}Z&&6DCO#NoZ}DCh>Lrcy9RtmHZ)RF};K|{ubukkEc69(& zs7HVw9pWdg_It_F_T9jCg3`XBmKC<0a!;?AI0dBpN&&|3`&qL~1G7$Gwd1~d$*kL% z`j))mA7;FIVS8)?TNEp9pNIAqBJF9z36qE}vgLm`>2`!B%6xd@li+{+u&McIGokp8^!Yi4uRA=kPBw z9-YYdj}^u4QA+$MInOiN1{cbFB4YZJO7yW}D{xWkn8c>TY5w#dSNyGretFhM5$DR; zht*RVRZp;D8X?9ylN15l0IA4j`E3}yYLVo?%?XIMk%4k%zHeXw_Y-O!ndA=+ze!yC zKLn9k8EYO&8@?P3NWk(3G27&S6aM~-6v_>LdAKIf*^GAgr3+Xtg`J~}&eVO5`fMtE zmYW-8N1D)}?knmGHSY&VDBIgy7_7+uEK)^rbW4j&vY&?EE*3xK++rkS&5$k#NBpbbYmDoEK?MD;_k$5E>ql)o zynCVOdjs|@ws>-r*OnWJA5iK7RW<)NQ83oL^%Y>)us-6y3=7`li<$!jNDgH2tvSY3 zhhr2Ry^)gk46h&t7X zWvhRlnb0EqJA#?Xiz!JW@eqym8Orf*n#TWvE?2M%AJJyu#>_jKiYBB2avNs8H~0Ea zCRX>&uN{zchao0Cdl~r`I_6ArY=v!bdAb|`jbwx0-oC`d4kZJGR|ghW`KVC)6qDmq z&Q8DwsN#5BN_dGaU{(C0WW4Ns%)F|zu&K$QX_~^a&Z>9g8_p%)TYU>2z+#zmG!=`D zNtaC@9q<88kqCv@oJ;&Q{~JWGW&Z_FO7D&xQEqDaG+dyJFq7yl=4BJS?a#j^&s(M0 z7^bhvP;cM?ARl6PnJg~@P8M%-Qp;IMX+*w<4Jer{uh&d``jyrFk5Dr?fHG{|@eY&~ zG7BJCnvR!4X5#*Rz|H!ejw)k)THPe*NQ{y1fial1ndmLX<@2llEE_%MGji~_>(e*C zC#r4om(t^*u~S*rMI-3}hP$B;cV;3~9D%sP$zxiazu3{g9&T!?*rJ3vl<6`$>GGse zs|AAcH~(xm|F-zd835J`P^sMTq?B%qJ;c#KOM~(L`q=-|{eSs&nN8P#l=|}z)N%+= z?J1ME%N=*ps4jL)#P40lE0}xI znLT@=dI#@DX%?$-|g!P_NhC`{KfV;XhI$coYR^7*aSYi!411h zG;eTEt7d1qwWalX^y?PzFI4nQvTK!Ok?+kOK*7^K!COA$OC;zJ}a$bZcD*ZNDN9cENi0Kod4rp32cKCdzHb$}&JV+8Y@*J3 zQ(+P!^kv`YD}>E93ker@NoIG>_&#||ai80Or**27@_LaiN=Bb`r^%dD&YYx<1d8J_ zdiNtGrkM1m=IL+sM#2E1ltS&7-<_BCx61%wDEL%VIPZAegm+T^jPahtew%H4}I_bE73r>4_ zfo({B1F-LDFvP6sEZDAz+c!_C=q1eg^X|7LmfMYf?AG;uLJggbaydiEk3oONP>P9I z{ZcaORWU{$tzE@~ym_Zn=jAMwH$O?N{h0Z^(oGGg08W~jv!n($e$}6t#xibj9*MLE z8*48JAvaPr!X*W2x)Vj3KFPU-B@lU10RWs9wUe%4%1)*iYHaGhAM<(KY!j~8z-iH< zDO$Y~t;kS5S9QQ@FI89hXq;(=-Fcd#2+WF-Rj=hn`1T~fDSlF~b`>jzyCAt5d8G^s zYXCO8hdg{`IHu-S;jKHZGr-Psbc9-HfEu?S<$BsBcE20F|4=-{aA{=QPUm!@^vjhO z`0fk=$EM5T%Lg5<+@3Fkx~Cn+r805yYKy92`;j;cKdW82^}@vztKn~jpoaXS!*m-c zEx1U)^5Sl~xbtS%(^DsSa|4&!X}RjOW2s|{h|Ul#3N>RF-VNuT!D~}LWNc- zo{9!2CyLf=nA8eZs@9RX$sJFMkBK~piKmHXKtgBSRz`QdDh(3Ob;G3^krBSi(Gu|K zrv?M!MT+UuA5~TGyxBwq?4#3~FbcN$BBgXT#+XBgt_{~uEVwU3HU@6ZukCmCNA7p7 z&b(d;PY85ciz7n`oA%Spx3hEU^Y#=`y*zDI5fN*Urp_3q8_dvU+VbKxMb;ioMP?^H zzxnsQ3-lU@n!)Nk5Cqf%fQ*d*mf~oN8q=?J80cR3ad_6xY-itulnh^%W!ZM1$-}X# zQLOK?Dx=M#4uQoK)R_*@L*awq_6z*Sz}}60j>_~!1|T(RadKG2e)Pl!adum-)cS@f z8LWsM-aJ^=F9K+$+PWm&;4MJ^kb&D(T(q4)yN6{&7nwOCt(jh|%&z1E@ybFMuIYe4 zotcpePAk43U(k=&KE~%BnQw<5 zgpHQ$vM|D0^1(M{-qh^Gj5W1X54#yqQ!`2C`Wj+MWT zguNB05IqUnFou{a!4tKp>2Hw=670ca&KKhMMmIA+AS%?%l^Q~nHX*F({$L}rVGSc` zOn@lqhF!;PcX*D`6FcbVK}iy`6}TR&sgy9gn5Id4J07*6m<}Vz_8sV8+A?1qwdc?~ zm7b8_lURdOa!=N@BW8?ym~yZV?bp5ANXEUUpT%9>-<}|#Y7_mY`pnwA-}v+1=3hc z?KAXU@+FRuZ;Rheu$Nhgoj8HDay;mg7VdCQhHoS+zkD+-Ylm#y;~G0_fDRWYX20yX zKUS9`Ii4|Ykyldhx?`Zj3$VVOoDa@IeVZPwKzb!RW|C?JcLJeudtF+-A)>w6=1C2u zgCpLKhSUAlZTK8lQ9O)#8C!AtMnRfwN!Hz~v5g!eOwzTbmMs|x+CvOo2jT+-s4#&9 zYw(eiQHb$QOam%~U$XdyT`=rRIWf0jDh#k89=ay*eb>U{efKYEJ>D!u8mz*l>|qKvEw zor!NYK&GcQCoG2wFE3W%ZY9XOi__jb?*lPOP({_G8<>ky4!w2gSg1E!)zn*n<>#Aq zbd4dEO>E@PaRxrm%DTf_?3JTMsP);8#i^oWDM*rV3khvWiF=PtLM8{zW^lB#!_K3= zKkfPXmU0EsN9qM72!{GP2e0hq+ zccoUe0xntXXr-Iq;JV(BI$5O)v}iI{QalFUc9AZB@jkn!x0-|?eJd`|B4#U2PHz<+oq|X zMWmAakPx+nZpY%zFEdgh*oP}R=O;Vg+q^-eW<92ytea%HZljZNve3W=*`YF#s^i+P zoiaEyu(B{bGG_is!gx0(LTUI))@J{jJ^(RRcJC*vUl}1pdF+KY{A01?5ky*zN zIgf7gr-Q5dU%3&8@ogI6#iVd7ZqXNO=XYvb4+JY@6#4WGsD#+{GIUMz3V02*?V6Nz zj?!QF)J{8&29$3%4sv_h1Q>1d8(m%1)a9-if795=?Yw9wBy?-!wsiwSp=LN0jT3`z zABh`ia!yE4@in?%>54dagRk>VEdK0+2z_!+YbZ?!jNWMf*mt((3N(oR^+N0@ydZNIa6W0Pha0<)1}q?LYgs zNb&8aNTah?ZFws6428Jpfet&jSxC3unzJR<>sAB00qYajX__+-I#_(Cf4(k>QfqEJ zkR(IfNR@U>Q1EelaPKO%(`m8=s~DX;t3I$L-pB&Tr}DcG_pHXA=P`I{r)y%RN<2+@ zYY$GIxUX7<%GcLh_GSQjK9Fu@&wMXfl$x7()K9|s`P~*%k1o4N>q|C4W$jX$b)H4e zWBd*WAvY;4wr%`C9uddB8r{`=mn^a z4zkuK53(ANsy^cey}Wzk$@PYq?CmuHTi!YhHu<8Pg!_Hyc$8nvEBP;~ZHy#*t7)>c1L;asLJBRiFSam$Xi zZ{JcmTgy+6tv+t!Q*%fv1_`90d}Kdj%e=?s@5;o3@5^pR2yd0y#WtsMstX&+<1x&8 zreI5czZ*HqLu;TkY0@J3Whz*2JYu%9{O5;>d5~?#E|q4z*(ME+Oyah~Clh1ZiWj2h zsU-26o!x}i@5r~v3VA;xGI9(>-r(d6py_adJKF2f(X4d)u0xUfMYX$VbYcAkVfgue7S^W4~+a&I598 z<&gF@iYOnmAj6yZ8VE($!}GH@uT;+S_l3*e|IFl}Wk1+#`=oQ^A9!P>%~lx2g80Y$J!50f`VQNMZIjGo#?sG5Rib-G!2XO=R)+L zO_A9{d~Hx-SHUtqXOgb%_v;1}q)3_@ zzMO=|$~z_RGqJG~RPRFj_FK_|c4IWn*_;r1H7*zVJ=p*W8$U(ro%dRi9Zcoc27Rn( zPpm}0wh3}}5+`q-=S_FbZ51iI=KGGjViS)!uVR#7`K7Sgme=Fzd_nd5A{B~lDU|yg z`F7tqM!!O_8ClF^T0b*eLVQ;&RZUh1k0}$gN4|H)wU%>FyI|W3WQw`H#TZWX^hT{sKrE_p(MfzMK#4`C`!< zs(y8!_-8yg!-pqIZ60^x27jE*qt`vl4B{EecIB5dR1-X#sPGPcl0As^Qe1Rgno8YB zG^;R&Ey%~V(($A*MZ%trow{%~{75rOJSM@%p4M#I=_XHmEcr~K>BzFDbcS1#6k0^q zOGmQ4%7tEeFPm#JU|QROk0KetCtD#H*sroz`vwz=}_PeRvyzkoo*anMBxH8{Q-H2K`so*v`G8sEXO=a`m5gx^m&| zx5=Uu+C9-xY=nVHYaSlK#YbPr9*0mw6=Sg1MbtNO#9DH8ys#OVBfz7R#|orz9D%ag zfuhD{*qi9!)Ti-YyM=om$rW6)Vy1X@1_Nu#IZJ_l6BcZGh9`B&+&L*cN~gn4y_{w$ zH(fqXhMqv1MYE{IedqO=q%{D>Rx>R2X9hSjVBdE_LJS~@l`u!4GBP|p!DU+z)fwLu zR2Mq+X%bHB%~6(y8xz!qKn>j=`SDKV1?C0mFnyTV#kes9M)}TkXhngXw27_i+wc%P zIRU%QW}}@_FO&8nr}J2f-1Ej*r_=V2Cv!v6sKLFGAo1uKbWuF_nTQw?IP)0IQQiKg zqSxoB2Kfn9x>kM3Ah_SXzfLk3cNApk<+e^BCdrV4gTlM1=gvlYdRuYwAiQ_8Yb`1- z&bgDQ<=W<|h`k)4DOA&|gaLG28p0W;ietO&%g;k1L_pbOFU4~@i{5W-x*A@ky0;xs zVA=7W)TIa7=^<0teL@rr(ZcT6hb(%MQOo6`TA??TW3C>bG+Yb3%DbbTK$AOP6%2w! z-onWN%yKx+PHhfb%9n>Mur<#F2>OmkwN&c^9797y{r%_qD{~djiITn9g<-PvFE;N- zm%b3afhYF@Kg4KlEQ8roTe{JEozsyJ_R3q>Yw{`jg|@qrc9VMhHm5LqUfLZiyJz3F z?Bf{B%evyTVz~%&w!ISZG=B7JU|Nd8M-(hb!zW79s$U@v9DuWfD#LapYiD1tpdXajpx@v+jvgY^xnsdnFK~8sOg=7s;Br2hII<< z*1e6cd+$!Z;mI!tdMffDrA9xcD_xTIh{i%*5W`XQt0u@=cVyQOlAk;Or}W$T=!1A%WcZT znzt~LC<#jV*@Bi-V|HeKCP?}V#B2zj=ed+hJP2~bhh@skYBgY$Tety@+uXqSR-$x( zXS-!jN*KTQdMZ*mGX)AlJSbgUqCDEqzUoXnhBhr;*7|Nt<-re_+D#sPpGt+z{@RzR z+HnZtxM&(=v|IWbrG|I;=}&nfq*lhsqCgXw>uzES%~wiccWh@?gIcIcgw1B`)s$?* zZz0HRiw0>V1E*8iXv9(WY5DQ#3ECL-!w%i$Jym}CZP>zxIdSxnc~i>61Fj(JqrcE1T;~A3txq@GQ z@Qn=pvkwPirBy?Q=q4~G=_cOYB|s}ly{|Q$OqBq^o={Qul0^kZ!ZgyDnBQrxth%Pz zTV}IOQ4I^^X?h>sf-H1$I07D!_%o2Eh^Ofa?!F{I&o{*0yMFjgT+~I1<4*WNYD2AC zHsw&(cxguTMz5=)tf0-a=b|aij|kEQ8F3}Z68!muC&!^=eTr8lyIs4V(Ze;D!K*PW zs0~hs*%P%{A|HQs6KJGp)!sY(K6LEJhesS!v`@L0HSsyVZU;0)cS+spX4=aRFF)v` z+j5r@A3P?fjxy{?q^03Fd66QTi{^H(@XBdDHuw&Lj~>ANme9C%*Xq;1aPkAZ{dL_@ zE)*t?G%=B3C05S}O4ZsM%U!lQoMv0N#w?cZtcH_K+z^ct|IVyhtbJ+_AKQE_@MFp* z+4TVQ=e)DMmn#x3a?>tszIldekWw-aF0pDIafOyMhm>8rDF(p(c(-fs_2|qBny6&p z%-ANFAlg48P7f;k{^0bbc(KK`dZy{%hBPH19+V|jOrvK2`WvOQ1nbBJ2`Cm2%xK&g z02iEfG!6QEvmyT8i9RdPTxYLLS|zRd0enW3?R@=QkNq6&z675+Cb_w=>5HNPu-kJ4 z&8eEt`EijFDbRUv;iz7i7M?fF)#?p5Tpy=BKqmpRowcYl*PG4RtnMshJF#^f*d#2N0$I?hYi3&Y7^RI8d?hZGI zHHVeEr^!BBL`PHEe>x#jZ~ZD(*ecS@ag!i#!CTkI!_YF6zbuBJb=j_VP4$TJP52w!9aUZd|)xClpz@C(2F2GcDjKsr~LP9`zd>Mlne^ z>YycSe)DkE8<_~gduB2gY&(DsdX#k3YB$z&7W@u_rKHE`-YcI%C9R4O+9_s2=xN_1k6DXscrNP0XQS{dO zdC_upr>y7bOY*22%Q5I@N7^1ZjNuwVvB&B)N?ekouAOnUAQ-%PdzE5us4r{#F+-%> zfFEN9P4v^R4WgRq8#SowX6>F&fmm2P3%Pl|p?$o~2_v}zvckRiYottGUK zCOU&H1d(x+ZTm8UX}PD|YU?GW#nIC$8&AJx66nCQD3aqVUDjxnX0*J)TSn!s5^a`@ z!9wce(7wbId>d>2=@&tA);=ECVMCrfJPdf}AdU@S2l7;uWO16lERlRaT}6SluilVg zD+o$R()^&BhuD4>w2UjSJl$I>hU}jFnXKtssWrWel<%$E>EwsVEJqC-Lp_4oB<_gA z0w7@_20Ui(L;%~@gM3Tgr_>;fJHS;-j)+~vjMw#HlStZHfof&2NjPxWy+$tUuCCwG zOh18SDHyz(zW{r$#PfF)F6-ZtxO>2QqbA_gPQ+Fx7^AZvJ-1{lbOaAY4yn4q4SYu) z&NuUQoVYYvZ*TxzRJTWkv0X^(Mb6}F*7rT(dQ52L=mE^^N8C?45hn|d=C6-r$~+iE za$mDHTF=bRmmgKR=R9a4!g1sZ?XFdLUrSXHgT@wJo^ zI~BvyWI;4u@FC}1F{#|T`NioX&x>y}n_Lsw6V{N7)zcDxokqAf+I&_u*&s&0MyP!xYZ%VnmNOoN`5mYSo9zY}li`^y z2Uenh;+bT2MR~%%Vn}~U8Tb(KL#aL98I-urFHLKSRQ)jvtST0;1=-+5N9m9E%7XKl`MvWM-L6Pb!GyYPfHQraSG^D=^{XR_^ zXiE@vZ<0s|Mx=;i1=U7(Wd#(wIJKdjmGLzxtTFOF?%uzod;aN#cqRN(CBI)q(FlPU?R5$; zuFtExF^S+@`yOV7|6I!I3>S;#0>tP)iAX@+sZj6x0RQFa2^AfLc4RIV(i8PC1xr4t zoE%QIFiC*}G|$q$ojnK6o0X$*kB({{ zas#rX#~eoIlP4So^>iD%&IcuUl!SP+j%i;^*0=jEeY8K|EHblJSGJB6eC<4c`T~r^ z$FO2k&+d%R>Rm+5>LC{so9zsBvs1Yn-OV!DQt3L)+m60-Wkvz^Or}Z$*7d z{1&L5F^@(`IZfP87$%KM-T8^!qi{OjmwPI}ouHz1uM3;u7Ebmj8w+wpvjoroe=;BE z$hA8=02w4X+EBJxLPA)p1Y-rc*SpwG;=#c9CRZsgoP4akoY>#f+K53%17&lOZT8n< z++H&}*F6ju56~LIu?z&NVo1%Ggji?Ic0ExC6X+<7gn06()Pw#v4<)&QX_p{AEv;xj z=)wWz?DKsLbDh`ixrtAF0orrLU-(wv3UjIc`C~+CGe@(iXZ#E^w_1Bw-S=H40sC;+ zn<9aQAt5BD*n59nOIpen6|u0PcX73NVM?<*&+EytVxZqs>s?ABhN0F53S&Rs0QuF$ zr5o9kQk}=E`J681hN^WYI$&If2<(6at!&kt&66 z?_!!{{HlXS36{&`_9MX>^RTf{?GEw98(V5)&%rG~)^9-z<~Pefs@s2U?(;j>emb~X zb@$Qu?%n_K*_!&$cNLP;&H&W$`;Xs(?E@7Af&=KtuzU@C(Wqa#XAaUY*q{o}`W_d~ z{eqe?OwOeLEpK25Yt04qUtkL2LnIv3^U>9VdRSsGzLvl|AM)e8;6OduJccF^C~yaA zodMN^Qr<rQ=%9?{Q24i=G!FIkDT3ZrU}Tj_D2`D)AwKjRT|yc98>(*0{~f+Xn0tV zM%S4PS(LcWxfr_Z^-Myis(tJ)e2wY&XyFWZ1pfR}F)CcGp%J z?w+svQ8XXK*UTuQaAsmU^4&X&GpM6gdkvyAX|@ulwQ;Ph)IM~Rn&Hb4o@L5X>)%!F zZJT`1G$pOZo)d#u2@iKLUz7#as;J^W_p364^WM& zsurrk6WCQy|nYL&#ZDerc4z--?*KX;*pWhpgfg^a{ znH>0m^1D+>=FM#pL*dCZ!{vBbrmLBD+2r|f zJ@Bmh#ZrltSjoG1tvc0!IrQ7bF=P?(fiP@BczKycwAd3^g!LzP?I0c-eyJMst(^jk zvj`3d5}jx|9>xJ#`a-NDT%nlPydL=YX4qZDgRVB-H_s$pf(i8hn4W`dHA|o zc7Na1u}{T%!ePcNoSWTv5$JXTAiyP;Z#x-U!nHayVz%#PvhL8Hbkk|!XC@i-=6Dsx zO4``{3VuQvnZl%pW`p^oi*t*&%Pk$<;}EZ`?{SqrA*y~(kn?;x`yHU2*M*QfcTFtn z_u;nOMHPxrLTMS{)^p_5u^q2Sm!E0@WnOF~AYV3+m5&o{C>1LQ};)>J(*ZD-%K&_%TWO(%6%Q~<}yp`#aR3+8-$#t8iyOAM$EP8yYd ztfb}ZC242aOdsm&rF-@qWkyUE%`kz0o$nl(S@YKU=%o9cRf=+PQVP%lj6UItTl%pn zHFlkgk-aIlw@ZJ<3td=6#|BuTMV8qq{{yohjf7ny1yUAxa`&$|l49~P_Qg=kY4aoA zhCR0AkOPAfs>;x7KzzQTI1z0xYCEUl7yB1b#Y#qyOD=e z?E~G5B~`PnKIO6F`4&OpFuMDkw0AwIYXunq!rHNDTP{58gGIfdV^) zDc2=-KA3NG)l`}cG>P^?;&Uxe$8@AQDjX0RBvveQz`ka1goxI5^NBJHhIf5#-`tYn zT-JQPUO42ifPfEpkN5zD!E}^)12)Yr>VXU8Y)^U__E?cV=XRrN-F_~REpw+W)bfIy zhrcnzyw$Syz?JXu#fQ4W?GNLArbmnh&BlG^I_u@atTCfypFPvX+>ztXZ3wFnlVidY z{dAqrQa-!uFNAhc{>ixoZa6v4<&HiL%@qe?#6mU7)GPWAarxTn#C=n|v?_)YDf<0( z>nh(i8`_D!4g#A2r4fvK{Hz;}cL*S(U_wT;MZ8k-wsKOfwcuiDWaoQ(rMON|Y9+Nq zo(45L)&Owq*T0eH#K|d`z*Nm`nTH%au>+UO#D#7Z={GlNcpJJWaRHe1No8OBM&XoWpI%hUgA$ z8k#UH$5p5LpaP5I)V@FK`?)BEOk~sP)~5|77^qb3Vi*9>&6*d^Pb(Bz^cYLSO1$=j zTM;hZ*p7f6n^*#Njdd~E3VfrXj50+b5d!zWnP>&p&BnQJ4Nivq2)s$o-bl9&G&ygB z1mh$F%COdUC#~ggsV=|Z0vNqoJVvKd^ekDpN?GD??vfGE73vJCg_&Y{UOFWan=Y-m zIKH>$v~d)rGgIO2tE{1|hc$3(>{<6c5+2%uuLV+v$&*<$!S=k!(Nj)(mfVS>G z`h9e&JyP&+(j|RscM4&)B3_e+{oCM}*z$EkrYI<{`ATpGE2!cOM`{gTshT5k*ehGy;c$X6PUhu2a*hpXqwi36;_&K%TG`8?&V zm=y^h+3C~8t3s}uuWfWjVpsg1uxOv3?bdZ}G@J~y6GWVzzd8Ewq0~jvyzCiwkcydQs#|_-!%uW3;BM|JB zbNP{Yui#UMh9(gLN>Mh+=A)+`>IS3URfny9agT|yG;Z8+8-4|zC35pOk0wt*o{*b> z2lSd*Wk38%}f#od#}SHFyy5G6MEGb=~^op zR5ZBOyG9r|N?vVQuV|pKl~DhnH_B`)VMg8naC{E+kcabAvudt{;-@j|g11Q>IZhvs zfD9Qm0km~xiu-g-U@;Tg#TZV3P$R~ReTlDzAaaqOo~qQyyV_cz4DqUM5X_XUji2|w z(_J()#_%u_XXgkfUJ>YdOSvX2Y&)ESJc(VszDQPZ?`&v&(D?9Qu92aWCB>8(HP%3t zYE9?7@cK01XnCPhkV<1XIVn!;4>Rn)42r37WNIl^?l~`-t3^ z9g``n{E+N1^MNADt1R0=jB7FtwXfb9p2E*axr%_^u$`=v5*8j5OCTtH8;I~UEfS_S z{YFDk%>lHkQI&KM3vYHWB4``E&+il6VvUouoT#R&1vBvj-^DKE zps9)jI>vPdXy{{O%P=K~pq+OkA* zXS$7jnnQ@qwfZ$l$@j-rJAk#+2nkYC!HVI+7TRK{;Z2v9#uIBFWL`|Z(SCpp{^wB!7^p>rbGP|L&{a`ZX!1T6t`XptaR?k-pG*W1NuCVN+ed0lyz-HN56VqbxdIP z-X@M1s9)vN53>zWTl;8rz>PS)0MhA$Vi$7LZmjJG7ThM&Klb~K4(UFTwQTJ~1Dj;n$_Fjz_cZhm8-rcxlOcAA}D=$)#mz+)oerM1&c#)mO!ygPnei`y|1!Rt|g)c|J|c zy6HS5%y}qj1Osp`r=>}0^ozrn6Xtv6JMT!?mQ(W#|j z6g=H5uN~A80VsE7maK=&pr^uj?{uRRABVj704wD~<@h?2tcr^F5ecvP5=k_3C{ z`5qLEMmM`ij@F*q)dL0Zdlc1!I{0#{#?C9rRHYlcV>g}Vc6HD{zgY_HcY-EX^ACy- zO7Q?}Ole!Za8l6UIKOtxlIqKa_^}1wzb87A9fd&Tj{Oh-rj9}n@2Fy~Gr!?NW<0%D%I z)*u*nU?UnNi527arHHswfUy8WTFha51(=0|xu6C$DHAJ?%9j#!?LU6LsR!)_PwS}n zapwSB0Z%UEz`6Hkr|Y4Jq((i6iZG$a{u*6mS1$wm@ySJz8vr@|fhT8b}Lbhr7lC%m-Bjvwbal}`EWT8dbH`YAYfA5fgj;p z;lNQ)P`BXBe*xn5Z-2@Eh}gkUuC-NQabTF@r5s;cV$jS_u0G?nxGHW{C{1muHc&xF zUqBb!;D;D%_u)xIxly7Z>os60~p;zKO z_1^%qFx+E^AbFmeuJ0Nqkf>+(L3lZMq538O&67vl>R%iN2K;ynMhrgs6*ViXq0ipO z{LSj7nPKr&5?ksFsB~+|OoMBtp0s8jl-?5?9asehye-}rZP0%OImobwK76&`B{ThD zE`UwT8G`*QmrUo$`25caRVz{wpNt>=ydkxcLl?M|e+oZh0ICy7pN8An{pR0+#9s_6 ze){tJ^ zh3bi|1R(0hIP;nL|GT{Zj_Hu{VWP#NFe9`3BmqB89e#)Y0)_rh4C&wFg)?#@ptm;o zP&8A=Qi#O{+R28-R{$YOMWpp*?>K%NM%jYEH_)~MqN@8zkHanzMrQPXv;R#xZMNb) zfzYq%w4?1s2mK#p!O4pKf?96X_DL6T;_Hh=`9StrfneR=c`^Rp)9!hg#q-pp0~m_= zMvZGm^NcN1f)$v&iLZqa=R#7BzcP}LGLXLoI@)Zz0DM<5=-<=-h1=x9xwI$Xv?oC#6gx|Gd zqTcVf2+{IB?*XzJ1*{=mVZ-bH%>_8O$cdBD-4h%yjjWy(eKFp*F&!a;yT@W5UKrVF z)CI||>~LMvtWj%UYb6s)Tnf9V$n#is&*U}rS_ioSiFulA=)4Pc_B(&(+O%!KkT+?G z07@i!osK8e{DIex0GvMXLo2@{nyKpdcBmXO+fmsGhddJUZ(8scQ$Buw)DLJZVALQjF`n)NI)>Xyqo8>LHcXn zo4f;$F#bgYGo*qwbY5i=%#jj$f4o%H=SxzAS;=wVBkwM~>~x+55V?Ka{%1Sy)q7nY z-h$c71F8KlEM{H5^F{EvB({ zF-Uc#X3z7a&GjIk60wi;dRRSUX98wTzy9`)IG`()6*$QM$J$p$#kF+Xo6I>d1=QZd1?!D)}cXD&y824BAXxO`I?^;#0 zYRxt0;tiNfK)YOOJcot$da3=X*OX)b>h-68)N3dbq1OGD6ma$DM5F;jdyMWzyM^4; zQz0~eu7hU89b1zs^ygr@k% z8p-Om;XaIT!BV_|s*pKRkjOpVd2|G?@07&Uh=0KqGL2^3#P5vo=Z%H`bz_Q%e{|y? zuqI(M&LM!<_ECq+9>4N=+D0h&^uODNO^gds!znbr33@J!L=0UV=2T#viG=ru{9UaU zZ=P9zDGz^2^j1zsZKv~Zl*oeKL2Zvi%vHUP-vQa6nLl~V&Sb>6f|bl(K|o}?!lQW1 z!DiaII{v^b`iRpOx_T7!WVvqbx5EZrNBMkEZhqB)z`tMW#fz5dXw-FIXUOMO3yHFN zvTq2`UMB5iI)4lOI;aOfhp$vEtgSv|(>j8n zlgrhZ1mxWZ?ifvtc|sLgIM8&{8E$c>h!RiE$NSDJtKIkO&6Ve9#dCQd{M?i$ z?g*n%1t!_$RzTG%e*7`?We3q{Wi_cH1FOXnjD#`ZxXb=Y+-E`luKE|b(nZD6rTt4A zd;q(Ng2J^Y+Rkj!U{D?bylWgKo6P&B1|N1tVh`Ee2kW9_oKh)iN_P5)fhiBeTkk5GQ0D(Y%Wf6R<)Upl-P2c*-YaGXe zlAV!yoLEfDfHoF#a(-1%oG<~!WVNDO6l*&P8QT__&c>uvs_vaiYa4h3T%A8%wBGog zrCCWh_e){#eA0`8E_;(t>+>*bY`;aFfS$_y+dcCfBh8NKW@6V*#B+6W+(ZYl)Xpft zw1en|FjqzkoN!&biLMTQ8g!^(iU>U!=9mK%+4R)_)a8{O`BwOHe;7e)rmHe4p?%cz z$7<}Q0?pMetb;GOvLK;wR((Hyl5=_PM4y$-(I8lb03B4X6*RSGXzl8h^&q2fLT)3I zmvcmBVk(8ej2e-HX<>aw{Us-(!9*%{#pfrq0$b>~t&YlABhXZ60d-0qemvGo&$}Zf zm3ro-TspNj;$}K|VrP|?)2ko%SEUm8TBK{$htjY&n3x#7q?_NuzJEw-vzPQURjETE zjxnf`<3B50$Ll;CtQ2+8pGC+~VWsyL=P@`)2CoZE^@v*av4Ur>+Xn%zLJQW;){=D+ z8m`go&fk?zwyYf86IDv1QU+90dE)vSqdM6c@v?XHT~1kWB39(*4K7g1N_m`>mFUWe z#cv4T_nVb#G?sdeZ8On`FVFG2G)Z&2+~`}Lko`>O{c{yM z=Hb4c7gHacT0JVs$}NGuT2bzAVJ}4vJsA7jYuo`2A@}ufoe7~;+NIkJAhPpJb~pM5 z1dpBZyY*N5erriC1_OIwn%hz4Su_EAL9CJO$m=GCu?q{YEml$a{lt0FgnM%-^FtOxw@5V8T*a2iMt_6GuB7Ht64c)del< zI}`D1i@K}$8v!lGVpfp zM46>?v|U+w!woH$s0WF5A`jd-_JlxgB@J>nm)kP-vUzOahn9lbTWD2qx!Ys!#{?W?@s>hLe|G~X0w9K4%( z^&+4=`UO|02y|&RdsF5o4!b|M9NWRn@ze8Ewo~OZgY20Vo z_Al#iHzU)WLpM)jas=U<@ zq;v|`lxsGOu%&;PsOh>mJ7^GufAZxj`K%1l&n0n*o<++=YXsbZoEI#WvXJb(Vu^JC znvOodvNfpq+^C_(q+O|dYo_BWb2#;~Bv&idQB)I9>TP<ID3*?_w+u+7_AFTW{u74;4XJWY ztr*c%dLdUnv0@8$cMIkkVZPSaryMQ(4k&VIv!z43uhw&mMM1{y(#6UXoq75}9IQKg z7VWosKP!~QCK!e-6O!HsHZn}3N1sdd18)QCKKtz#h90D>+?I=z4OVEp6lL+WgQ!71 z?%$4~4fu(41%Fucto|8igc|fL&{lP`s+x{|2@n08X!_;tidx!0Vs8t-Sj)k+d*#vb zwuZHe)#o!=2_^hF6Q`)l1CzPr_enGaq1gbdp1wGoLkg*I4ye3+L5!0dO6@zl0HI=mbJ4{?)THZ0FaM6ZB9ZX zhn{1T5boxg;|%-@mGN0hwMm)m6hS;Gus`D`Ppvxpct&@10$PLK0(<~#{i6NI$dWEk z*s7L)3u6#8!DwN>-ZHG_Bw1^|Fzv^yDC6?p8USghP~Q4gzjhzDNw64#;n1A_WT}e1?O3%9@8tyTnI%5*06?BtN6x za|_@GNSUjULe&9cy~J;`U0urJ<3MVToJ?81YGeTW6VwFUYA?1!9>bDo!a~vE+ZyiV z?}X?-rW`Vu`9$3l`#ZK59A9G>|YWcE`C+$(<%NG8<+n$$?g%CoD~ms(p(#2E0Bc||@%`v?tQr9>*!YSo9jK!LA2FK?p~v?D3oV zH0+w3Tz$cOtv8cf1}Z+TqZ~leyFp~H2sp2T+4|LI>qyYDrsKWK7#&`I*we{QLi0Il z@Mu=Y|=~C{#OF^MiRWuiorV#}7$cLML2$+y;?0GZvSM9t%{~ zQnlM)W0u&yj$!`|VOtULowT0YA}t{M!SL`@Cqs;#p= zh4Xkv;*u-WBPM>RaXVkkiM+13Q(q%qBh9dq3El&A6xW{VjC*yRyTm+buvj2& zdz3>CEw&_Ybl%?>me~wGQ9J~^o`%IWPg-%}x`vD=6+anqfx&c4+W;HiUAq~;0?LSk zI7>RZ*;Ah})DV|MPgggg)eQ}ksDQ~&*ruslA%P6973Svm65Wl}r0rh|V%zDyZa7H7@ITId<=0dXnYDw5*-eBGUoFzg&ch$7OUMRx%*tTAgc}?6pNk%B3 zV8uBVkT<+Om|KA6rs0}+GAFiDbMF}5b}*27tID^r0p=j}Ii9NE9{_PV&2IC&Lg6z? z5Z*YhFOHugXPJ@*@_loYGF-g;#zhWEeZhSrX=DL~V3m!oj@|BX~QD+|!n;BLg}CKy)f8vm<@yrwnc3J8A1qonP@JgFw%LkTGQPg~ zrur!B$4|We8x|$QqRF%FwaT@rjgxS^NKJ0j`9dzX6#WRTwTmLXb6`!Ud5_9Xia-MB zHGPUw5TRj9d;n4^Bzghb!llb#*%t-56C7t)9P$?PvuYace9J<(u09(qWHhtMS z{-HO&AzoSBbWcY+Qm4Hj2xq2;rIQX5*i?U)Y>9S(21byewjtJQP z;`IUSM=kG9DLu7oP|E+3Y!bVZzqJKwNLuSa?4+|L-%H|HUuX{UaYnu+@8gmgfF9>y zqPC&x%-G=#-l`(wZPt#?ljos1^O>KtGtRO9Zf8+fq!ieC8GoTTsU@#1cyf*xY&u%8 zdw&GWW+pMtE_rMlPKRyYJMR^9(wEh}c`n%a21Nsmi<*PsI?F*MwhLp#19L`O&8DW{ zMg}OxTyVJP`<~^6>><~;RQodMGn0=7Q(Mnb1$cu)3O>$F=T`+-_7XdNKlNtgoj)WS`Fys*-+x__W3oio$>M$ z>_|DA`b=ClI_^1FxEtELeQo@g+|cznOK*3jO?W!N24o>>-}|j(+W5M`#oQv!yPek_ znph*0r{CMUmYbXl!p`cPr!LyNVRhT2R1Tga06OUX99T;?SH8;JQ(P;Fv!gJpDLjK_X=n-=IYjaDs{W@`%)7ay+vJ0^* zwx)@K>u|EGN`9484IB+Do=tzfmXbk7P5QYNOys<>fM&p+|0heT#zA5WHX+;D%T7{@ z?QAK%d9TlY&e+!bLB>1y;oC*Q_0_g~iJ!xAwRCTSDmmEcYB_WT)5%!6F1E-3X9ZJh zcOHZWZ&2|PRxkMD;UGZLzcC549Xo3nsbD{6&Rz13 z&$*@~>Y%l?{By2E9rx(PK;^v`rI-XQ8NiJuUgnES-O%D{4c8rfJ^0v0S3C`ul%Bv< zHH>^tY;)=EWUUMvx`ntg^cr|eVU*pZEYYLUFVMg`5cx3+7^#)oEBpE`S_U*SBmkPE zu`KybHN#ODhyDF;^*eL72YCjIKVy|@Sfa=n>VoT}efJ676Dsur^6X{Eoo?Z?y}8eX zm?pa>55Vg`*(9^}6@Yj{K_=w{@SEL??9JU6vqz<^!i{mPgocuQi?suY?udMzg0T*8 zJCod|*ZgKzS9kKx8mF4hCVY*bD8pZ#y^%6bb!&%a?B!Iw*u;E+N;m7EcM2#s;eWia z-C4qH5!ln1pf#-j!8P`-+p%M9eGr-&gFVru%o8i%88n$U#{hISq=bNk6WBJ|U?kI= zdGbAZpfQCt?y|4L;uFtOg(muWhd?Bw3u7hYgc3`o=R=bRaT`B#>Yq_V5+V~X-lu4B z8kg}FAGXL6#!Jx7N6*``g@0bYd9Pv~Pd>3(q1kTeS;^~aL5c$0281!3nvOZ9iVD5< zx4{RYHa(tHaOhherE*y8NU31Eki0PwqGU^+X?2_NK-t(dM=OKO?H#P;VH|cmI2UtR z&Gr@bK5S)jDc#?(YFcsYilt{=n`uTR+|Y5jlN=(X4!n15xinD8u&Xg`${B2l>zYS} z=80Y@WtKIY6%n*KNLGgw9s0>{7Du5%;)F#W^#$BM%x@uRM$J~K^FZSc3mbE|{g;93 zj;EVxY1k#LsiHwp?9}pldVx>ZFK;3TFWi>F%uMhDP6-3|c$gm)*E(Vg-+I69U*^=( zmHfw>UPxPfC6Qx(r=9R_?mjzMLxYnt*c9&OB`?y;p4OY9^3t|?c|&O}YMx+bYApf> zo$${_ouUS_P}R5#&DLt{^0P8MioAo6&BoI(^66d}Z*Q~4tQAkcMguC-jp(0ouv%Bo>d$B3p*@ruD^FA`az*9&%#F$%x2Srqrb{a z`mh(KygsH|h#)sk3l**%*Lz@x&wjzV>J9eH}Z1wdUy$BNCDp;%s9!$JqW1m#e{q zT_-yzYT&F(1Z_?j5I)R0GsW0w0>Y%tRY~PPw-6J5V8cME_dO1Do&Dh_p zQiq??7BXrNV8k0HNg%4FE!pB?l;qjQ*T~+E-0!Tu8(D&3(|D1QJqN4S@6a%k!%#<51C5W zq7c+DHqi1pgCc^4I-~Bf1FS!?yhzvvVN3x|Fb*L zI&B+G>O}N-Xz!M@`kZlg_&wX^r5Kn=KKiD8e}(k~pnBCmt$o^9M(|}DRP{lAas(exq;`*eSNL41|&b@2p3 zqT`uZg;bk9WbNNc$5F*<1>k{$|OANKNXRK9ryM;%WLrH_}f&u|DcLKWxNPZVD=da zCZ2{8wlbXY+Rh(B>noxFCDTCfUi~Vm>ED;HQ-p)Qt~(PnG=wc+pk*%`Rrs;!wwm?o79XtVp)M#2kUj$R?w5H~|JkHW0zxGIz(IuuicTCp z+q1t*LjH^PfuPx|qbDk}>^N-yzBIJZ?<5|sB+c(G(uBE&UeqgF?rh;@1^z8ZV5~w2s;9-)5+q?_Ov$t%GseK_X4WjZ%!`PY=lDZpdIxKL2Wt=;G}bwZP0mrPyRbz zA`>Q1i4x~5YII;|;Lcjz_P9@1VTKhME{A|8PQ-fK2SQgF7HU-!`6*U+kRULAfW$QSNL z1_v454~!ub@0AM2GjZGdV?~N2TuLwv^Y~(jOQnT z)wo!CEay7k?k$WuY%nCv!tTU?m%^8?djwcgIKueZm+7Dy^N)wo3qvZ`u0}ohL`%=A z5`#hWQdqH2oe`P_frkAKHtkOc`mpJCpI!vpz%*@5WysD8pBuBysz?&54>wF@H|&Fk zCpA;yodTKWydn(+ZAV$kEMT+EGLI5vIm;y1O3~GJ8x||Mr{7~D{}2&OPp4NQElWgH z&-SNMoV|>il*njRr!zTj)a!mqDy(a#G8v_fjf3VR<=_!R)a%>WDP;=jqrT-CtBCPS zx9qQ1(KMvkQaipU@fEDJh{6#5;ygF_BEss6;<0{R(}_m1jHEP49KUIfH_cjq%ycg0 zQY>OM5ikR~7M(&lPiWa41}u2t9uEhuCvD4@Mm^fuS`Q4)mcDMMmyf=)scc3bIwEoO zKjq*ku9=Q&qrhU8O_Ssol=#3#3%?)Y^%`cdRC8_owndU%acj7*KwIbYVt_a}X4)=#hfu z9un^;>fyfa8hUffrnwlp3XVU+qd53U4i{;jx?+-io`1>lM74iknb*9U`dLX4=3ypjrfT5QRC8-B4*BB( zg8up32djFjmxLnR_lsjKWeNF;ZE%Mb4-T1^JQJX;j>Jod6X&HA4mp>{f;xwB-N(aX z%{z*g#maec`Ds@(d(`Pd()8<<6IM5Y)6)_eqm}b!H$1DQ<-1FEfl!h#Hn(Ce3Keh< z2=RPftCwe)k%gj|m|@IFcU;}N?D#}y6{<53+dVqSN<`88Mafhuy?{47l<-mc;1Mj3 zWGQ#KQz7RW$DkE)cz-L}Jm8SoTzf2eUFCWE=y$8B`e^!|b%O&h(w7R?;I1CC0Wk-T z;&mgvTZO-O5RFp#9n!p`h{%>P!FzJ;kw9)YbDeW;=}t&bn@>Pnm*}y9O`!i5M8l{3 zCmjIO-zWl!|K?{r8vg>)nyzEEl@bIt@u1PQ>D^r>btoWyzw4sV+q;U^(R2AxXHf?K zV2L%^mFNmm5O?Ni2yU0Xx6l&F-16dCOi>#-Uud8!A_*VWd>xf$)NW0unKkbx?h`1* z;I<>tBsJGc5^7H9)Og;3w{Pn9z#GxHKfV_u9x`vj7pu?y0j8AKkB8S|rIkXxe_V3& zK6~Nwdu1^5TAkux{TJSFCX$%9aei>aG(4!{udw|Dqh0}BDPBve4%m@n@lRijIVw!1 zVOXUZyY?Q+gmia^Bw@(#VO8r$-g3Cq0nVLg5{SLV?G|rS@M-2OdL4*r4w2b#H7J7{ z1SeW8HJbRov+#n7_4hCN?a!n~Pc}UBEo(Ir&r~1y;t1<`{}c% z-+8KtdiKF-8Kfksk+ZnXyC<$^=S!}clR(J>+x>lobs`ox{*)oULUj~~H2yP{zINp0 z0i(Vy*@PYCGB$20fT8_B74yj9RS=K#l93Pd^+8;Ua@Uy1ZcPb4V4j3}gUJnd^h&qU z)?k``Kd19ZR!mv^6&2NBKQ}3Q>v2-IL)6pkeuJjQyTp4Lf&kT);N><^kKbims;{;) zcoEF+buy1~%r5#KNfMvh1^Z~8=lH@+UzsMro6tgxL_@7G$*E0Qm9qqbX>nRkXqg6k z;66+*ne4%1qV*-?Sj>(zSd`;zE~3>!{X#=-{_`3#iki!Q^_SslS77rXJWaryh3{6h zmdCt;YRrNo-Ll5>Zu`v+<>4!bwEahG?!M{pw6vWGl&ls%)xxwQz zZoQ&9aIvaJQ#FEU&4MwPwL4#b)J!QCv})W=DwktDHwQxGJo_N2(8AQ**X%Fb!6KF_ zyQPm?j~kbIA_+VP&1(F-F6v6fcc083J@3-)V;5T8o0z!CnuR}V;n38I!VxeAKdf|! zvGFFVKJyXHic#il`+5VBwblrtaj07s7p3EG8#V0R(*1-r-2tf&r+ac>qd$?Ta9pDr z3ly$DtUK!{ms~dY_!5t3fe0FDgQ;qD@kDgivdfp~iYYDdbVEwl`F!RzH3*wbZ$ye; zPP?Aq8C2-GG-`I5Deu_m37(96YD0206C=sx6WIJfe=WN2A{IY%g#-$1v)(<9zCx0s zMZq+soh;$$-@RnBQbxO!BWMwXlJ4AL9*`4fwWL~a(5DPqWH9>&4VR@WLrN*Ues>Og8@)gJw0L}_+ybvEvK;P0-U=< z%j_!pA@7b$K8W_K!>S91a14L(h6!J_#`~4=Fv@*y9l@r|W2bv`6O*a0JC~+eqk3!i z{6tl1htFUm$raKb*GQqPL6vphhy};v4P%_}v+2ic;zzB`IE2n3d=9AE=CG%J@W;pP zw);f4>y5a|)0CDIt-H8K#i6ff0`B*hfUF6mu|ppgLb}swaZX;jlcDriU9BHxz=Uow zGTBT$G!OdOOOAkKO9Zq(qNdBqSZt)O!pq^9?rwf$a{wZ*ZLT1i<`s% zpDMwU2zbSNbtmVdM!tr1uY9Jr%Lrn}K_` z9L1Xa<<1+$zt){Wv?t<`(hzFV6_o`&ev}8mRsiz&ib6@%|B^NI`dd7cS;20L9!bb&{pPRW3XU`qZ#IZ zk3HsGVT+*|7BfZymEc?F4TULtr>8&eP^aZzi(D%@_*J2Q_`zvPddTGIaO8O>u!ITK z1O8m@d1IA}6*6uAEgx>;?nL2R?FmX-H7c!Znf1Fe9Hr@g*ued7)~bT)2)P>2Ffoz3 z7k1>l6*nVG=y1wsPV6Wi5N?VtZ^yS?nipo);@OFkPm~XXS2M&MSg>tG=~ zB}jkyh~s(Id5`_=ngew2o;sX$Fo}O%r;Eqhe!9|XnSjsQ!2;>mHhu=~x6BM=bBXMP z?V6A~8ebjH5dX65=ifxhqu#zS`s460Ecn3#b})Cb;)wBw%P`_=-igIGtjjIDK+~@0 z;y%;>^N%w>9LFF4oBeo0jcdet#)rUGiWb&HlGN774M4z$GI@pGhnzX5MNpXG=0@Jc zR9P*iumeU5>&?pQ<(f&4S<=nQ+Hou;(z&2qXBQ)=HuP-{;Y6V`s~fEWYrsimQ_csl z*c!dV#5*jQHyERirdM=Fsc#a-uJ`RcM`DHNdj+%x_3y6Ni46#0#C}*+buDKl^Xs`= zR9rN99>7+*SnPOk3@)T@wej2>TF54kl?f;R{`KKWR@s7Cg(nT`UY0xh>2 ziwznh3UE<@k7rAV@o)EEqBS!XO&3QsJsxuezkfPbQSoT$Va@-bn&Q?fmT8DfSxJWO z7S$ZjPT|B?VSP~0f^^e|s>r5_vSw5sm`mC)cYb>RLHr5=jRdj0(sn8}?1LMBq8Vuq zVFb96&(^kOnZPz4%!RqMYLHWh&#KlHc_Gnl}i*M0S+ zxrMfNkq93re2y%wK^*FSI=^`CmxdH9HEf5L{rvw9D9wfb0iRtvXlscB%@>h^oN7jD8L=<+255G zSB()YeY=-jCp(7$D_3O5xAQwz*v@kRZ#WWP=z+5WU--g9N)JAiPG+CK_dA)$5{ai0 z?<0KUFMksf67l-MnF0p#1=8Fz`z%teBgy`f!}qU%lovb(G>8;-5tOh@rB@(A@mMbq zodP{q{(rH-(o2beopmBU|1iury6{w8yPD-luu>eVzJTKXdE}L2Kt@Bi;6u2;-?Fa$ zd-U?FskVBK9q|({s&yKI`c@{rU-b748vii) z0WB#OmT7%m%S?J-+ExOoTEeOVsp$%SkdTs~8-w{RWz4H0!)w5=9Jx8to(LL_)f0O0 z+V}+hxBdPD&l>N=p8-#3BoeB(dd4XRr8xb6HOd>lFzV<;f(WN${`&bzgxl{)d9O^g zlU-il%dgpFYXUE}YES8shGBPpfR^J*4>Ye2+HUGL^B|37PPvCsvzS&z5f>%(X?C_;vs?DVOXMJF?uqfK~mmH75R+;+SuYuRHcg+wdipijMTka*P$7XGNE*^2bgcF?1tOeQVgH|KXIxKz| znp~s&{8$j|X`WUxp|{0)p*f0i_iG%XClda<3(3YY&=d=HJShK{5X6V@UZuJ ze>y%}XPgBMR*pNax+C-%wLlT8$DTJaUf=ZB&)A2muW$n=X+=;!_8=FOzm!|U&;)MN zsC_Q?Lj9HD(2P9^zK&p0tFn7PGXXuM4KClzdkPrRxfmV3A4{_m9B0C-eWfsJQa~8n zE+baUBF95RCY^g6W+7z`!9MccYAjpV10Syv5j%dnv1zK$bZ1Z1$GdPQEb!Xy3{_m5 zKC9=!Sy|l z!c`i^javYGuVON{N4Y5fTV~|HXK&1t4dL#niyp)+u-|&VB9K;jdXN>ZOJ6@?qd!z@ z-9mUT?{>f4rep_NYf=_9 zU|TgQh?<&jQ*wZPnPIL?rp*xM`}KO_*9noiLi);y>`*io=;Y5fPtpu@RD3?&0>)ez z0Gim-2BlK=gFsqeoh-fmK}`5{zF)odQ9%bhrYD2j-LuW>s+*dpx&@=aXA4|cA?W#K zKAx+2zEgY1)lz!Y7cy_di(@sk7b!l*!ZF)wxX5-L_Q6= z(*6eD6Ad5fx2vW}xV~F3nx9%WLMZR{0e(Bx?IY~3=1P7VJXBXQIZsxb^Cr)d$6z)X z{vDfs{%xfaBs6eI3xnnNoiKc#>un%ZNAeksu)oXaNePs#DWju7V@{^YD3JSi2 zWfU54BANN8wWBzjImlsT!3Or`Sze}W;c}i0F4UW2IDV(Q=|AU&ycF7?H)U1+6%dy0 z&Kkbz6}@i}y%{(OeTCI;_bO3DVY`zI)({!JfGVGn1uVqd_6X-5do_X;p-7S)l< zxHcNu@wERk?I2=gv}j{w|3x_3|NGS+-5uy+a3-=#1D)8djtdpLL!2L|Nl3ppSEu`| zj?JV8WFE}%SU>>VG?E;s_nBHR>?cMKORYfI5$L$+xXuuzsglCx%ZJ_M{Gov0EymWN zV0?T;W4@l5{@TtWEo|LMcaH`>cfFPJStm1KB`tslnZ?RzH7;eX#$eV0@H)X8^$KD+e9_myMaJg~ zeP?g~$(3JGd;m;8=>jL``nb)U6>c<~9s*zxy^!F(+pRzQ-K&0jgl!Mpax9>QG9Iq4 z97QTkIJ@P1p!c(X)-(w$A1N#@a&~i$Y|6)Rd%AF+|49t|PXODi2NQ>L(@r2JOW-nH z;?l`J;w7Bi+HE}2FP;23Ho(JwZ* zPgj2d-k-j*rv3<~4-dUw@b0li{7tj})f5&GcaXGdOBR2HDm=G4sqbHZ`Q<4l{rEY2 zGI_*-H!G$;Ou@0c1l(`H_8-+RqOpLc7VC@N?G1iBp63BDCaTSWD8FpsU(h+8^dHFC zJzvn@{H;LKUpjdzuKh!mkZX|C$anotp149VartEy>wlfJ|F#__@N@W~R?#&23jtGy zNwbynjxZRL(x!mB-#yG71``&rP&E5oU*@?Y<>g(%m{24GuUZsore?G)Q z>c$?>_dViggEH@zkK;y}A!})Q&vKdE?~0L0eL?hEBG!v3mZ{!i@ppB7jNSsQHRql5+zXajI*xn=QUj3{*nYZV9UzNe+% zy+gC`mQGVYWg9;#XP~7l#-LlFOQO`LlUcYvONNHVTEu_wBE;&asubxDQO_b9M0!pO zvz~x}r+c=brZbhbanY5VJ2kmeUM;!DKXK-u4&eqmOl@=sD1Jt~CKKj`THb}{~ zFcZB+SOjX9ld2?e4oSLPP5H(4AJ_|xR1$1;YYo4#4vC(=xX}OJx-DJ05j$9Pu%b{I zc0yCs3oVW@iuSx?OJYvbz4jf*05fMZA+~BEI5p(s!$wuv3u8t9y;H6ds=t$&dU}Af zmtHE$Bn4CB(%Fbe*)05L5x@eQAsfnmZ-HCi1@;O$q|e>{JtYsm-!T>Mp5MOB5wC{} z97OC-uFOX%su`j_VR%ES!>9iKJwHSKMSQOG9a~h1V?WO@YvAF)*eAuhIAFMct$-W` z99VsPK=xGZYL0VmBsoTo903L@(XaVVCaYPNT>2~-aZZ!J>6@UPs=H+@2m)Y0%8rCH z`peSx*RMdtp#_*vB{BTB+GKBlg;a8Ik&UCOxqNVP4%D>^U0L5yI`Uwy)HM!NCQon`hFLxXbpG0bQ6wo?7LaDK0P$IUdERa;e8 z&ei-?`I~gn7w^Pp-rSPl`bMS}W#*q(K;^EUkG)4Sxs2@jx1s^5$Ptai}X@ zN(u`z$dD8;bJtfE03M4}}?ogBUOT2`lu)Blg>H{OEzGh-#WfD^*bKA^atD%jl>vDpWNviwnO7U4Z-f(*q1jebghzx&om^zT`AZTQVW1|8#gU-AK5iQkBB zSw+HpLVwt-Yl|DBEse;S7-5$Ju?7F$&ANE;91FOC;kXm&SaK&RPf`Om*L_My`-@5b zzh5WOsp!L#eaDRS#Iv$6gR&;WUfQ33JR-iFUkAF;`Dnpp13?>b7(q)q?b!~8-( zu3I)mt0c4oG6EeBq?lK~xo~v&`3dw1$G2I|V?}$!b|wU{pht>@`$@vz48H>6PzOvu zO`HsgVg|I?1a4(e8pb;2He;- zgn?zL;&n+cS9bZz7v9)#S-|s~OZr~*J$Y(mbm4%$7k|z5{BM2#_snjQ{Gm+J@-Q(C zUC)l61wsu_eCE9N>nQjC{DN=7{(N$>t;yZKlsX$>uSw4jLP5W9VE(;^Y+JyvlndI% z0*9*wZ-%Wr8M8jClL_UeSR|*KDMQ-!0qoVnSo92wM`Dt)K4HaTk!6u98Hlr{ABs${ zugyMI#$?GZ1&!aaOZREZI3{{PuH>vj{i&Q8Ybd-O5 z!x%MEzS&b_mgA2a+}fnUbp+M?+)j&lPup>JkwBzwpSQwNHDx!>n^y$Vj6?mE=X-_+ zJ=)6QD~V?K%0juyZB$v% z8=VxC>aV!p<4Q>EX6L5u4M~b6A`S!G3kC5A3Z<%D;38=!sM=OtuEn2x+E>O%ULU;p zIRP}@5hw03!Cc)90m7i+{DVRnnzXosNavSLTcy-lc%qrsx6FcyV+wBXm{@5#XD@wd zBglSX4=zDJe#oYI2x@v3)KDb$S5PBm7nQa$KvOpE-iQV?juryf)*n@A!+VsZ6e!sB zkh2RjDHLyfklr05k+SRg z$LyHup(0iM6B9s#oD(RXU_%fYXJ>+@c}3Us>OKok9GG zVg+uZutf(lwH|ig%3{-mvxY)lt0_s8*p*}OVF`V>#KVfdF*o(j{Was3qzf@+!n*y+ zSllW5OQdX5(9=YWsF>xPG$UdGjoh}$A~Lt**Q6p5JTH(NEOb>~mwqP?QM*Te z^KoVB-Ga1IZGoWet(9@(p5futCn>E)sa&ib$ZOyVz=0~9mrDxjMp{DMNI|(lvOFs3 zq#E5W>hlTODI>Ep0{YC)#fhf7+F6u`-qpanU+iw%%rLNq%UK-JI<`<+5*6Kz9trcsedvAYuF<7;3j`QOhyuLlzCxN?^N!`WMhMYXo= z!&?LqP(Ue>8j$XkhB1JlyGx`&KspB;6_M^vVd#=>P*7rqkZzC|nxVUXi@l%yKF@xi z?YH0K`$L2S)>`-6d0yvvUf1#liGxbrJLHS~RljewzB45vhSV`^tPw*FjYW=c z$sb0z=r zbNqognIT`MSgWP;HVjNG^Nl$vh(UVO*_aP0F6nGi@*?b4<0y_Xg3+Z*oJ|VhZ2S(u zR{G62U@Pcl3rcBa{y)MzX7&iVU^-iKxbHIc?OsD2&sRYhvdNxT;nXpbmxJ*d#Ig@_ zMz3Ga^@|Ss*CCLQ1Z+z21#hjEN@M}Bh<5Nj^CoYae@HH}`D$U`pzWXUU=i#+gEOcw_$t9bNK~a~lZ2%v8p??O4~=~T7Kgz)Gdp!j z89GMuXY1ts=s(e5sfinu{9T~?Z+vyV?g-gUmg7onkF4U$p23Dfr0yP{_clNl7HVl@L&bfaY_-UmVNu-b?3WkAo z2@-vf;dU<{oN9FQbDrcsjKK;v#-=`qgjA*-mqo}S6Ki0Q%Parqi);Q}F&gIUk^e*b z7uz~GL-6*Um1gNrQmU)kY*_;XooQqy=`N!i)R0Xb8taskQ`-qR&%u*O7;rDvn}1t7 z`;ReQA;qx3X&5SCJ}6XUxr2A1SPfo_Q_4uYj)jR{<9?g52i^?%tC{Z=_{V%rk&4=z zA5ib3}d3Rvy6E{cD;0H7+@g1?!VSJ{?4+72fai zH-Qb6WhoiSE(6e74nsw8ptb&VZ!oMsb*gjz;!}dS)iHob6wP%gQcfyUdZn@9EM9 zN^aDs(f(MO#NorJpmOKWc~xDWwnciN%a_uA!-dybD&P=W@xn+R$(!|e7TA#Vi24Na zJmu^~sOnaF$j<47-zYG5h%cj!cMH4|=1@9Pc$>#M*y)3Idw+Ep*MV!^k_j^JLx<;2 zqR7u&&b$Kz5ifoaG)>LgJ#Rm2xU#Fa0GsL#e7?iZ{N@%qu#i|if}oX@FPD%NrC02^0< ziDc#3BhPjE<*QHo!5FLWEDf1k&Mva1C+9?Ne1DPWeHNbNE^vbwVmJ-epvK^1Qc-w_ z9}btK4i1d?q)P5aL=~&HwovqdfKjkAWa_M`WTS_OcPaKsb%+a{RN+hF=V)w)-7-0s zVzn(bmbVxz*i5&BYe$ZxA~KJZOn!Jn<$_;gbb55(q`}m?rz6bz?on2(Cmz6En&L|0 z%P}b)_&S@C_1Icjn}-myMHIENcI#(4sud!fid%5HD==7M53IkA@>pmliWIYdoO*>} z*Cms?_#*D4QghT|0X;eqD?gU+AIbW0EzHPM;~U%gMJ9NF3u?S0Sh{7z5QU%PM5J)R zdQwS&u?P7LYe1|uhxs;tBzO~CmwMxv*fGbeWi-z2$tqky6Q;pY5h6HDV4*0=YPukw z)s@ERhI~3I%T$&rTgY;1^J!g_4Au66GcU?A`Zj1maqaHffC~njv`dsI)jRm*XOf*N zry@0p^-H99N zGf`mc?)I#7w7wlUGam?>NA78dH)Vj;zN^#`E7TRqb8Y~b4AJ>~XZHuiC!MwI6vEra z?86?u-0BLy72l3~zcX6-4YVaS7v(YcO_d>hp6%w{Bl+pEz)YvtBs1rFE#(*H6#Po$ z5{(0=ZKtb0kqJv9!=Ey8P+H{X5%)1+)W9;y4-kpY0l#3xw82KqiRwIW@hbM+i2Npt zB-q36Gi)?SXt0QT-vy0)5N7zwOtLG}l``>mJC>stSsxWtHAUlgjA_}tTJ;rMmlx}A zx5S52`5B-6M&1Xey^W!ZQD|0s{8NDHS)QM2kCVw#k{(s|mWtqI|2C+&y=L!$dPr%x zEB$B5+hZr3f)1#qrXtFTlcKLXfk_M-t(EfTuf&Y}Gel@|Owk_fhMo?2>}Q@LWPj$Ei^#zN;LRHKO>q@%HBK&)*_tU&)U&qhr_%8AH_-50(s z!YBO?OsM_uSf6)pgDw;wVM?jN&~;(K4D* zdEQ^p(lP5epmc|9wOes%mzgoaAnjq_bcQT-zamLHQA4l8I!s-~fnzrDZ9}_^$tfWV z^>dCj!r=~7+dT{@7zAZJcoJ<*hY2FQ|8XX9&j05H@VecGiFSqg_gxH>4l%})(yBH{ zrMUdy`&g!L=nQ7(EJ89*{LhH;Bq;-kmnD2-xY8oP=5IlhS0+I-q5)5~4p=yXa6k(@ z1U`g$j|f94oVMCtp3ikqN<0#^AXnljc(#Chb0 zN=b=i5oB7PC*FI7n$qPNH|oy*zV*(@ho-BUd@>$&Ty)d3n&|2i-Ip$>#9U=drM1@0 z#uwSeT`6fN(D}&%^Wh$7d-nV~<_#3pVO5X1dA?GwPks)~yGrQ~sgkjQ56OcTdr>KH z#rc@sja`@3Ak+ITjY$rLJUMwj^eQ8?&83JbpgJ;eKDaD04VSM3%!jAv?KEuv9HYmI znwJG)1ntq@S%4;&vg1!>?_vw*mpy3joaMJ}{E|*iUq|s|&&gQ47PsEE-%LG8W`&^7 zkTEeU4i#fQGax(2sbrif;Hr$=x!k?gM=Vc>>6HX*@o8wIhuE-uoFV*}Nl(F%Z~bBy z;dP{%opHsUIa>$Z;XkR2G0z-BmzIg8my&|l!yd!JX)KVQ&%cDD4Dx9B>fX#qwq_ii z)z0dF3^{7R{Be1B8*Z99WW4lpi7nF+vhzgY{t^?F;sCFt;_T_OiE{Sd(@3ybnk%MU zog;0X2dib^Zbx|AK~e=BOSm*?+fF)qTA+EFM2#9M@epnv?>TlNTKM3HyVAkY6P7FU z51i@n=7*Fcxe%3RWWlCIH;wvc9@mKlM2@}6Tb;_sdr*M)(Ofx z=ZdI)W<`OSs6}_v9_;WWhw9?$S8St7Cz?YtD1J2y(mBed5OB|ZH~ZE4degcX!$D$* z971tKNyZb7poMOaT!>er1MB6*v%mw`Qbpgx98{dekJofAPFtO2ZZbp1J^T)&1~Hi9 zL4ck##h0J^P|6g*0f#`Beq6ZWAOuE{(*VZj@hB&n<+U+J;}2XR(Y}vV$d~ng^QGMITwJQ*H8H~Hb6VeX8lCDlW>)r* zco@Ty8=}ja(5P0$IGa?R2@V4G_gvl&+*Muse)Kfeh~dgllxDlHIb5CQ!Z@dB+I%*A zUL%+DmWWurcwL8!3J(sjl5A(be8skr#wNF9LGmipB%7I26*fUQdI+N&HCNWoYDSbM9f>PEJN-%f{soQm~&R#=dbh z6W?}N+cu~mxR~<<#-aZ=xdlrFhODoN?L6yNw~RUHQSV)UoXcZr-g@+ea77h>NM4nu z)})vd3@UsoCG1Zko1ZCO?trFqaAq1zsGLx66IbKMA5Mthd0h2AHpS4+8Ob%UHN-xX zFp7{Vq`C2=@>0U?Yn8*7FBuN?^$rw4AxCzjgWHE+Wz5b0^a9|Rb=X= z@Y2u}HQ(3!Zgo5r(G6cCRmtxF=ThT2r78V_fNO{s%lQRiTELOKqQue+9-7CG%jSmH z71jaoCCFX_TdaaH;!rAbPQ%G!k#VgibM~U5B4-PFDR1sU@1Z4qwq&u$l2Y3HSR~=B zq|=F3Qo!z@&%Ft~^|c(o9~#Ax{6*=W)gVTGrBJyyDE4|-Cj4Chfei~;jb+@!X#6Gb z?J9}i-l;<)Q?P3^=T}8jC!F&oiwChL4kHgG-}hjKmMXvIXbfz1?vdP` z#C|`bOv8v$)SB_I|IK`Y8}7=2=%<*9-<-(A8WYQkx7DzKQt`Ji8-8E~Mu`L%rB}-6 zro+kd_4iN4p)>xmC3ddG_v>Ic0!AIU?FJ92PNyH;Euz)bQ^Dv53m3_5N#xkZS%`6^vdYAXGfDiBu(2yKJ?j0Jp%6xGUI#i3~)iB7A=e;L{ykDlaznMirUN~yX=rmVvu&HK8usf zt*X}woci+SSs~281H$;B+k5fUP) zJFgV0U{Tkge6Hg41O}hZl7lZO3z>fqABF{3Ap`dB6bg)XX|NgYp>_<&6fX%^7_TRW zLzUY7s`|&vP;p`5bvhML&qG@B{~h^%d3yg}kM(~=VGe}fe2jn>DQqCCg4=1XH=WvB z3dV2xmeB;8I+KHDprX)lSzUB+Ojpm)wfW`ZZJ0C=hnY2G$42E1SJkZz-6RlWZsU|0-4ob1bQI;Z1J2;l<1wUGP5ZbGI1o> z_kuaXA}GxTh)-Jxf%|*c|8f7QXhR3jTwOQxNw}fNuRhQp&*KmI0=7{dO1r|gXrT`c z#>h7jmvaTqi}rih?S=oVy(+{IXQ?=!zh^eQVAoOW%xT`|=fFUa)u%lM`fg7O7+;2I zIoYAL34;S7Ab6vbZ~prjvwU;~d=L?cwfcwDTT;Io8E@KrJ-bNwV zmBwYr*)Vf*w7W4&#n5-Td9Qr$mjE(H#K2Lh?CqomAL~GYZIlVl^d~^55KQ5eqeRDSks z8S!aWe15P}B(d6{8WCdq_Z>RO$el4F)thO>C=>TN`LXkTpdX>q8D&5}2AKDm8^`8e zZJ?wh=hw)o-MPd?*NWSc9|yA|D>psTaLdEpPDGQL>Ug#9;^1A20ZI03%Q^OC602Hk zi`FRr%qtJ&VC3;;a~QVPxvkE3#7UapX?fsTH=7YdxnD~Q_2JxH@ubbcpe8 zdI)bXlY+7ZDBha%`0r<&g>r^C9{kIErw%QaFEONI3)2Z8QoNGiB#Sxdv87)vT3%pY z^=5@fU$}EdKU=4ce`ZS)eQ|WD;+F2(T*ivKUQ8-BL0zRWan`er`q|dPBZseN2X%y=9b1c)!zT z+f-1^1z-H~J>~HU*W!u1q$Tpwp>)qq znFOMjo_p11oV0F}O>$XPpR;3u@UAytG#-1@*LYs4NR@u|&9arXeK~-D!j=xT(@G|t zY1`}W_AP1?rm!Yfr>siIl?y?jJoo$ND9WnD8ld!p{0zPn6NCbydBvqs*n@$&CDBuHbTNFR%XhB@d}@ZkFG z=CYYjl3nUPwjZPRr%2OJkIkJq$B*7pFZDG8ZuznYd(!J=Y%|%9lTLV?C0u z4rUj-^tYlyDGI0b43k;55?_xW_A4j2ozHPyNk6umP_=$n?z5Xlb5d>7)Yj~HQF!Na zTicH<+4m%QrM`W7cX|Nh)q1D-@H$@%@-ubHo{!8g?Y9|xfR&UZ2;llYv-2)<7Ja{m z2k*7s>jVyz6-5js*iga4_+w5$%SeI+%GgK+4jX}m=iD_MoUAg|47K@pvG_f z2s(A50UF*(yBFUj+v3oVcIGPLA7ytwA}i(IoRW0ZM%Awy#~yVp8|N9g-)QJ-{<8S# zysf1U=zhxHzhAo(k5sC_HYRp46>?8uL)2E+PK^us3~O9?)2PvMELA{_eX?pto@+1c zs_E&W&w=gkxj#+3Aybn~8Wc5q;#1WVpe6YbwMl#@RRh%Z^;!A4-PSIuz`PqqbMbuf z$EUoF6iZgDff?K8)xA`o(?kPO35BC$#|tqsT)6dK8f|>j=&aeqPPhD(vlI?o?vdRB zpWi`ErZ;=GUx{Bjbl7%KKJv=n?>Mt-d0d-@+~55vXV#sa|BVLzI6S+9z}|rSV7`;` zCLTQ86voeXN)O}|p1ysf&d#4*#^tk3L{%H>NNr3tN$%q(2E z?sghZJh0NCv*?xu`v3$b)dHEsm1NfIWk2p^~vW{xsy$+-HGQB#+J*C3J+fSUWG4KwBCCl*DYxe8-$qT{}ElwWEZhP9KL z8<+Sbo19zII`OzOY83V5og`6(!SvU6nFylMnG-b-c}aA%(@)E*!c547=TP$Ek4J?S zE4dmVVWml3s&&?f(IKlp0ueeT5?U5_4Y z(L-6A(-7+yUQU-7aNYYWOoo_~}+hc`nJu(IDxaSet!zXap_BnLG${&mH&jYk;oQ z=EzU?XmCQYg#O<4w8DJNvBx|?uds)xwcz<}c5Lw>7!R_*YgT>{*Z#$Km?=-QSrjMz zu5KFDIsLq(sWB`j`)~!U>%*4joX0&g4n|vhM$A}Ig$A{`VdG?7hRk6`Fqf{}D7KM? ztwT{La1`unj|*|W?$a*8oiB0vS|QRK=WaNs?ikr6JAP6xm~^<&VBM{gzbUrlv3@o4 z+_0KgA8SAXRbKtn;IAUYpC~ke1UB$HF)B~LoDL`o)>`MXfKPk>1}ujqV(8&=VtmU0 zGp1YfjvZY9e$_BuLtjg0j__%%&pCiHMki;@=dF^-^kDn|B5LOJZgG8<-D{(mbua}z z#EP|j_}XJH+IPHqx%c?>fC|NiYoJ8Vx zAAs#pFtFFqOEp{W%av|>Tt+E(E#hf@|FSsKl!;8NlT2R%Rwe$$#i6^SA@1x~zl&@K(_RegBTurV_4;pysrT)U$SqIA4rg9FoA)srPS{_gzQHRr zmrr8~hV@mGWQ@3Ry#c<%xL&^Pbk+EF+Fi2ZpL0~Ai>ts?Qq8!=5{i>)SNm6aL*jQ5 zim{@WP?P7G@p27L~|~86fxbj|7!fK%Axa;X3AkI4OzPEwAL-R#L zpU7+_bhfyr3zmM>DiwJR*7>-uY-yA^A`gxHqR02F`m|dZMZ>+K>vEP$($%pBz8Xs| zmTm%2CcP%Dvi>o}OvT(hs}->+Ao*#BQJorQ^1Iv%Hf17)@I@lw4*|n8OoD!UOx+tL zFM0OPz-d<9X$LC0IPdM=Ddper`UGF~sDH~r5dG-r6`3npo_@7quW@xx?H+oDv3Q<3rs zJ<_v#!?osB)ZlQaUDV(Z)IGX!wl;M4a?3vE2x^(ts6E{?a(BA&$xy0SmTT@*t&vil zNmFC)Yd^mWFV!QogQUq+*Qhw{+O1*eI*#XP4YeQ|?jXUrHsiS|vM{p~>Y9oEW?LjW zm(=lmda}iSda}eeyjeCOy=&S{VNDsJ&E- zb!{fYeqUAC&83Rc`@}{#=e3OS;l~umHW5#c1++wrO45I(Q^3#+05KMl9a+V#maS@K z?XuXh7bjy=4Bt7GfmO2B%KdD5qV+XkNRLw7DJs zK3`h7QUsA{VrG#4x6PAX?Zux6O$i?(V#w@q92Zw{_-VTLk+-?iXi47P8RwsGHpDK! z$(=$?7bJqxD9>vGLU}pjuLikJlrwj#iqT#LV3Fa(9lVDX#fc+yv#xtMSJs40I<7M_vU^4c$PswGqeebCm04XU^m_&c zgTJl#qpO)MYx$-5cWVAE{f&|iw~)0qcXvTdJ1bcPt2S{4 znRtzpb1vF}WvGl~INIb^ij|RuRr&-Nn8nCUqFSGN!sX~o!Ftt-oGPgP>5)|TBQ4=R z=5P&|26H%C1JzHuP=Lr{l1KI16^Ko|B8C(Q@glPHQ+KV@^Tq13Rj5Prck?tT$x;11 z6d}7-D@%7X(Hff6z{CleUujo!+^5bJs-IyE(}1~@i6n0x=j}O`aIJ#f5bGF?kefXS*(5FB-6>Ks&h#4uJh>TnBuw`i*W~3)^pB7 zVVyF(i`Sffm8?M2yJ70_GPWk^YWNJPKVxMHhw$LCF0X|3)9L(Yql7>_zgc3lht==q z`y5E&IrYB=NL5V%BSo>|#&vRTe%qAe0v-i<0=)o5%Onhd)>wwg%DVw05{z5`9T3R5 zm7}FlUpfAD_I!kYYrA?=di7IKc$Z~bXi^b^!L-SFxt!TR9Eexx0&V~xWIMj4{6Ki! zNB^pVi`!T8T;Zg~uVv$6=^*p$uJ}=N_HOI)WiF*r%cm%X_~Xf=RQ(XCI1`tpx(|uy zXt>{mmR+)lIpGDB#4GmtG|^23;p4(93d1O^(Vzsrd2xNt?=wouEysPK_gORxzK4Ep zb~{rkE{Pdz-kEeBKmNRm$W|VMN58}{^`O7l(NTch2}Qi#1UF0c2JPVN1k>7(KZDIy zwftMn^`L9Dc)_SMMPQWmjg>^RUqIW)gB?+#5cJ+rh%E40(FGv$BSDUdtY~8+>Zgfz zkrpDGmtzEJQSw9Nc=T0Iy%72!T?RF47%^Mq5N?+qD4!1aV#h}cSr);g&w5@S1g}6_ z^}qazqq)JAVgK4kAWkaN(`ET{@u957)U*dK@y)x+;Nnm(!*!M+(jbDm%8s zCmArzkSO|xeXruncDg$ROVCRfk<98^N@L+p`{E1j+;sPw-@VN4(bzI-YSy?FfZ&N> zn`s187p~j`A60{r9tJXt-2=~w`T)CoWv+)?8u@Yh=Bu_nvK_ZI>MSdi%y=krQ@`k< zOi{HcY}?Htm{1SHk2oI}Ied#mWqnsW&NbhX@i!Ipyjn8#9sT@Nq>u}CiAul`Y!v_= zB!O&J!h|klzHsaubt5l>SB#X;d*1$!F71NBkn~!1O;^7qu9S^EVq@3UZB@h;TFF=~!AlA$3`VWX;n7$4Oq+*y^7tS0_Z$1d>u}-Ee-<8b!cmko9PfLAf{GDJmAu{@Tp4Wv?SOW5gUyc zObpT6+IYal&L+l%eASg3(mo!7vskBHj%QZtWG8Z?0+CDUu9yp%cf0qWx;a_dR#pKi z;PVNb-s+^*%qKqSx$o{~En4#}Rez#HkOboOOla?=U|CcnD2U5w<38^k8B1N|h=$i| zAI%7dgq(2tu$-qE1c0q&txaj`kWpC)0kCzzw5#u?^{b#)5miyT^>Z92hF(c8mV0Y^ z>O0cE&UT4yWJ>K;S3<7N?suQfg5R}pK1VM>^7*i4W+hfk)@af3%Tjtls#aa+N!TZJn3Ib@(r`KK~c?m|_Nx;@P&I3}MDNh|oOX@)Hu0P_6hbmEe{i5~^K1H^n-ijz)H`}~gCGw^nQ0b0$^??5K9(i}M{?O%(2KgYUDFEiVX#Q-$ZPdzhW0zR zt^AHJ-S;|8S~OAJ@%It$PA--fWlZ0D67#}$9%Z|p`UDPoc;X^)2G;qyktKRsA9n87 z3A&b43N%Y9_&zG!P=n8?@r5l+_R4nP+))^vXAYf>#-%5*;R*@!e7yjdw1@gMCALzO zE0{W@>?RTU#ESxs%?$VJahh)49FE&GuAV~s?QdN^#V_`5)J_)m+uU7vU)gCk6%odz zuurcPBgOlo7noOUyLmLhF$-kcDeVH1gaR$EFQ5kvG`LSLpg!?8I&fhK%qL$;@7F!K z;p(J5nWoTSVBo&rgZy?ds+Xc*4V=FXD+8`OyRLU9Z?1~^&oeh*tJS$o`)mMyzzD$B zRZlRWCwz$zXzy_&fVXp+kacPknTzF7=Mt_6W5l|D)!;~3GrSiH-FTmy{9AYjQ)g(67-zNW z%MWMoRxg%NbrE|IG}2Qk9h-@YE~Bx~N53nPYiwUXVx;r)UM{cdqi5sGkf_Ij>WB*D z;Am$W{SLD5r21iYG(vxWiff&4R@>Y@#Wf8)1MI^>YHV3U^UMcFaEz`gt5x|&guc!T z{_ox~d|wP~mu(GBZfXoPV7hfu2Lha0VC8GaSM>BmMW{%ld7;=|`qhXY4RqgBe6rWm zP6zPcP@a#B<}!wn2W$A%YVCGiOX~|M+~%$!^Bp`%>FN&>={ZY8CwzR)x%GP=VZ_pi z^%G<<+dLC1M&(qCC%VO z$S$@bg=An;fAQIxJzISFU{iR?p!r5-_Qn)7q~;ax87MUeIZn<7cRK=4fO4mFSfl2% zH%5>EXf~Pp>8kv(-i1YU`ii*)dq6~Z?%^T0e16z~+=2Ge;4OHRDB&`JmfBh4w*($F zVJ;%po0aTWQa;B|6c~u^-fn;4D;A44SX;avV{6J;B#uX)dhAa0RRATzpj~Zr(vKfk zx;QtPjbOlXQbVWD^Sc>g%UFlKY5|08X*2chVn6wj zTc5dtem>D<+UB@*cTUl&f?zi}IE_IWScN>8DjTFf%5RM>zVO6@Z#qS)QrpGjrS7hz zZSF>TPmJAM?Jagvn(J*g4bEdDkx@nj5Pk1YtjV9Zs&MrD-p?p3u0h$eKn>X{0_r}$ zw{`Lctx7;_QN_?YY&Dj6*8wfAQfICOS64bp4Dl!6S+f2P7WFE*Ep0*N=)m<^$zj{r zv)YFYw{g<(zF(&>G74uo4J?Br6w#^1M5KV!9eo{LhXX+)MYS0%$#L&M!_YJDpEMOPPA^xh}{H)Mic`Gf5HOLYd z!?Su=Vp~h(iSNJc2G*$twOM#a9ozr`gLLz&a>_i(6SGK9Hs7#;F4&S_MXAHv)7s1d8$1UM9_TS7E`8gSNFj<4)8hxH465AilgbSqkDZVj2o^0e|e zAJ%^zsV<*^HQG*VBV(^uDZ@nFD3+&Ck5fi!ozwQy*!QwB4;5J@F+ocvx}N2Yx1NO( zEs!50U(ecfx-7SA2SS|3Jm`{QC$!;YBgSfqXfRoCHt4CQp|njKPHYgI;uy`o8VgFp0fWlf>2UF1ssrI^+kw-DS;~}n7`SeuI@7gX4dZW^;_Y>eNHZ|laIn3yy~=XZEoxM`gYI1 z^fx7Qa8(Tnb!Ar%vCZ638u0Vth;xjui_QKT*{>$7t7BNZ<5mR9%QuZMJU^q2Ti`8C z^64I9PuL1+w_#oWw5xUTWGWBe!$J|X8BEufzu2u`eUgnGyd1k#nACi9!WBCg`D2YU z=F|2RYTcJvi?Bx|_y-u*o|nG}-!JyMf0_A*Ta zl=$@{AC9ZwQ_yyhL=e$AvzwlZrJCODT5`%2JX)MB2v^iK7i$H`(+{V`HI$y?OCH2* zP*B7-&DKA`FFMwaYzvqhkiGUQbPGM;w|&je?Y0vov?|mV!Uh-?>YSpu1yANU-nVkK z8bmJTq3X+2PTPK5dhmN5!+c`KUfJuN>`=*kU1kEYFEj2H#8bo)32M1{V=PV(bt)X2 zRzJH#?QK))vuf!VA&;&=Jjw#=HD}qt_Muhaa`apC>w|ge?n`2saq)-|q_;iu)WNz` ze5v=*fpTXwzSE)7|RA;o{gD zQY{E@hzs}?_!E#Ax=avnw0}XYV%0$dr#eb2_WOxn8=%r^Tbo%rvdAg>(6Fx49(a6bG?B30Agl zzGn8(-<=grbFpQzDfZ~KoKff(-3Qq+mL`j>sgmM{a13jFFGYvE?Hdx>b1V#uZ=9Vw<)B(OypZD>wl{w_D2W`k%TwAkW`zmadP zqO%=)mVFC??9e~WXf{FEL zKY?vZvs6G;9f3N8D^ftay~?z$iT>($0G^c*aDDZsUN{Tk3MC9kE7B#M*4CjG_H)#* zr8kWvJ_E8|OZfgJ(E&H9Ft#T7ubcdl_v@AT8(_PiYN)&mM17cm$2xT77VCAL-M>u> zR(JX7v;e#9E!w<00|WI%bKp{M1O*8IPCMtu_a^ZQi&`Vw>kyU7vHx(sY+ z_(B;4kd>YwzyVJUQpfzom7pK07~*!YMMgW}W{nrW-86eKXP%Lz?7;iWGu+Hu+&UET^wJ*T)v9-MYtKH zmu1)emlpNcamirAc>x=WotDo2^{4rL9KTH6d%%50O&*+ya(Z9E9&|2M`@x)2eyqoE zIfCz3UH>oPK<74wFAe}OA+fTXRPkpX%n_uSlgvQH)?a*WJb!$xy_D4*-4zX2Xs1>qia#^P?DGFcD;?TN_Zr28pJ1_{G%yb3$`p zVHN>wsd271s7hpn-7x^e`cgFX{y+7g!F?d^?T| zj~5TH>{+w3oNE$J;jU!tlZh zB6i)fK!bq2BDb(PaboUIXcPNS`8aCWZNXbC2hj&d58(t(d_S9AZ2N6K3 zwp44)WTIKu!&;m|^St*+MyTAsXE{x2)5HprphJy4HHMl@T&f&9jGFa^sIt)I!%q7E z1w%es8tpe(>#bxC>;6k$!+P)M>456Q!@_FKJYPjFvPVRj9_fIJqvpP6m1kC*cLE#J zzouFx{pXivf$R@;HA5>rpWY(7F8nhrFF{XciOOTwYlOcp?sz<0UV|KqkZ-uoEj-H{ zAi8F^J9g~XS__0LSaKWQ$y8E3hA9bc1ed6S6q^QdYmU; z)t$PaBZfYJc+%e_TEr&@rvjJ@a8L~7=v9pz{Ar}i%=F}9V?%XU-5M@dlqQ|7)PS!0 zD*-wBEC{b0oI^Trkyy3>>{OBosh1*=O)jR(SD{NioDQK|T>>s1yhY9$1IeAq3!-07 zp_7e;NJpB*K-NPsy4WI1yjxi#n^7^40&qD17PIeLr>49Pb(Id>cg=n71+ZpM83q8s zgT&QAi(w$vcCnVN$a_$G^rJ{ASdC#on>yB1Mw`Nt7!qHI(IuiuC$PsA(@)yhuIG7o z(A}s#xhq8PNk$uH>zQrAP9%#+?mcbM|f@&IYuRX0yg zh1lAe%nA#$;&_OU+g_)dL69?Iw5CSnX2_3Bbgyn%y#0RhQ$VgrO_jvZ8Rg%RIUOq- z$&J5EcW?Bx*$T73Z81m6+hrGte8ybCF`$q;O~Z%Cq6)+sI0VF5mhg~+{>P^N8fD;m zw$H#&$^gIERMx|TPXct;$SEXNW(K2+ISdz%K352#3z}|xGNZ3U z3y>h*KUmLlC_Lz2Xa`~dh$9?8sRxnj)W8p&0CPz#yq=}zSt%XXQt(-Vl|3S4m$_2n zv_Oxh_;FCyk85gEoUX&*@M9TR@dEv|n|<|;YLUI^y(re%_mf z4}V-`KItLSrJ@PaM6xd^9=y{X3`6Lk3n$<<7wBRIO2vL{#d%G{Gu=WUQ07%fXhV~D zXWe>>0IWho0u+rQg^&TXXe`49FfeYy#>L@rc0{I7Gxi7<@&-GL6OoFLX(}72h7L$G zuB?I-VnN=}dD_Wo?k@caa{7kTd^xVnS&rTmN~{m6GvDY|bL+)eZNK}H1HjlU_T&vI zbgT8Rf&Z}7K0$y19$n#evw@n$mlsxnfyz4M3~B(?%xOxd3kn4qVUHtf3WLkRhkG0O7K&!nw$T?1&r+YJy__0e8a` z^^z0=9XNQv%d*1*h_^j;E#xK4`FkxCKz&V7h9K`)+d-TJO$k)3t%%h9n&8`&3^b`x z?{t?2wG10RLTNOsR6x3Tk4ouT*?~QmHz?ba@;%f1uE zqh7Wcd@`ZAF2s8;Bw&8up7+}yX;B)C?&TN8vLkQaG%Ac#GYxW*jZ#6gcpWdQNSOdm z;{^e|C2VL>JR$^3ZJHXAjWyssHQ?%8i#?#91%xvR(1`9!nTn~KvPVyBim=q^jeDYZ z^1M7iKTI)mBrWp7)amF~$C$Qr&9g6=X#|z@5`Bx*V`vuH$mKJ*OAUnUKC8fDn(TS+ zrmG6DXV&`*%=y@0AOusDL*gYVDbw@D=^p*=>t`~(T8 z4)ryAeONwiB+NP}`SMFA$k0A}D5<8G+XtjA#^-)c0X0dqHEtA`n?K-+^j2S%(_c7i zTNErua7wLl2rLLSZ>G4UfE@tcNX5&~vR}&Su@~QaL5;+ATwl)~oDyW}zpGDl z-rrsb*|*_ELpqokz3ww1=*YR35ncWyoRfZe`7$g8b3JO{tb|F$lT2YaGk=Dpf2>2vqaJ75!zU^vixm}T z`Z+I*O$NymneIN&D3{%qX?C?)YoH(DIr7{(XkRK#HBojNVLQx|9Qcq2a(}^27Cf#M zLuYZm&bXDzo4?<1N5D>)%-X!~1Sv5%mi_8`dB2ihoV8sYr{Y7jjV2j2*Vf8Q3I>Z> z$ppa6lZGc8zSx|?bl~}VfEEMMfT)R0IeDwtf@K|gN7Rp%NPss68b)s&EtDr}$U<+uNKR>5Mfl`qQk99cO(MM}Q7{L9xIgCv&Y&@8kEU+|$JE5s&D9abVbuDPBLO_Rq-P7}^0Lfj8pqhLn>D;-L_C5zx*7Px zPHkuNM*m~L)o-Z$;?(qmN4M&Y7wr&Kqf*|TALZv{J9F4Pu?qa42k%aHG&mI&s!P;M zLhC*s0^95StRm)U%zBK$xZ6D)Wl*2`8G?n@Zo)t;Hq`7Db(bPbw9>6-!88>u)`l%7 zK9w#UqCH5&yRbqvlsSEeYMZlNgjwbcBXfuCFu$&F7~(6RDTZoGgMnUGVz6m(f2*Z2 zJN5xD@uB5O3eN7`^x*HTBuZ%){mc)l((FsbA?bGNCgRH^(NE4_(lkir(-kKix#La< zVKvu*xcTttTfR;2e&95*RL%cc_}e5lbUUMvXpEHWVwsxN}+PyF5VB*Sg$ zp2E|iYJQ^J$1Mtsv9*cktX&0;=L8)H%oZww>1c({Z;~KZEJ8v~ycH{rQ-q;aYZ)t% zbup`{`D~g?x51KTI%7{$RZBVc093h4Ds=*2YMI*89etCuo8GdJ^NkRsNF@uPL|JM|*>@L_47jIH36g_wN3?4!cu<*siB zTj^_62&h5m{rB(t{O1kgE1aWKRE1ZaL7j|8y`?yKB#L6>s6M!m2*v^K~XzdmQ!Sh4PEx@?3Xi zDU$DeSTM0k8yXL`R8Wh}gbF^dXKket=TyJ{nQ21!B-*^8MNhcjM}xYeuZP#Is(Gg> z2tY+@hRxV~`ozsq zehj*pwwVc#X_FzMS7^ITbYnve!qeR@))~*eH+2Lz|0QfOz7(ko8qZ$u-gT|9kK?nS zW~aH$5n(@0Z*i^Ft9=rC2t-GDq6duYN_9L&_4a^->7)g5V2LaB4(2p=M?GAa@%jEx z)qRR29N}mT)tJ$!74$`^svdplA8w}t+(W7Wtd{oN|F}X8p{ezqcByx}oPTW4zD$70 z@Z<&U?Xfcd^cVb^It*>aOZxkUQ9hB)u0BADes1)pqj!#=L|})tMfZZFiV_lMDS4hQ zluO&5lU)sz$YadCvsU{a8LTPswzsTX<737{jJR}~idvnyvG4kZ#HOZHNaBSgtH$X4 zbfaMNDRX;s>(^$L8cL*EWcH0zY`1OJ9+;6``F=#zb{8_z@IA&`lFuqjLU`siYWfih z7TiqJC4!t~cD`m6-ix#IUHv-mi8?FzGbydI9?zUv%>AT(Hqey=KP|l9VGvZBRPE(C zypBG4_5v%L{T!;MEjC9*`y&lY?S-Sux9>=)SUL1qC&Nbfi`GOJktg_=TK!UvKt7~W z@T$U7yc+^s?$8XTIjU7G-v5F7?l{kHqCO{n&Cq?91uF}V|0dhPVqu_m{u&t@{l2b? zz=4+7_uf(vzYND{X!Zcjhr^Dnt~P?jtZx?1gNX1gAzTT`8z#bniP}w5c`3DJ)ssY^ z(KN6{D@_H}%WJpWch*S2<6(0MuHQZbz}+W^h+m>Qon7=EdV+DefDJGkK}62*UG*1> zM5~j;BYJn`=o^4nlVQsqNjL$Omm=v_NevP96)C<*1wdr`@sa=z7+`36UIDcHUN!ar zxnNOrfFRm_v1!(Y+<~5-6$^$>#7(qe-^}2tZ5GT+6lPy^zk8M5G@ZLRag^L)r^@Gn za00yYYoVDC<Mp+}CP+*F&xa8do#rTs5<3lIR+u58Y$>Sx!oVPFb8h5rtB89G0@Xtk+V#_%eM`9c% z_<*`svp4k6d3TbtcMF_m#yB^Zf~@^C(}GQ|I-E!mplZd9@2as;iND zTgd<6%NJYD^X5irju4BL&tMw`W3_w#K&}0_hvA0P@REk!QqwF(&SZ>Oe#{llX!cJ< z13^D-110^c#GF=#FarO%h~*6Jb@g2GhNADP_rkE$w)Tbop@!yf80v&T`Ds7x4L|1JA$%4$MsdYH^j&Jx##^ zz(Y-^b!tsi@>YIcF6QxXMVLo~g73lU1Z{fF0UV+(jdg298T5mD9-g)j+!2y6xaPKN q`$ZmE;J|b)`$R&gI?l*v`VTy}T(zUrP4ff;5O})!xvX +#include +#include +#include + +static thread_local NodeID local_node_id = E_ROOT_NODE; + +namespace pinpoint { + +// inspired by https://github.com/progschj/ThreadPool/blob/master/ThreadPool.h +// https://en.cppreference.com/w/cpp/thread/packaged_task +template +auto pin_func(const char *name, F &&f, Args &&... args) + -> std::future::type> { + + local_node_id = pinpoint_start_trace(local_node_id); + pinpoint_add_clue(local_node_id, PP_INTERCEPTOR_NAME, name, E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_SERVER_TYPE, PP_C_CPP_METHOD, + E_LOC_CURRENT); + + using return_type = typename std::result_of::type; + + auto task = std::make_shared>( + std::bind(std::forward(f), std::forward(args)...)); + + std::future res = task->get_future(); + + (*task)(); + + local_node_id = pinpoint_end_trace(local_node_id); + return res; +} +template +inline std::future::type> +async(F &&f, Args &&... args) { + local_node_id = pinpoint_start_trace(local_node_id); + + pinpoint_add_clue(local_node_id, PP_INTERCEPTOR_NAME, "pinpoint::async", + E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_SERVER_TYPE, PP_INVOCATION_CALL_TYPE, + E_LOC_CURRENT); + + int32_t async_id = random() % 99999; + std::string async_id_str = std::to_string(async_id); + pinpoint_add_clue(local_node_id, PP_ASYNC_CALL_ID, async_id_str.c_str(), + E_LOC_CURRENT); + int32_t sequence_id = pinpoint_get_sequence_id(local_node_id); + + using return_type = typename std::result_of::type; + + auto task = std::make_shared>( + std::bind(std::forward(f), std::forward(args)...)); + + char buf[128]; + int size = 0; + size = pinpoint_get_context_key(local_node_id, PP_TRANSCATION_ID, buf, 128); + std::string tid(buf, size); + + size = pinpoint_get_context_key(local_node_id, PP_SPAN_ID, buf, 128); + std::string sid(buf, size); + + size = pinpoint_get_context_key(local_node_id, PP_APP_NAME, buf, 128); + std::string app_name(buf, size); + size = pinpoint_get_context_key(local_node_id, PP_APP_ID, buf, 128); + std::string app_id(buf, size); + + auto pinpoint_wrapper_func = [=]() -> return_type { + local_node_id = pinpoint_start_trace(local_node_id); + pinpoint_add_clue(local_node_id, PP_APP_NAME, app_name.c_str(), + E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_APP_ID, app_id.c_str(), E_LOC_CURRENT); + + pinpoint_add_clue(local_node_id, PP_TRANSCATION_ID, tid.c_str(), + E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_SPAN_ID, sid.c_str(), E_LOC_CURRENT); + + pinpoint_add_clue(local_node_id, PP_SERVER_TYPE, PP_C_CPP_METHOD, + E_LOC_CURRENT); + pinpoint_set_async_ctx(local_node_id, async_id, sequence_id); + (*task)(); + local_node_id = pinpoint_end_trace(local_node_id); + return task->get_future().get(); + }; + + auto async_res = std::async(std::launch::async, pinpoint_wrapper_func); + local_node_id = pinpoint_end_trace(local_node_id); + return async_res; +} + +} // namespace pinpoint + +// @author eeliu \ No newline at end of file diff --git a/testapps/cpp/readme.md b/testapps/cpp/readme.md new file mode 100644 index 000000000..91707c9a6 --- /dev/null +++ b/testapps/cpp/readme.md @@ -0,0 +1,37 @@ +### Compile + +``` +$ mkdir build && cd build && cmake .. && make +$ ./server +$ # client command +$ curl http://127.0.0.1:8080/create_async_task +$ curl http://127.0.0.1:8080/hi +``` + +### Needs help + +https://github.com/pinpoint-apm/pinpoint-c-agent/issues/new?assignees=&labels=&projects=&template=custom.md&title=[CXX] + +### Explanation + +#### 1. How to trace async in cpp ? + +Sleep was called in a background thread which can be find in async block like `⇆`. + +![async](image.png) + +```cpp + p_svr.Get("/create_async_task", + [](const httplib::Request &, httplib::Response &res) { + auto task = []() -> int { + pinpoint::pin_func("sleep", sleep, 2); + return 0; + }; + auto async_res = pinpoint::async(task); + pinpoint::pin_func("sleep", sleep, 2); + pp_trace("async_task: %d", async_res.get()); + + res.status = StatusCode::OK_200; + res.set_content("sleep 5s!", "text/plain"); + }); +``` \ No newline at end of file diff --git a/testapps/cpp/server.cpp b/testapps/cpp/server.cpp new file mode 100644 index 000000000..bf43c6bc3 --- /dev/null +++ b/testapps/cpp/server.cpp @@ -0,0 +1,98 @@ +#include "common.h" +#include "httplib.h" +#include "pinpoint_define.h" +#include "pinpoint_helper.h" +#include +#include +#include + +const char *app_id = "cd.dev.test.cpp"; +const char *app_name = "cd.dev.test.cxx"; + +using Server = httplib::Server; +using StatusCode = httplib::StatusCode; + +class PinpointServer : public Server { +private: + std::string genSpanId() { return std::to_string(rand() % 100000000l); } + + std::string genTid() { + std::string tid = app_id; + return tid + "^" + std::to_string(pinpoint_start_time()) + "^" + + std::to_string(generate_unique_id()); + } + +protected: + void entry(const httplib::Request &request, httplib::Response &response, + Handler origin_handler) { + + local_node_id = pinpoint_start_trace(local_node_id); + pinpoint_add_clue(local_node_id, PP_REQ_URI, request.path.c_str(), + E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_REQ_CLIENT, request.remote_addr.c_str(), + E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_REQ_SERVER, request.local_addr.c_str(), + E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_SERVER_TYPE, PP_C_CPP, E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_INTERCEPTOR_NAME, "C_CPP Request", + E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_APP_NAME, app_name, E_LOC_CURRENT); + pinpoint_add_clue(local_node_id, PP_APP_ID, app_id, E_LOC_CURRENT); + pinpoint_set_context_key(local_node_id, PP_APP_NAME, app_name); + pinpoint_set_context_key(local_node_id, PP_APP_ID, app_id); + + std::string tid = genTid(); + std::string span_id = genSpanId(); + pinpoint_add_clue(local_node_id, PP_TRANSCATION_ID, tid.c_str(), + E_LOC_CURRENT); + pinpoint_set_context_key(local_node_id, PP_TRANSCATION_ID, tid.c_str()); + + pinpoint_add_clue(local_node_id, PP_SPAN_ID, span_id.c_str(), + E_LOC_CURRENT); + pinpoint_set_context_key(local_node_id, PP_SPAN_ID, span_id.c_str()); + + origin_handler(request, response); + + std::string status_str = std::to_string(response.status); + pinpoint_add_clues(local_node_id, PP_HTTP_STATUS_CODE, status_str.c_str(), + E_LOC_CURRENT); + local_node_id = pinpoint_end_trace(local_node_id); + } + +public: + Server &Get(const std::string &pattern, Handler handler) { + + return Server::Get(pattern, std::bind(&PinpointServer::entry, this, + std::placeholders::_1, + std::placeholders::_2, handler)); + }; +}; + +int main(void) { + pinpoint_set_agent("tcp:dev-collector:10000", 10, -1, 1300); + register_logging_cb(nullptr, 1); + + PinpointServer p_svr; + + p_svr.Get("/hi", [](const httplib::Request &, httplib::Response &res) { + res.status = StatusCode::OK_200; + res.set_content("Hello pinpoint-c-agent !", "text/plain"); + }); + + p_svr.Get("/create_async_task", + [](const httplib::Request &, httplib::Response &res) { + auto task = []() -> int { + pinpoint::pin_func("sleep", sleep, 2); + return 0; + }; + auto async_res = pinpoint::async(task); + pinpoint::pin_func("sleep", sleep, 2); + pp_trace("async_task: %d", async_res.get()); + + res.status = StatusCode::OK_200; + res.set_content("sleep 5s!", "text/plain"); + }); + + pp_trace(" server start at: 8080"); + p_svr.listen("0.0.0.0", 8080); +} \ No newline at end of file diff --git a/tests/add_root_trace.phpt b/tests/add_root_trace.phpt index 6dfd26453..3c513ab11 100644 --- a/tests/add_root_trace.phpt +++ b/tests/add_root_trace.phpt @@ -21,17 +21,17 @@ $id = _pinpoint_end_trace($id); $id = _pinpoint_end_trace($id); $id = _pinpoint_end_trace($id); --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] -[pinpoint] [%d] [%d] [128] add clue key:name value:Foo -[pinpoint] [%d] [%d] [128] pinpoint_start child [127] -[pinpoint] [%d] [%d] [127] add clues:global:global_value -[pinpoint] [%d] [%d] [127] add clue key:global value:global_value -[pinpoint] [%d] [%d] [127] add clues:name:Foo1 -[pinpoint] [%d] [%d] [127] pinpoint_start child [126] -[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":%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 +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [128] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [128] pinpoint_start child [127] +[pinpoint] [%d:%d] [127] add anno_v2 global:global_value +[pinpoint] [%d:%d] [127] add anno_v1 key:global value:global_value +[pinpoint] [%d:%d] [127] add anno_v2 name:Foo1 +[pinpoint] [%d:%d] [127] pinpoint_start child [126] +[pinpoint] [%d:%d] [126] add anno_v1 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,"anno":["global:global_value"],"event":[{":E":%d,":S":%d,":depth":1,":seq":0,"anno":["name:Foo1"]},{":E":%d,":S":%d,":depth":2,":seq":1,"name":"Foo2"}],"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/app_info_test.phpt b/tests/app_info_test.phpt index e505f9cc0..db02c7c6e 100644 --- a/tests/app_info_test.phpt +++ b/tests/app_info_test.phpt @@ -12,5 +12,5 @@ pinpoint_php.DebugReport=true var_dump(_pinpoint_start_time()); var_dump("APP".'^'.strval(_pinpoint_start_time()).'^'.strval(_pinpoint_unique_id())); --EXPECTF-- -int(%d) +float(%d) string(%d) "APP^%d^%d" \ No newline at end of file diff --git a/tests/drop_trace_test.phpt b/tests/drop_trace_test.phpt index 0049c3825..b8cf92119 100644 --- a/tests/drop_trace_test.phpt +++ b/tests/drop_trace_test.phpt @@ -15,9 +15,9 @@ _pinpoint_add_clue("args",'a,$b'); _pinpoint_add_clue("ret",'a,$b'); _pinpoint_end_trace(); --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] -[pinpoint] [%d] [%d]change current [128] status, before:2,now:4 -[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]current [128] span dropped,due to TRACE_BLOCK -[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done! \ No newline at end of file +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d]change current [128] status, before:2,now:4 +[pinpoint] [%d:%d] [128] add anno_v1 key:args value:a,$b +[pinpoint] [%d:%d] [128] add anno_v1 key:ret value:a,$b +[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/mark_as_error.phpt b/tests/mark_as_error.phpt index fcc26a30c..800a7f00b 100644 --- a/tests/mark_as_error.phpt +++ b/tests/mark_as_error.phpt @@ -17,11 +17,11 @@ _pinpoint_add_clue("ret",'a,$b'); _pinpoint_mark_as_error("message you cared","filename you cared",1023); echo _pinpoint_end_trace()."\n"; --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] -[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:(:/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] add anno_v1 key:args value:a,$b +[pinpoint] [%d:%d] [128] add anno_v1 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:(:/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/node_test.phpt b/tests/node_test.phpt index eb958c420..af39d1e7d 100644 --- a/tests/node_test.phpt +++ b/tests/node_test.phpt @@ -25,11 +25,11 @@ _pinpoint_get_context('b',$unexist_node); _pinpoint_end_trace($unexist_node); --EXPECTF-- -[pinpoint] [%d] [%d] start_trace [1024] failed with #1024 is not alive -[pinpoint] [%d] [%d] pinpoint_add_clue [1024] failed. Reason: #1024 is not alive,parameters:adf:fdfd -[pinpoint] [%d] [%d] pinpoint_add_clue [1024] failed. Reason: #1024 is not alive,parameters:adf:fdfd -[pinpoint] [%d] [%d] pinpoint_set_context_key [1024] failed with out_of_range. #1024 is not alive,parameters:b:b -[pinpoint] [%d] [%d] pinpoint_add_clues [1024] failed. Reason #1024 is not alive,parameters:32:fdfd -[pinpoint] [%d] [%d] pinpoint_add_clues [1024] failed. Reason #1024 is not alive,parameters:32:fdfd -[pinpoint] [%d] [%d] pinpoint_get_context_key [1024] failed with #1024 is not alive, parameters:b -[pinpoint] [%d] [%d]end_trace 1024 out_of_range exception: #1024 is not alive \ No newline at end of file +[pinpoint] [%d:%d] start_trace [1024] failed with #1024 is not alive +[pinpoint] [%d:%d] pinpoint_add_clue [1024] failed. Reason: #1024 is not alive,parameters:adf:fdfd +[pinpoint] [%d:%d] pinpoint_add_clue [1024] failed. Reason: #1024 is not alive,parameters:adf:fdfd +[pinpoint] [%d:%d] pinpoint_set_context_key [1024] failed with out_of_range. #1024 is not alive,parameters:b:b +[pinpoint] [%d:%d] pinpoint_add_clues [1024] failed. Reason #1024 is not alive,parameters:32:fdfd +[pinpoint] [%d:%d] pinpoint_add_clues [1024] failed. Reason #1024 is not alive,parameters:32:fdfd +[pinpoint] [%d:%d] pinpoint_get_context_key [1024] failed with #1024 is not alive, parameters:b +[pinpoint] [%d:%d]end_trace 1024 out_of_range exception: #1024 is not alive \ No newline at end of file diff --git a/tests/pinpoint_get_caller_arg.phpt b/tests/pinpoint_get_caller_arg.phpt index 0f244c7d8..0687b8c6c 100644 --- a/tests/pinpoint_get_caller_arg.phpt +++ b/tests/pinpoint_get_caller_arg.phpt @@ -38,13 +38,13 @@ echo "error: $error\n"; curl_close($ch); --EXPECTF-- -[pinpoint] [%d] [%d]try to interceptor function=curl_exec -[pinpoint] [%d] [%d]added interceptor on `function`: curl_exec success +[pinpoint] [%d:%d]try to interceptor function=curl_exec +[pinpoint] [%d:%d]added interceptor on `function`: curl_exec success case: curl_init() -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_exec -[pinpoint] [%d] [%d] call_interceptor_before:curl_exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_exec +[pinpoint] [%d:%d] call_interceptor_before:curl_exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` status_code 200 -[pinpoint] [%d] [%d]call_interceptor_end: curl_exec +[pinpoint] [%d:%d]call_interceptor_end: curl_exec error: -[pinpoint] [%d] [%d]start free interceptor: curl_exec \ No newline at end of file +[pinpoint] [%d:%d]start free interceptor: curl_exec \ No newline at end of file diff --git a/tests/pinpoint_get_this.phpt b/tests/pinpoint_get_this.phpt index babd50895..ae5027fb2 100644 --- a/tests/pinpoint_get_this.phpt +++ b/tests/pinpoint_get_this.phpt @@ -54,8 +54,8 @@ string(3) "123" update foo members int(1234) string(14) "hello pinpoint" -[pinpoint] [%d] [%d]pinpoint_get_this: not support, no this +[pinpoint] [%d:%d]pinpoint_get_this: not support, no this bool(false) test static method -[pinpoint] [%d] [%d]pinpoint_get_this: not support, no this +[pinpoint] [%d:%d]pinpoint_get_this: not support, no this bool(false) \ No newline at end of file diff --git a/tests/pinpoint_join_cut_curl_7.phpt b/tests/pinpoint_join_cut_curl_7.phpt index d13e7d061..8e00e8531 100644 --- a/tests/pinpoint_join_cut_curl_7.phpt +++ b/tests/pinpoint_join_cut_curl_7.phpt @@ -91,8 +91,7 @@ _pinpoint_join_cut( echo "case: curl_init() \n"; -$my_curl_init = curl_init; -$ch = my_curl_init(); +$ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "http://httpbin.org/anything"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ @@ -131,100 +130,100 @@ echo "error:$error \n"; curl_close($ch); --EXPECTF-- -[pinpoint] [%d] [%d]try to interceptor function=curl_init -[pinpoint] [%d] [%d]added interceptor on `function`: curl_init success -[pinpoint] [%d] [%d]try to interceptor function=curl_exec -[pinpoint] [%d] [%d]added interceptor on `function`: curl_exec success -[pinpoint] [%d] [%d]try to interceptor function=curl_setopt -[pinpoint] [%d] [%d]added interceptor on `function`: curl_setopt success +[pinpoint] [%d:%d]try to interceptor function=curl_init +[pinpoint] [%d:%d]added interceptor on `function`: curl_init success +[pinpoint] [%d:%d]try to interceptor function=curl_exec +[pinpoint] [%d:%d]added interceptor on `function`: curl_exec success +[pinpoint] [%d:%d]try to interceptor function=curl_setopt +[pinpoint] [%d:%d]added interceptor on `function`: curl_setopt success case: curl_init() -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_init +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_init on_before NULL -[pinpoint] [%d] [%d] call_interceptor_before:curl_init return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:curl_init return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end resource(4) of type (curl) -get resource [pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +get resource [pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(42) -not working[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +not working[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]call_interceptor_end: curl_init -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_init +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(10002) test CURLOPT_URL -[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval -[pinpoint] [%d] [%d]argv size:2 -[pinpoint] [%d] [%d]error: replace_ex_caller_parameters return `size` does not matched +[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(7) zval +[pinpoint] [%d:%d]argv size:2 +[pinpoint] [%d:%d]error: replace_ex_caller_parameters return `size` does not match on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(19913) test CURLOPT_RETURNTRANSFER -[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval -[pinpoint] [%d] [%d]argv size:3 -[pinpoint] [%d] [%d]error: replace_ex_caller_parameters return `type` does not matched expected:3 give:4 +[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(7) zval +[pinpoint] [%d:%d]argv size:3 +[pinpoint] [%d:%d]error: replace_ex_caller_parameters return `type` does not match expected:3 give:4 on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(10023) value must be affected -[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval -[pinpoint] [%d] [%d]argv size:3 -[pinpoint] [%d] [%d]args[2] type:7 in:1 va:2 +[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(7) zval +[pinpoint] [%d:%d]argv size:3 +[pinpoint] [%d:%d]args[2] type:7 in:1 va:2 on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_exec +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_exec on_before resource(4) of type (curl) request url: http://httpbin.org/anything -[pinpoint] [%d] [%d] call_interceptor_before:curl_exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:curl_exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_exec +[pinpoint] [%d:%d]call_interceptor_end: curl_exec error: case : curl_init with variable -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_init +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_init on_before string(27) "http://httpbin.org/anything" -[pinpoint] [%d] [%d] call_interceptor_before:curl_init return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:curl_init return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end resource(5) of type (curl) -get resource [pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +get resource [pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(42) -not working[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +not working[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]call_interceptor_end: curl_init -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_init +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(19913) test CURLOPT_RETURNTRANSFER -[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval -[pinpoint] [%d] [%d]argv size:3 -[pinpoint] [%d] [%d]error: replace_ex_caller_parameters return `type` does not matched expected:3 give:4 +[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(7) zval +[pinpoint] [%d:%d]argv size:3 +[pinpoint] [%d:%d]error: replace_ex_caller_parameters return `type` does not match expected:3 give:4 on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(10023) value must be affected -[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval -[pinpoint] [%d] [%d]argv size:3 -[pinpoint] [%d] [%d]args[2] type:7 in:1 va:2 +[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(7) zval +[pinpoint] [%d:%d]argv size:3 +[pinpoint] [%d:%d]args[2] type:7 in:1 va:2 on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_exec +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_exec on_before resource(5) of type (curl) request url: http://httpbin.org/anything -[pinpoint] [%d] [%d] call_interceptor_before:curl_exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:curl_exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_exec +[pinpoint] [%d:%d]call_interceptor_end: curl_exec error: -[pinpoint] [%d] [%d]start free interceptor: curl_init -[pinpoint] [%d] [%d]start free interceptor: curl_exec -[pinpoint] [%d] [%d]start free interceptor: curl_setopt \ No newline at end of file +[pinpoint] [%d:%d]start free interceptor: curl_init +[pinpoint] [%d:%d]start free interceptor: curl_exec +[pinpoint] [%d:%d]start free interceptor: curl_setopt \ No newline at end of file diff --git a/tests/pinpoint_join_cut_curl_8.phpt b/tests/pinpoint_join_cut_curl_8.phpt index 2f2812969..cfef3aeb4 100644 --- a/tests/pinpoint_join_cut_curl_8.phpt +++ b/tests/pinpoint_join_cut_curl_8.phpt @@ -130,104 +130,104 @@ echo "error:$error \n"; curl_close($ch); --EXPECTF-- -[pinpoint] [%d] [%d]try to interceptor function=curl_init -[pinpoint] [%d] [%d]added interceptor on `function`: curl_init success -[pinpoint] [%d] [%d]try to interceptor function=curl_exec -[pinpoint] [%d] [%d]added interceptor on `function`: curl_exec success -[pinpoint] [%d] [%d]try to interceptor function=curl_setopt -[pinpoint] [%d] [%d]added interceptor on `function`: curl_setopt success +[pinpoint] [%d:%d]try to interceptor function=curl_init +[pinpoint] [%d:%d]added interceptor on `function`: curl_init success +[pinpoint] [%d:%d]try to interceptor function=curl_exec +[pinpoint] [%d:%d]added interceptor on `function`: curl_exec success +[pinpoint] [%d:%d]try to interceptor function=curl_setopt +[pinpoint] [%d:%d]added interceptor on `function`: curl_setopt success case: curl_init() -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_init +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_init on_before NULL -[pinpoint] [%d] [%d] call_interceptor_before:curl_init return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:curl_init return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end object(CurlHandle)#10 (0) { } -get resource [pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +get resource [pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(42) -not working[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +not working[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]call_interceptor_end: curl_init -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_init +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(10002) test CURLOPT_URL -[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval -[pinpoint] [%d] [%d]argv size:2 -[pinpoint] [%d] [%d]error: replace_ex_caller_parameters return `size` does not matched +[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(7) zval +[pinpoint] [%d:%d]argv size:2 +[pinpoint] [%d:%d]error: replace_ex_caller_parameters return `size` does not match on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(19913) test CURLOPT_RETURNTRANSFER -[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval -[pinpoint] [%d] [%d]argv size:3 -[pinpoint] [%d] [%d]error: replace_ex_caller_parameters return `type` does not matched expected:3 give:4 +[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(7) zval +[pinpoint] [%d:%d]argv size:3 +[pinpoint] [%d:%d]error: replace_ex_caller_parameters return `type` does not match expected:3 give:4 on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(10023) value must be affected -[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval -[pinpoint] [%d] [%d]argv size:3 -[pinpoint] [%d] [%d]args[2] type:7 in:1 va:2 +[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(7) zval +[pinpoint] [%d:%d]argv size:3 +[pinpoint] [%d:%d]args[2] type:7 in:1 va:2 on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_exec +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_exec on_before object(CurlHandle)#10 (0) { } request url: http://httpbin.org/anything -[pinpoint] [%d] [%d] call_interceptor_before:curl_exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:curl_exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_exec +[pinpoint] [%d:%d]call_interceptor_end: curl_exec error: case : curl_init with variable -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_init +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_init on_before string(27) "http://httpbin.org/anything" -[pinpoint] [%d] [%d] call_interceptor_before:curl_init return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:curl_init return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end object(CurlHandle)#11 (0) { } -get resource [pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +get resource [pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(42) -not working[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +not working[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]call_interceptor_end: curl_init -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_init +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(19913) test CURLOPT_RETURNTRANSFER -[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval -[pinpoint] [%d] [%d]argv size:3 -[pinpoint] [%d] [%d]error: replace_ex_caller_parameters return `type` does not matched expected:3 give:4 +[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(7) zval +[pinpoint] [%d:%d]argv size:3 +[pinpoint] [%d:%d]error: replace_ex_caller_parameters return `type` does not match expected:3 give:4 on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(10023) value must be affected -[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval -[pinpoint] [%d] [%d]argv size:3 -[pinpoint] [%d] [%d]args[2] type:7 in:1 va:2 +[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(7) zval +[pinpoint] [%d:%d]argv size:3 +[pinpoint] [%d:%d]args[2] type:7 in:1 va:2 on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_exec +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_exec on_before object(CurlHandle)#11 (0) { } request url: http://httpbin.org/anything -[pinpoint] [%d] [%d] call_interceptor_before:curl_exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:curl_exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_exec +[pinpoint] [%d:%d]call_interceptor_end: curl_exec error: -[pinpoint] [%d] [%d]start free interceptor: curl_init -[pinpoint] [%d] [%d]start free interceptor: curl_exec -[pinpoint] [%d] [%d]start free interceptor: curl_setopt \ No newline at end of file +[pinpoint] [%d:%d]start free interceptor: curl_init +[pinpoint] [%d:%d]start free interceptor: curl_exec +[pinpoint] [%d:%d]start free interceptor: curl_setopt \ No newline at end of file diff --git a/tests/pinpoint_join_cut_extend_pdo.phpt b/tests/pinpoint_join_cut_extend_pdo.phpt index 8165f8e94..55bcdd7c8 100644 --- a/tests/pinpoint_join_cut_extend_pdo.phpt +++ b/tests/pinpoint_join_cut_extend_pdo.phpt @@ -96,17 +96,17 @@ $ret = $pdo->exec($sql); --EXPECTF-- -[pinpoint] [%d] [%d]try to interceptor module(class)/function=pdo:__construct -[pinpoint] [%d] [%d]added interceptor on `module`: pdo::__construct success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=pdo:exec -[pinpoint] [%d] [%d]added interceptor on `module`: pdo::exec success -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::__construct +[pinpoint] [%d:%d]try to interceptor module(class)/function=pdo:__construct +[pinpoint] [%d:%d]added interceptor on `module`: pdo::__construct success +[pinpoint] [%d:%d]try to interceptor module(class)/function=pdo:exec +[pinpoint] [%d:%d]added interceptor on `module`: pdo::exec success +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::__construct on_before: mysql:host=dev-mysql;dbname=employees attached dsn -[pinpoint] [%d] [%d] call_interceptor_before:pdo::__construct return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:pdo::__construct return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: pdo::__construct +[pinpoint] [%d:%d]call_interceptor_end: pdo::__construct int(4) object(PDOStatement)#8 (1) { ["queryString"]=> @@ -149,5 +149,5 @@ array(2) { } string(3) "123" string(37) "mysql:host=dev-mysql;dbname=employees" -[pinpoint] [%d] [%d]start free interceptor: pdo::__construct -[pinpoint] [%d] [%d]start free interceptor: pdo::exec \ No newline at end of file +[pinpoint] [%d:%d]start free interceptor: pdo::__construct +[pinpoint] [%d:%d]start free interceptor: pdo::exec \ No newline at end of file diff --git a/tests/pinpoint_join_cut_mysqli.phpt b/tests/pinpoint_join_cut_mysqli.phpt index 46338e284..bd692b761 100644 --- a/tests/pinpoint_join_cut_mysqli.phpt +++ b/tests/pinpoint_join_cut_mysqli.phpt @@ -68,20 +68,20 @@ mysqli_stmt_execute($stmt); --EXPECTF-- -[pinpoint] [%d] [%d]try to interceptor function=mysqli_query -[pinpoint] [%d] [%d]added interceptor on `function`: mysqli_query success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=mysqli:query -[pinpoint] [%d] [%d]added interceptor on `module`: mysqli::query success -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:mysqli::query +[pinpoint] [%d:%d]try to interceptor function=mysqli_query +[pinpoint] [%d:%d]added interceptor on `function`: mysqli_query success +[pinpoint] [%d:%d]try to interceptor module(class)/function=mysqli:query +[pinpoint] [%d:%d]added interceptor on `module`: mysqli::query success +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:mysqli::query dev-mysql via TCP/IP -[pinpoint] [%d] [%d] call_interceptor_before:mysqli::query return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` -[pinpoint] [%d] [%d]call_interceptor_end: mysqli::query +[pinpoint] [%d:%d] call_interceptor_before:mysqli::query return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d]call_interceptor_end: mysqli::query Select returned 1000 rows. -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:mysqli_query +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:mysqli_query dev-mysql via TCP/IP -[pinpoint] [%d] [%d] call_interceptor_before:mysqli_query return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` -[pinpoint] [%d] [%d]call_interceptor_end: mysqli_query -[pinpoint] [%d] [%d]start free interceptor: mysqli_query -[pinpoint] [%d] [%d]start free interceptor: mysqli::query \ No newline at end of file +[pinpoint] [%d:%d] call_interceptor_before:mysqli_query return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d]call_interceptor_end: mysqli_query +[pinpoint] [%d:%d]start free interceptor: mysqli_query +[pinpoint] [%d:%d]start free interceptor: mysqli::query \ No newline at end of file diff --git a/tests/pinpoint_join_cut_pdo.phpt b/tests/pinpoint_join_cut_pdo.phpt index b6eb49f42..15638d1bd 100644 --- a/tests/pinpoint_join_cut_pdo.phpt +++ b/tests/pinpoint_join_cut_pdo.phpt @@ -94,34 +94,34 @@ $ret = $pdo->exec($sql); --EXPECTF-- -[pinpoint] [%d] [%d]try to interceptor module(class)/function=pdo:__construct -[pinpoint] [%d] [%d]added interceptor on `module`: pdo::__construct success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=pdo:exec -[pinpoint] [%d] [%d]added interceptor on `module`: pdo::exec success +[pinpoint] [%d:%d]try to interceptor module(class)/function=pdo:__construct +[pinpoint] [%d:%d]added interceptor on `module`: pdo::__construct success +[pinpoint] [%d:%d]try to interceptor module(class)/function=pdo:exec +[pinpoint] [%d:%d]added interceptor on `module`: pdo::exec success case: pdo() -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::__construct +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::__construct on_before: mysql:host=dev-mysql;dbname=employees attached dsn -[pinpoint] [%d] [%d] call_interceptor_before:pdo::__construct return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:pdo::__construct return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: pdo::__construct -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec +[pinpoint] [%d:%d]call_interceptor_end: pdo::__construct +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec PDO::exec: on_before: CREATE table IF NOT EXISTS pdo_test( ID INT( 11 ) AUTO_INCREMENT PRIMARY KEY, Name VARCHAR( 250 ) NOT NULL, AGE tinyint(1) unsigned NOT NULL default '1' ); -[pinpoint] [%d] [%d] call_interceptor_before:pdo::exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:pdo::exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` PDO::exec : on_end -[pinpoint] [%d] [%d]call_interceptor_end: pdo::exec -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec +[pinpoint] [%d:%d]call_interceptor_end: pdo::exec +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec PDO::exec: on_before: INSERT INTO pdo_test (NAME, AGE) VALUES ('a',1),('b',1),('c',3),('d',1); -[pinpoint] [%d] [%d] call_interceptor_before:pdo::exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:pdo::exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` PDO::exec : on_end -[pinpoint] [%d] [%d]call_interceptor_end: pdo::exec +[pinpoint] [%d:%d]call_interceptor_end: pdo::exec int(4) object(PDOStatement)#8 (1) { ["queryString"]=> @@ -164,11 +164,11 @@ array(2) { } string(3) "123" string(37) "mysql:host=dev-mysql;dbname=employees" -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec PDO::exec: on_before: DROP TABLE pdo_test -[pinpoint] [%d] [%d] call_interceptor_before:pdo::exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:pdo::exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` PDO::exec : on_end -[pinpoint] [%d] [%d]call_interceptor_end: pdo::exec -[pinpoint] [%d] [%d]start free interceptor: pdo::__construct -[pinpoint] [%d] [%d]start free interceptor: pdo::exec \ No newline at end of file +[pinpoint] [%d:%d]call_interceptor_end: pdo::exec +[pinpoint] [%d:%d]start free interceptor: pdo::__construct +[pinpoint] [%d:%d]start free interceptor: pdo::exec \ No newline at end of file diff --git a/tests/pinpoint_join_cut_pdo_8.phpt b/tests/pinpoint_join_cut_pdo_8.phpt index 810c01d34..b2caee0c0 100644 --- a/tests/pinpoint_join_cut_pdo_8.phpt +++ b/tests/pinpoint_join_cut_pdo_8.phpt @@ -102,36 +102,36 @@ $ret = $pdo->exec($sql); --EXPECTF-- -[pinpoint] [%d] [%d]try to interceptor module(class)/function=pdo:__construct -[pinpoint] [%d] [%d]added interceptor on `module`: pdo::__construct success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=pdo:exec -[pinpoint] [%d] [%d]added interceptor on `module`: pdo::exec success +[pinpoint] [%d:%d]try to interceptor module(class)/function=pdo:__construct +[pinpoint] [%d:%d]added interceptor on `module`: pdo::__construct success +[pinpoint] [%d:%d]try to interceptor module(class)/function=pdo:exec +[pinpoint] [%d:%d]added interceptor on `module`: pdo::exec success case: pdo() -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::__construct +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::__construct on_before: mysql:host=dev-mysql;dbname=employees attached dsn -[pinpoint] [%d] [%d] call_interceptor_before:pdo::__construct return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:pdo::__construct return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: pdo::__construct -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec +[pinpoint] [%d:%d]call_interceptor_end: pdo::__construct +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec PDO::exec: on_before: CREATE table IF NOT EXISTS pdo_test( ID INT( 11 ) AUTO_INCREMENT PRIMARY KEY, Name VARCHAR( 250 ) NOT NULL, AGE tinyint(1) unsigned NOT NULL default '1' ); mysql:host=dev-mysql;dbname=employees -[pinpoint] [%d] [%d] call_interceptor_before:pdo::exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:pdo::exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` PDO::exec : on_end -[pinpoint] [%d] [%d]call_interceptor_end: pdo::exec -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec +[pinpoint] [%d:%d]call_interceptor_end: pdo::exec +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec PDO::exec: on_before: INSERT INTO pdo_test (NAME, AGE) VALUES ('a',1),('b',1),('c',3),('d',1); mysql:host=dev-mysql;dbname=employees -[pinpoint] [%d] [%d] call_interceptor_before:pdo::exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:pdo::exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` PDO::exec : on_end -[pinpoint] [%d] [%d]call_interceptor_end: pdo::exec +[pinpoint] [%d:%d]call_interceptor_end: pdo::exec int(4) object(PDOStatement)#9 (1) { ["queryString"]=> @@ -173,12 +173,12 @@ array(2) { } } string(37) "mysql:host=dev-mysql;dbname=employees" -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec PDO::exec: on_before: DROP TABLE pdo_test mysql:host=dev-mysql;dbname=employees -[pinpoint] [%d] [%d] call_interceptor_before:pdo::exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:pdo::exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` PDO::exec : on_end -[pinpoint] [%d] [%d]call_interceptor_end: pdo::exec -[pinpoint] [%d] [%d]start free interceptor: pdo::__construct -[pinpoint] [%d] [%d]start free interceptor: pdo::exec \ No newline at end of file +[pinpoint] [%d:%d]call_interceptor_end: pdo::exec +[pinpoint] [%d:%d]start free interceptor: pdo::__construct +[pinpoint] [%d:%d]start free interceptor: pdo::exec \ No newline at end of file diff --git a/tests/pinpoint_join_cut_redis.phpt b/tests/pinpoint_join_cut_redis.phpt index c1b6da409..d23a29f14 100644 --- a/tests/pinpoint_join_cut_redis.phpt +++ b/tests/pinpoint_join_cut_redis.phpt @@ -154,135 +154,135 @@ $redis->mSet(['foo' => 'foo', 'bar' => 'bar', 'baz' => 'baz']); var_dump($redis->exists('foo', 'bar', 'baz', 'not exists')); $redis->flushdb(); --EXPECTF-- -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:info -[pinpoint] [%d] [%d]added interceptor on `module`: redis::info success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:get -[pinpoint] [%d] [%d]added interceptor on `module`: redis::get success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:set -[pinpoint] [%d] [%d]added interceptor on `module`: redis::set success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:setnx -[pinpoint] [%d] [%d]added interceptor on `module`: redis::setnx success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:append -[pinpoint] [%d] [%d]added interceptor on `module`: redis::append success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:getrange -[pinpoint] [%d] [%d]added interceptor on `module`: redis::getrange success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:setrange -[pinpoint] [%d] [%d]added interceptor on `module`: redis::setrange success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:strlen -[pinpoint] [%d] [%d]added interceptor on `module`: redis::strlen success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:getbit -[pinpoint] [%d] [%d]added interceptor on `module`: redis::getbit success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:setbit -[pinpoint] [%d] [%d]added interceptor on `module`: redis::setbit success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:mset -[pinpoint] [%d] [%d]added interceptor on `module`: redis::mset success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:msetnx -[pinpoint] [%d] [%d]added interceptor on `module`: redis::msetnx success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:info +[pinpoint] [%d:%d]added interceptor on `module`: redis::info success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:get +[pinpoint] [%d:%d]added interceptor on `module`: redis::get success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:set +[pinpoint] [%d:%d]added interceptor on `module`: redis::set success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:setnx +[pinpoint] [%d:%d]added interceptor on `module`: redis::setnx success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:append +[pinpoint] [%d:%d]added interceptor on `module`: redis::append success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:getrange +[pinpoint] [%d:%d]added interceptor on `module`: redis::getrange success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:setrange +[pinpoint] [%d:%d]added interceptor on `module`: redis::setrange success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:strlen +[pinpoint] [%d:%d]added interceptor on `module`: redis::strlen success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:getbit +[pinpoint] [%d:%d]added interceptor on `module`: redis::getbit success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:setbit +[pinpoint] [%d:%d]added interceptor on `module`: redis::setbit success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:mset +[pinpoint] [%d:%d]added interceptor on `module`: redis::mset success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:msetnx +[pinpoint] [%d:%d]added interceptor on `module`: redis::msetnx success case: redis(xxx) -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::info +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::info Redis::info before: -[pinpoint] [%d] [%d] call_interceptor_before:redis::info return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::info return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::info end -[pinpoint] [%d] [%d]call_interceptor_end: redis::info +[pinpoint] [%d:%d]call_interceptor_end: redis::info case: redis() -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::info +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::info Redis::info before: -[pinpoint] [%d] [%d] call_interceptor_before:redis::info return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::info return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::info end -[pinpoint] [%d] [%d]call_interceptor_end: redis::info +[pinpoint] [%d:%d]call_interceptor_end: redis::info case: redis() -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::info +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::info Redis::info before: -[pinpoint] [%d] [%d] call_interceptor_before:redis::info return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::info return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::info end -[pinpoint] [%d] [%d]call_interceptor_end: redis::info +[pinpoint] [%d:%d]call_interceptor_end: redis::info case: strings -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::get +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::get Redis::get before: a -[pinpoint] [%d] [%d] call_interceptor_before:redis::get return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::get return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::get end -[pinpoint] [%d] [%d]call_interceptor_end: redis::get -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::set +[pinpoint] [%d:%d]call_interceptor_end: redis::get +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::set Redis::set before: a : b -[pinpoint] [%d] [%d] call_interceptor_before:redis::set return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::set return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::set end -[pinpoint] [%d] [%d]call_interceptor_end: redis::set -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::setnx +[pinpoint] [%d:%d]call_interceptor_end: redis::set +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::setnx Redis::setNx before: a : 10 -[pinpoint] [%d] [%d] call_interceptor_before:redis::setnx return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::setnx return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::setNx end -[pinpoint] [%d] [%d]call_interceptor_end: redis::setnx -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::append +[pinpoint] [%d:%d]call_interceptor_end: redis::setnx +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::append Redis::append before: ar : aa -[pinpoint] [%d] [%d] call_interceptor_before:redis::append return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::append return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::append end -[pinpoint] [%d] [%d]call_interceptor_end: redis::append -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::setrange +[pinpoint] [%d:%d]call_interceptor_end: redis::append +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::setrange Redis::setRange before: ar -[pinpoint] [%d] [%d] call_interceptor_before:redis::setrange return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::setrange return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::setRange end -[pinpoint] [%d] [%d]call_interceptor_end: redis::setrange -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::get +[pinpoint] [%d:%d]call_interceptor_end: redis::setrange +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::get Redis::get before: ar -[pinpoint] [%d] [%d] call_interceptor_before:redis::get return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::get return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::get end -[pinpoint] [%d] [%d]call_interceptor_end: redis::get -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::getrange +[pinpoint] [%d:%d]call_interceptor_end: redis::get +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::getrange Redis::getRange before: ar -[pinpoint] [%d] [%d] call_interceptor_before:redis::getrange return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::getrange return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::getRange end -[pinpoint] [%d] [%d]call_interceptor_end: redis::getrange -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::strlen +[pinpoint] [%d:%d]call_interceptor_end: redis::getrange +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::strlen Redis::strlen before: ar -[pinpoint] [%d] [%d] call_interceptor_before:redis::strlen return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::strlen return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::strlen end -[pinpoint] [%d] [%d]call_interceptor_end: redis::strlen -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::getbit +[pinpoint] [%d:%d]call_interceptor_end: redis::strlen +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::getbit Redis::getBit before: ar : 1 -[pinpoint] [%d] [%d] call_interceptor_before:redis::getbit return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::getbit return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::getBit end -[pinpoint] [%d] [%d]call_interceptor_end: redis::getbit -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::setbit +[pinpoint] [%d:%d]call_interceptor_end: redis::getbit +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::setbit Redis::setBit before: ar -[pinpoint] [%d] [%d] call_interceptor_before:redis::setbit return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::setbit return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::setBit end -[pinpoint] [%d] [%d]call_interceptor_end: redis::setbit -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::get +[pinpoint] [%d:%d]call_interceptor_end: redis::setbit +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::get Redis::get before: ar -[pinpoint] [%d] [%d] call_interceptor_before:redis::get return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::get return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::get end -[pinpoint] [%d] [%d]call_interceptor_end: redis::get +[pinpoint] [%d:%d]call_interceptor_end: redis::get string(2) "bb" -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::mset +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::mset Redis::mSet before: -[pinpoint] [%d] [%d] call_interceptor_before:redis::mset return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::mset return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::mSet end -[pinpoint] [%d] [%d]call_interceptor_end: redis::mset +[pinpoint] [%d:%d]call_interceptor_end: redis::mset int(3) -[pinpoint] [%d] [%d]start free interceptor: redis::info -[pinpoint] [%d] [%d]start free interceptor: redis::get -[pinpoint] [%d] [%d]start free interceptor: redis::set -[pinpoint] [%d] [%d]start free interceptor: redis::setnx -[pinpoint] [%d] [%d]start free interceptor: redis::append -[pinpoint] [%d] [%d]start free interceptor: redis::getrange -[pinpoint] [%d] [%d]start free interceptor: redis::setrange -[pinpoint] [%d] [%d]start free interceptor: redis::strlen -[pinpoint] [%d] [%d]start free interceptor: redis::getbit -[pinpoint] [%d] [%d]start free interceptor: redis::setbit -[pinpoint] [%d] [%d]start free interceptor: redis::mset -[pinpoint] [%d] [%d]start free interceptor: redis::msetnx \ No newline at end of file +[pinpoint] [%d:%d]start free interceptor: redis::info +[pinpoint] [%d:%d]start free interceptor: redis::get +[pinpoint] [%d:%d]start free interceptor: redis::set +[pinpoint] [%d:%d]start free interceptor: redis::setnx +[pinpoint] [%d:%d]start free interceptor: redis::append +[pinpoint] [%d:%d]start free interceptor: redis::getrange +[pinpoint] [%d:%d]start free interceptor: redis::setrange +[pinpoint] [%d:%d]start free interceptor: redis::strlen +[pinpoint] [%d:%d]start free interceptor: redis::getbit +[pinpoint] [%d:%d]start free interceptor: redis::setbit +[pinpoint] [%d:%d]start free interceptor: redis::mset +[pinpoint] [%d:%d]start free interceptor: redis::msetnx \ No newline at end of file diff --git a/tests/stack_fetal_error.phpt b/tests/stack_fetal_error.phpt index dbbc0d221..2076bdfe5 100644 --- a/tests/stack_fetal_error.phpt +++ b/tests/stack_fetal_error.phpt @@ -36,7 +36,7 @@ class Foo{ } function Test(){ - throw new \Exception("I am testting"); + throw new \Exception("I am testing"); } _pinpoint_start_trace(); @@ -50,18 +50,18 @@ try{ _pinpoint_start_trace(); --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] -[pinpoint] [%d] [%d] [128] pinpoint_start child [127] -[pinpoint] [%d] [%d] [127] add clue key:name value:Foo -[pinpoint] [%d] [%d]apm_error_cb called +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [128] pinpoint_start child [127] +[pinpoint] [%d:%d] [127] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d]apm_error_cb called -Fatal error: Uncaught Exception: I am testting in %s:27 +Fatal error: Uncaught Exception: I am testing in %s:27 Stack trace: #0 %s(34): Test() #1 {main} 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:(:/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 +[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 testing in %s:27\nStack trace:\n#0 %s(34): Test()\n#1 {main}\n thrown"},"event":[{":E":%d,":S":%d,":depth":1,":seq":0,"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/trace_api_context.phpt b/tests/trace_api_context.phpt index 7926469c4..867699b6c 100644 --- a/tests/trace_api_context.phpt +++ b/tests/trace_api_context.phpt @@ -43,28 +43,28 @@ _pinpoint_end_trace($id); pinpoint_status(); ?> --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [0] pinpoint_start child [128] string(1) "a" string(1) "b" string(1) "c" -[pinpoint] [%d] [%d] pinpoint_get_context_key [128] failed with map::at, parameters:not exist +[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:(:/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] +[pinpoint] [%d:%d]this span:({":E":%d,":FT":1500,":S":%d}) +[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] string(1) "c" string(1) "b" string(1) "a" -[pinpoint] [%d] [%d] pinpoint_get_context_key [127] failed with map::at, parameters:not exist +[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:({":E":%d,":FT":1500,":S":%d,"calls":[{":E":%d,":S":%d}]}) -[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [127] pinpoint_end_trace Done! +[pinpoint] [%d:%d]this span:({":E":%d,":FT":1500,":S":%d,"event":[{":E":%d,":S":%d,":depth":1,":seq":0}]}) +[pinpoint] [%d:%d] [128] pinpoint_end_trace Done! { - "common_library_version" : "0.5.0", + "common_library_version" : "0.6.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 cb46e434a..9ad00817d 100644 --- a/tests/trace_api_context_tcp.phpt +++ b/tests/trace_api_context_tcp.phpt @@ -4,7 +4,7 @@ Check call statck --INI-- pinpoint_php.CollectorHost=tcp:127.0.0.1:9999 -pinpoint_php.SendSpanTimeOutMs=0 +pinpoint_php.SendSpanTimeOutMs=-1 pinpoint_php.UnitTest=true ;pinpoint_php._limit for internal use. User do not use it pinpoint_php._limit=yes @@ -43,30 +43,28 @@ _pinpoint_end_trace($id); pinpoint_status(); ?> --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [0] pinpoint_start child [128] string(1) "a" string(1) "b" string(1) "c" -[pinpoint] [%d] [%d] pinpoint_get_context_key [128] failed with map::at, parameters:not exist +[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:(127.0.0.1:9999) -[pinpoint] [%d] [%d]write event -[pinpoint] [%d] [%d]_do_write_data@%d send data error:(%d) fd:(%d) -[pinpoint] [%d] [%d]reset peer:%d -[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done! -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] -[pinpoint] [%d] [%d] [128] pinpoint_start child [127] +[pinpoint] [%d:%d]this span:({":E":%d,":FT":1500,":S":%d}) +[pinpoint] [%d:%d][unittest] current span was dropped +[pinpoint] [%d:%d] [128] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [128] pinpoint_start child [127] string(1) "c" string(1) "b" string(1) "a" -[pinpoint] [%d] [%d] pinpoint_get_context_key [127] failed with map::at, parameters:not exist +[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:({":E":%d,":FT":1500,":S":%d,"calls":[{":E":%d,":S":%d}]}) -[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [127] pinpoint_end_trace Done! +[pinpoint] [%d:%d]this span:({":E":%d,":FT":1500,":S":%d,"event":[{":E":%d,":S":%d,":depth":1,":seq":0}]}) +[pinpoint] [%d:%d][unittest] current span was dropped +[pinpoint] [%d:%d] [128] pinpoint_end_trace Done! { - "common_library_version" : "0.5.0", + "common_library_version" : "0.6.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 8ab82c655..817c8f2d6 100644 --- a/tests/trace_api_test.phpt +++ b/tests/trace_api_test.phpt @@ -53,83 +53,83 @@ echo _pinpoint_end_trace()."\n"; ?> --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [0] pinpoint_start child [128] 128 -[pinpoint] [%d] [%d] [128] add clue key:name value:ouput_234 -[pinpoint] [%d] [%d] [128] pinpoint_start child [127] +[pinpoint] [%d:%d] [128] add anno_v1 key:name value:ouput_234 +[pinpoint] [%d:%d] [128] pinpoint_start child [127] 127 -[pinpoint] [%d] [%d] [127] add clue key:name value:Foo -[pinpoint] [%d] [%d] [127] add clues:1:234,3432 -[pinpoint] [%d] [%d] [127] add clues:2:234 -[pinpoint] [%d] [%d] [127] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [127] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [127] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [127] add anno_v2 2:234 +[pinpoint] [%d:%d] [127] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [126] +[pinpoint] [%d:%d] [128] pinpoint_start child [126] 126 -[pinpoint] [%d] [%d] [126] add clue key:name value:Foo -[pinpoint] [%d] [%d] [126] add clues:1:234,3432 -[pinpoint] [%d] [%d] [126] add clues:2:234 -[pinpoint] [%d] [%d] [126] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [126] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [126] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [126] add anno_v2 2:234 +[pinpoint] [%d:%d] [126] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [125] +[pinpoint] [%d:%d] [128] pinpoint_start child [125] 125 -[pinpoint] [%d] [%d] [125] add clue key:name value:Foo -[pinpoint] [%d] [%d] [125] add clues:1:234,3432 -[pinpoint] [%d] [%d] [125] add clues:2:234 -[pinpoint] [%d] [%d] [125] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [125] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [125] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [125] add anno_v2 2:234 +[pinpoint] [%d:%d] [125] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [124] +[pinpoint] [%d:%d] [128] pinpoint_start child [124] 124 -[pinpoint] [%d] [%d] [124] add clue key:name value:Foo -[pinpoint] [%d] [%d] [124] add clues:1:234,3432 -[pinpoint] [%d] [%d] [124] add clues:2:234 -[pinpoint] [%d] [%d] [124] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [124] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [124] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [124] add anno_v2 2:234 +[pinpoint] [%d:%d] [124] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [123] +[pinpoint] [%d:%d] [128] pinpoint_start child [123] 123 -[pinpoint] [%d] [%d] [123] add clue key:name value:Foo -[pinpoint] [%d] [%d] [123] add clues:1:234,3432 -[pinpoint] [%d] [%d] [123] add clues:2:234 -[pinpoint] [%d] [%d] [123] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [123] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [123] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [123] add anno_v2 2:234 +[pinpoint] [%d:%d] [123] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [122] +[pinpoint] [%d:%d] [128] pinpoint_start child [122] 122 -[pinpoint] [%d] [%d] [122] add clue key:name value:Foo -[pinpoint] [%d] [%d] [122] add clues:1:234,3432 -[pinpoint] [%d] [%d] [122] add clues:2:234 -[pinpoint] [%d] [%d] [122] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [122] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [122] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [122] add anno_v2 2:234 +[pinpoint] [%d:%d] [122] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [121] +[pinpoint] [%d:%d] [128] pinpoint_start child [121] 121 -[pinpoint] [%d] [%d] [121] add clue key:name value:Foo -[pinpoint] [%d] [%d] [121] add clues:1:234,3432 -[pinpoint] [%d] [%d] [121] add clues:2:234 -[pinpoint] [%d] [%d] [121] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [121] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [121] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [121] add anno_v2 2:234 +[pinpoint] [%d:%d] [121] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [120] +[pinpoint] [%d:%d] [128] pinpoint_start child [120] 120 -[pinpoint] [%d] [%d] [120] add clue key:name value:Foo -[pinpoint] [%d] [%d] [120] add clues:1:234,3432 -[pinpoint] [%d] [%d] [120] add clues:2:234 -[pinpoint] [%d] [%d] [120] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [120] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [120] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [120] add anno_v2 2:234 +[pinpoint] [%d:%d] [120] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [119] +[pinpoint] [%d:%d] [128] pinpoint_start child [119] 119 -[pinpoint] [%d] [%d] [119] add clue key:name value:Foo -[pinpoint] [%d] [%d] [119] add clues:1:234,3432 -[pinpoint] [%d] [%d] [119] add clues:2:234 -[pinpoint] [%d] [%d] [119] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [119] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [119] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [119] add anno_v2 2:234 +[pinpoint] [%d:%d] [119] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [118] +[pinpoint] [%d:%d] [128] pinpoint_start child [118] 118 -[pinpoint] [%d] [%d] [118] add clue key:name value:Foo -[pinpoint] [%d] [%d] [118] add clues:1:234,3432 -[pinpoint] [%d] [%d] [118] add clues:2:234 -[pinpoint] [%d] [%d] [118] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [118] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [118] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [118] add anno_v2 2:234 +[pinpoint] [%d:%d] [118] pinpoint_end_trace Done! 128 -[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:(:/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] [128] add anno_v1 key:args value:a,$b +[pinpoint] [%d:%d] [128] add anno_v1 key:ret value:a,$b +[pinpoint] [%d:%d]this span:({":E":%d,":FT":1500,":S":%d,"args":"a,$b","event":[{":E":%d,":S":%d,":depth":1,":seq":0,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":1,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":2,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":3,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":4,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":5,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":6,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":7,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":8,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":9,"anno":["1:234,3432","2:234"],"name":"Foo"}],"name":"ouput_234","ret":"a,$b"}) +[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 51457e7f9..33fdd8c08 100644 --- a/tests/trace_api_with_id.phpt +++ b/tests/trace_api_with_id.phpt @@ -45,22 +45,22 @@ _pinpoint_add_clue("name","Foo",$id); $id = _pinpoint_end_trace($id); --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] -[pinpoint] [%d] [%d] [128] add clue key:name value:Foo -[pinpoint] [%d] [%d] [128] pinpoint_start child [127] -[pinpoint] [%d] [%d] [127] add clues:name:Foo1 -[pinpoint] [%d] [%d] [127] pinpoint_start child [126] -[pinpoint] [%d] [%d] [126] add clue key:name value:Foo2 -[pinpoint] [%d] [%d] [126] pinpoint_end_trace Done! -[pinpoint] [%d] [%d] [127] pinpoint_start child [125] -[pinpoint] [%d] [%d] [125] add clues:name:Foo3 -[pinpoint] [%d] [%d] [125] add clue key:name value:Foo4 -[pinpoint] [%d] [%d] [125] pinpoint_end_trace Done! -[pinpoint] [%d] [%d] [127] add clues:name:Foo5 -[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:(:/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] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [128] pinpoint_start child [127] +[pinpoint] [%d:%d] [127] add anno_v2 name:Foo1 +[pinpoint] [%d:%d] [127] pinpoint_start child [126] +[pinpoint] [%d:%d] [126] add anno_v1 key:name value:Foo2 +[pinpoint] [%d:%d] [126] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [127] pinpoint_start child [125] +[pinpoint] [%d:%d] [125] add anno_v2 name:Foo3 +[pinpoint] [%d:%d] [125] add anno_v1 key:name value:Foo4 +[pinpoint] [%d:%d] [125] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [127] add anno_v2 name:Foo5 +[pinpoint] [%d:%d] [127] add anno_v1 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,"event":[{":E":%d,":S":%d,":depth":1,":seq":0,"EXP":"too heavy, throw it","anno":["name:Foo1","name:Foo5"]},{":E":%d,":S":%d,":depth":2,":seq":1,"name":"Foo2"},{":E":%d,":S":%d,":depth":2,":seq":2,"anno":["name:Foo3"],"name":"Foo4"}],"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! Uncaught exception: too heavy, throw it \ No newline at end of file diff --git a/tests/trace_had_root.phpt b/tests/trace_had_root.phpt new file mode 100644 index 000000000..d565be5eb --- /dev/null +++ b/tests/trace_had_root.phpt @@ -0,0 +1,40 @@ +--TEST-- +Test trace_had_root +--SKIPIF-- + +--INI-- +pinpoint_php.CollectorHost=unix:/unexist_file.sock +pinpoint_php.SendSpanTimeOutMs=-1 +pinpoint_php.UnitTest=true +pinpoint_php.DebugReport=true + +--FILE-- + +--EXPECTF-- +case not trace pass +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +case root trace pass +[pinpoint] [%d:%d] [128] pinpoint_start child [127] +case sub trace pass +[pinpoint] [%d:%d] [127] pinpoint_end_trace Done! +[pinpoint] [%d:%d]this span:({":E":%d,":FT":1500,":S":%d,"event":[{":E":%d,":S":%d,":depth":1,":seq":0}]}) +[pinpoint] [%d:%d][unittest] current span was dropped +[pinpoint] [%d:%d] [128] pinpoint_end_trace Done! \ No newline at end of file diff --git a/tests/trace_limit_test-i448.phpt b/tests/trace_limit_test-i448.phpt index 5067f09b4..0270a516d 100644 --- a/tests/trace_limit_test-i448.phpt +++ b/tests/trace_limit_test-i448.phpt @@ -34,15 +34,15 @@ if(_pinpoint_trace_limit()) _pinpoint_end_trace($id); --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] -[pinpoint] [%d] [%d] [128] pinpoint_start child [127] +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [128] pinpoint_start child [127] string(1) "c" string(1) "b" string(1) "a" -[pinpoint] [%d] [%d] pinpoint_get_context_key [127] failed with map::at, parameters:not exist +[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: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 +[pinpoint] [%d:%d] [127] pinpoint_end_trace Done! +[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 e963ef034..6c710dcd1 100644 --- a/tests/trace_limit_test.phpt +++ b/tests/trace_limit_test.phpt @@ -19,5 +19,5 @@ if(_pinpoint_trace_limit() || _pinpoint_trace_limit() ||_pinpoint_trace_limit() echo "_pinpoint_trace_limit failed"; } --EXPECTF-- -[pinpoint] [%d] [%d]This span dropped. max_trace_limit:2 current_tick:2 onLine:0 +[pinpoint] [%d:%d]This span dropped. max_trace_limit:2 current_tick:2 onLine:0 pass \ No newline at end of file diff --git a/tests_macos/add_root_trace.phpt b/tests_macos/add_root_trace.phpt index 5aad9b2c4..33f0b35eb 100644 --- a/tests_macos/add_root_trace.phpt +++ b/tests_macos/add_root_trace.phpt @@ -21,16 +21,16 @@ $id = _pinpoint_end_trace($id); $id = _pinpoint_end_trace($id); $id = _pinpoint_end_trace($id); --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] -[pinpoint] [%d] [%d] [128] add clue key:name value:Foo -[pinpoint] [%d] [%d] [128] pinpoint_start child [127] -[pinpoint] [%d] [%d] [127] add clues:global:global_value -[pinpoint] [%d] [%d] [127] add clue key:global value:global_value -[pinpoint] [%d] [%d] [127] add clues:name:Foo1 -[pinpoint] [%d] [%d] [127] pinpoint_start child [126] -[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":%d,":S":%d,"name":"Foo2"}],"clues":["name:Foo1"]}],"clues":["global:global_value"],"global":"global_value","name":"Foo"}) -[pinpoint] [%d] [%d][unittest] current span was dropped -[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done! \ No newline at end of file +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [128] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [128] pinpoint_start child [127] +[pinpoint] [%d:%d] [127] add anno_v2 global:global_value +[pinpoint] [%d:%d] [127] add anno_v1 key:global value:global_value +[pinpoint] [%d:%d] [127] add anno_v2 name:Foo1 +[pinpoint] [%d:%d] [127] pinpoint_start child [126] +[pinpoint] [%d:%d] [126] add anno_v1 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,"anno":["global:global_value"],"event":[{":E":%d,":S":%d,":depth":1,":seq":0,"anno":["name:Foo1"]},{":E":%d,":S":%d,":depth":2,":seq":1,"name":"Foo2"}],"global":"global_value","name":"Foo"}) +[pinpoint] [%d:%d][unittest] current span was dropped +[pinpoint] [%d:%d] [128] pinpoint_end_trace Done! \ No newline at end of file diff --git a/tests_macos/aop_helper_api.phpt b/tests_macos/aop_helper_api.phpt deleted file mode 100644 index 937e17422..000000000 --- a/tests_macos/aop_helper_api.phpt +++ /dev/null @@ -1,194 +0,0 @@ ---TEST-- -app info ---SKIPIF-- - ---INI-- -pinpoint_php.DebugReport=false ---FILE-- -foo('hello pinpoint',1,array('1'=>2,'c'=>3,'e'=>5)); -Foo::static_foo('hello pinpoint',1,array('1'=>2,'c'=>3,'e'=>5)); -$foo->test_none(); -var_dump($foo->return_all("23",1,null)); - -echo "test anonymous \n"; -$name = 'eeliu'; -$nobody = function ($arg) use (&$name) { - var_dump(\pinpoint_get_func_ref_args()); - $name = 'eeliu-01'; - $arg = $arg.$name; - return \pinpoint_get_func_ref_args(); -}; -var_dump($nobody("hello ")); -echo "\n"; - -echo "test pinpoint_get_func_ref_args call in call_user_func_array \n"; - -function foo_ref($a,&$b,&$c) -{ - var_dump(func_get_args()); - $b = 10; - $c = 11; - return array($b,$c); -} - -function aop_foo_ref($a,&$b,&$c) -{ - $args = \pinpoint_get_func_ref_args(); - return call_user_func_array('foo_ref',$args); -} -$b =2; -$c = 12; -var_dump(aop_foo_ref("adf",$b,$c)); -echo "b = $b \n"; -echo "c = $c \n"; - ---EXPECTF-- -array(4) { - [0]=> - &int(100) - [1]=> - int(1) - [2]=> - int(3) - [3]=> - int(4) -} -string(12) "hello php!!!" - -Warning: pinpoint_get_func_ref_args(): Called from the global scope - no function context in %s on line 18 -bool(false) -call __construct -array(2) { - [0]=> - int(1) - [1]=> - int(2) -} -array(3) { - [0]=> - string(14) "hello pinpoint" - [1]=> - int(1) - [2]=> - array(3) { - [1]=> - int(2) - ["c"]=> - int(3) - ["e"]=> - int(5) - } -} -array(3) { - [0]=> - string(14) "hello pinpoint" - [1]=> - int(1) - [2]=> - array(3) { - [1]=> - int(2) - ["c"]=> - int(3) - ["e"]=> - int(5) - } -} -array(0) { -} -array(3) { - [0]=> - string(2) "23" - [1]=> - int(1) - [2]=> - NULL -} -test anonymous -array(1) { - [0]=> - string(6) "hello " -} -array(1) { - [0]=> - string(14) "hello eeliu-01" -} - -test pinpoint_get_func_ref_args call in call_user_func_array -array(3) { - [0]=> - string(3) "adf" - [1]=> - int(2) - [2]=> - int(12) -} -array(2) { - [0]=> - int(10) - [1]=> - int(11) -} -b = 10 -c = 11 -call __destruct -array(0) { -} \ No newline at end of file diff --git a/tests_macos/drop_trace_test.phpt b/tests_macos/drop_trace_test.phpt index 68da7e593..dacdb316f 100644 --- a/tests_macos/drop_trace_test.phpt +++ b/tests_macos/drop_trace_test.phpt @@ -15,9 +15,9 @@ _pinpoint_add_clue("args",'a,$b'); _pinpoint_add_clue("ret",'a,$b'); _pinpoint_end_trace(); --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] -[pinpoint] [%d] [%d]change current [128] status, before:2,now:4 -[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]current [128] span dropped,due to TRACE_BLOCK -[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done! \ No newline at end of file +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d]change current [128] status, before:2,now:4 +[pinpoint] [%d:%d] [128] add anno_v1 key:args value:a,$b +[pinpoint] [%d:%d] [128] add anno_v1 key:ret value:a,$b +[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_macos/mark_as_error.phpt b/tests_macos/mark_as_error.phpt index 93800c286..2c91fde67 100644 --- a/tests_macos/mark_as_error.phpt +++ b/tests_macos/mark_as_error.phpt @@ -17,10 +17,10 @@ _pinpoint_add_clue("ret",'a,$b'); _pinpoint_mark_as_error("message you cared","filename you cared",1023); echo _pinpoint_end_trace()."\n"; --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] -[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][unittest] current span was dropped -[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [128] add anno_v1 key:args value:a,$b +[pinpoint] [%d:%d] [128] add anno_v1 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][unittest] current span was dropped +[pinpoint] [%d:%d] [128] pinpoint_end_trace Done! 0 \ No newline at end of file diff --git a/tests_macos/node_test.phpt b/tests_macos/node_test.phpt index 24ac02760..e5c5b2410 100644 --- a/tests_macos/node_test.phpt +++ b/tests_macos/node_test.phpt @@ -25,11 +25,11 @@ _pinpoint_get_context('b',$unexist_node); _pinpoint_end_trace($unexist_node); --EXPECTF-- -[pinpoint] [%d] [%d] start_trace [1024] failed with #1024 is not alive -[pinpoint] [%d] [%d] pinpoint_add_clue [1024] failed. Reason: #1024 is not alive,parameters:adf:fdfd -[pinpoint] [%d] [%d] pinpoint_add_clue [1024] failed. Reason: #1024 is not alive,parameters:adf:fdfd -[pinpoint] [%d] [%d] pinpoint_set_context_key [1024] failed with out_of_range. #1024 is not alive,parameters:b:b -[pinpoint] [%d] [%d] pinpoint_add_clues [1024] failed. Reason #1024 is not alive,parameters:32:fdfd -[pinpoint] [%d] [%d] pinpoint_add_clues [1024] failed. Reason #1024 is not alive,parameters:32:fdfd -[pinpoint] [%d] [%d] pinpoint_get_context_key [1024] failed with #1024 is not alive, parameters:b -[pinpoint] [%d] [%d]end_trace 1024 out_of_range exception: #1024 is not alive \ No newline at end of file +[pinpoint] [%d:%d] start_trace [1024] failed with #1024 is not alive +[pinpoint] [%d:%d] pinpoint_add_clue [1024] failed. Reason: #1024 is not alive,parameters:adf:fdfd +[pinpoint] [%d:%d] pinpoint_add_clue [1024] failed. Reason: #1024 is not alive,parameters:adf:fdfd +[pinpoint] [%d:%d] pinpoint_set_context_key [1024] failed with out_of_range. #1024 is not alive,parameters:b:b +[pinpoint] [%d:%d] pinpoint_add_clues [1024] failed. Reason #1024 is not alive,parameters:32:fdfd +[pinpoint] [%d:%d] pinpoint_add_clues [1024] failed. Reason #1024 is not alive,parameters:32:fdfd +[pinpoint] [%d:%d] pinpoint_get_context_key [1024] failed with #1024 is not alive, parameters:b +[pinpoint] [%d:%d]end_trace 1024 out_of_range exception: #1024 is not alive \ No newline at end of file diff --git a/tests_macos/pinpoint_get_caller_arg.phpt b/tests_macos/pinpoint_get_caller_arg.phpt index 9dfb10dd2..2711f3169 100644 --- a/tests_macos/pinpoint_get_caller_arg.phpt +++ b/tests_macos/pinpoint_get_caller_arg.phpt @@ -51,13 +51,13 @@ echo "error: $error\n"; curl_close($ch); --EXPECTF-- -[pinpoint] [%d] [%d]try to interceptor function=curl_exec -[pinpoint] [%d] [%d]added interceptor on `function`: curl_exec success +[pinpoint] [%d:%d]try to interceptor function=curl_exec +[pinpoint] [%d:%d]added interceptor on `function`: curl_exec success case: curl_init() -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_exec -[pinpoint] [%d] [%d] call_interceptor_before:curl_exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_exec +[pinpoint] [%d:%d] call_interceptor_before:curl_exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` status_code 200 -[pinpoint] [%d] [%d]call_interceptor_end: curl_exec +[pinpoint] [%d:%d]call_interceptor_end: curl_exec error: -[pinpoint] [%d] [%d]start free interceptor: curl_exec \ No newline at end of file +[pinpoint] [%d:%d]start free interceptor: curl_exec \ No newline at end of file diff --git a/tests_macos/pinpoint_get_this.phpt b/tests_macos/pinpoint_get_this.phpt index babd50895..ae5027fb2 100644 --- a/tests_macos/pinpoint_get_this.phpt +++ b/tests_macos/pinpoint_get_this.phpt @@ -54,8 +54,8 @@ string(3) "123" update foo members int(1234) string(14) "hello pinpoint" -[pinpoint] [%d] [%d]pinpoint_get_this: not support, no this +[pinpoint] [%d:%d]pinpoint_get_this: not support, no this bool(false) test static method -[pinpoint] [%d] [%d]pinpoint_get_this: not support, no this +[pinpoint] [%d:%d]pinpoint_get_this: not support, no this bool(false) \ No newline at end of file diff --git a/tests_macos/pinpoint_join_cut_curl_7.phpt b/tests_macos/pinpoint_join_cut_curl_7.phpt index 72ef024dd..3e8421332 100644 --- a/tests_macos/pinpoint_join_cut_curl_7.phpt +++ b/tests_macos/pinpoint_join_cut_curl_7.phpt @@ -40,7 +40,7 @@ _pinpoint_join_cut( function ($e) { echo "on_exception \n"; var_dump($e); - } + }, ); _pinpoint_join_cut( @@ -57,7 +57,7 @@ _pinpoint_join_cut( function ($e) { echo "on_exception \n"; var_dump($e); - } + }, ); _pinpoint_join_cut( @@ -89,7 +89,7 @@ _pinpoint_join_cut( function ($e) { echo "on_exception \n"; var_dump($e); - } + }, ); @@ -134,100 +134,100 @@ echo "error:$error \n"; curl_close($ch); --EXPECTF-- -[pinpoint] [%d] [%d]try to interceptor function=curl_init -[pinpoint] [%d] [%d]added interceptor on `function`: curl_init success -[pinpoint] [%d] [%d]try to interceptor function=curl_exec -[pinpoint] [%d] [%d]added interceptor on `function`: curl_exec success -[pinpoint] [%d] [%d]try to interceptor function=curl_setopt -[pinpoint] [%d] [%d]added interceptor on `function`: curl_setopt success +[pinpoint] [%d:%d]try to interceptor function=curl_init +[pinpoint] [%d:%d]added interceptor on `function`: curl_init success +[pinpoint] [%d:%d]try to interceptor function=curl_exec +[pinpoint] [%d:%d]added interceptor on `function`: curl_exec success +[pinpoint] [%d:%d]try to interceptor function=curl_setopt +[pinpoint] [%d:%d]added interceptor on `function`: curl_setopt success case: curl_init() -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_init +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_init on_before NULL -[pinpoint] [%d] [%d] call_interceptor_before:curl_init return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:curl_init return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end resource(4) of type (curl) -get resource [pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +get resource [pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(42) -not working[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +not working[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]call_interceptor_end: curl_init -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_init +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(10002) test CURLOPT_URL -[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval -[pinpoint] [%d] [%d]argv size:2 -[pinpoint] [%d] [%d]error: replace_ex_caller_parameters return `size` does not matched +[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(7) zval +[pinpoint] [%d:%d]argv size:2 +[pinpoint] [%d:%d]error: replace_ex_caller_parameters return `size` does not match on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(19913) test CURLOPT_RETURNTRANSFER -[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval -[pinpoint] [%d] [%d]argv size:3 -[pinpoint] [%d] [%d]error: replace_ex_caller_parameters return `type` does not matched expected:3 give:4 +[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(7) zval +[pinpoint] [%d:%d]argv size:3 +[pinpoint] [%d:%d]error: replace_ex_caller_parameters return `type` does not match expected:3 give:4 on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(10023) value must be affected -[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval -[pinpoint] [%d] [%d]argv size:3 -[pinpoint] [%d] [%d]args[2] type:7 in:1 va:2 +[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(7) zval +[pinpoint] [%d:%d]argv size:3 +[pinpoint] [%d:%d]args[2] type:7 in:1 va:2 on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_exec +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_exec on_before resource(4) of type (curl) request url: http://httpbin.org/anything -[pinpoint] [%d] [%d] call_interceptor_before:curl_exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:curl_exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_exec +[pinpoint] [%d:%d]call_interceptor_end: curl_exec error: case : curl_init with variable -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_init +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_init on_before string(27) "http://httpbin.org/anything" -[pinpoint] [%d] [%d] call_interceptor_before:curl_init return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:curl_init return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end resource(5) of type (curl) -get resource [pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +get resource [pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(42) -not working[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +not working[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]call_interceptor_end: curl_init -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_init +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(19913) test CURLOPT_RETURNTRANSFER -[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval -[pinpoint] [%d] [%d]argv size:3 -[pinpoint] [%d] [%d]error: replace_ex_caller_parameters return `type` does not matched expected:3 give:4 +[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(7) zval +[pinpoint] [%d:%d]argv size:3 +[pinpoint] [%d:%d]error: replace_ex_caller_parameters return `type` does not match expected:3 give:4 on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(10023) value must be affected -[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval -[pinpoint] [%d] [%d]argv size:3 -[pinpoint] [%d] [%d]args[2] type:7 in:1 va:2 +[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(7) zval +[pinpoint] [%d:%d]argv size:3 +[pinpoint] [%d:%d]args[2] type:7 in:1 va:2 on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_exec +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_exec on_before resource(5) of type (curl) request url: http://httpbin.org/anything -[pinpoint] [%d] [%d] call_interceptor_before:curl_exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:curl_exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_exec +[pinpoint] [%d:%d]call_interceptor_end: curl_exec error: -[pinpoint] [%d] [%d]start free interceptor: curl_init -[pinpoint] [%d] [%d]start free interceptor: curl_exec -[pinpoint] [%d] [%d]start free interceptor: curl_setopt \ No newline at end of file +[pinpoint] [%d:%d]start free interceptor: curl_init +[pinpoint] [%d:%d]start free interceptor: curl_exec +[pinpoint] [%d:%d]start free interceptor: curl_setopt \ No newline at end of file diff --git a/tests_macos/pinpoint_join_cut_curl_8.phpt b/tests_macos/pinpoint_join_cut_curl_8.phpt index ba1726d12..e45e1ba41 100644 --- a/tests_macos/pinpoint_join_cut_curl_8.phpt +++ b/tests_macos/pinpoint_join_cut_curl_8.phpt @@ -10,7 +10,7 @@ if (version_compare(phpversion(), '8.0.0', '<')){ print "skip only works in php8"; } if(getenv('SKIP_WINDOWS_ACTION', true)){ - print "skip"; + print "skip"; } ?> --INI-- @@ -131,104 +131,104 @@ echo "error:$error \n"; curl_close($ch); --EXPECTF-- -[pinpoint] [%d] [%d]try to interceptor function=curl_init -[pinpoint] [%d] [%d]added interceptor on `function`: curl_init success -[pinpoint] [%d] [%d]try to interceptor function=curl_exec -[pinpoint] [%d] [%d]added interceptor on `function`: curl_exec success -[pinpoint] [%d] [%d]try to interceptor function=curl_setopt -[pinpoint] [%d] [%d]added interceptor on `function`: curl_setopt success +[pinpoint] [%d:%d]try to interceptor function=curl_init +[pinpoint] [%d:%d]added interceptor on `function`: curl_init success +[pinpoint] [%d:%d]try to interceptor function=curl_exec +[pinpoint] [%d:%d]added interceptor on `function`: curl_exec success +[pinpoint] [%d:%d]try to interceptor function=curl_setopt +[pinpoint] [%d:%d]added interceptor on `function`: curl_setopt success case: curl_init() -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_init +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_init on_before NULL -[pinpoint] [%d] [%d] call_interceptor_before:curl_init return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:curl_init return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end object(CurlHandle)#10 (0) { } -get resource [pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +get resource [pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(42) -not working[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +not working[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]call_interceptor_end: curl_init -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_init +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(10002) test CURLOPT_URL -[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval -[pinpoint] [%d] [%d]argv size:2 -[pinpoint] [%d] [%d]error: replace_ex_caller_parameters return `size` does not matched +[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(7) zval +[pinpoint] [%d:%d]argv size:2 +[pinpoint] [%d:%d]error: replace_ex_caller_parameters return `size` does not match on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(19913) test CURLOPT_RETURNTRANSFER -[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval -[pinpoint] [%d] [%d]argv size:3 -[pinpoint] [%d] [%d]error: replace_ex_caller_parameters return `type` does not matched expected:3 give:4 +[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(7) zval +[pinpoint] [%d:%d]argv size:3 +[pinpoint] [%d:%d]error: replace_ex_caller_parameters return `type` does not match expected:3 give:4 on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(10023) value must be affected -[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval -[pinpoint] [%d] [%d]argv size:3 -[pinpoint] [%d] [%d]args[2] type:7 in:1 va:2 +[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(7) zval +[pinpoint] [%d:%d]argv size:3 +[pinpoint] [%d:%d]args[2] type:7 in:1 va:2 on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_exec +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_exec on_before object(CurlHandle)#10 (0) { } request url: http://httpbin.org/anything -[pinpoint] [%d] [%d] call_interceptor_before:curl_exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:curl_exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_exec +[pinpoint] [%d:%d]call_interceptor_end: curl_exec error: case : curl_init with variable -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_init +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_init on_before string(27) "http://httpbin.org/anything" -[pinpoint] [%d] [%d] call_interceptor_before:curl_init return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:curl_init return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end object(CurlHandle)#11 (0) { } -get resource [pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +get resource [pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(42) -not working[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +not working[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]call_interceptor_end: curl_init -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_init +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(19913) test CURLOPT_RETURNTRANSFER -[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval -[pinpoint] [%d] [%d]argv size:3 -[pinpoint] [%d] [%d]error: replace_ex_caller_parameters return `type` does not matched expected:3 give:4 +[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(7) zval +[pinpoint] [%d:%d]argv size:3 +[pinpoint] [%d:%d]error: replace_ex_caller_parameters return `type` does not match expected:3 give:4 on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt int(10023) value must be affected -[pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval -[pinpoint] [%d] [%d]argv size:3 -[pinpoint] [%d] [%d]args[2] type:7 in:1 va:2 +[pinpoint] [%d:%d] call_interceptor_before:curl_setopt return type(7) zval +[pinpoint] [%d:%d]argv size:3 +[pinpoint] [%d:%d]args[2] type:7 in:1 va:2 on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_setopt -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_exec +[pinpoint] [%d:%d]call_interceptor_end: curl_setopt +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_exec on_before object(CurlHandle)#11 (0) { } request url: http://httpbin.org/anything -[pinpoint] [%d] [%d] call_interceptor_before:curl_exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:curl_exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: curl_exec +[pinpoint] [%d:%d]call_interceptor_end: curl_exec error: -[pinpoint] [%d] [%d]start free interceptor: curl_init -[pinpoint] [%d] [%d]start free interceptor: curl_exec -[pinpoint] [%d] [%d]start free interceptor: curl_setopt \ No newline at end of file +[pinpoint] [%d:%d]start free interceptor: curl_init +[pinpoint] [%d:%d]start free interceptor: curl_exec +[pinpoint] [%d:%d]start free interceptor: curl_setopt \ No newline at end of file diff --git a/tests_macos/pinpoint_join_cut_extend_pdo.phpt b/tests_macos/pinpoint_join_cut_extend_pdo.phpt index d1c61f04a..8fae0bd3b 100644 --- a/tests_macos/pinpoint_join_cut_extend_pdo.phpt +++ b/tests_macos/pinpoint_join_cut_extend_pdo.phpt @@ -10,11 +10,11 @@ if (version_compare(phpversion(), '8.2.0', '>=')){ print "skip"; print phpversion() . ">= 8.2.0"; } - + if(getenv('SKIP_WINDOWS_ACTION', true)){ print "skip"; } - + ?> --INI-- pinpoint_php.DebugReport=true @@ -99,17 +99,17 @@ $ret = $pdo->exec($sql); --EXPECTF-- -[pinpoint] [%d] [%d]try to interceptor module(class)/function=pdo:__construct -[pinpoint] [%d] [%d]added interceptor on `module`: pdo::__construct success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=pdo:exec -[pinpoint] [%d] [%d]added interceptor on `module`: pdo::exec success -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::__construct +[pinpoint] [%d:%d]try to interceptor module(class)/function=pdo:__construct +[pinpoint] [%d:%d]added interceptor on `module`: pdo::__construct success +[pinpoint] [%d:%d]try to interceptor module(class)/function=pdo:exec +[pinpoint] [%d:%d]added interceptor on `module`: pdo::exec success +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::__construct on_before: mysql:host=dev-mysql;dbname=employees attached dsn -[pinpoint] [%d] [%d] call_interceptor_before:pdo::__construct return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:pdo::__construct return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: pdo::__construct +[pinpoint] [%d:%d]call_interceptor_end: pdo::__construct int(4) object(PDOStatement)#8 (1) { ["queryString"]=> @@ -152,5 +152,5 @@ array(2) { } string(3) "123" string(37) "mysql:host=dev-mysql;dbname=employees" -[pinpoint] [%d] [%d]start free interceptor: pdo::__construct -[pinpoint] [%d] [%d]start free interceptor: pdo::exec \ No newline at end of file +[pinpoint] [%d:%d]start free interceptor: pdo::__construct +[pinpoint] [%d:%d]start free interceptor: pdo::exec \ No newline at end of file diff --git a/tests_macos/pinpoint_join_cut_mysqli.phpt b/tests_macos/pinpoint_join_cut_mysqli.phpt index 08af04fb6..7c1f7eaaa 100644 --- a/tests_macos/pinpoint_join_cut_mysqli.phpt +++ b/tests_macos/pinpoint_join_cut_mysqli.phpt @@ -1,5 +1,5 @@ --TEST-- -pinpoint_php pinpoint_join_cut_mysqli +pinpoint_php pinpoint_join_cut_redis --SKIPIF-- exec($sql); --EXPECTF-- -[pinpoint] [%d] [%d]try to interceptor module(class)/function=pdo:__construct -[pinpoint] [%d] [%d]added interceptor on `module`: pdo::__construct success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=pdo:exec -[pinpoint] [%d] [%d]added interceptor on `module`: pdo::exec success +[pinpoint] [%d:%d]try to interceptor module(class)/function=pdo:__construct +[pinpoint] [%d:%d]added interceptor on `module`: pdo::__construct success +[pinpoint] [%d:%d]try to interceptor module(class)/function=pdo:exec +[pinpoint] [%d:%d]added interceptor on `module`: pdo::exec success case: pdo() -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::__construct +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::__construct on_before: mysql:host=dev-mysql;dbname=employees attached dsn -[pinpoint] [%d] [%d] call_interceptor_before:pdo::__construct return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:pdo::__construct return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: pdo::__construct -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec +[pinpoint] [%d:%d]call_interceptor_end: pdo::__construct +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec PDO::exec: on_before: CREATE table IF NOT EXISTS pdo_test( ID INT( 11 ) AUTO_INCREMENT PRIMARY KEY, Name VARCHAR( 250 ) NOT NULL, AGE tinyint(1) unsigned NOT NULL default '1' ); -[pinpoint] [%d] [%d] call_interceptor_before:pdo::exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:pdo::exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` PDO::exec : on_end -[pinpoint] [%d] [%d]call_interceptor_end: pdo::exec -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec +[pinpoint] [%d:%d]call_interceptor_end: pdo::exec +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec PDO::exec: on_before: INSERT INTO pdo_test (NAME, AGE) VALUES ('a',1),('b',1),('c',3),('d',1); -[pinpoint] [%d] [%d] call_interceptor_before:pdo::exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:pdo::exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` PDO::exec : on_end -[pinpoint] [%d] [%d]call_interceptor_end: pdo::exec +[pinpoint] [%d:%d]call_interceptor_end: pdo::exec int(4) object(PDOStatement)#8 (1) { ["queryString"]=> @@ -166,11 +166,11 @@ array(2) { } string(3) "123" string(37) "mysql:host=dev-mysql;dbname=employees" -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec PDO::exec: on_before: DROP TABLE pdo_test -[pinpoint] [%d] [%d] call_interceptor_before:pdo::exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:pdo::exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` PDO::exec : on_end -[pinpoint] [%d] [%d]call_interceptor_end: pdo::exec -[pinpoint] [%d] [%d]start free interceptor: pdo::__construct -[pinpoint] [%d] [%d]start free interceptor: pdo::exec \ No newline at end of file +[pinpoint] [%d:%d]call_interceptor_end: pdo::exec +[pinpoint] [%d:%d]start free interceptor: pdo::__construct +[pinpoint] [%d:%d]start free interceptor: pdo::exec \ No newline at end of file diff --git a/tests_macos/pinpoint_join_cut_pdo_8.phpt b/tests_macos/pinpoint_join_cut_pdo_8.phpt index 73b3c2f1d..6e0fc1850 100644 --- a/tests_macos/pinpoint_join_cut_pdo_8.phpt +++ b/tests_macos/pinpoint_join_cut_pdo_8.phpt @@ -105,36 +105,36 @@ $ret = $pdo->exec($sql); --EXPECTF-- -[pinpoint] [%d] [%d]try to interceptor module(class)/function=pdo:__construct -[pinpoint] [%d] [%d]added interceptor on `module`: pdo::__construct success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=pdo:exec -[pinpoint] [%d] [%d]added interceptor on `module`: pdo::exec success +[pinpoint] [%d:%d]try to interceptor module(class)/function=pdo:__construct +[pinpoint] [%d:%d]added interceptor on `module`: pdo::__construct success +[pinpoint] [%d:%d]try to interceptor module(class)/function=pdo:exec +[pinpoint] [%d:%d]added interceptor on `module`: pdo::exec success case: pdo() -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::__construct +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::__construct on_before: mysql:host=dev-mysql;dbname=employees attached dsn -[pinpoint] [%d] [%d] call_interceptor_before:pdo::__construct return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:pdo::__construct return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: pdo::__construct -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec +[pinpoint] [%d:%d]call_interceptor_end: pdo::__construct +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec PDO::exec: on_before: CREATE table IF NOT EXISTS pdo_test( ID INT( 11 ) AUTO_INCREMENT PRIMARY KEY, Name VARCHAR( 250 ) NOT NULL, AGE tinyint(1) unsigned NOT NULL default '1' ); mysql:host=dev-mysql;dbname=employees -[pinpoint] [%d] [%d] call_interceptor_before:pdo::exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:pdo::exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` PDO::exec : on_end -[pinpoint] [%d] [%d]call_interceptor_end: pdo::exec -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec +[pinpoint] [%d:%d]call_interceptor_end: pdo::exec +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec PDO::exec: on_before: INSERT INTO pdo_test (NAME, AGE) VALUES ('a',1),('b',1),('c',3),('d',1); mysql:host=dev-mysql;dbname=employees -[pinpoint] [%d] [%d] call_interceptor_before:pdo::exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:pdo::exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` PDO::exec : on_end -[pinpoint] [%d] [%d]call_interceptor_end: pdo::exec +[pinpoint] [%d:%d]call_interceptor_end: pdo::exec int(4) object(PDOStatement)#9 (1) { ["queryString"]=> @@ -176,12 +176,12 @@ array(2) { } } string(37) "mysql:host=dev-mysql;dbname=employees" -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec PDO::exec: on_before: DROP TABLE pdo_test mysql:host=dev-mysql;dbname=employees -[pinpoint] [%d] [%d] call_interceptor_before:pdo::exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:pdo::exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` PDO::exec : on_end -[pinpoint] [%d] [%d]call_interceptor_end: pdo::exec -[pinpoint] [%d] [%d]start free interceptor: pdo::__construct -[pinpoint] [%d] [%d]start free interceptor: pdo::exec \ No newline at end of file +[pinpoint] [%d:%d]call_interceptor_end: pdo::exec +[pinpoint] [%d:%d]start free interceptor: pdo::__construct +[pinpoint] [%d:%d]start free interceptor: pdo::exec \ No newline at end of file diff --git a/tests_macos/pinpoint_join_cut_redis.phpt b/tests_macos/pinpoint_join_cut_redis.phpt index a6ab98036..f24cb5f5c 100644 --- a/tests_macos/pinpoint_join_cut_redis.phpt +++ b/tests_macos/pinpoint_join_cut_redis.phpt @@ -124,6 +124,7 @@ foreach ($points as $point) { } + echo "case: redis(xxx) \n"; $redis = new Redis([ @@ -161,135 +162,135 @@ $redis->mSet(['foo' => 'foo', 'bar' => 'bar', 'baz' => 'baz']); var_dump($redis->exists('foo', 'bar', 'baz', 'not exists')); $redis->flushdb(); --EXPECTF-- -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:info -[pinpoint] [%d] [%d]added interceptor on `module`: redis::info success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:get -[pinpoint] [%d] [%d]added interceptor on `module`: redis::get success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:set -[pinpoint] [%d] [%d]added interceptor on `module`: redis::set success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:setnx -[pinpoint] [%d] [%d]added interceptor on `module`: redis::setnx success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:append -[pinpoint] [%d] [%d]added interceptor on `module`: redis::append success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:getrange -[pinpoint] [%d] [%d]added interceptor on `module`: redis::getrange success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:setrange -[pinpoint] [%d] [%d]added interceptor on `module`: redis::setrange success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:strlen -[pinpoint] [%d] [%d]added interceptor on `module`: redis::strlen success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:getbit -[pinpoint] [%d] [%d]added interceptor on `module`: redis::getbit success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:setbit -[pinpoint] [%d] [%d]added interceptor on `module`: redis::setbit success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:mset -[pinpoint] [%d] [%d]added interceptor on `module`: redis::mset success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:msetnx -[pinpoint] [%d] [%d]added interceptor on `module`: redis::msetnx success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:info +[pinpoint] [%d:%d]added interceptor on `module`: redis::info success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:get +[pinpoint] [%d:%d]added interceptor on `module`: redis::get success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:set +[pinpoint] [%d:%d]added interceptor on `module`: redis::set success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:setnx +[pinpoint] [%d:%d]added interceptor on `module`: redis::setnx success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:append +[pinpoint] [%d:%d]added interceptor on `module`: redis::append success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:getrange +[pinpoint] [%d:%d]added interceptor on `module`: redis::getrange success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:setrange +[pinpoint] [%d:%d]added interceptor on `module`: redis::setrange success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:strlen +[pinpoint] [%d:%d]added interceptor on `module`: redis::strlen success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:getbit +[pinpoint] [%d:%d]added interceptor on `module`: redis::getbit success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:setbit +[pinpoint] [%d:%d]added interceptor on `module`: redis::setbit success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:mset +[pinpoint] [%d:%d]added interceptor on `module`: redis::mset success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:msetnx +[pinpoint] [%d:%d]added interceptor on `module`: redis::msetnx success case: redis(xxx) -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::info +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::info Redis::info before: -[pinpoint] [%d] [%d] call_interceptor_before:redis::info return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::info return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::info end -[pinpoint] [%d] [%d]call_interceptor_end: redis::info +[pinpoint] [%d:%d]call_interceptor_end: redis::info case: redis() -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::info +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::info Redis::info before: -[pinpoint] [%d] [%d] call_interceptor_before:redis::info return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::info return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::info end -[pinpoint] [%d] [%d]call_interceptor_end: redis::info +[pinpoint] [%d:%d]call_interceptor_end: redis::info case: redis() -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::info +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::info Redis::info before: -[pinpoint] [%d] [%d] call_interceptor_before:redis::info return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::info return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::info end -[pinpoint] [%d] [%d]call_interceptor_end: redis::info +[pinpoint] [%d:%d]call_interceptor_end: redis::info case: strings -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::get +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::get Redis::get before: a -[pinpoint] [%d] [%d] call_interceptor_before:redis::get return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::get return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::get end -[pinpoint] [%d] [%d]call_interceptor_end: redis::get -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::set +[pinpoint] [%d:%d]call_interceptor_end: redis::get +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::set Redis::set before: a : b -[pinpoint] [%d] [%d] call_interceptor_before:redis::set return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::set return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::set end -[pinpoint] [%d] [%d]call_interceptor_end: redis::set -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::setnx +[pinpoint] [%d:%d]call_interceptor_end: redis::set +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::setnx Redis::setNx before: a : 10 -[pinpoint] [%d] [%d] call_interceptor_before:redis::setnx return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::setnx return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::setNx end -[pinpoint] [%d] [%d]call_interceptor_end: redis::setnx -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::append +[pinpoint] [%d:%d]call_interceptor_end: redis::setnx +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::append Redis::append before: ar : aa -[pinpoint] [%d] [%d] call_interceptor_before:redis::append return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::append return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::append end -[pinpoint] [%d] [%d]call_interceptor_end: redis::append -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::setrange +[pinpoint] [%d:%d]call_interceptor_end: redis::append +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::setrange Redis::setRange before: ar -[pinpoint] [%d] [%d] call_interceptor_before:redis::setrange return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::setrange return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::setRange end -[pinpoint] [%d] [%d]call_interceptor_end: redis::setrange -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::get +[pinpoint] [%d:%d]call_interceptor_end: redis::setrange +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::get Redis::get before: ar -[pinpoint] [%d] [%d] call_interceptor_before:redis::get return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::get return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::get end -[pinpoint] [%d] [%d]call_interceptor_end: redis::get -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::getrange +[pinpoint] [%d:%d]call_interceptor_end: redis::get +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::getrange Redis::getRange before: ar -[pinpoint] [%d] [%d] call_interceptor_before:redis::getrange return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::getrange return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::getRange end -[pinpoint] [%d] [%d]call_interceptor_end: redis::getrange -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::strlen +[pinpoint] [%d:%d]call_interceptor_end: redis::getrange +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::strlen Redis::strlen before: ar -[pinpoint] [%d] [%d] call_interceptor_before:redis::strlen return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::strlen return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::strlen end -[pinpoint] [%d] [%d]call_interceptor_end: redis::strlen -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::getbit +[pinpoint] [%d:%d]call_interceptor_end: redis::strlen +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::getbit Redis::getBit before: ar : 1 -[pinpoint] [%d] [%d] call_interceptor_before:redis::getbit return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::getbit return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::getBit end -[pinpoint] [%d] [%d]call_interceptor_end: redis::getbit -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::setbit +[pinpoint] [%d:%d]call_interceptor_end: redis::getbit +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::setbit Redis::setBit before: ar -[pinpoint] [%d] [%d] call_interceptor_before:redis::setbit return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::setbit return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::setBit end -[pinpoint] [%d] [%d]call_interceptor_end: redis::setbit -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::get +[pinpoint] [%d:%d]call_interceptor_end: redis::setbit +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::get Redis::get before: ar -[pinpoint] [%d] [%d] call_interceptor_before:redis::get return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::get return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::get end -[pinpoint] [%d] [%d]call_interceptor_end: redis::get +[pinpoint] [%d:%d]call_interceptor_end: redis::get string(2) "bb" -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::mset +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::mset Redis::mSet before: -[pinpoint] [%d] [%d] call_interceptor_before:redis::mset return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::mset return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::mSet end -[pinpoint] [%d] [%d]call_interceptor_end: redis::mset +[pinpoint] [%d:%d]call_interceptor_end: redis::mset int(3) -[pinpoint] [%d] [%d]start free interceptor: redis::info -[pinpoint] [%d] [%d]start free interceptor: redis::get -[pinpoint] [%d] [%d]start free interceptor: redis::set -[pinpoint] [%d] [%d]start free interceptor: redis::setnx -[pinpoint] [%d] [%d]start free interceptor: redis::append -[pinpoint] [%d] [%d]start free interceptor: redis::getrange -[pinpoint] [%d] [%d]start free interceptor: redis::setrange -[pinpoint] [%d] [%d]start free interceptor: redis::strlen -[pinpoint] [%d] [%d]start free interceptor: redis::getbit -[pinpoint] [%d] [%d]start free interceptor: redis::setbit -[pinpoint] [%d] [%d]start free interceptor: redis::mset -[pinpoint] [%d] [%d]start free interceptor: redis::msetnx \ No newline at end of file +[pinpoint] [%d:%d]start free interceptor: redis::info +[pinpoint] [%d:%d]start free interceptor: redis::get +[pinpoint] [%d:%d]start free interceptor: redis::set +[pinpoint] [%d:%d]start free interceptor: redis::setnx +[pinpoint] [%d:%d]start free interceptor: redis::append +[pinpoint] [%d:%d]start free interceptor: redis::getrange +[pinpoint] [%d:%d]start free interceptor: redis::setrange +[pinpoint] [%d:%d]start free interceptor: redis::strlen +[pinpoint] [%d:%d]start free interceptor: redis::getbit +[pinpoint] [%d:%d]start free interceptor: redis::setbit +[pinpoint] [%d:%d]start free interceptor: redis::mset +[pinpoint] [%d:%d]start free interceptor: redis::msetnx \ No newline at end of file diff --git a/tests_macos/stack_fetal_error.phpt b/tests_macos/stack_fetal_error.phpt index 1a390eb8c..eb56fe516 100644 --- a/tests_macos/stack_fetal_error.phpt +++ b/tests_macos/stack_fetal_error.phpt @@ -32,7 +32,7 @@ class Foo{ } function Test(){ - throw new \Exception("I am testting"); + throw new \Exception("I am testing"); } _pinpoint_start_trace(); @@ -46,17 +46,17 @@ try{ _pinpoint_start_trace(); --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] -[pinpoint] [%d] [%d] [128] pinpoint_start child [127] -[pinpoint] [%d] [%d] [127] add clue key:name value:Foo -[pinpoint] [%d] [%d]apm_error_cb called +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [128] pinpoint_start child [127] +[pinpoint] [%d:%d] [127] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d]apm_error_cb called -Fatal error: Uncaught Exception: I am testting in %s:23 +Fatal error: Uncaught Exception: I am testing in %s:23 Stack trace: #0 %s(30): Test() #1 {main} thrown in %s on line 23 -[pinpoint] [%d] [%d] [127] pinpoint_end_trace Done! -[pinpoint] [%d] [%d]this span:({":E":%d,":FT":1500,":S":%d,"ERR":{"file":"%s","line":23,"msg":"Uncaught Exception: I am testting in %s:23\nStack trace:\n#0 %s(30): Test()\n#1 {main}\n thrown"},"calls":[{":E":%d,":S":%d,"name":"Foo"}]}) -[pinpoint] [%d] [%d][unittest] current span was dropped -[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done! \ No newline at end of file +[pinpoint] [%d:%d] [127] pinpoint_end_trace Done! +[pinpoint] [%d:%d]this span:({":E":%d,":FT":1500,":S":%d,"ERR":{"file":"%s","line":23,"msg":"Uncaught Exception: I am testing in %s:23\nStack trace:\n#0 %s(30): Test()\n#1 {main}\n thrown"},"event":[{":E":%d,":S":%d,":depth":1,":seq":0,"name":"Foo"}]}) +[pinpoint] [%d:%d][unittest] current span was dropped +[pinpoint] [%d:%d] [128] pinpoint_end_trace Done! \ No newline at end of file diff --git a/tests_macos/trace_api_context.phpt b/tests_macos/trace_api_context.phpt new file mode 100644 index 000000000..ed8764b3c --- /dev/null +++ b/tests_macos/trace_api_context.phpt @@ -0,0 +1,70 @@ +--TEST-- +Check call statck +--SKIPIF-- + +--INI-- +pinpoint_php.CollectorHost=tcp:127.0.0.1:9999 +pinpoint_php.SendSpanTimeOutMs=-1 +pinpoint_php.UnitTest=true +;pinpoint_php._limit for internal use. User do not use it +pinpoint_php._limit=yes +pinpoint_php.DebugReport=true +--FILE-- + +--EXPECTF-- +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +string(1) "a" +string(1) "b" +string(1) "c" +[pinpoint] [%d:%d] pinpoint_get_context_key [128] failed with map::at: key not found, parameters:not exist +bool(false) +[pinpoint] [%d:%d]this span:({":E":%d,":FT":1500,":S":%d}) +[pinpoint] [%d:%d][unittest] current span was dropped +[pinpoint] [%d:%d] [128] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [128] pinpoint_start child [127] +string(1) "c" +string(1) "b" +string(1) "a" +[pinpoint] [%d:%d] pinpoint_get_context_key [127] failed with map::at: key not found, parameters:not exist +bool(false) +[pinpoint] [%d:%d] [127] pinpoint_end_trace Done! +[pinpoint] [%d:%d]this span:({":E":%d,":FT":1500,":S":%d,"event":[{":E":%d,":S":%d,":depth":1,":seq":0}]}) +[pinpoint] [%d:%d][unittest] current span was dropped +[pinpoint] [%d:%d] [128] pinpoint_end_trace Done! +{ + "common_library_version" : "0.6.0", + "pool_free_node" : 128, + "pool_total_node" : 128 +} \ No newline at end of file diff --git a/tests_macos/trace_api_context_tcp.phpt b/tests_macos/trace_api_context_tcp.phpt index 7df436569..ed8764b3c 100644 --- a/tests_macos/trace_api_context_tcp.phpt +++ b/tests_macos/trace_api_context_tcp.phpt @@ -43,28 +43,28 @@ _pinpoint_end_trace($id); pinpoint_status(); ?> --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [0] pinpoint_start child [128] string(1) "a" string(1) "b" string(1) "c" -[pinpoint] [%d] [%d] pinpoint_get_context_key [128] failed with map::at: key not found, parameters:not exist +[pinpoint] [%d:%d] pinpoint_get_context_key [128] failed with map::at: key not found, parameters:not exist bool(false) -[pinpoint] [%d] [%d]this span:({":E":%d,":FT":1500,":S":%d}) -[pinpoint] [%d] [%d][unittest] current span was dropped -[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done! -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] -[pinpoint] [%d] [%d] [128] pinpoint_start child [127] +[pinpoint] [%d:%d]this span:({":E":%d,":FT":1500,":S":%d}) +[pinpoint] [%d:%d][unittest] current span was dropped +[pinpoint] [%d:%d] [128] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [128] pinpoint_start child [127] string(1) "c" string(1) "b" string(1) "a" -[pinpoint] [%d] [%d] pinpoint_get_context_key [127] failed with map::at: key not found, parameters:not exist +[pinpoint] [%d:%d] pinpoint_get_context_key [127] failed with map::at: key not found, parameters:not exist 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][unittest] current span was dropped -[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [127] pinpoint_end_trace Done! +[pinpoint] [%d:%d]this span:({":E":%d,":FT":1500,":S":%d,"event":[{":E":%d,":S":%d,":depth":1,":seq":0}]}) +[pinpoint] [%d:%d][unittest] current span was dropped +[pinpoint] [%d:%d] [128] pinpoint_end_trace Done! { - "common_library_version" : "%s", + "common_library_version" : "0.6.0", "pool_free_node" : 128, "pool_total_node" : 128 } \ No newline at end of file diff --git a/tests_macos/trace_api_test.phpt b/tests_macos/trace_api_test.phpt index 362d035a3..f29be3c8f 100644 --- a/tests_macos/trace_api_test.phpt +++ b/tests_macos/trace_api_test.phpt @@ -4,7 +4,7 @@ Check call statck --INI-- pinpoint_php.CollectorHost=tcp:localhost:10000 -pinpoint_php.SendSpanTimeOutMs=0 +pinpoint_php.SendSpanTimeOutMs=-1 pinpoint_php.UnitTest=true ;pinpoint_php._limit for internal use. User do not use it pinpoint_php._limit=yes @@ -53,82 +53,82 @@ echo _pinpoint_end_trace()."\n"; ?> --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [0] pinpoint_start child [128] 128 -[pinpoint] [%d] [%d] [128] add clue key:name value:ouput_234 -[pinpoint] [%d] [%d] [128] pinpoint_start child [127] +[pinpoint] [%d:%d] [128] add anno_v1 key:name value:ouput_234 +[pinpoint] [%d:%d] [128] pinpoint_start child [127] 127 -[pinpoint] [%d] [%d] [127] add clue key:name value:Foo -[pinpoint] [%d] [%d] [127] add clues:1:234,3432 -[pinpoint] [%d] [%d] [127] add clues:2:234 -[pinpoint] [%d] [%d] [127] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [127] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [127] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [127] add anno_v2 2:234 +[pinpoint] [%d:%d] [127] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [126] +[pinpoint] [%d:%d] [128] pinpoint_start child [126] 126 -[pinpoint] [%d] [%d] [126] add clue key:name value:Foo -[pinpoint] [%d] [%d] [126] add clues:1:234,3432 -[pinpoint] [%d] [%d] [126] add clues:2:234 -[pinpoint] [%d] [%d] [126] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [126] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [126] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [126] add anno_v2 2:234 +[pinpoint] [%d:%d] [126] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [125] +[pinpoint] [%d:%d] [128] pinpoint_start child [125] 125 -[pinpoint] [%d] [%d] [125] add clue key:name value:Foo -[pinpoint] [%d] [%d] [125] add clues:1:234,3432 -[pinpoint] [%d] [%d] [125] add clues:2:234 -[pinpoint] [%d] [%d] [125] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [125] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [125] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [125] add anno_v2 2:234 +[pinpoint] [%d:%d] [125] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [124] +[pinpoint] [%d:%d] [128] pinpoint_start child [124] 124 -[pinpoint] [%d] [%d] [124] add clue key:name value:Foo -[pinpoint] [%d] [%d] [124] add clues:1:234,3432 -[pinpoint] [%d] [%d] [124] add clues:2:234 -[pinpoint] [%d] [%d] [124] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [124] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [124] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [124] add anno_v2 2:234 +[pinpoint] [%d:%d] [124] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [123] +[pinpoint] [%d:%d] [128] pinpoint_start child [123] 123 -[pinpoint] [%d] [%d] [123] add clue key:name value:Foo -[pinpoint] [%d] [%d] [123] add clues:1:234,3432 -[pinpoint] [%d] [%d] [123] add clues:2:234 -[pinpoint] [%d] [%d] [123] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [123] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [123] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [123] add anno_v2 2:234 +[pinpoint] [%d:%d] [123] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [122] +[pinpoint] [%d:%d] [128] pinpoint_start child [122] 122 -[pinpoint] [%d] [%d] [122] add clue key:name value:Foo -[pinpoint] [%d] [%d] [122] add clues:1:234,3432 -[pinpoint] [%d] [%d] [122] add clues:2:234 -[pinpoint] [%d] [%d] [122] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [122] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [122] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [122] add anno_v2 2:234 +[pinpoint] [%d:%d] [122] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [121] +[pinpoint] [%d:%d] [128] pinpoint_start child [121] 121 -[pinpoint] [%d] [%d] [121] add clue key:name value:Foo -[pinpoint] [%d] [%d] [121] add clues:1:234,3432 -[pinpoint] [%d] [%d] [121] add clues:2:234 -[pinpoint] [%d] [%d] [121] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [121] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [121] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [121] add anno_v2 2:234 +[pinpoint] [%d:%d] [121] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [120] +[pinpoint] [%d:%d] [128] pinpoint_start child [120] 120 -[pinpoint] [%d] [%d] [120] add clue key:name value:Foo -[pinpoint] [%d] [%d] [120] add clues:1:234,3432 -[pinpoint] [%d] [%d] [120] add clues:2:234 -[pinpoint] [%d] [%d] [120] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [120] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [120] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [120] add anno_v2 2:234 +[pinpoint] [%d:%d] [120] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [119] +[pinpoint] [%d:%d] [128] pinpoint_start child [119] 119 -[pinpoint] [%d] [%d] [119] add clue key:name value:Foo -[pinpoint] [%d] [%d] [119] add clues:1:234,3432 -[pinpoint] [%d] [%d] [119] add clues:2:234 -[pinpoint] [%d] [%d] [119] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [119] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [119] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [119] add anno_v2 2:234 +[pinpoint] [%d:%d] [119] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [118] +[pinpoint] [%d:%d] [128] pinpoint_start child [118] 118 -[pinpoint] [%d] [%d] [118] add clue key:name value:Foo -[pinpoint] [%d] [%d] [118] add clues:1:234,3432 -[pinpoint] [%d] [%d] [118] add clues:2:234 -[pinpoint] [%d] [%d] [118] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [118] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [118] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [118] add anno_v2 2:234 +[pinpoint] [%d:%d] [118] pinpoint_end_trace Done! 128 -[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:(localhost:10000) -[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [128] add anno_v1 key:args value:a,$b +[pinpoint] [%d:%d] [128] add anno_v1 key:ret value:a,$b +[pinpoint] [%d:%d]this span:({":E":%d,":FT":1500,":S":%d,"args":"a,$b","event":[{":E":%d,":S":%d,":depth":1,":seq":0,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":1,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":2,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":3,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":4,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":5,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":6,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":7,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":8,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":9,"anno":["1:234,3432","2:234"],"name":"Foo"}],"name":"ouput_234","ret":"a,$b"}) +[pinpoint] [%d:%d][unittest] current span was dropped +[pinpoint] [%d:%d] [128] pinpoint_end_trace Done! 0 \ No newline at end of file diff --git a/tests_macos/trace_api_with_id.phpt b/tests_macos/trace_api_with_id.phpt index 0393917b4..f842e4512 100644 --- a/tests_macos/trace_api_with_id.phpt +++ b/tests_macos/trace_api_with_id.phpt @@ -45,21 +45,21 @@ _pinpoint_add_clue("name","Foo",$id); $id = _pinpoint_end_trace($id); --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] -[pinpoint] [%d] [%d] [128] add clue key:name value:Foo -[pinpoint] [%d] [%d] [128] pinpoint_start child [127] -[pinpoint] [%d] [%d] [127] add clues:name:Foo1 -[pinpoint] [%d] [%d] [127] pinpoint_start child [126] -[pinpoint] [%d] [%d] [126] add clue key:name value:Foo2 -[pinpoint] [%d] [%d] [126] pinpoint_end_trace Done! -[pinpoint] [%d] [%d] [127] pinpoint_start child [125] -[pinpoint] [%d] [%d] [125] add clues:name:Foo3 -[pinpoint] [%d] [%d] [125] add clue key:name value:Foo4 -[pinpoint] [%d] [%d] [125] pinpoint_end_trace Done! -[pinpoint] [%d] [%d] [127] add clues:name:Foo5 -[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][unittest] current span was dropped -[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [128] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [128] pinpoint_start child [127] +[pinpoint] [%d:%d] [127] add anno_v2 name:Foo1 +[pinpoint] [%d:%d] [127] pinpoint_start child [126] +[pinpoint] [%d:%d] [126] add anno_v1 key:name value:Foo2 +[pinpoint] [%d:%d] [126] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [127] pinpoint_start child [125] +[pinpoint] [%d:%d] [125] add anno_v2 name:Foo3 +[pinpoint] [%d:%d] [125] add anno_v1 key:name value:Foo4 +[pinpoint] [%d:%d] [125] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [127] add anno_v2 name:Foo5 +[pinpoint] [%d:%d] [127] add anno_v1 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,"event":[{":E":%d,":S":%d,":depth":1,":seq":0,"EXP":"too heavy, throw it","anno":["name:Foo1","name:Foo5"]},{":E":%d,":S":%d,":depth":2,":seq":1,"name":"Foo2"},{":E":%d,":S":%d,":depth":2,":seq":2,"anno":["name:Foo3"],"name":"Foo4"}],"name":"Foo"}) +[pinpoint] [%d:%d][unittest] current span was dropped +[pinpoint] [%d:%d] [128] pinpoint_end_trace Done! Uncaught exception: too heavy, throw it \ No newline at end of file diff --git a/tests_macos/trace_had_root.phpt b/tests_macos/trace_had_root.phpt new file mode 100644 index 000000000..d565be5eb --- /dev/null +++ b/tests_macos/trace_had_root.phpt @@ -0,0 +1,40 @@ +--TEST-- +Test trace_had_root +--SKIPIF-- + +--INI-- +pinpoint_php.CollectorHost=unix:/unexist_file.sock +pinpoint_php.SendSpanTimeOutMs=-1 +pinpoint_php.UnitTest=true +pinpoint_php.DebugReport=true + +--FILE-- + +--EXPECTF-- +case not trace pass +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +case root trace pass +[pinpoint] [%d:%d] [128] pinpoint_start child [127] +case sub trace pass +[pinpoint] [%d:%d] [127] pinpoint_end_trace Done! +[pinpoint] [%d:%d]this span:({":E":%d,":FT":1500,":S":%d,"event":[{":E":%d,":S":%d,":depth":1,":seq":0}]}) +[pinpoint] [%d:%d][unittest] current span was dropped +[pinpoint] [%d:%d] [128] pinpoint_end_trace Done! \ No newline at end of file diff --git a/tests_macos/trace_limit_test-i448.phpt b/tests_macos/trace_limit_test-i448.phpt index 8cabc233b..0c9327c4f 100644 --- a/tests_macos/trace_limit_test-i448.phpt +++ b/tests_macos/trace_limit_test-i448.phpt @@ -34,15 +34,15 @@ if(_pinpoint_trace_limit()) _pinpoint_end_trace($id); --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] -[pinpoint] [%d] [%d] [128] pinpoint_start child [127] +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [128] pinpoint_start child [127] string(1) "c" string(1) "b" string(1) "a" -[pinpoint] [%d] [%d] pinpoint_get_context_key [127] failed with map::at: key not found, parameters:not exist +[pinpoint] [%d:%d] pinpoint_get_context_key [127] failed with map::at: key not found, 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: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 +[pinpoint] [%d:%d] [127] pinpoint_end_trace Done! +[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_macos/trace_limit_test.phpt b/tests_macos/trace_limit_test.phpt index 40162c5ce..771cd80fe 100644 --- a/tests_macos/trace_limit_test.phpt +++ b/tests_macos/trace_limit_test.phpt @@ -19,5 +19,5 @@ if(_pinpoint_trace_limit() || _pinpoint_trace_limit() ||_pinpoint_trace_limit() echo "_pinpoint_trace_limit failed"; } --EXPECTF-- -[pinpoint] [%d] [%d]This span dropped. max_trace_limit:2 current_tick:2 onLine:0 +[pinpoint] [%d:%d]This span dropped. max_trace_limit:2 current_tick:2 onLine:0 pass \ No newline at end of file diff --git a/tests_win32/add_root_trace.phpt b/tests_win32/add_root_trace.phpt index be0fbbca3..33f0b35eb 100644 --- a/tests_win32/add_root_trace.phpt +++ b/tests_win32/add_root_trace.phpt @@ -4,7 +4,7 @@ Test pinpoint_unique_id --INI-- pinpoint_php.CollectorHost=tcp:localhost:10000 -pinpoint_php.SendSpanTimeOutMs=0 +pinpoint_php.SendSpanTimeOutMs=-1 pinpoint_php.UnitTest=true pinpoint_php.DebugReport=true --FILE-- @@ -21,16 +21,16 @@ $id = _pinpoint_end_trace($id); $id = _pinpoint_end_trace($id); $id = _pinpoint_end_trace($id); --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] -[pinpoint] [%d] [%d] [128] add clue key:name value:Foo -[pinpoint] [%d] [%d] [128] pinpoint_start child [127] -[pinpoint] [%d] [%d] [127] add clues:global:global_value -[pinpoint] [%d] [%d] [127] add clue key:global value:global_value -[pinpoint] [%d] [%d] [127] add clues:name:Foo1 -[pinpoint] [%d] [%d] [127] pinpoint_start child [126] -[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":%d,":S":%d,"name":"Foo2"}],"clues":["name:Foo1"]}],"clues":["global:global_value"],"global":"global_value","name":"Foo"}) -[pinpoint] [%d] [%d]agent try to connect:(localhost:10000) -[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done! \ No newline at end of file +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [128] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [128] pinpoint_start child [127] +[pinpoint] [%d:%d] [127] add anno_v2 global:global_value +[pinpoint] [%d:%d] [127] add anno_v1 key:global value:global_value +[pinpoint] [%d:%d] [127] add anno_v2 name:Foo1 +[pinpoint] [%d:%d] [127] pinpoint_start child [126] +[pinpoint] [%d:%d] [126] add anno_v1 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,"anno":["global:global_value"],"event":[{":E":%d,":S":%d,":depth":1,":seq":0,"anno":["name:Foo1"]},{":E":%d,":S":%d,":depth":2,":seq":1,"name":"Foo2"}],"global":"global_value","name":"Foo"}) +[pinpoint] [%d:%d][unittest] current span was dropped +[pinpoint] [%d:%d] [128] pinpoint_end_trace Done! \ No newline at end of file diff --git a/tests_win32/aop_helper_api.phpt b/tests_win32/aop_helper_api.phpt deleted file mode 100644 index 937e17422..000000000 --- a/tests_win32/aop_helper_api.phpt +++ /dev/null @@ -1,194 +0,0 @@ ---TEST-- -app info ---SKIPIF-- - ---INI-- -pinpoint_php.DebugReport=false ---FILE-- -foo('hello pinpoint',1,array('1'=>2,'c'=>3,'e'=>5)); -Foo::static_foo('hello pinpoint',1,array('1'=>2,'c'=>3,'e'=>5)); -$foo->test_none(); -var_dump($foo->return_all("23",1,null)); - -echo "test anonymous \n"; -$name = 'eeliu'; -$nobody = function ($arg) use (&$name) { - var_dump(\pinpoint_get_func_ref_args()); - $name = 'eeliu-01'; - $arg = $arg.$name; - return \pinpoint_get_func_ref_args(); -}; -var_dump($nobody("hello ")); -echo "\n"; - -echo "test pinpoint_get_func_ref_args call in call_user_func_array \n"; - -function foo_ref($a,&$b,&$c) -{ - var_dump(func_get_args()); - $b = 10; - $c = 11; - return array($b,$c); -} - -function aop_foo_ref($a,&$b,&$c) -{ - $args = \pinpoint_get_func_ref_args(); - return call_user_func_array('foo_ref',$args); -} -$b =2; -$c = 12; -var_dump(aop_foo_ref("adf",$b,$c)); -echo "b = $b \n"; -echo "c = $c \n"; - ---EXPECTF-- -array(4) { - [0]=> - &int(100) - [1]=> - int(1) - [2]=> - int(3) - [3]=> - int(4) -} -string(12) "hello php!!!" - -Warning: pinpoint_get_func_ref_args(): Called from the global scope - no function context in %s on line 18 -bool(false) -call __construct -array(2) { - [0]=> - int(1) - [1]=> - int(2) -} -array(3) { - [0]=> - string(14) "hello pinpoint" - [1]=> - int(1) - [2]=> - array(3) { - [1]=> - int(2) - ["c"]=> - int(3) - ["e"]=> - int(5) - } -} -array(3) { - [0]=> - string(14) "hello pinpoint" - [1]=> - int(1) - [2]=> - array(3) { - [1]=> - int(2) - ["c"]=> - int(3) - ["e"]=> - int(5) - } -} -array(0) { -} -array(3) { - [0]=> - string(2) "23" - [1]=> - int(1) - [2]=> - NULL -} -test anonymous -array(1) { - [0]=> - string(6) "hello " -} -array(1) { - [0]=> - string(14) "hello eeliu-01" -} - -test pinpoint_get_func_ref_args call in call_user_func_array -array(3) { - [0]=> - string(3) "adf" - [1]=> - int(2) - [2]=> - int(12) -} -array(2) { - [0]=> - int(10) - [1]=> - int(11) -} -b = 10 -c = 11 -call __destruct -array(0) { -} \ No newline at end of file diff --git a/tests_win32/drop_trace_test.phpt b/tests_win32/drop_trace_test.phpt index 68da7e593..dacdb316f 100644 --- a/tests_win32/drop_trace_test.phpt +++ b/tests_win32/drop_trace_test.phpt @@ -15,9 +15,9 @@ _pinpoint_add_clue("args",'a,$b'); _pinpoint_add_clue("ret",'a,$b'); _pinpoint_end_trace(); --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] -[pinpoint] [%d] [%d]change current [128] status, before:2,now:4 -[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]current [128] span dropped,due to TRACE_BLOCK -[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done! \ No newline at end of file +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d]change current [128] status, before:2,now:4 +[pinpoint] [%d:%d] [128] add anno_v1 key:args value:a,$b +[pinpoint] [%d:%d] [128] add anno_v1 key:ret value:a,$b +[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_win32/mark_as_error.phpt b/tests_win32/mark_as_error.phpt index b47e4b91e..2c91fde67 100644 --- a/tests_win32/mark_as_error.phpt +++ b/tests_win32/mark_as_error.phpt @@ -4,7 +4,7 @@ pinpoint_php internal test case [pinpoint_test_main] --INI-- pinpoint_php.CollectorHost=tcp:localhost:10000 -pinpoint_php.SendSpanTimeOutMs=0 +pinpoint_php.SendSpanTimeOutMs=-1 pinpoint_php.UnitTest=true ;pinpoint_php._limit for internal use. User do not use it pinpoint_php._limit=yes @@ -17,10 +17,10 @@ _pinpoint_add_clue("ret",'a,$b'); _pinpoint_mark_as_error("message you cared","filename you cared",1023); echo _pinpoint_end_trace()."\n"; --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] -[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:(localhost:10000) -[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [128] add anno_v1 key:args value:a,$b +[pinpoint] [%d:%d] [128] add anno_v1 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][unittest] current span was dropped +[pinpoint] [%d:%d] [128] pinpoint_end_trace Done! 0 \ No newline at end of file diff --git a/tests_win32/node_test.phpt b/tests_win32/node_test.phpt index 24ac02760..e5c5b2410 100644 --- a/tests_win32/node_test.phpt +++ b/tests_win32/node_test.phpt @@ -25,11 +25,11 @@ _pinpoint_get_context('b',$unexist_node); _pinpoint_end_trace($unexist_node); --EXPECTF-- -[pinpoint] [%d] [%d] start_trace [1024] failed with #1024 is not alive -[pinpoint] [%d] [%d] pinpoint_add_clue [1024] failed. Reason: #1024 is not alive,parameters:adf:fdfd -[pinpoint] [%d] [%d] pinpoint_add_clue [1024] failed. Reason: #1024 is not alive,parameters:adf:fdfd -[pinpoint] [%d] [%d] pinpoint_set_context_key [1024] failed with out_of_range. #1024 is not alive,parameters:b:b -[pinpoint] [%d] [%d] pinpoint_add_clues [1024] failed. Reason #1024 is not alive,parameters:32:fdfd -[pinpoint] [%d] [%d] pinpoint_add_clues [1024] failed. Reason #1024 is not alive,parameters:32:fdfd -[pinpoint] [%d] [%d] pinpoint_get_context_key [1024] failed with #1024 is not alive, parameters:b -[pinpoint] [%d] [%d]end_trace 1024 out_of_range exception: #1024 is not alive \ No newline at end of file +[pinpoint] [%d:%d] start_trace [1024] failed with #1024 is not alive +[pinpoint] [%d:%d] pinpoint_add_clue [1024] failed. Reason: #1024 is not alive,parameters:adf:fdfd +[pinpoint] [%d:%d] pinpoint_add_clue [1024] failed. Reason: #1024 is not alive,parameters:adf:fdfd +[pinpoint] [%d:%d] pinpoint_set_context_key [1024] failed with out_of_range. #1024 is not alive,parameters:b:b +[pinpoint] [%d:%d] pinpoint_add_clues [1024] failed. Reason #1024 is not alive,parameters:32:fdfd +[pinpoint] [%d:%d] pinpoint_add_clues [1024] failed. Reason #1024 is not alive,parameters:32:fdfd +[pinpoint] [%d:%d] pinpoint_get_context_key [1024] failed with #1024 is not alive, parameters:b +[pinpoint] [%d:%d]end_trace 1024 out_of_range exception: #1024 is not alive \ No newline at end of file diff --git a/tests_win32/pinpoint_get_caller_arg.phpt b/tests_win32/pinpoint_get_caller_arg.phpt index 9dfb10dd2..2711f3169 100644 --- a/tests_win32/pinpoint_get_caller_arg.phpt +++ b/tests_win32/pinpoint_get_caller_arg.phpt @@ -51,13 +51,13 @@ echo "error: $error\n"; curl_close($ch); --EXPECTF-- -[pinpoint] [%d] [%d]try to interceptor function=curl_exec -[pinpoint] [%d] [%d]added interceptor on `function`: curl_exec success +[pinpoint] [%d:%d]try to interceptor function=curl_exec +[pinpoint] [%d:%d]added interceptor on `function`: curl_exec success case: curl_init() -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_exec -[pinpoint] [%d] [%d] call_interceptor_before:curl_exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:curl_exec +[pinpoint] [%d:%d] call_interceptor_before:curl_exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` status_code 200 -[pinpoint] [%d] [%d]call_interceptor_end: curl_exec +[pinpoint] [%d:%d]call_interceptor_end: curl_exec error: -[pinpoint] [%d] [%d]start free interceptor: curl_exec \ No newline at end of file +[pinpoint] [%d:%d]start free interceptor: curl_exec \ No newline at end of file diff --git a/tests_win32/pinpoint_get_this.phpt b/tests_win32/pinpoint_get_this.phpt index babd50895..ae5027fb2 100644 --- a/tests_win32/pinpoint_get_this.phpt +++ b/tests_win32/pinpoint_get_this.phpt @@ -54,8 +54,8 @@ string(3) "123" update foo members int(1234) string(14) "hello pinpoint" -[pinpoint] [%d] [%d]pinpoint_get_this: not support, no this +[pinpoint] [%d:%d]pinpoint_get_this: not support, no this bool(false) test static method -[pinpoint] [%d] [%d]pinpoint_get_this: not support, no this +[pinpoint] [%d:%d]pinpoint_get_this: not support, no this bool(false) \ No newline at end of file diff --git a/tests_win32/pinpoint_join_cut_curl_7.phpt b/tests_win32/pinpoint_join_cut_curl_7.phpt index 72ef024dd..bfdf771be 100644 --- a/tests_win32/pinpoint_join_cut_curl_7.phpt +++ b/tests_win32/pinpoint_join_cut_curl_7.phpt @@ -160,7 +160,7 @@ int(10002) test CURLOPT_URL [pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval [pinpoint] [%d] [%d]argv size:2 -[pinpoint] [%d] [%d]error: replace_ex_caller_parameters return `size` does not matched +[pinpoint] [%d] [%d]error: replace_ex_caller_parameters return `size` does not match on_end [pinpoint] [%d] [%d]call_interceptor_end: curl_setopt [pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt @@ -168,7 +168,7 @@ int(19913) test CURLOPT_RETURNTRANSFER [pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval [pinpoint] [%d] [%d]argv size:3 -[pinpoint] [%d] [%d]error: replace_ex_caller_parameters return `type` does not matched expected:3 give:4 +[pinpoint] [%d] [%d]error: replace_ex_caller_parameters return `type` does not match expected:3 give:4 on_end [pinpoint] [%d] [%d]call_interceptor_end: curl_setopt [pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt @@ -208,7 +208,7 @@ int(19913) test CURLOPT_RETURNTRANSFER [pinpoint] [%d] [%d] call_interceptor_before:curl_setopt return type(7) zval [pinpoint] [%d] [%d]argv size:3 -[pinpoint] [%d] [%d]error: replace_ex_caller_parameters return `type` does not matched expected:3 give:4 +[pinpoint] [%d] [%d]error: replace_ex_caller_parameters return `type` does not match expected:3 give:4 on_end [pinpoint] [%d] [%d]call_interceptor_end: curl_setopt [pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:curl_setopt diff --git a/tests_win32/pinpoint_join_cut_curl_8.phpt b/tests_win32/pinpoint_join_cut_curl_8.phpt index ba1726d12..dce9eac42 100644 --- a/tests_win32/pinpoint_join_cut_curl_8.phpt +++ b/tests_win32/pinpoint_join_cut_curl_8.phpt @@ -10,7 +10,7 @@ if (version_compare(phpversion(), '8.0.0', '<')){ print "skip only works in php8"; } if(getenv('SKIP_WINDOWS_ACTION', true)){ - print "skip"; + print "skip"; } ?> --INI-- @@ -18,6 +18,7 @@ pinpoint_php.DebugReport=true --EXTENSIONS-- json +curl --FILE-- @@ -71,20 +73,20 @@ mysqli_stmt_execute($stmt); --EXPECTF-- -[pinpoint] [%d] [%d]try to interceptor function=mysqli_query -[pinpoint] [%d] [%d]added interceptor on `function`: mysqli_query success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=mysqli:query -[pinpoint] [%d] [%d]added interceptor on `module`: mysqli::query success -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:mysqli::query +[pinpoint] [%d:%d]try to interceptor function=mysqli_query +[pinpoint] [%d:%d]added interceptor on `function`: mysqli_query success +[pinpoint] [%d:%d]try to interceptor module(class)/function=mysqli:query +[pinpoint] [%d:%d]added interceptor on `module`: mysqli::query success +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:mysqli::query dev-mysql via TCP/IP -[pinpoint] [%d] [%d] call_interceptor_before:mysqli::query return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` -[pinpoint] [%d] [%d]call_interceptor_end: mysqli::query +[pinpoint] [%d:%d] call_interceptor_before:mysqli::query return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d]call_interceptor_end: mysqli::query Select returned 1000 rows. -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:mysqli_query +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:mysqli_query dev-mysql via TCP/IP -[pinpoint] [%d] [%d] call_interceptor_before:mysqli_query return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` -[pinpoint] [%d] [%d]call_interceptor_end: mysqli_query -[pinpoint] [%d] [%d]start free interceptor: mysqli_query -[pinpoint] [%d] [%d]start free interceptor: mysqli::query \ No newline at end of file +[pinpoint] [%d:%d] call_interceptor_before:mysqli_query return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d]call_interceptor_end: mysqli_query +[pinpoint] [%d:%d]start free interceptor: mysqli_query +[pinpoint] [%d:%d]start free interceptor: mysqli::query \ No newline at end of file diff --git a/tests_win32/pinpoint_join_cut_pdo_8.phpt b/tests_win32/pinpoint_join_cut_pdo_8.phpt index 5c569de60..6e0fc1850 100644 --- a/tests_win32/pinpoint_join_cut_pdo_8.phpt +++ b/tests_win32/pinpoint_join_cut_pdo_8.phpt @@ -11,7 +11,7 @@ if (version_compare(phpversion(), '8.2.0', '<')) print "skip"; print phpversion() ."< 8.2.0"; } -if(getenv('SKIP_WINDOWS_ACTION', true)){ +if(getenv('SKIP_MACOS_ACTION', true)){ print "skip"; } ?> @@ -105,36 +105,36 @@ $ret = $pdo->exec($sql); --EXPECTF-- -[pinpoint] [%d] [%d]try to interceptor module(class)/function=pdo:__construct -[pinpoint] [%d] [%d]added interceptor on `module`: pdo::__construct success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=pdo:exec -[pinpoint] [%d] [%d]added interceptor on `module`: pdo::exec success +[pinpoint] [%d:%d]try to interceptor module(class)/function=pdo:__construct +[pinpoint] [%d:%d]added interceptor on `module`: pdo::__construct success +[pinpoint] [%d:%d]try to interceptor module(class)/function=pdo:exec +[pinpoint] [%d:%d]added interceptor on `module`: pdo::exec success case: pdo() -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::__construct +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::__construct on_before: mysql:host=dev-mysql;dbname=employees attached dsn -[pinpoint] [%d] [%d] call_interceptor_before:pdo::__construct return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:pdo::__construct return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` on_end -[pinpoint] [%d] [%d]call_interceptor_end: pdo::__construct -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec +[pinpoint] [%d:%d]call_interceptor_end: pdo::__construct +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec PDO::exec: on_before: CREATE table IF NOT EXISTS pdo_test( ID INT( 11 ) AUTO_INCREMENT PRIMARY KEY, Name VARCHAR( 250 ) NOT NULL, AGE tinyint(1) unsigned NOT NULL default '1' ); mysql:host=dev-mysql;dbname=employees -[pinpoint] [%d] [%d] call_interceptor_before:pdo::exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:pdo::exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` PDO::exec : on_end -[pinpoint] [%d] [%d]call_interceptor_end: pdo::exec -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec +[pinpoint] [%d:%d]call_interceptor_end: pdo::exec +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec PDO::exec: on_before: INSERT INTO pdo_test (NAME, AGE) VALUES ('a',1),('b',1),('c',3),('d',1); mysql:host=dev-mysql;dbname=employees -[pinpoint] [%d] [%d] call_interceptor_before:pdo::exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:pdo::exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` PDO::exec : on_end -[pinpoint] [%d] [%d]call_interceptor_end: pdo::exec +[pinpoint] [%d:%d]call_interceptor_end: pdo::exec int(4) object(PDOStatement)#9 (1) { ["queryString"]=> @@ -176,12 +176,12 @@ array(2) { } } string(37) "mysql:host=dev-mysql;dbname=employees" -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:pdo::exec PDO::exec: on_before: DROP TABLE pdo_test mysql:host=dev-mysql;dbname=employees -[pinpoint] [%d] [%d] call_interceptor_before:pdo::exec return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:pdo::exec return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` PDO::exec : on_end -[pinpoint] [%d] [%d]call_interceptor_end: pdo::exec -[pinpoint] [%d] [%d]start free interceptor: pdo::__construct -[pinpoint] [%d] [%d]start free interceptor: pdo::exec \ No newline at end of file +[pinpoint] [%d:%d]call_interceptor_end: pdo::exec +[pinpoint] [%d:%d]start free interceptor: pdo::__construct +[pinpoint] [%d:%d]start free interceptor: pdo::exec \ No newline at end of file diff --git a/tests_win32/pinpoint_join_cut_redis.phpt b/tests_win32/pinpoint_join_cut_redis.phpt index 2ec54f32d..19b4b7aad 100644 --- a/tests_win32/pinpoint_join_cut_redis.phpt +++ b/tests_win32/pinpoint_join_cut_redis.phpt @@ -129,24 +129,24 @@ echo "case: redis(xxx) \n"; $redis = new Redis([ 'host' => 'redis', - 'port' => 6379, + 'port' => 6389, 'connectTimeout' => 2.5 ]); assert($redis->info() !== false); echo "case: redis() \n"; $redis = new Redis(); -$redis->connect('redis', 6379); +$redis->connect('redis', 6389); assert($redis->info() !== false); echo "case: redis() \n"; $redis = new Redis(); -$redis->pconnect('redis', 6379); +$redis->pconnect('redis', 6389); assert($redis->info() !== false); echo "case: strings \n"; $redis = new Redis(); -$redis->pconnect('redis', 6379); +$redis->pconnect('redis', 6389); $redis->get("a"); $redis->set("a", "b"); $redis->setNx("a", "10"); @@ -162,135 +162,135 @@ $redis->mSet(['foo' => 'foo', 'bar' => 'bar', 'baz' => 'baz']); var_dump($redis->exists('foo', 'bar', 'baz', 'not exists')); $redis->flushdb(); --EXPECTF-- -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:info -[pinpoint] [%d] [%d]added interceptor on `module`: redis::info success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:get -[pinpoint] [%d] [%d]added interceptor on `module`: redis::get success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:set -[pinpoint] [%d] [%d]added interceptor on `module`: redis::set success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:setnx -[pinpoint] [%d] [%d]added interceptor on `module`: redis::setnx success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:append -[pinpoint] [%d] [%d]added interceptor on `module`: redis::append success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:getrange -[pinpoint] [%d] [%d]added interceptor on `module`: redis::getrange success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:setrange -[pinpoint] [%d] [%d]added interceptor on `module`: redis::setrange success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:strlen -[pinpoint] [%d] [%d]added interceptor on `module`: redis::strlen success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:getbit -[pinpoint] [%d] [%d]added interceptor on `module`: redis::getbit success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:setbit -[pinpoint] [%d] [%d]added interceptor on `module`: redis::setbit success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:mset -[pinpoint] [%d] [%d]added interceptor on `module`: redis::mset success -[pinpoint] [%d] [%d]try to interceptor module(class)/function=redis:msetnx -[pinpoint] [%d] [%d]added interceptor on `module`: redis::msetnx success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:info +[pinpoint] [%d:%d]added interceptor on `module`: redis::info success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:get +[pinpoint] [%d:%d]added interceptor on `module`: redis::get success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:set +[pinpoint] [%d:%d]added interceptor on `module`: redis::set success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:setnx +[pinpoint] [%d:%d]added interceptor on `module`: redis::setnx success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:append +[pinpoint] [%d:%d]added interceptor on `module`: redis::append success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:getrange +[pinpoint] [%d:%d]added interceptor on `module`: redis::getrange success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:setrange +[pinpoint] [%d:%d]added interceptor on `module`: redis::setrange success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:strlen +[pinpoint] [%d:%d]added interceptor on `module`: redis::strlen success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:getbit +[pinpoint] [%d:%d]added interceptor on `module`: redis::getbit success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:setbit +[pinpoint] [%d:%d]added interceptor on `module`: redis::setbit success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:mset +[pinpoint] [%d:%d]added interceptor on `module`: redis::mset success +[pinpoint] [%d:%d]try to interceptor module(class)/function=redis:msetnx +[pinpoint] [%d:%d]added interceptor on `module`: redis::msetnx success case: redis(xxx) -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::info +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::info Redis::info before: -[pinpoint] [%d] [%d] call_interceptor_before:redis::info return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::info return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::info end -[pinpoint] [%d] [%d]call_interceptor_end: redis::info +[pinpoint] [%d:%d]call_interceptor_end: redis::info case: redis() -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::info +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::info Redis::info before: -[pinpoint] [%d] [%d] call_interceptor_before:redis::info return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::info return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::info end -[pinpoint] [%d] [%d]call_interceptor_end: redis::info +[pinpoint] [%d:%d]call_interceptor_end: redis::info case: redis() -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::info +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::info Redis::info before: -[pinpoint] [%d] [%d] call_interceptor_before:redis::info return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::info return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::info end -[pinpoint] [%d] [%d]call_interceptor_end: redis::info +[pinpoint] [%d:%d]call_interceptor_end: redis::info case: strings -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::get +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::get Redis::get before: a -[pinpoint] [%d] [%d] call_interceptor_before:redis::get return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::get return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::get end -[pinpoint] [%d] [%d]call_interceptor_end: redis::get -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::set +[pinpoint] [%d:%d]call_interceptor_end: redis::get +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::set Redis::set before: a : b -[pinpoint] [%d] [%d] call_interceptor_before:redis::set return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::set return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::set end -[pinpoint] [%d] [%d]call_interceptor_end: redis::set -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::setnx +[pinpoint] [%d:%d]call_interceptor_end: redis::set +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::setnx Redis::setNx before: a : 10 -[pinpoint] [%d] [%d] call_interceptor_before:redis::setnx return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::setnx return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::setNx end -[pinpoint] [%d] [%d]call_interceptor_end: redis::setnx -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::append +[pinpoint] [%d:%d]call_interceptor_end: redis::setnx +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::append Redis::append before: ar : aa -[pinpoint] [%d] [%d] call_interceptor_before:redis::append return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::append return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::append end -[pinpoint] [%d] [%d]call_interceptor_end: redis::append -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::setrange +[pinpoint] [%d:%d]call_interceptor_end: redis::append +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::setrange Redis::setRange before: ar -[pinpoint] [%d] [%d] call_interceptor_before:redis::setrange return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::setrange return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::setRange end -[pinpoint] [%d] [%d]call_interceptor_end: redis::setrange -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::get +[pinpoint] [%d:%d]call_interceptor_end: redis::setrange +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::get Redis::get before: ar -[pinpoint] [%d] [%d] call_interceptor_before:redis::get return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::get return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::get end -[pinpoint] [%d] [%d]call_interceptor_end: redis::get -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::getrange +[pinpoint] [%d:%d]call_interceptor_end: redis::get +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::getrange Redis::getRange before: ar -[pinpoint] [%d] [%d] call_interceptor_before:redis::getrange return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::getrange return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::getRange end -[pinpoint] [%d] [%d]call_interceptor_end: redis::getrange -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::strlen +[pinpoint] [%d:%d]call_interceptor_end: redis::getrange +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::strlen Redis::strlen before: ar -[pinpoint] [%d] [%d] call_interceptor_before:redis::strlen return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::strlen return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::strlen end -[pinpoint] [%d] [%d]call_interceptor_end: redis::strlen -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::getbit +[pinpoint] [%d:%d]call_interceptor_end: redis::strlen +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::getbit Redis::getBit before: ar : 1 -[pinpoint] [%d] [%d] call_interceptor_before:redis::getbit return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::getbit return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::getBit end -[pinpoint] [%d] [%d]call_interceptor_end: redis::getbit -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::setbit +[pinpoint] [%d:%d]call_interceptor_end: redis::getbit +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::setbit Redis::setBit before: ar -[pinpoint] [%d] [%d] call_interceptor_before:redis::setbit return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::setbit return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::setBit end -[pinpoint] [%d] [%d]call_interceptor_end: redis::setbit -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::get +[pinpoint] [%d:%d]call_interceptor_end: redis::setbit +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::get Redis::get before: ar -[pinpoint] [%d] [%d] call_interceptor_before:redis::get return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::get return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::get end -[pinpoint] [%d] [%d]call_interceptor_end: redis::get +[pinpoint] [%d:%d]call_interceptor_end: redis::get string(2) "bb" -[pinpoint] [%d] [%d]pinpoint_interceptor_handler_entry: handle func/method:redis::mset +[pinpoint] [%d:%d]pinpoint_interceptor_handler_entry: handle func/method:redis::mset Redis::mSet before: -[pinpoint] [%d] [%d] call_interceptor_before:redis::mset return type(1) zval -[pinpoint] [%d] [%d]replace_ex_caller_parameters return value must be `an array` +[pinpoint] [%d:%d] call_interceptor_before:redis::mset return type(1) zval +[pinpoint] [%d:%d]replace_ex_caller_parameters return value must be `an array` Redis::mSet end -[pinpoint] [%d] [%d]call_interceptor_end: redis::mset +[pinpoint] [%d:%d]call_interceptor_end: redis::mset int(3) -[pinpoint] [%d] [%d]start free interceptor: redis::info -[pinpoint] [%d] [%d]start free interceptor: redis::get -[pinpoint] [%d] [%d]start free interceptor: redis::set -[pinpoint] [%d] [%d]start free interceptor: redis::setnx -[pinpoint] [%d] [%d]start free interceptor: redis::append -[pinpoint] [%d] [%d]start free interceptor: redis::getrange -[pinpoint] [%d] [%d]start free interceptor: redis::setrange -[pinpoint] [%d] [%d]start free interceptor: redis::strlen -[pinpoint] [%d] [%d]start free interceptor: redis::getbit -[pinpoint] [%d] [%d]start free interceptor: redis::setbit -[pinpoint] [%d] [%d]start free interceptor: redis::mset -[pinpoint] [%d] [%d]start free interceptor: redis::msetnx \ No newline at end of file +[pinpoint] [%d:%d]start free interceptor: redis::info +[pinpoint] [%d:%d]start free interceptor: redis::get +[pinpoint] [%d:%d]start free interceptor: redis::set +[pinpoint] [%d:%d]start free interceptor: redis::setnx +[pinpoint] [%d:%d]start free interceptor: redis::append +[pinpoint] [%d:%d]start free interceptor: redis::getrange +[pinpoint] [%d:%d]start free interceptor: redis::setrange +[pinpoint] [%d:%d]start free interceptor: redis::strlen +[pinpoint] [%d:%d]start free interceptor: redis::getbit +[pinpoint] [%d:%d]start free interceptor: redis::setbit +[pinpoint] [%d:%d]start free interceptor: redis::mset +[pinpoint] [%d:%d]start free interceptor: redis::msetnx \ No newline at end of file diff --git a/tests_win32/stack_fetal_error.phpt b/tests_win32/stack_fetal_error.phpt index 16ed5924d..eb56fe516 100644 --- a/tests_win32/stack_fetal_error.phpt +++ b/tests_win32/stack_fetal_error.phpt @@ -4,7 +4,7 @@ pinpoint_php internal test case [pinpoint_test_main] --INI-- pinpoint_php.CollectorHost=tcp:localhost:10000 -pinpoint_php.SendSpanTimeOutMs=0 +pinpoint_php.SendSpanTimeOutMs=-1 pinpoint_php.UnitTest=true ;pinpoint_php._limit for internal use. User do not use it pinpoint_php._limit=yes @@ -32,7 +32,7 @@ class Foo{ } function Test(){ - throw new \Exception("I am testting"); + throw new \Exception("I am testing"); } _pinpoint_start_trace(); @@ -46,17 +46,17 @@ try{ _pinpoint_start_trace(); --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] -[pinpoint] [%d] [%d] [128] pinpoint_start child [127] -[pinpoint] [%d] [%d] [127] add clue key:name value:Foo -[pinpoint] [%d] [%d]apm_error_cb called +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [128] pinpoint_start child [127] +[pinpoint] [%d:%d] [127] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d]apm_error_cb called -Fatal error: Uncaught Exception: I am testting in %s:23 +Fatal error: Uncaught Exception: I am testing in %s:23 Stack trace: #0 %s(30): Test() #1 {main} thrown in %s on line 23 -[pinpoint] [%d] [%d] [127] pinpoint_end_trace Done! -[pinpoint] [%d] [%d]this span:({":E":%d,":FT":1500,":S":%d,"ERR":{"file":"%s","line":23,"msg":"Uncaught Exception: I am testting in %s:23\nStack trace:\n#0 %s(30): Test()\n#1 {main}\n thrown"},"calls":[{":E":%d,":S":%d,"name":"Foo"}]}) -[pinpoint] [%d] [%d]agent try to connect:(localhost:10000) -[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done! \ No newline at end of file +[pinpoint] [%d:%d] [127] pinpoint_end_trace Done! +[pinpoint] [%d:%d]this span:({":E":%d,":FT":1500,":S":%d,"ERR":{"file":"%s","line":23,"msg":"Uncaught Exception: I am testing in %s:23\nStack trace:\n#0 %s(30): Test()\n#1 {main}\n thrown"},"event":[{":E":%d,":S":%d,":depth":1,":seq":0,"name":"Foo"}]}) +[pinpoint] [%d:%d][unittest] current span was dropped +[pinpoint] [%d:%d] [128] pinpoint_end_trace Done! \ No newline at end of file diff --git a/tests_win32/trace_api_context_tcp.phpt b/tests_win32/trace_api_context_tcp.phpt index d6323c3e6..44681cc2b 100644 --- a/tests_win32/trace_api_context_tcp.phpt +++ b/tests_win32/trace_api_context_tcp.phpt @@ -4,7 +4,7 @@ Check call statck --INI-- pinpoint_php.CollectorHost=tcp:127.0.0.1:9999 -pinpoint_php.SendSpanTimeOutMs=0 +pinpoint_php.SendSpanTimeOutMs=-1 pinpoint_php.UnitTest=true ;pinpoint_php._limit for internal use. User do not use it pinpoint_php._limit=yes @@ -43,27 +43,28 @@ _pinpoint_end_trace($id); pinpoint_status(); ?> --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [0] pinpoint_start child [128] string(1) "a" string(1) "b" string(1) "c" -[pinpoint] [%d] [%d] pinpoint_get_context_key [128] failed with invalid map key, parameters:not exist +[pinpoint] [%d:%d] pinpoint_get_context_key [128] failed with invalid map key, parameters:not exist bool(false) -[pinpoint] [%d] [%d]this span:({":E":%d,":FT":1500,":S":%d}) -[pinpoint] [%d] [%d]agent try to connect:(127.0.0.1:9999) -[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done! -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] -[pinpoint] [%d] [%d] [128] pinpoint_start child [127] +[pinpoint] [%d:%d]this span:({":E":%d,":FT":1500,":S":%d}) +[pinpoint] [%d:%d][unittest] current span was dropped +[pinpoint] [%d:%d] [128] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [128] pinpoint_start child [127] string(1) "c" string(1) "b" string(1) "a" -[pinpoint] [%d] [%d] pinpoint_get_context_key [127] failed with invalid map key, parameters:not exist +[pinpoint] [%d:%d] pinpoint_get_context_key [127] failed with invalid map key, parameters:not exist 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] [128] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [127] pinpoint_end_trace Done! +[pinpoint] [%d:%d]this span:({":E":%d,":FT":1500,":S":%d,"event":[{":E":%d,":S":%d,":depth":1,":seq":0}]}) +[pinpoint] [%d:%d][unittest] current span was dropped +[pinpoint] [%d:%d] [128] pinpoint_end_trace Done! { - "common_library_version" : "%s", + "common_library_version" : "0.6.0", "pool_free_node" : 128, "pool_total_node" : 128 } \ No newline at end of file diff --git a/tests_win32/trace_api_test.phpt b/tests_win32/trace_api_test.phpt index 362d035a3..f29be3c8f 100644 --- a/tests_win32/trace_api_test.phpt +++ b/tests_win32/trace_api_test.phpt @@ -4,7 +4,7 @@ Check call statck --INI-- pinpoint_php.CollectorHost=tcp:localhost:10000 -pinpoint_php.SendSpanTimeOutMs=0 +pinpoint_php.SendSpanTimeOutMs=-1 pinpoint_php.UnitTest=true ;pinpoint_php._limit for internal use. User do not use it pinpoint_php._limit=yes @@ -53,82 +53,82 @@ echo _pinpoint_end_trace()."\n"; ?> --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [0] pinpoint_start child [128] 128 -[pinpoint] [%d] [%d] [128] add clue key:name value:ouput_234 -[pinpoint] [%d] [%d] [128] pinpoint_start child [127] +[pinpoint] [%d:%d] [128] add anno_v1 key:name value:ouput_234 +[pinpoint] [%d:%d] [128] pinpoint_start child [127] 127 -[pinpoint] [%d] [%d] [127] add clue key:name value:Foo -[pinpoint] [%d] [%d] [127] add clues:1:234,3432 -[pinpoint] [%d] [%d] [127] add clues:2:234 -[pinpoint] [%d] [%d] [127] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [127] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [127] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [127] add anno_v2 2:234 +[pinpoint] [%d:%d] [127] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [126] +[pinpoint] [%d:%d] [128] pinpoint_start child [126] 126 -[pinpoint] [%d] [%d] [126] add clue key:name value:Foo -[pinpoint] [%d] [%d] [126] add clues:1:234,3432 -[pinpoint] [%d] [%d] [126] add clues:2:234 -[pinpoint] [%d] [%d] [126] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [126] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [126] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [126] add anno_v2 2:234 +[pinpoint] [%d:%d] [126] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [125] +[pinpoint] [%d:%d] [128] pinpoint_start child [125] 125 -[pinpoint] [%d] [%d] [125] add clue key:name value:Foo -[pinpoint] [%d] [%d] [125] add clues:1:234,3432 -[pinpoint] [%d] [%d] [125] add clues:2:234 -[pinpoint] [%d] [%d] [125] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [125] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [125] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [125] add anno_v2 2:234 +[pinpoint] [%d:%d] [125] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [124] +[pinpoint] [%d:%d] [128] pinpoint_start child [124] 124 -[pinpoint] [%d] [%d] [124] add clue key:name value:Foo -[pinpoint] [%d] [%d] [124] add clues:1:234,3432 -[pinpoint] [%d] [%d] [124] add clues:2:234 -[pinpoint] [%d] [%d] [124] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [124] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [124] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [124] add anno_v2 2:234 +[pinpoint] [%d:%d] [124] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [123] +[pinpoint] [%d:%d] [128] pinpoint_start child [123] 123 -[pinpoint] [%d] [%d] [123] add clue key:name value:Foo -[pinpoint] [%d] [%d] [123] add clues:1:234,3432 -[pinpoint] [%d] [%d] [123] add clues:2:234 -[pinpoint] [%d] [%d] [123] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [123] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [123] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [123] add anno_v2 2:234 +[pinpoint] [%d:%d] [123] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [122] +[pinpoint] [%d:%d] [128] pinpoint_start child [122] 122 -[pinpoint] [%d] [%d] [122] add clue key:name value:Foo -[pinpoint] [%d] [%d] [122] add clues:1:234,3432 -[pinpoint] [%d] [%d] [122] add clues:2:234 -[pinpoint] [%d] [%d] [122] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [122] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [122] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [122] add anno_v2 2:234 +[pinpoint] [%d:%d] [122] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [121] +[pinpoint] [%d:%d] [128] pinpoint_start child [121] 121 -[pinpoint] [%d] [%d] [121] add clue key:name value:Foo -[pinpoint] [%d] [%d] [121] add clues:1:234,3432 -[pinpoint] [%d] [%d] [121] add clues:2:234 -[pinpoint] [%d] [%d] [121] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [121] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [121] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [121] add anno_v2 2:234 +[pinpoint] [%d:%d] [121] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [120] +[pinpoint] [%d:%d] [128] pinpoint_start child [120] 120 -[pinpoint] [%d] [%d] [120] add clue key:name value:Foo -[pinpoint] [%d] [%d] [120] add clues:1:234,3432 -[pinpoint] [%d] [%d] [120] add clues:2:234 -[pinpoint] [%d] [%d] [120] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [120] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [120] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [120] add anno_v2 2:234 +[pinpoint] [%d:%d] [120] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [119] +[pinpoint] [%d:%d] [128] pinpoint_start child [119] 119 -[pinpoint] [%d] [%d] [119] add clue key:name value:Foo -[pinpoint] [%d] [%d] [119] add clues:1:234,3432 -[pinpoint] [%d] [%d] [119] add clues:2:234 -[pinpoint] [%d] [%d] [119] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [119] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [119] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [119] add anno_v2 2:234 +[pinpoint] [%d:%d] [119] pinpoint_end_trace Done! 128 -[pinpoint] [%d] [%d] [128] pinpoint_start child [118] +[pinpoint] [%d:%d] [128] pinpoint_start child [118] 118 -[pinpoint] [%d] [%d] [118] add clue key:name value:Foo -[pinpoint] [%d] [%d] [118] add clues:1:234,3432 -[pinpoint] [%d] [%d] [118] add clues:2:234 -[pinpoint] [%d] [%d] [118] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [118] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [118] add anno_v2 1:234,3432 +[pinpoint] [%d:%d] [118] add anno_v2 2:234 +[pinpoint] [%d:%d] [118] pinpoint_end_trace Done! 128 -[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:(localhost:10000) -[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [128] add anno_v1 key:args value:a,$b +[pinpoint] [%d:%d] [128] add anno_v1 key:ret value:a,$b +[pinpoint] [%d:%d]this span:({":E":%d,":FT":1500,":S":%d,"args":"a,$b","event":[{":E":%d,":S":%d,":depth":1,":seq":0,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":1,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":2,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":3,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":4,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":5,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":6,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":7,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":8,"anno":["1:234,3432","2:234"],"name":"Foo"},{":E":%d,":S":%d,":depth":1,":seq":9,"anno":["1:234,3432","2:234"],"name":"Foo"}],"name":"ouput_234","ret":"a,$b"}) +[pinpoint] [%d:%d][unittest] current span was dropped +[pinpoint] [%d:%d] [128] pinpoint_end_trace Done! 0 \ No newline at end of file diff --git a/tests_win32/trace_api_with_id.phpt b/tests_win32/trace_api_with_id.phpt index 627a56262..f842e4512 100644 --- a/tests_win32/trace_api_with_id.phpt +++ b/tests_win32/trace_api_with_id.phpt @@ -4,7 +4,7 @@ Test pinpoint_unique_id --INI-- pinpoint_php.CollectorHost=tcp:localhost:10000 -pinpoint_php.SendSpanTimeOutMs=0 +pinpoint_php.SendSpanTimeOutMs=-1 pinpoint_php.UnitTest=true pinpoint_php.DebugReport=true --FILE-- @@ -45,21 +45,21 @@ _pinpoint_add_clue("name","Foo",$id); $id = _pinpoint_end_trace($id); --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] -[pinpoint] [%d] [%d] [128] add clue key:name value:Foo -[pinpoint] [%d] [%d] [128] pinpoint_start child [127] -[pinpoint] [%d] [%d] [127] add clues:name:Foo1 -[pinpoint] [%d] [%d] [127] pinpoint_start child [126] -[pinpoint] [%d] [%d] [126] add clue key:name value:Foo2 -[pinpoint] [%d] [%d] [126] pinpoint_end_trace Done! -[pinpoint] [%d] [%d] [127] pinpoint_start child [125] -[pinpoint] [%d] [%d] [125] add clues:name:Foo3 -[pinpoint] [%d] [%d] [125] add clue key:name value:Foo4 -[pinpoint] [%d] [%d] [125] pinpoint_end_trace Done! -[pinpoint] [%d] [%d] [127] add clues:name:Foo5 -[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:(localhost:10000) -[pinpoint] [%d] [%d] [128] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [128] add anno_v1 key:name value:Foo +[pinpoint] [%d:%d] [128] pinpoint_start child [127] +[pinpoint] [%d:%d] [127] add anno_v2 name:Foo1 +[pinpoint] [%d:%d] [127] pinpoint_start child [126] +[pinpoint] [%d:%d] [126] add anno_v1 key:name value:Foo2 +[pinpoint] [%d:%d] [126] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [127] pinpoint_start child [125] +[pinpoint] [%d:%d] [125] add anno_v2 name:Foo3 +[pinpoint] [%d:%d] [125] add anno_v1 key:name value:Foo4 +[pinpoint] [%d:%d] [125] pinpoint_end_trace Done! +[pinpoint] [%d:%d] [127] add anno_v2 name:Foo5 +[pinpoint] [%d:%d] [127] add anno_v1 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,"event":[{":E":%d,":S":%d,":depth":1,":seq":0,"EXP":"too heavy, throw it","anno":["name:Foo1","name:Foo5"]},{":E":%d,":S":%d,":depth":2,":seq":1,"name":"Foo2"},{":E":%d,":S":%d,":depth":2,":seq":2,"anno":["name:Foo3"],"name":"Foo4"}],"name":"Foo"}) +[pinpoint] [%d:%d][unittest] current span was dropped +[pinpoint] [%d:%d] [128] pinpoint_end_trace Done! Uncaught exception: too heavy, throw it \ No newline at end of file diff --git a/tests_win32/trace_had_root.phpt b/tests_win32/trace_had_root.phpt new file mode 100644 index 000000000..d565be5eb --- /dev/null +++ b/tests_win32/trace_had_root.phpt @@ -0,0 +1,40 @@ +--TEST-- +Test trace_had_root +--SKIPIF-- + +--INI-- +pinpoint_php.CollectorHost=unix:/unexist_file.sock +pinpoint_php.SendSpanTimeOutMs=-1 +pinpoint_php.UnitTest=true +pinpoint_php.DebugReport=true + +--FILE-- + +--EXPECTF-- +case not trace pass +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +case root trace pass +[pinpoint] [%d:%d] [128] pinpoint_start child [127] +case sub trace pass +[pinpoint] [%d:%d] [127] pinpoint_end_trace Done! +[pinpoint] [%d:%d]this span:({":E":%d,":FT":1500,":S":%d,"event":[{":E":%d,":S":%d,":depth":1,":seq":0}]}) +[pinpoint] [%d:%d][unittest] current span was dropped +[pinpoint] [%d:%d] [128] pinpoint_end_trace Done! \ No newline at end of file diff --git a/tests_win32/trace_limit_test-i448.phpt b/tests_win32/trace_limit_test-i448.phpt index fc062b311..0aa9a3577 100644 --- a/tests_win32/trace_limit_test-i448.phpt +++ b/tests_win32/trace_limit_test-i448.phpt @@ -34,15 +34,15 @@ if(_pinpoint_trace_limit()) _pinpoint_end_trace($id); --EXPECTF-- -[pinpoint] [%d] [%d] [0] pinpoint_start child [128] -[pinpoint] [%d] [%d] [128] pinpoint_start child [127] +[pinpoint] [%d:%d] [0] pinpoint_start child [128] +[pinpoint] [%d:%d] [128] pinpoint_start child [127] string(1) "c" string(1) "b" string(1) "a" -[pinpoint] [%d] [%d] pinpoint_get_context_key [127] failed with invalid map key, parameters:not exist +[pinpoint] [%d:%d] pinpoint_get_context_key [127] failed with invalid map key, 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: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 +[pinpoint] [%d:%d] [127] pinpoint_end_trace Done! +[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_win32/trace_limit_test.phpt b/tests_win32/trace_limit_test.phpt index 40162c5ce..771cd80fe 100644 --- a/tests_win32/trace_limit_test.phpt +++ b/tests_win32/trace_limit_test.phpt @@ -19,5 +19,5 @@ if(_pinpoint_trace_limit() || _pinpoint_trace_limit() ||_pinpoint_trace_limit() echo "_pinpoint_trace_limit failed"; } --EXPECTF-- -[pinpoint] [%d] [%d]This span dropped. max_trace_limit:2 current_tick:2 onLine:0 +[pinpoint] [%d:%d]This span dropped. max_trace_limit:2 current_tick:2 onLine:0 pass \ No newline at end of file