【优化】更加优雅地打印配置加载错误。默认不再显示大段的堆栈信息

main
walon 2021-07-29 18:14:15 +08:00
parent 54685289af
commit df722abb4a
14 changed files with 162 additions and 26 deletions

View File

@ -262,6 +262,10 @@ Options:
else else
{ {
s_logger.Error("GenJob fail. err:{err} msg:{msg}", res.ErrCode, res.ErrMsg); s_logger.Error("GenJob fail. err:{err} msg:{msg}", res.ErrCode, res.ErrMsg);
if (!string.IsNullOrEmpty(res.StackTrace))
{
s_logger.Debug("StackTrace: {}", res.StackTrace);
}
} }
return 1; return 1;

View File

@ -8,5 +8,6 @@ namespace Luban.Common
READ_FILE_FAIL, READ_FILE_FAIL,
JOB_ARGUMENT_ERROR, JOB_ARGUMENT_ERROR,
JOB_EXCEPTION, JOB_EXCEPTION,
DATA_PARSE_ERROR,
} }
} }

View File

@ -70,6 +70,8 @@ namespace Luban.Common.Protos
public List<FileInfo> ScatteredFiles { get; set; } = new List<FileInfo>(); public List<FileInfo> ScatteredFiles { get; set; } = new List<FileInfo>();
public string StackTrace { get; set; }
public override int GetTypeId() public override int GetTypeId()
{ {
return 0; return 0;
@ -81,6 +83,7 @@ namespace Luban.Common.Protos
os.WriteString(ErrMsg); os.WriteString(ErrMsg);
Bright.Common.SerializationUtil.Serialize(os, FileGroups); Bright.Common.SerializationUtil.Serialize(os, FileGroups);
Bright.Common.SerializationUtil.Serialize(os, ScatteredFiles); Bright.Common.SerializationUtil.Serialize(os, ScatteredFiles);
os.WriteString(StackTrace);
} }
public override void Deserialize(ByteBuf os) public override void Deserialize(ByteBuf os)
{ {
@ -88,6 +91,7 @@ namespace Luban.Common.Protos
ErrMsg = os.ReadString(); ErrMsg = os.ReadString();
Bright.Common.SerializationUtil.Deserialize(os, FileGroups); Bright.Common.SerializationUtil.Deserialize(os, FileGroups);
Bright.Common.SerializationUtil.Deserialize(os, ScatteredFiles); Bright.Common.SerializationUtil.Deserialize(os, ScatteredFiles);
StackTrace = os.ReadString();
} }
} }

View File

@ -0,0 +1,44 @@
using Luban.Job.Cfg.Defs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Luban.Job.Cfg.DataCreators
{
public class DataCreateException : System.Exception
{
private List<(DefBean, DefField)> VariablePath { get; } = new();
public string OriginDataLocation { get; set; }
public string DataLocationInFile { get; }
public string OriginErrorMsg { get; }
public string OriginStackTrace { get; }
public DataCreateException(Exception e, string dataLocation) : base("DataCreateException", e)
{
this.OriginStackTrace = e.StackTrace;
this.OriginErrorMsg = e.Message;
this.DataLocationInFile = dataLocation;
}
public void Push(DefBean bean, DefField f)
{
VariablePath.Add((bean, f));
}
public string VariableFullPathStr
{
get
{
var path = new List<(DefBean, DefField)>(VariablePath);
path.Reverse();
return string.Join(" => ", path.Select(b => $"{{{b.Item1.FullName}}}.{b.Item2.Name}"));
}
}
}
}

View File

@ -336,9 +336,16 @@ namespace Luban.Job.Cfg.DataCreators
list.Add(f.CType.Apply(this, f.Remapper, new ExcelStream(stream.ReadCell(), sep, false), ass)); list.Add(f.CType.Apply(this, f.Remapper, new ExcelStream(stream.ReadCell(), sep, false), ass));
} }
} }
catch (DataCreateException dce)
{
dce.Push(bean, f);
throw;
}
catch (Exception e) catch (Exception e)
{ {
throw new InvalidExcelDataException($"读取结构:{bean.FullName} 字段:{f.Name} 出错 ==> {e.Message}", e); var dce = new DataCreateException(e, stream.CurrentExcelPosition);
dce.Push(bean, f);
throw dce;
} }
} }
return list; return list;

