1b0e7dd80Sopenharmony_ci/*
2b0e7dd80Sopenharmony_ci * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3b0e7dd80Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4b0e7dd80Sopenharmony_ci * you may not use this file except in compliance with the License.
5b0e7dd80Sopenharmony_ci * You may obtain a copy of the License at
6b0e7dd80Sopenharmony_ci *
7b0e7dd80Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8b0e7dd80Sopenharmony_ci *
9b0e7dd80Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10b0e7dd80Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11b0e7dd80Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b0e7dd80Sopenharmony_ci * See the License for the specific language governing permissions and
13b0e7dd80Sopenharmony_ci * limitations under the License.
14b0e7dd80Sopenharmony_ci */
15b0e7dd80Sopenharmony_ci
16b0e7dd80Sopenharmony_ci#include "hitrace/hitracechainc.h"
17b0e7dd80Sopenharmony_ci#include <sched.h>
18b0e7dd80Sopenharmony_ci#include <stdatomic.h>
19b0e7dd80Sopenharmony_ci#include <stdio.h>
20b0e7dd80Sopenharmony_ci#include <stdlib.h>
21b0e7dd80Sopenharmony_ci#include <string.h>
22b0e7dd80Sopenharmony_ci#include <sys/time.h>
23b0e7dd80Sopenharmony_ci#include "securec.h"
24b0e7dd80Sopenharmony_ci#include "hilog/log.h"
25b0e7dd80Sopenharmony_ci#include "hilog_trace.h"
26b0e7dd80Sopenharmony_ci#include "hitracechain_inner.h"
27b0e7dd80Sopenharmony_ci#include "hitrace_meter_wrapper.h"
28b0e7dd80Sopenharmony_ci#include "hitrace_meter_c.h"
29b0e7dd80Sopenharmony_ci
30b0e7dd80Sopenharmony_ci#undef LOG_DOMAIN
31b0e7dd80Sopenharmony_ci#undef LOG_TAG
32b0e7dd80Sopenharmony_cistatic const unsigned int LOG_DOMAIN = 0xD002D33;
33b0e7dd80Sopenharmony_cistatic const char* LOG_TAG = "HiTraceC";
34b0e7dd80Sopenharmony_cistatic const int BUFF_ZERO_NUMBER = 0;
35b0e7dd80Sopenharmony_cistatic const int BUFF_ONE_NUMBER = 1;
36b0e7dd80Sopenharmony_cistatic const int BUFF_TWO_NUMBER = 2;
37b0e7dd80Sopenharmony_ci
38b0e7dd80Sopenharmony_citypedef struct HiTraceChainIdStruct {
39b0e7dd80Sopenharmony_ci    union {
40b0e7dd80Sopenharmony_ci#if __BYTE_ORDER == __LITTLE_ENDIAN
41b0e7dd80Sopenharmony_ci        struct {
42b0e7dd80Sopenharmony_ci            uint64_t reserved : 4;
43b0e7dd80Sopenharmony_ci            uint64_t usecond : 20;
44b0e7dd80Sopenharmony_ci            uint64_t second : 16;
45b0e7dd80Sopenharmony_ci            uint64_t cpuId : 4;
46b0e7dd80Sopenharmony_ci            uint64_t deviceId : 20;
47b0e7dd80Sopenharmony_ci        };
48b0e7dd80Sopenharmony_ci        struct {
49b0e7dd80Sopenharmony_ci            uint64_t padding : 4;
50b0e7dd80Sopenharmony_ci            uint64_t chainId : 60;
51b0e7dd80Sopenharmony_ci        };
52b0e7dd80Sopenharmony_ci#elif __BYTE_ORDER == __BIG_ENDIAN
53b0e7dd80Sopenharmony_ci        struct {
54b0e7dd80Sopenharmony_ci            uint64_t deviceId : 20;
55b0e7dd80Sopenharmony_ci            uint64_t cpuId : 4;
56b0e7dd80Sopenharmony_ci            uint64_t second : 16;
57b0e7dd80Sopenharmony_ci            uint64_t usecond : 20;
58b0e7dd80Sopenharmony_ci            uint64_t reserved : 4;
59b0e7dd80Sopenharmony_ci        };
60b0e7dd80Sopenharmony_ci        struct {
61b0e7dd80Sopenharmony_ci            uint64_t chainId : 60;
62b0e7dd80Sopenharmony_ci            uint64_t padding : 4;
63b0e7dd80Sopenharmony_ci        };
64b0e7dd80Sopenharmony_ci#else
65b0e7dd80Sopenharmony_ci#error "ERROR: No BIG_LITTLE_ENDIAN defines."
66b0e7dd80Sopenharmony_ci#endif
67b0e7dd80Sopenharmony_ci    };
68b0e7dd80Sopenharmony_ci} HiTraceChainIdStruct;
69b0e7dd80Sopenharmony_ci
70b0e7dd80Sopenharmony_citypedef struct HiTraceIdStructExtra {
71b0e7dd80Sopenharmony_ci    uint32_t setTls : 1;
72b0e7dd80Sopenharmony_ci    uint32_t reserved : 31;
73b0e7dd80Sopenharmony_ci} HiTraceIdStructExtra;
74b0e7dd80Sopenharmony_ci
75b0e7dd80Sopenharmony_citypedef struct HiTraceIdStructInner {
76b0e7dd80Sopenharmony_ci    HiTraceIdStruct id;
77b0e7dd80Sopenharmony_ci    HiTraceIdStructExtra extra;
78b0e7dd80Sopenharmony_ci} HiTraceIdStructInner;
79b0e7dd80Sopenharmony_ci
80b0e7dd80Sopenharmony_cistatic __thread HiTraceIdStructInner g_hiTraceId = {{0, 0, 0, 0, 0, 0}, {0, 0}};
81b0e7dd80Sopenharmony_ci
82b0e7dd80Sopenharmony_cistatic inline HiTraceIdStructInner* GetThreadIdInner(void)
83b0e7dd80Sopenharmony_ci{
84b0e7dd80Sopenharmony_ci    return &g_hiTraceId;
85b0e7dd80Sopenharmony_ci}
86b0e7dd80Sopenharmony_ci
87b0e7dd80Sopenharmony_ciHiTraceIdStruct HiTraceChainGetId(void)
88b0e7dd80Sopenharmony_ci{
89b0e7dd80Sopenharmony_ci    HiTraceIdStructInner* pThreadId = GetThreadIdInner();
90b0e7dd80Sopenharmony_ci    return pThreadId->id;
91b0e7dd80Sopenharmony_ci}
92b0e7dd80Sopenharmony_ci
93b0e7dd80Sopenharmony_civoid HiTraceChainSetId(const HiTraceIdStruct* pId)
94b0e7dd80Sopenharmony_ci{
95b0e7dd80Sopenharmony_ci    if (!HiTraceChainIsValid(pId)) {
96b0e7dd80Sopenharmony_ci        return;
97b0e7dd80Sopenharmony_ci    }
98b0e7dd80Sopenharmony_ci
99b0e7dd80Sopenharmony_ci    HiTraceIdStructInner* pThreadId = GetThreadIdInner();
100b0e7dd80Sopenharmony_ci    pThreadId->id = *pId;
101b0e7dd80Sopenharmony_ci    return;
102b0e7dd80Sopenharmony_ci}
103b0e7dd80Sopenharmony_ci
104b0e7dd80Sopenharmony_civoid HiTraceChainClearId(void)
105b0e7dd80Sopenharmony_ci{
106b0e7dd80Sopenharmony_ci    HiTraceIdStructInner* pThreadId = GetThreadIdInner();
107b0e7dd80Sopenharmony_ci    HiTraceChainInitId(&(pThreadId->id));
108b0e7dd80Sopenharmony_ci    return;
109b0e7dd80Sopenharmony_ci}
110b0e7dd80Sopenharmony_ci
111b0e7dd80Sopenharmony_cistatic inline int HiTraceChainGetDeviceId(void)
112b0e7dd80Sopenharmony_ci{
113b0e7dd80Sopenharmony_ci    // save device id and use it later
114b0e7dd80Sopenharmony_ci    static atomic_int deviceId = 0;
115b0e7dd80Sopenharmony_ci
116b0e7dd80Sopenharmony_ci    if (deviceId == 0) {
117b0e7dd80Sopenharmony_ci        struct timeval tv;
118b0e7dd80Sopenharmony_ci        gettimeofday(&tv, NULL);
119b0e7dd80Sopenharmony_ci        srand(tv.tv_sec);
120b0e7dd80Sopenharmony_ci        deviceId = random();
121b0e7dd80Sopenharmony_ci    }
122b0e7dd80Sopenharmony_ci    return deviceId;
123b0e7dd80Sopenharmony_ci}
124b0e7dd80Sopenharmony_ci
125b0e7dd80Sopenharmony_cistatic inline unsigned int HiTraceChainGetCpuId(void)
126b0e7dd80Sopenharmony_ci{
127b0e7dd80Sopenharmony_ci    // Using vdso call will make get_cpu_id faster: sched_getcpu()
128b0e7dd80Sopenharmony_ci    static atomic_uint cpuId = 0;
129b0e7dd80Sopenharmony_ci    cpuId++;
130b0e7dd80Sopenharmony_ci
131b0e7dd80Sopenharmony_ci    return cpuId;
132b0e7dd80Sopenharmony_ci}
133b0e7dd80Sopenharmony_ci
134b0e7dd80Sopenharmony_cistatic inline uint64_t HiTraceChainCreateChainId(void)
135b0e7dd80Sopenharmony_ci{
136b0e7dd80Sopenharmony_ci    // get timestamp. Using vdso call(no system call)
137b0e7dd80Sopenharmony_ci    struct timeval tv;
138b0e7dd80Sopenharmony_ci    gettimeofday(&tv, NULL);
139b0e7dd80Sopenharmony_ci    HiTraceChainIdStruct chainId = {
140b0e7dd80Sopenharmony_ci        .padding = 0,
141b0e7dd80Sopenharmony_ci        .chainId = 0
142b0e7dd80Sopenharmony_ci    };
143b0e7dd80Sopenharmony_ci    chainId.deviceId = (uint64_t)(HiTraceChainGetDeviceId());
144b0e7dd80Sopenharmony_ci    chainId.cpuId = HiTraceChainGetCpuId();
145b0e7dd80Sopenharmony_ci    chainId.second = (uint64_t)(tv.tv_sec);
146b0e7dd80Sopenharmony_ci    chainId.usecond = (uint64_t)(tv.tv_usec);
147b0e7dd80Sopenharmony_ci    return chainId.chainId;
148b0e7dd80Sopenharmony_ci}
149b0e7dd80Sopenharmony_ci
150b0e7dd80Sopenharmony_ciHiTraceIdStruct HiTraceChainBegin(const char* name, int flags)
151b0e7dd80Sopenharmony_ci{
152b0e7dd80Sopenharmony_ci    HiTraceIdStruct id;
153b0e7dd80Sopenharmony_ci    HiTraceChainInitId(&id);
154b0e7dd80Sopenharmony_ci
155b0e7dd80Sopenharmony_ci    if ((flags < HITRACE_FLAG_MIN) || (flags > HITRACE_FLAG_MAX)) {
156b0e7dd80Sopenharmony_ci        return id;
157b0e7dd80Sopenharmony_ci    }
158b0e7dd80Sopenharmony_ci
159b0e7dd80Sopenharmony_ci    HiTraceIdStructInner* pThreadId = GetThreadIdInner();
160b0e7dd80Sopenharmony_ci    if (HiTraceChainIsValid(&(pThreadId->id))) {
161b0e7dd80Sopenharmony_ci        return id;
162b0e7dd80Sopenharmony_ci    }
163b0e7dd80Sopenharmony_ci
164b0e7dd80Sopenharmony_ci    id.valid = HITRACE_ID_VALID;
165b0e7dd80Sopenharmony_ci    id.ver = HITRACE_VER_1;
166b0e7dd80Sopenharmony_ci    id.chainId = HiTraceChainCreateChainId();
167b0e7dd80Sopenharmony_ci    id.flags = (uint64_t)flags;
168b0e7dd80Sopenharmony_ci    id.spanId = 0;
169b0e7dd80Sopenharmony_ci    id.parentSpanId = 0;
170b0e7dd80Sopenharmony_ci
171b0e7dd80Sopenharmony_ci    pThreadId->id = id;
172b0e7dd80Sopenharmony_ci
173b0e7dd80Sopenharmony_ci    if (!HiTraceChainIsFlagEnabled(&id, HITRACE_FLAG_NO_BE_INFO)) {
174b0e7dd80Sopenharmony_ci        HILOG_INFO(LOG_CORE, "HiTraceBegin name:%{public}s flags:0x%{public}.2x.", name ? name : "", (int)id.flags);
175b0e7dd80Sopenharmony_ci    }
176b0e7dd80Sopenharmony_ci    return id;
177b0e7dd80Sopenharmony_ci}
178b0e7dd80Sopenharmony_ci
179b0e7dd80Sopenharmony_civoid HiTraceChainEnd(const HiTraceIdStruct* pId)
180b0e7dd80Sopenharmony_ci{
181b0e7dd80Sopenharmony_ci    if (!HiTraceChainIsValid(pId)) {
182b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "HiTraceEnd error: invalid end id.");
183b0e7dd80Sopenharmony_ci        return;
184b0e7dd80Sopenharmony_ci    }
185b0e7dd80Sopenharmony_ci
186b0e7dd80Sopenharmony_ci    HiTraceIdStructInner* pThreadId = GetThreadIdInner();
187b0e7dd80Sopenharmony_ci    if (!HiTraceChainIsValid(&(pThreadId->id))) {
188b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "HiTraceEnd error: invalid thread id.");
189b0e7dd80Sopenharmony_ci        return;
190b0e7dd80Sopenharmony_ci    }
191b0e7dd80Sopenharmony_ci
192b0e7dd80Sopenharmony_ci    if (HiTraceChainGetChainId(pId) != HiTraceChainGetChainId(&(pThreadId->id))) {
193b0e7dd80Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "HiTraceEnd error: end id(%{public}llx) != thread id(%{public}llx).",
194b0e7dd80Sopenharmony_ci                    (unsigned long long)pId->chainId, (unsigned long long)pThreadId->id.chainId);
195b0e7dd80Sopenharmony_ci        return;
196b0e7dd80Sopenharmony_ci    }
197b0e7dd80Sopenharmony_ci
198b0e7dd80Sopenharmony_ci    if (!HiTraceChainIsFlagEnabled(&(pThreadId->id), HITRACE_FLAG_NO_BE_INFO)) {
199b0e7dd80Sopenharmony_ci        HILOG_DEBUG(LOG_CORE, "HiTraceEnd.");
200b0e7dd80Sopenharmony_ci    }
201b0e7dd80Sopenharmony_ci
202b0e7dd80Sopenharmony_ci    HiTraceChainInitId(&(pThreadId->id));
203b0e7dd80Sopenharmony_ci    return;
204b0e7dd80Sopenharmony_ci}
205b0e7dd80Sopenharmony_ci
206b0e7dd80Sopenharmony_ci// BKDRHash
207b0e7dd80Sopenharmony_cistatic uint32_t HashFunc(const void* pData, uint32_t dataLen)
208b0e7dd80Sopenharmony_ci{
209b0e7dd80Sopenharmony_ci    const uint32_t seed = 131;
210b0e7dd80Sopenharmony_ci
211b0e7dd80Sopenharmony_ci    if ((!pData) || dataLen == 0) {
212b0e7dd80Sopenharmony_ci        return 0;
213b0e7dd80Sopenharmony_ci    }
214b0e7dd80Sopenharmony_ci
215b0e7dd80Sopenharmony_ci    uint32_t hash = 0;
216b0e7dd80Sopenharmony_ci    uint32_t len = dataLen;
217b0e7dd80Sopenharmony_ci    char* p = (char*)pData;
218b0e7dd80Sopenharmony_ci
219b0e7dd80Sopenharmony_ci    for (; len > 0; --len) {
220b0e7dd80Sopenharmony_ci        hash = (hash * seed) + (*p++);
221b0e7dd80Sopenharmony_ci    }
222b0e7dd80Sopenharmony_ci
223b0e7dd80Sopenharmony_ci    return hash;
224b0e7dd80Sopenharmony_ci}
225b0e7dd80Sopenharmony_ci
226b0e7dd80Sopenharmony_ciHiTraceIdStruct HiTraceChainCreateSpan(void)
227b0e7dd80Sopenharmony_ci{
228b0e7dd80Sopenharmony_ci    static const uint32_t hashDataNum = 5;
229b0e7dd80Sopenharmony_ci
230b0e7dd80Sopenharmony_ci    HiTraceIdStruct id = HiTraceChainGetId();
231b0e7dd80Sopenharmony_ci    if (!HiTraceChainIsValid(&id)) {
232b0e7dd80Sopenharmony_ci        return id;
233b0e7dd80Sopenharmony_ci    }
234b0e7dd80Sopenharmony_ci
235b0e7dd80Sopenharmony_ci    if (HiTraceChainIsFlagEnabled(&id, HITRACE_FLAG_DONOT_CREATE_SPAN)) {
236b0e7dd80Sopenharmony_ci        return id;
237b0e7dd80Sopenharmony_ci    }
238b0e7dd80Sopenharmony_ci
239b0e7dd80Sopenharmony_ci    // create child span id
240b0e7dd80Sopenharmony_ci    struct timeval tv;
241b0e7dd80Sopenharmony_ci    gettimeofday(&tv, NULL);
242b0e7dd80Sopenharmony_ci
243b0e7dd80Sopenharmony_ci    uint32_t hashData[hashDataNum];
244b0e7dd80Sopenharmony_ci    hashData[0] = (uint32_t)(HiTraceChainGetDeviceId());  // 0: device id
245b0e7dd80Sopenharmony_ci    hashData[1] = id.parentSpanId;                   // 1: parent span id
246b0e7dd80Sopenharmony_ci    hashData[2] = id.spanId;                         // 2: span id
247b0e7dd80Sopenharmony_ci    hashData[3] = (uint32_t)(tv.tv_sec);             // 3: second
248b0e7dd80Sopenharmony_ci    hashData[4] = (uint32_t)(tv.tv_usec);            // 4: usecond
249b0e7dd80Sopenharmony_ci
250b0e7dd80Sopenharmony_ci    uint32_t hash = HashFunc(hashData, hashDataNum * sizeof(uint32_t));
251b0e7dd80Sopenharmony_ci
252b0e7dd80Sopenharmony_ci    id.parentSpanId = id.spanId;
253b0e7dd80Sopenharmony_ci    id.spanId = hash;
254b0e7dd80Sopenharmony_ci    return id;
255b0e7dd80Sopenharmony_ci}
256b0e7dd80Sopenharmony_ci
257b0e7dd80Sopenharmony_civoid HiTraceChainTracepointInner(HiTraceCommunicationMode mode, HiTraceTracepointType type,
258b0e7dd80Sopenharmony_ci    const HiTraceIdStruct* pId, const char* fmt, va_list args)
259b0e7dd80Sopenharmony_ci{
260b0e7dd80Sopenharmony_ci    static const int tpBufferSize = 1024;
261b0e7dd80Sopenharmony_ci    static const char* hiTraceTypeStr[] = { "CS", "CR", "SS", "SR", "GENERAL", };
262b0e7dd80Sopenharmony_ci    static const char* hiTraceModeStr[] = { "DEFAULT", "THREAD", "PROCESS", "DEVICE", };
263b0e7dd80Sopenharmony_ci    static const int hitraceMask = 3;
264b0e7dd80Sopenharmony_ci
265b0e7dd80Sopenharmony_ci    if ((mode < HITRACE_CM_MIN) || (mode > HITRACE_CM_MAX)) {
266b0e7dd80Sopenharmony_ci        return;
267b0e7dd80Sopenharmony_ci    }
268b0e7dd80Sopenharmony_ci    if ((type < HITRACE_TP_MIN) || (type > HITRACE_TP_MAX)) {
269b0e7dd80Sopenharmony_ci        return;
270b0e7dd80Sopenharmony_ci    }
271b0e7dd80Sopenharmony_ci
272b0e7dd80Sopenharmony_ci    if (!HiTraceChainIsValid(pId)) {
273b0e7dd80Sopenharmony_ci        return;
274b0e7dd80Sopenharmony_ci    }
275b0e7dd80Sopenharmony_ci
276b0e7dd80Sopenharmony_ci    char buff[tpBufferSize];
277b0e7dd80Sopenharmony_ci    if (type == HITRACE_TP_CS || type == HITRACE_TP_CR) {
278b0e7dd80Sopenharmony_ci        buff[BUFF_ZERO_NUMBER] = 'C';
279b0e7dd80Sopenharmony_ci    }
280b0e7dd80Sopenharmony_ci
281b0e7dd80Sopenharmony_ci    if (type == HITRACE_TP_SR || type == HITRACE_TP_SS) {
282b0e7dd80Sopenharmony_ci        buff[BUFF_ZERO_NUMBER] = 'S';
283b0e7dd80Sopenharmony_ci    }
284b0e7dd80Sopenharmony_ci    buff[BUFF_ONE_NUMBER] = '#';
285b0e7dd80Sopenharmony_ci    buff[BUFF_TWO_NUMBER] = '#';
286b0e7dd80Sopenharmony_ci
287b0e7dd80Sopenharmony_ci#pragma clang diagnostic push
288b0e7dd80Sopenharmony_ci#pragma clang diagnostic ignored "-Wformat-nonliteral"
289b0e7dd80Sopenharmony_ci    // if using privacy parameter: vsnprintf => hilog_vsnprintf
290b0e7dd80Sopenharmony_ci    int ret = vsnprintf_s(buff + hitraceMask, tpBufferSize - hitraceMask, tpBufferSize - 1 - hitraceMask, fmt, args);
291b0e7dd80Sopenharmony_ci#pragma clang diagnostic pop
292b0e7dd80Sopenharmony_ci    if (ret == -1) { // -1: vsnprintf_s copy string fail
293b0e7dd80Sopenharmony_ci        return;
294b0e7dd80Sopenharmony_ci    }
295b0e7dd80Sopenharmony_ci    if (type == HITRACE_TP_CS || type == HITRACE_TP_SR) {
296b0e7dd80Sopenharmony_ci        StartTraceChainPoint(pId, buff);
297b0e7dd80Sopenharmony_ci    }
298b0e7dd80Sopenharmony_ci
299b0e7dd80Sopenharmony_ci    if (type == HITRACE_TP_CR || type == HITRACE_TP_SS) {
300b0e7dd80Sopenharmony_ci        HiTraceFinishTrace(HITRACE_TAG_OHOS);
301b0e7dd80Sopenharmony_ci    }
302b0e7dd80Sopenharmony_ci
303b0e7dd80Sopenharmony_ci    if (!HiTraceChainIsFlagEnabled(pId, HITRACE_FLAG_TP_INFO) &&
304b0e7dd80Sopenharmony_ci        !HiTraceChainIsFlagEnabled(pId, HITRACE_FLAG_D2D_TP_INFO)) {
305b0e7dd80Sopenharmony_ci        // Both tp and d2d-tp flags are disabled.
306b0e7dd80Sopenharmony_ci        return;
307b0e7dd80Sopenharmony_ci    } else if (!HiTraceChainIsFlagEnabled(pId, HITRACE_FLAG_TP_INFO) && (mode != HITRACE_CM_DEVICE)) {
308b0e7dd80Sopenharmony_ci        // Only d2d-tp flag is enabled. But the communication mode is not device-to-device.
309b0e7dd80Sopenharmony_ci        return;
310b0e7dd80Sopenharmony_ci    }
311b0e7dd80Sopenharmony_ci    HILOG_INFO(LOG_CORE, "<%{public}s,%{public}s,[%{public}llx,%{public}llx,%{public}llx]> %{public}s",
312b0e7dd80Sopenharmony_ci               hiTraceModeStr[mode], hiTraceTypeStr[type], (unsigned long long)pId->chainId,
313b0e7dd80Sopenharmony_ci               (unsigned long long)pId->spanId, (unsigned long long)pId->parentSpanId, buff + hitraceMask);
314b0e7dd80Sopenharmony_ci    return;
315b0e7dd80Sopenharmony_ci}
316b0e7dd80Sopenharmony_ci
317b0e7dd80Sopenharmony_civoid HiTraceChainTracepointWithArgs(HiTraceTracepointType type, const HiTraceIdStruct* pId, const char* fmt,
318b0e7dd80Sopenharmony_ci    va_list args)
319b0e7dd80Sopenharmony_ci{
320b0e7dd80Sopenharmony_ci    HiTraceChainTracepointInner(HITRACE_CM_DEFAULT, type, pId, fmt, args);
321b0e7dd80Sopenharmony_ci}
322b0e7dd80Sopenharmony_ci
323b0e7dd80Sopenharmony_civoid HiTraceChainTracepointExWithArgs(HiTraceCommunicationMode mode, HiTraceTracepointType type,
324b0e7dd80Sopenharmony_ci    const HiTraceIdStruct* pId, const char* fmt, va_list args)
325b0e7dd80Sopenharmony_ci{
326b0e7dd80Sopenharmony_ci    HiTraceChainTracepointInner(mode, type, pId, fmt, args);
327b0e7dd80Sopenharmony_ci}
328b0e7dd80Sopenharmony_ci
329b0e7dd80Sopenharmony_civoid HiTraceChainTracepoint(HiTraceTracepointType type, const HiTraceIdStruct* pId, const char* fmt, ...)
330b0e7dd80Sopenharmony_ci{
331b0e7dd80Sopenharmony_ci    va_list args;
332b0e7dd80Sopenharmony_ci    va_start(args, fmt);
333b0e7dd80Sopenharmony_ci    HiTraceChainTracepointInner(HITRACE_CM_DEFAULT, type, pId, fmt, args);
334b0e7dd80Sopenharmony_ci    va_end(args);
335b0e7dd80Sopenharmony_ci    return;
336b0e7dd80Sopenharmony_ci}
337b0e7dd80Sopenharmony_ci
338b0e7dd80Sopenharmony_civoid HiTraceChainTracepointEx(HiTraceCommunicationMode mode, HiTraceTracepointType type, const HiTraceIdStruct* pId,
339b0e7dd80Sopenharmony_ci    const char* fmt, ...)
340b0e7dd80Sopenharmony_ci{
341b0e7dd80Sopenharmony_ci    va_list args;
342b0e7dd80Sopenharmony_ci    va_start(args, fmt);
343b0e7dd80Sopenharmony_ci    HiTraceChainTracepointInner(mode, type, pId, fmt, args);
344b0e7dd80Sopenharmony_ci    va_end(args);
345b0e7dd80Sopenharmony_ci    return;
346b0e7dd80Sopenharmony_ci}
347b0e7dd80Sopenharmony_ci
348b0e7dd80Sopenharmony_ciint HiTraceChainGetInfo(uint64_t* chainId, uint32_t* flags, uint64_t* spanId, uint64_t* parentSpanId)
349b0e7dd80Sopenharmony_ci{
350b0e7dd80Sopenharmony_ci    if (!chainId || !flags || !spanId || !parentSpanId) {
351b0e7dd80Sopenharmony_ci        return HITRACE_INFO_FAIL;
352b0e7dd80Sopenharmony_ci    }
353b0e7dd80Sopenharmony_ci
354b0e7dd80Sopenharmony_ci    HiTraceIdStruct id = HiTraceChainGetId();
355b0e7dd80Sopenharmony_ci    if (!HiTraceChainIsValid(&id)) {
356b0e7dd80Sopenharmony_ci        return HITRACE_INFO_FAIL;
357b0e7dd80Sopenharmony_ci    }
358b0e7dd80Sopenharmony_ci
359b0e7dd80Sopenharmony_ci    if (HiTraceChainIsFlagEnabled(&id, HITRACE_FLAG_DONOT_ENABLE_LOG)) {
360b0e7dd80Sopenharmony_ci        return HITRACE_INFO_FAIL;
361b0e7dd80Sopenharmony_ci    }
362b0e7dd80Sopenharmony_ci
363b0e7dd80Sopenharmony_ci    *chainId = HiTraceChainGetChainId(&id);
364b0e7dd80Sopenharmony_ci    *flags = HiTraceChainGetFlags(&id);
365b0e7dd80Sopenharmony_ci
366b0e7dd80Sopenharmony_ci    if (HiTraceChainIsFlagEnabled(&id, HITRACE_FLAG_DONOT_CREATE_SPAN)) {
367b0e7dd80Sopenharmony_ci        *spanId = 0;
368b0e7dd80Sopenharmony_ci        *parentSpanId = 0;
369b0e7dd80Sopenharmony_ci        return HITRACE_INFO_ALL_VALID_EXCEPT_SPAN;
370b0e7dd80Sopenharmony_ci    }
371b0e7dd80Sopenharmony_ci
372b0e7dd80Sopenharmony_ci    *spanId = HiTraceChainGetSpanId(&id);
373b0e7dd80Sopenharmony_ci    *parentSpanId = HiTraceChainGetParentSpanId(&id);
374b0e7dd80Sopenharmony_ci    return HITRACE_INFO_ALL_VALID;
375b0e7dd80Sopenharmony_ci}
376b0e7dd80Sopenharmony_ci
377b0e7dd80Sopenharmony_ciHiTraceIdStruct HiTraceChainSaveAndSetId(const HiTraceIdStruct* pId)
378b0e7dd80Sopenharmony_ci{
379b0e7dd80Sopenharmony_ci    HiTraceIdStruct oldId = g_hiTraceId.id;
380b0e7dd80Sopenharmony_ci    if (pId != NULL && pId->valid == HITRACE_ID_VALID) {
381b0e7dd80Sopenharmony_ci        g_hiTraceId.id = *pId;
382b0e7dd80Sopenharmony_ci    }
383b0e7dd80Sopenharmony_ci    return oldId;
384b0e7dd80Sopenharmony_ci}
385b0e7dd80Sopenharmony_ci
386b0e7dd80Sopenharmony_civoid HiTraceChainRestoreId(const HiTraceIdStruct* pId)
387b0e7dd80Sopenharmony_ci{
388b0e7dd80Sopenharmony_ci    if (pId != NULL) {
389b0e7dd80Sopenharmony_ci        g_hiTraceId.id = *pId;
390b0e7dd80Sopenharmony_ci    }
391b0e7dd80Sopenharmony_ci}
392b0e7dd80Sopenharmony_ci
393b0e7dd80Sopenharmony_cistatic void __attribute__((constructor)) HiTraceChainInit(void)
394b0e7dd80Sopenharmony_ci{
395b0e7dd80Sopenharmony_ci    // Call HiLog Register Interface
396b0e7dd80Sopenharmony_ci    HiLogRegisterGetIdFun(HiTraceChainGetInfo);
397b0e7dd80Sopenharmony_ci}
398b0e7dd80Sopenharmony_ci
399b0e7dd80Sopenharmony_cistatic void __attribute__((destructor)) HiTraceChainFini(void)
400b0e7dd80Sopenharmony_ci{
401b0e7dd80Sopenharmony_ci    HiLogUnregisterGetIdFun(HiTraceChainGetInfo);
402b0e7dd80Sopenharmony_ci}
403