> For the complete documentation index, see [llms.txt](https://tarscloud.gitbook.io/tarsdocs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tarscloud.gitbook.io/tarsdocs/tarscpp/tars-cookie.md).

# Cookie 支持

## 概念说明

tars cookie 是在服务调用链上传播的信息，业务可以在调用链的上游设置 cookie，并在调用链的下游获取 cookie

## 使用场景

### 透传命令字优先级

接入 Svr 在 cookie 中设置请求命令字 id 和请求命令字优先级，透传到后端，后端可以根据这些信息定制自己的过载保护策略（譬如优先拒绝低优先级请求）

### 透传 msgno 和 uid

接入 Svr 在 cookie 中设置消息序列号(msgno)和用户 id(uid), 后端服务可以取出 cookie，并将 msgno 和 uid 打印在日志头中（这一步可以通过封装日志宏来自动处理）； 这样定位问题时，可以通过 uid 或者 msgno 来快速查找日志（譬如 A 调用 B 的场景，看到 A 的错误日志，则可以复制出 msgno，前往 B 服务快捷查找到该请求的日志）； 业务也可以把日志上报到 elk 等检索平台，便于通过 msgno 查找到所有日志

## 和染色关系

1. cookie 和染色类似，都可以在调用链上传播
2. 染色从概念上来说，一般只针对少量请求；而 cookie 针对全量请求
3. 染色会打印一份集中染色日志，而 cookie 不会
4. cookie 和染色可以同时使用，既针对全量请求设置 cookie，针对小部分需要特殊处理的请求进行染色（并且如果日志中有打印 cookie 中 msgno 和 uid 的话，在集中染色日志查找一个请求的完整日志也会很方便）
5. 使用全量请求染色也可以实现类似 cookie 的功能，但是这样相当于丢失了染色功能，只有 cookie 功能，而且此时磁盘 I/O 和使用容量会翻倍
6. 设置/读取 cookie 的函数使用 map 参数，方便业务定制各种信息，使用起来更加友好

## 使用示例

### 设置 cookie

```cpp
#include "servant/Cookie.h"
CookieOp cookieOp;
map<string, string> cookie;
cookie["msgno"] = "12345";
cookie["uid"] = "67890";
cookieOp.setCookie(cookie);
```

### 获取 cookie

#### 从线程私有数据中获取 cookie

```cpp
#include "servant/Cookie.h"
map<string, string> & cookie = CookieOp::getCookie();
TLOGDEBUG("cookie:" << TC_Common::tostr(cookie.begin(), cookie.end()) << endl);
TLOGDEBUG("msgno:" << cookie["msgno"] << endl);
```

#### 从 current 对象中获取 cookie

```cpp
map<string, string> & cookie = current->getCookie();
TLOGDEBUG("current cookie:" << TC_Common::tostr(cookie.begin(), cookie.end()) << endl);
TLOGDEBUG("msgno:" << cookie["msgno"] << endl);
```

## 具体应用

### 接入服务设置 cookie

接入服务在 RPC 调用之前，在 cookie 中设置 msgno 和 uid

```cpp
#include "servant/Cookie.h"

CookieOp cookieOp;
map<string, string> cookie;
cookie["msgno"] = genMsgNo();
cookie["uid"] = uid;
cookieOp.setCookie(cookie);
UserInfoServantPrx->async_getUserInfo(cb, ...);
```

### 后端服务打印日志

后端服务使用如下定制的宏来打印日志，日志头会自动带上 msgno 和 uid

```cpp
LOG_ERROR("call DBProxy.getUserInfo failed, ret:" << ret);
```

LOG\_ERROR 宏定义如下

```cpp
#define LOG_ERROR(msg) \
    TLOGERROR(__FILENAME__ << ":" << __LINE__ << ":" << __FUNCTION__ << "|" << CookieOp::getCookie()["msgno"] << "|" << CookieOp::getCookie()["uid"] << "|" << msg << endl);
```

### 查看日志

查看每个后端服务的日志，可以看到每条日志上都带上了 msgno 和 uid, 同一个请求在所有服务中的日志，msgno 和 uid 相同，其中 af4686091585191682152580023 和 10001 分别为 msgno 和 uid

#### UserInfoSvr 的日志

```
2020-03-26 11:01:22|24209|DEBUG|UserInfoServantImp.cpp:1019:getUserInfo|af4686091585191682152580023|10001|call DBProxy.getUserInfo failed, ret:-1
```

#### DBProxySvr 的日志

```
2020-03-26 11:01:22|12359|DEBUG|DBProxyServantImp.cpp:720:getUserInfo|af4686091585191682152580023|10001|sql is: select * from t_user wehre uid = '10001'
2020-03-26 11:01:22|12359|ERROR|DBProxyServantImp.cpp:723:getUserInfo|af4686091585191682152580023|10001|access db timeout
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://tarscloud.gitbook.io/tarsdocs/tarscpp/tars-cookie.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
