162 lines
3.9 KiB
TypeScript
162 lines
3.9 KiB
TypeScript
/*
|
|
* Copyright 2025 coze-dev Authors
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
import { isAxiosError } from 'axios';
|
|
import { logger, reporter } from '@coze-arch/logger';
|
|
import { isApiError } from '@coze-arch/bot-http';
|
|
|
|
import { isChunkError } from './source-error';
|
|
import { isCustomError, type CustomError } from './custom-error';
|
|
import { ReportEventNames, type CertainErrorName } from './const';
|
|
const loggerWithScope = logger.createLoggerWith({
|
|
ctx: {
|
|
namespace: 'bot-error',
|
|
scope: 'certain-error',
|
|
},
|
|
});
|
|
const notInstanceError = (error: Error) => !(error instanceof Error);
|
|
|
|
const errorList: { func: (error: Error) => boolean; name: CertainErrorName }[] =
|
|
[
|
|
{
|
|
func: isCustomError,
|
|
name: 'CustomError',
|
|
},
|
|
{
|
|
func: isAxiosError,
|
|
name: 'AxiosError',
|
|
},
|
|
{
|
|
func: isApiError,
|
|
name: 'ApiError',
|
|
},
|
|
{
|
|
func: isChunkError,
|
|
name: 'ChunkLoadError',
|
|
},
|
|
{
|
|
func: notInstanceError,
|
|
name: 'notInstanceError',
|
|
},
|
|
];
|
|
|
|
const handleCertainError: (error: Error) => void = error => {
|
|
const errorName = getErrorName(error);
|
|
|
|
loggerWithScope.info({
|
|
message: 'handleCertainError',
|
|
meta: {
|
|
errorName,
|
|
error,
|
|
},
|
|
});
|
|
|
|
if (errorName === 'unknown') {
|
|
return;
|
|
}
|
|
|
|
// Report a custom error
|
|
if (errorName === 'CustomError') {
|
|
const { eventName, msg } = error as CustomError;
|
|
// Supplement unified reporting custom error event_name for monitoring
|
|
loggerWithScope.persist.error({
|
|
eventName: ReportEventNames.CustomErrorReport,
|
|
message: msg,
|
|
error,
|
|
meta: {
|
|
name: error.name,
|
|
originEventName: eventName, // originEventName
|
|
originErrorMessage: msg, // Original error msg
|
|
},
|
|
});
|
|
loggerWithScope.persist.error({
|
|
eventName,
|
|
message: msg,
|
|
error,
|
|
meta: {
|
|
name: error.name,
|
|
},
|
|
});
|
|
return;
|
|
}
|
|
|
|
// Filter out custom events that have been reported
|
|
if (errorName === 'ApiError' || errorName === 'AxiosError') {
|
|
return;
|
|
}
|
|
|
|
// ChunkLoad failed, not reported, static resource exception statistics in slardar
|
|
if (errorName === 'ChunkLoadError') {
|
|
reporter.info({
|
|
message: 'chunkLoadError',
|
|
meta: {
|
|
error,
|
|
errorName: error.name,
|
|
message: error.message,
|
|
stack: error.stack,
|
|
},
|
|
});
|
|
return;
|
|
}
|
|
|
|
// Error that does not inherit Error, current case (semi form validation)
|
|
if (errorName === 'notInstanceError') {
|
|
let errorInfo;
|
|
try {
|
|
errorInfo =
|
|
typeof error === 'object' ? JSON.stringify(error) : String(error);
|
|
} catch (e) {
|
|
errorInfo = 'notInstanceError json is invalid';
|
|
}
|
|
loggerWithScope.persist.error({
|
|
eventName: ReportEventNames.NotInstanceError,
|
|
message: errorInfo,
|
|
error,
|
|
meta: {
|
|
name: 'notInstanceError',
|
|
errorInfo,
|
|
},
|
|
});
|
|
return;
|
|
}
|
|
};
|
|
export const getErrorName = (error: Error) => {
|
|
if (!error) {
|
|
return 'unknown';
|
|
}
|
|
const result = errorList.find(({ func }) => func(error));
|
|
if (result && result.name) {
|
|
return result.name;
|
|
}
|
|
return 'unknown';
|
|
};
|
|
|
|
export const isCertainError = (error: Error) => {
|
|
const errorName = getErrorName(error);
|
|
return errorName !== 'unknown';
|
|
};
|
|
export const sendCertainError = (
|
|
error: Error,
|
|
handle?: (reason: string) => void,
|
|
) => {
|
|
if (isCertainError(error)) {
|
|
handleCertainError(error);
|
|
return;
|
|
}
|
|
|
|
handle?.(error?.message);
|
|
};
|