feat!: affine cloud support (#3813)

Co-authored-by: Hongtao Lye <codert.sn@gmail.com>
Co-authored-by: liuyi <forehalo@gmail.com>
Co-authored-by: LongYinan <lynweklm@gmail.com>
Co-authored-by: X1a0t <405028157@qq.com>
Co-authored-by: JimmFly <yangjinfei001@gmail.com>
Co-authored-by: Peng Xiao <pengxiao@outlook.com>
Co-authored-by: xiaodong zuo <53252747+zuoxiaodong0815@users.noreply.github.com>
Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
Co-authored-by: Qi <474021214@qq.com>
Co-authored-by: danielchim <kahungchim@gmail.com>
This commit is contained in:
Alex Yang
2023-08-29 05:07:05 -05:00
committed by GitHub
parent d0145c6f38
commit 2f6c4e3696
414 changed files with 19469 additions and 7591 deletions
+174
View File
@@ -0,0 +1,174 @@
export const SPAN_ID_BYTES = 8;
export const TRACE_ID_BYTES = 16;
export const TRACE_VERSION = '00';
export const TRACE_FLAG = '01';
const BytesBuffer = Array(32);
type TraceSpan = {
name: string;
spanId: string;
displayName: {
value: string;
truncatedByteCount: number;
};
startTime: string;
endTime: string;
attributes: {
attributeMap: {
requestId: {
stringValue: {
value: string;
truncatedByteCount: number;
};
};
};
droppedAttributesCount: number;
};
};
/**
* inspired by open-telemetry/opentelemetry-js
*/
export function generateRandUTF16Chars(bytes: number) {
for (let i = 0; i < bytes * 2; i++) {
BytesBuffer[i] = Math.floor(Math.random() * 16) + 48;
// valid hex characters in the range 48-57 and 97-102
if (BytesBuffer[i] >= 58) {
BytesBuffer[i] += 39;
}
}
return String.fromCharCode(...BytesBuffer.slice(0, bytes * 2));
}
export class TraceReporter {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
static traceReportEndpoint = process.env.TRACE_REPORT_ENDPOINT!;
static shouldReportTrace = process.env.SHOULD_REPORT_TRACE;
private spansCache = new Array<TraceSpan>();
private reportIntervalId: number | undefined | NodeJS.Timeout;
private reportInterval = 60_000;
private static instance: TraceReporter;
public static getInstance(): TraceReporter {
if (!TraceReporter.instance) {
const instance = (TraceReporter.instance = new TraceReporter());
instance.initTraceReport();
}
return TraceReporter.instance;
}
public cacheTrace(
traceId: string,
spanId: string,
requestId: string,
startTime: string
) {
const span = TraceReporter.createTraceSpan(
traceId,
spanId,
requestId,
startTime
);
this.spansCache.push(span);
if (this.spansCache.length <= 1) {
this.initTraceReport();
}
}
public uploadTrace(
traceId: string,
spanId: string,
requestId: string,
startTime: string
) {
const span = TraceReporter.createTraceSpan(
traceId,
spanId,
requestId,
startTime
);
TraceReporter.reportToTraceEndpoint(JSON.stringify({ spans: [span] }));
}
public static reportToTraceEndpoint(payload: string): void {
if (typeof navigator !== 'undefined') {
navigator.sendBeacon(TraceReporter.traceReportEndpoint, payload);
} else {
fetch(TraceReporter.traceReportEndpoint, {
method: 'POST',
mode: 'cors',
cache: 'no-cache',
headers: {
'Content-Type': 'application/json',
},
body: payload,
}).catch(console.warn);
}
}
public static createTraceSpan(
traceId: string,
spanId: string,
requestId: string,
startTime: string
): TraceSpan {
return {
name: `projects/{GCP_PROJECT_ID}/traces/${traceId}/spans/${spanId}`,
spanId,
displayName: {
value: 'fetch',
truncatedByteCount: 0,
},
startTime,
endTime: new Date().toISOString(),
attributes: {
attributeMap: {
requestId: {
stringValue: {
value: requestId,
truncatedByteCount: 0,
},
},
},
droppedAttributesCount: 0,
},
};
}
private initTraceReport = () => {
if (!this.reportIntervalId && TraceReporter.shouldReportTrace) {
if (typeof window !== 'undefined') {
this.reportIntervalId = window.setInterval(
this.reportHandler,
this.reportInterval
);
} else {
this.reportIntervalId = setInterval(
this.reportHandler,
this.reportInterval
);
}
}
};
private reportHandler = () => {
if (this.spansCache.length <= 0) {
clearInterval(this.reportIntervalId);
this.reportIntervalId = undefined;
return;
}
TraceReporter.reportToTraceEndpoint(
JSON.stringify({ spans: [...this.spansCache] })
);
this.spansCache = [];
};
}
export const traceReporter = !process.env.SHOULD_REPORT_TRACE
? null
: TraceReporter.getInstance();