View File

@ -128,9 +128,16 @@ namespace Luban.Job.Cfg.DataCreators
list.Add(f.CType.Apply(this, row.GetSubTitleNamedRow(fname), f.IsMultiRow /* 肯定是 false */, f.IsNullable)); list.Add(f.CType.Apply(this, row.GetSubTitleNamedRow(fname), f.IsMultiRow /* 肯定是 false */, f.IsNullable));
} }
} }
catch (DataCreateException dce)
{
dce.Push(bean, f);
throw;
}
catch (Exception e) catch (Exception e)
{ {
throw new Exception($"读取结构:{bean.FullName} 字段:{fname} 读取 出错 ==> {e.Message}", e); var dce = new DataCreateException(e, $"列:{fname}");
dce.Push(bean, f);
throw dce;
} }
} }
else else
@ -154,9 +161,16 @@ namespace Luban.Job.Cfg.DataCreators
list.Add(f.CType.Apply(ExcelDataCreator.Ins, null, row.GetMultiRowStream(f.Name, sep), (DefAssembly)bean.AssemblyBase)); list.Add(f.CType.Apply(ExcelDataCreator.Ins, null, row.GetMultiRowStream(f.Name, sep), (DefAssembly)bean.AssemblyBase));
} }
} }
catch (DataCreateException dce)
{
dce.Push(bean, f);
throw;
}
catch (Exception e) catch (Exception e)
{ {
throw new Exception($"读取结构:{bean.FullName} 多行字段:{f.Name} 读取 出错 ==> {e.Message}", e); var dce = new DataCreateException(e, "");
dce.Push(bean, f);
throw dce;
} }
} }
else else
@ -166,9 +180,16 @@ namespace Luban.Job.Cfg.DataCreators
{ {
list.Add(f.CType.Apply(ExcelDataCreator.Ins, f.Remapper, stream, (DefAssembly)bean.AssemblyBase)); list.Add(f.CType.Apply(ExcelDataCreator.Ins, f.Remapper, stream, (DefAssembly)bean.AssemblyBase));
} }
catch (DataCreateException dce)
{
dce.Push(bean, f);
throw;
}
catch (Exception e) catch (Exception e)
{ {
throw new Exception($"读取结构:{bean.FullName} 字段:{f.Name} 位置:{stream.CurrentExcelPosition} 出错 ==> {e.Message}", e); var dce = new DataCreateException(e, stream.CurrentExcelPosition);
dce.Push(bean, f);
throw dce;
} }
} }
} }

View File

@ -130,40 +130,47 @@ namespace Luban.Job.Cfg.DataCreators
} }
var fields = new List<DType>(); var fields = new List<DType>();
foreach (var field in implBean.HierarchyFields) foreach (DefField f in implBean.HierarchyFields)
{ {
if (x.TryGetProperty(field.Name, out var ele)) if (x.TryGetProperty(f.Name, out var ele))
{ {
if (ele.ValueKind == JsonValueKind.Null || ele.ValueKind == JsonValueKind.Undefined) if (ele.ValueKind == JsonValueKind.Null || ele.ValueKind == JsonValueKind.Undefined)
{ {
if (field.CType.IsNullable) if (f.CType.IsNullable)
{ {
fields.Add(null); fields.Add(null);
} }
else else
{ {
throw new Exception($"结构:{implBean.FullName} 字段:{field.Name} 不能 null or undefined "); throw new Exception($"结构:{implBean.FullName} 字段:{f.Name} 不能 null or undefined ");
} }
} }
else else
{ {
try try
{ {
fields.Add(field.CType.Apply(this, ele, ass)); fields.Add(f.CType.Apply(this, ele, ass));
}
catch (DataCreateException dce)
{
dce.Push(bean, f);
throw;
} }
catch (Exception e) catch (Exception e)
{ {
throw new Exception($"结构:{implBean.FullName} 字段:{field.Name} 读取失败 => {e.Message}", e); var dce = new DataCreateException(e, "");
dce.Push(bean, f);
throw dce;
} }
} }
} }
else if (field.CType.IsNullable) else if (f.CType.IsNullable)
{ {
fields.Add(null); fields.Add(null);
} }
else else
{ {
throw new Exception($"结构:{implBean.FullName} 字段:{field.Name} 缺失"); throw new Exception($"结构:{implBean.FullName} 字段:{f.Name} 缺失");
} }
} }
return new DBean(bean, implBean, fields); return new DBean(bean, implBean, fields);

