.net webapi 过滤器使用(记录访问日志)
常用的过滤器有三种:OnAuthorization、ActionFilterAttribute、ExceptionFilterAttribute
本文件主要记录使用ActionFilterAttribute记录接口的访问日志,包括请求参数、响应结果,耗时等
直接上代码:
1 using Newtonsoft.Json; 2 using System; 3 using System.Collections.Generic; 4 using System.IO; 5 using System.Linq; 6 using System.Text; 7 using System.Web; 8 using System.Web.Http.Controllers; 9 using System.Web.Http.Filters; 10 using WebApi.Models; 11 12 namespace WebApi.App_Start 13 { 14 /// <summary> 15 /// 在Action方法运行之前调用 16 /// 1、所有请求流水先写TXT日志 17 /// 2、再启动作业程序把日志转存到指定位置 18 /// 3、分析日志进指定表,并删除日志 19 /// </summary> 20 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] 21 public class WebApiTrackerAttribute : ActionFilterAttribute 22 { 23 private readonly string Key = "_thisWebApiOnActionMonitorLog_"; 24 public override void OnActionExecuting(HttpActionContext actionContext) 25 { 26 base.OnActionExecuting(actionContext); 27 WebApiMonitorLog MonLog = new WebApiMonitorLog(); 28 MonLog.ExecuteStartTime = DateTime.Now; 29 //获取Action 参数 30 MonLog.ActionParams = actionContext.ActionArguments; 31 MonLog.HttpRequestHeaders = actionContext.Request.Headers.ToString(); 32 MonLog.HttpMethod = actionContext.Request.Method.Method; 33 34 actionContext.Request.Properties[Key] = MonLog; 35 var form = System.Web.HttpContext.Current.Request.Form; 36 #region 如果参数是实体对象,获取序列化后的数据 37 Stream stream = actionContext.Request.Content.ReadAsStreamAsync().Result; 38 Encoding encoding = Encoding.UTF8; 39 stream.Position = 0; 40 string responseData = ""; 41 using (StreamReader reader = new StreamReader(stream, encoding)) 42 { 43 responseData = reader.ReadToEnd().ToString(); 44 } 45 if (!string.IsNullOrWhiteSpace(responseData) && !MonLog.ActionParams.ContainsKey("__EntityParamsList__")) 46 { 47 MonLog.ActionParams["__EntityParamsList__"] = responseData; 48 } 49 #endregion 50 } 51 52 /// <summary> 53 /// 在Action方法运行之后调用 54 /// </summary> 55 /// <param name="actionExecutedContext"></param> 56 public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) 57 { 58 //加上按线程数存 59 int thread = 0; 60 try 61 { 62 thread = System.Threading.Thread.CurrentThread.ManagedThreadId; 63 } 64 catch 65 { 66 thread = 0; 67 } 68 WebApiMonitorLog MonLog = actionExecutedContext.Request.Properties[Key] as WebApiMonitorLog; 69 MonLog.ExecuteEndTime = DateTime.Now; 70 MonLog.ActionName = actionExecutedContext.ActionContext.ActionDescriptor.ActionName; 71 MonLog.ControllerName = actionExecutedContext.ActionContext.ActionDescriptor.ControllerDescriptor.ControllerName; 72 MonLog.Response = actionExecutedContext.Response.Content.ReadAsStringAsync().Result; 73 //Aisidi.Log.LogBuilder.Write(MonLog.ControllerName + "_" + System.DateTime.Now.Hour, MonLog.GetLoginfo()); 74 //高并发,用线程写法 75 76 string pathtxt = HttpContext.Current.Server.MapPath("/WebApiLog/"); 77 //TODO 写日志(txt格式) 78 79 80 //Aisidi.Log.LogBuilder.Write(MonLog.ControllerName + "_" + System.DateTime.Now.Hour + "_ThreadNum_" + thread, MonLog.GetLoginfo()); 81 if (actionExecutedContext.Exception != null) 82 { 83 string apiname = ""; 84 string Msg = string.Format(@" 85 请求【{0}Controller】的【{1}】产生异常: 86 Action参数:{2} 87 Http请求头:{3} 88 客户端IP:{4}, 89 HttpMethod:{5}", MonLog.ControllerName, MonLog.ActionName, MonLog.GetCollections(MonLog.ActionParams, out apiname), MonLog.HttpRequestHeaders, MonLog.GetIP(), MonLog.HttpMethod); 90 91 //TODO 写日志(txt格式) 92 } 93 } 94 } 95 /// <summary> 96 /// 监控日志对象 97 /// </summary> 98 public class WebApiMonitorLog 99 { 100 public string ControllerName 101 { 102 get; 103 set; 104 } 105 public string ActionName 106 { 107 get; 108 set; 109 } 110 111 public DateTime ExecuteStartTime 112 { 113 get; 114 set; 115 } 116 public DateTime ExecuteEndTime 117 { 118 get; 119 set; 120 } 121 /// <summary> 122 /// 请求的Action 参数 123 /// </summary> 124 public Dictionary<string, object> ActionParams 125 { 126 get; 127 set; 128 } 129 /// <summary> 130 /// Http请求头 131 /// </summary> 132 public string HttpRequestHeaders 133 { 134 get; 135 set; 136 } 137 138 /// <summary> 139 /// 请求方式 140 /// </summary> 141 public string HttpMethod 142 { 143 get; 144 set; 145 } 146 /// <summary> 147 /// 请求的IP地址 148 /// </summary> 149 public string IP 150 { 151 get; 152 set; 153 } 154 155 public string Response { get; set; } 156 157 public string GetLoginfo() 158 { 159 string apiname = ""; 160 string reqcontent = GetCollections(ActionParams, out apiname); 161 if (reqcontent.ToLower().Contains("apiname")) 162 { 163 apiname = JsonConvert.DeserializeObject<ApiRequest>(apiname).apiname; 164 } 165 string arguments = JsonConvert.SerializeObject(new webapi_logtxt 166 { 167 reqtime = ExecuteStartTime, 168 rsptime = ExecuteEndTime, 169 dealtime = (ExecuteEndTime - ExecuteStartTime).TotalSeconds.ToString(), 170 reqcontent = reqcontent, 171 rspcontent = Response, 172 apiname = apiname 173 }); 174 return arguments; 175 } 176 177 /// <summary> 178 /// 获取Action 参数 179 /// </summary> 180 /// <param name="Collections"></param> 181 /// <returns></returns> 182 public string GetCollections(Dictionary<string, object> Collections, out string apiname) 183 { 184 apiname = ""; 185 string Parameters = string.Empty; 186 if (Collections == null || Collections.Count == 0) 187 { 188 return Parameters; 189 } 190 foreach (string key in Collections.Keys) 191 { 192 Parameters += string.Format("{0}={1}&", key, Collections[key]); 193 if (key == "__EntityParamsList__") 194 { 195 apiname = Collections[key].ToString(); 196 } 197 } 198 if (!string.IsNullOrWhiteSpace(Parameters) && Parameters.EndsWith("&")) 199 { 200 Parameters = Parameters.Substring(0, Parameters.Length - 1); 201 } 202 return Parameters; 203 } 204 205 /// <summary> 206 /// 获取IP 207 /// </summary> 208 /// <returns></returns> 209 public string GetIP() 210 { 211 string ip = string.Empty; 212 if (!string.IsNullOrEmpty(System.Web.HttpContext.Current.Request.ServerVariables["HTTP_VIA"])) 213 ip = Convert.ToString(System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]); 214 if (string.IsNullOrEmpty(ip)) 215 ip = Convert.ToString(System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]); 216 return ip; 217 } 218 } 219 public class webapi_logtxt 220 { 221 /// <summary> 222 /// 请求时间 223 /// </summary> 224 public DateTime reqtime { get; set; } 225 /// <summary> 226 /// 响应时间 227 /// </summary> 228 public DateTime rsptime { get; set; } 229 /// <summary> 230 /// 处理时长 231 /// </summary> 232 public string dealtime { get; set; } 233 /// <summary> 234 /// 请求内容 235 /// </summary> 236 public string reqcontent { get; set; } 237 /// <summary> 238 /// 响应内容 239 /// </summary> 240 public string rspcontent { get; set; } 241 /// <summary> 242 /// 接口方法名称 243 /// </summary> 244 public string apiname { get; set; } 245 } 246 }
编写作业,定时去分析上面日志(只动过时日志),高并发控制,防止异常,估不建议在正常接口中进行操作数据库或分析作业日志
1 public void ReadFildWebApiLog() 2 { 3 //读取文件(1小时之前的文件) 4 //检验临时文件夹的文件是否超过1小时 5 string webLogTxt = System.Configuration.ConfigurationManager.AppSettings["WebApiLogFilePath"]; 6 if (!string.IsNullOrEmpty(webLogTxt)) 7 { 8 IsoDateTimeConverter timeFormat = new IsoDateTimeConverter(); 9 timeFormat.DateTimeFormat = "yyyy-MM-dd HH:mm:ss.fff"; 10 List<string> webLogTxtList = new FileUtilHelper().GetFiles(webLogTxt, -60); 11 string content = ""; 12 List<webapi_log> webapi_logList = null; 13 List<ishop_webapi_log> ishop_webapi_logList = null; 14 List<ishop_webapi_log_dtl> ishop_webapi_log_dtlList = null; 15 foreach (var weblog in webLogTxtList) 16 { 17 ishop_webapi_logList = new List<ishop_webapi_log>(); 18 ishop_webapi_log_dtlList = new List<ishop_webapi_log_dtl>(); 19 webapi_logList = new List<webapi_log>(); 20 content = System.IO.File.ReadAllText(webLogTxt + weblog); 21 var contentList = content.Split('\n'); 22 foreach (var con in contentList) 23 { 24 if (!string.IsNullOrEmpty(con)) 25 { 26 webapi_logList.Add(JsonConvert.DeserializeObject<webapi_log>(con)); 27 } 28 } 29 foreach (var log in webapi_logList) 30 { 31 string logid = Guid.NewGuid().ToString(); 32 string logdtlid = Guid.NewGuid().ToString(); 33 ishop_webapi_logList.Add(new ishop_webapi_log 34 { 35 id = logid, 36 apiname = log.apiname, 37 controllers = weblog.Split('_')[0].ToString(), 38 createtime = System.DateTime.Now, 39 dealtime = log.dealtime, 40 reqtime = log.reqtime, 41 rsptime = log.rsptime 42 }); 43 ishop_webapi_log_dtlList.Add(new ishop_webapi_log_dtl 44 { 45 id = logdtlid, 46 refid = logid, 47 reqcontent = log.reqcontent, 48 rspcontent = log.rspcontent 49 }); 50 } 51 //存储数据库 52 if (ishop_webapi_logDal.BatchAdd_SQL(ishop_webapi_logList, "ishop_webapi_log", ishavekey: false) > 0 && ishop_webapi_log_dtlDal.BatchAdd_SQL(ishop_webapi_log_dtlList, "ishop_webapi_log_dtl", ishavekey: false) > 0) 53 { 54 55 //删除文件 56 System.IO.File.Delete(webLogTxt + weblog); 57 } 58 } 59 } 60 61 }