# sf nest trace

## 配置使trace生效
在src目录创建trace.ts
```typescript
const traceConfig = config().trace
// @ts-ignore
initTracingWithProvider({
  ...traceConfig,
  ignoreIncomingRequestHook: (request) => {
  const urls = [
    '/deploy/ready',
    '/deploy/live',
  ]
  for (const url of urls) {
    if (request.url === url) {
      return true
    }
  }
  return false
}
})
```
在main.ts导入trace.ts, **注意必须在@nestjs/core之前, nest-winston之后**
```typescript
import {
  WINSTON_MODULE_NEST_PROVIDER,
  WINSTON_MODULE_PROVIDER,
  WinstonModule,
} from 'nest-winston'
import './trace.js'

```

在module模块添加新的module
```typescript
SfNestTraceModule.forRootAsync({
  imports: [ConfigModule],
  inject: [ConfigService],
  useFactory: (confSvc: ConfigService) => {
    const config = confSvc.get('trace');
    return {
      ...config,
    };
  },
})
```


可以在想要添加span的代码添加@Span()手动创建span
```typescript
@Span()
async getSoftRoutingConnectionInfo(id: string) {
const resp = await firstValueFrom(
  this.httpService.post('http://localhost:8083/soft-router/conn-info',
    {},
    {
      headers:{
        Authorization: scopeUtils.getRequest().token
      }
    }))
return resp.data
}
```

## 示例配置文件(config.trace)
isTraceOn: 标记是否启用trace
withConsoleExporter: 是否启用console输出
endpoint: opentelemetry服务
metadata: 其他内容: 如字节需要添加"X-ByteAPM-AppKey"
serviceName: 服务名称
```js
trace: {
    endpoint: process.env.TRACE_GRPC_ENDPOINT || 'http://apmplus-cn-shanghai.volces.com:4317',
    isTraceOn: process.env.IS_TRACE_ON || "1",
    withConsoleExporter: false,
    metadata: {
      "X-ByteAPM-AppKey": process.env.TRACE_APP_KEY || '',
    },
    serviceName: process.env.TRACE_APP_KEY || 'sf_qa'
  }
```

## 请求返回traceId
默认配置会放在http response header里的TraceId头
如果需要在自己的接口内容返回可以这样
```typescript
import { trace } from '@opentelemetry/api'
@Injectable()
export class ResultInterceptor implements NestInterceptor {
  intercept(ctx: ExecutionContext, next: CallHandler) {
    const response = ctx.switchToHttp().getResponse();
    response.statusCode = HttpStatusCode.Ok;
    const requestId = scopeUtils.getRequestId();
    return next.handle().pipe(
      map((data) => {
          const result = {
            code: 0,
            message: 'success',
            data: data,
            traceId: trace.getActiveSpan()?.spanContext().traceId || ''
          }
          return result;
        }
      )
    )
  }}
```