View File

@ -172,29 +172,36 @@ namespace Luban.Job.Cfg.DataCreators
} }
var fields = new List<DType>(); var fields = new List<DType>();
foreach (var field in implBean.HierarchyFields) foreach (DefField f in implBean.HierarchyFields)
{ {
var ele = table[field.Name]; var ele = table[f.Name];
if (ele != null) if (ele != null)
{ {
try try
{ {
// Console.WriteLine("field:{0} type:{1} value:{2}", field.Name, ele.GetType(), ele); // Console.WriteLine("field:{0} type:{1} value:{2}", field.Name, ele.GetType(), ele);
fields.Add(field.CType.Apply(this, ele, ass)); fields.Add(f.CType.Apply(this, ele, ass));
}
catch (DataCreateException dce)
{
dce.Push(implBean, f);
throw;
} }
catch (Exception e) catch (Exception e)
{ {
throw new Exception($"结构:{implBean.FullName} 字段:{field.Name} 读取失败 => {e.Message}", e); var dce = new DataCreateException(e, "");
dce.Push(bean, f);
throw dce;
} }
} }
else if (field.CType.IsNullable) else if (f.CType.IsNullable)
{ {
fields.Add(null); fields.Add(null);
} }
else else
{ {
throw new Exception($"结构:{implBean.FullName} 字段:{field.Name} 缺失"); throw new Exception($"结构:{implBean.FullName} 字段:{f.Name} 缺失");
} }
} }
return new DBean(bean, implBean, fields); return new DBean(bean, implBean, fields);

View File

@ -98,7 +98,8 @@ namespace Luban.Job.Cfg.DataCreators
} }
catch (Exception e) catch (Exception e)
{ {
throw new Exception($"位置:{stream.CurrentExcelPosition} 出错 ==> {e.Message}", e); var dce = new DataCreateException(e, stream.CurrentExcelPosition);
throw dce;
} }
} }
return list; return list;
@ -132,7 +133,8 @@ namespace Luban.Job.Cfg.DataCreators
} }
catch (Exception e) catch (Exception e)
{ {
throw new Exception($"位置:{stream.CurrentExcelPosition} 出错 ==> {e.Message}", e); var dce = new DataCreateException(e, stream.CurrentExcelPosition);
throw dce;
} }
} }
return new DMap(type, map); return new DMap(type, map);

View File

@ -114,26 +114,33 @@ namespace Luban.Job.Cfg.DataCreators
} }
var fields = new List<DType>(); var fields = new List<DType>();
foreach (var field in implBean.HierarchyFields) foreach (DefField f in implBean.HierarchyFields)
{ {
var feles = x.Elements(field.Name); var feles = x.Elements(f.Name);
XElement fele = feles.FirstOrDefault(); XElement fele = feles.FirstOrDefault();
if (fele == null) if (fele == null)
{ {
if (field.CType.IsNullable) if (f.CType.IsNullable)
{ {
fields.Add(null); fields.Add(null);
continue; continue;
} }
throw new Exception($"字段:{field.Name} 缺失"); throw new Exception($"字段:{f.Name} 缺失");
} }
try try
{ {
fields.Add(field.CType.Apply(this, fele, ass)); fields.Add(f.CType.Apply(this, fele, ass));
}
catch (DataCreateException dce)
{
dce.Push(implBean, f);
throw;
} }
catch (Exception e) catch (Exception e)
{ {
throw new Exception($"结构:{implBean.FullName} 字段:{field.Name} 读取失败 => {e.Message}", e); var dce = new DataCreateException(e, "");
dce.Push(bean, f);
throw dce;
} }
} }

View File

@ -1,3 +1,4 @@
using Luban.Job.Cfg.DataCreators;
using System; using System;
using System.IO; using System.IO;
@ -25,6 +26,10 @@ namespace Luban.Job.Cfg.DataSources
source.Load(url, sheetName, stream, exportTestData); source.Load(url, sheetName, stream, exportTestData);
return source; return source;
} }
catch (DataCreateException dce)
{
throw;
}
catch (Exception e) catch (Exception e)
{ {
throw new Exception($"文件{url} 加载失败 ==> {e.Message}", e); throw new Exception($"文件{url} 加载失败 ==> {e.Message}", e);

View File

@ -1,4 +1,5 @@
using ExcelDataReader; using ExcelDataReader;
using Luban.Job.Cfg.DataCreators;
using Luban.Job.Cfg.Datas; using Luban.Job.Cfg.Datas;
using Luban.Job.Cfg.Defs; using Luban.Job.Cfg.Defs;
using Luban.Job.Common.Types; using Luban.Job.Common.Types;
@ -66,6 +67,11 @@ namespace Luban.Job.Cfg.DataSources.Excel
{ {
datas.AddRange(sheet.ReadMulti(type, ((DefBean)type.Bean).IsMultiRow)); datas.AddRange(sheet.ReadMulti(type, ((DefBean)type.Bean).IsMultiRow));
} }
catch (DataCreateException dce)
{
dce.OriginDataLocation = sheet.RawUrl;
throw;
}
catch (Exception e) catch (Exception e)
{ {
throw new Exception($"sheet:{sheet.Name} ==> {e.Message} {e.StackTrace}", e); throw new Exception($"sheet:{sheet.Name} ==> {e.Message} {e.StackTrace}", e);

View File

@ -2,6 +2,7 @@ using Bright.Time;
using CommandLine; using CommandLine;
using Luban.Common.Protos; using Luban.Common.Protos;
using Luban.Common.Utils; using Luban.Common.Utils;
using Luban.Job.Cfg.DataCreators;
using Luban.Job.Cfg.Defs; using Luban.Job.Cfg.Defs;
using Luban.Job.Cfg.Generate; using Luban.Job.Cfg.Generate;
using Luban.Job.Cfg.RawDefs; using Luban.Job.Cfg.RawDefs;
@ -424,6 +425,17 @@ namespace Luban.Job.Cfg
res.ScatteredFiles.AddRange(genScatteredFiles); res.ScatteredFiles.AddRange(genScatteredFiles);
} }
} }
catch (DataCreateException e)
{
res.ErrCode = Luban.Common.EErrorCode.DATA_PARSE_ERROR;
res.ErrMsg = $@"加载数据失败.
: {e.OriginDataLocation}
: {e.DataLocationInFile}
Err: {e.OriginErrorMsg}
: {e.VariableFullPathStr}
";
res.StackTrace = e.OriginStackTrace;
}
catch (Exception e) catch (Exception e)
{ {
res.ErrCode = Luban.Common.EErrorCode.JOB_EXCEPTION; res.ErrCode = Luban.Common.EErrorCode.JOB_EXCEPTION;

View File

@ -1,6 +1,7 @@
using Bright.Time; using Bright.Time;
using Luban.Common.Utils; using Luban.Common.Utils;
using Luban.Job.Cfg.Cache; using Luban.Job.Cfg.Cache;
using Luban.Job.Cfg.DataCreators;
using Luban.Job.Cfg.Datas; using Luban.Job.Cfg.Datas;
using Luban.Job.Cfg.DataSources; using Luban.Job.Cfg.DataSources;
using Luban.Job.Cfg.Defs; using Luban.Job.Cfg.Defs;
@ -186,6 +187,14 @@ namespace Luban.Job.Cfg.Utils
return record != null ? new List<Record> { record } : new List<Record>(); return record != null ? new List<Record> { record } : new List<Record>();
} }
} }
catch (DataCreateException dce)
{
if (string.IsNullOrWhiteSpace(dce.OriginDataLocation))
{
dce.OriginDataLocation = originFile;
}
throw;
}
catch (Exception e) catch (Exception e)
{ {
throw new Exception($"配置文件:{originFile} 生成失败. ==> {e.Message}", e); throw new Exception($"配置文件:{originFile} 生成失败. ==> {e.Message}", e);