本文主要介绍在请求WebApi时,监控Action执行的时间,及Action传递的参数值,以及Http请求头信息。采用log4net记录监控日志,通过日志记录的时间方便我们定位哪一个Action执行的时间过长,进而采取优化的手段。

监控日志监控的指标如下图

监控程序实现

改监控程序主要继承ActionFilterAttribute类,在命名空间:System.Web.Http.Filters中,重写OnActionExecuted(HttpActionExecutedContext actionExecutedContext) 和OnActionExecuting(HttpActionContext actionContext)两个方法。在上一篇文章介绍MVC的监控也是重写ActionFilterAttribute类,但是MVC的ActionFilterAttribute在System.Web.Mvc命名空间下。

1、监控日志对象
/// <summary>
/// 监控日志对象
/// </summary>
public class WebApiMonitorLog
{
public string ControllerName
{
get;
set;
}
public string ActionName
{
get;
set;
} public DateTime ExecuteStartTime
{
get;
set;
}
public DateTime ExecuteEndTime
{
get;
set;
}
/// <summary>
/// 请求的Action 参数
/// </summary>
public Dictionary<string, object> ActionParams
{
get;
set;
}
/// <summary>
/// Http请求头
/// </summary>
public string HttpRequestHeaders
{
get;
set;
} /// <summary>
/// 请求方式
/// </summary>
public string HttpMethod
{
get;
set;
}
/// <summary>
/// 请求的IP地址
/// </summary>
public string IP
{
get;
set;
} /// <summary>
/// 获取监控指标日志
/// </summary>
/// <param name="mtype"></param>
/// <returns></returns>
public string GetLoginfo()
{
string Msg = @"
Action执行时间监控:
ControllerName:{0}Controller
ActionName:{1}
开始时间:{2}
结束时间:{3}
总 时 间:{4}秒
Action参数:{5}
Http请求头:{6}
客户端IP:{7},
HttpMethod:{8}
";
return string.Format(Msg,
ControllerName,
ActionName,
ExecuteStartTime,
ExecuteEndTime,
(ExecuteEndTime - ExecuteStartTime).TotalSeconds,
GetCollections(ActionParams),
HttpRequestHeaders,
IP,
HttpMethod);
} /// <summary>
/// 获取Action 参数
/// </summary>
/// <param name="Collections"></param>
/// <returns></returns>
public string GetCollections(Dictionary<string, object> Collections)
{
string Parameters = string.Empty;
if (Collections == null || Collections.Count == )
{
return Parameters;
}
foreach (string key in Collections.Keys)
{
Parameters += string.Format("{0}={1}&", key, Collections[key]);
}
if (!string.IsNullOrWhiteSpace(Parameters) && Parameters.EndsWith("&"))
{
Parameters = Parameters.Substring(, Parameters.Length - );
}
return Parameters;
} /// <summary>
/// 获取IP
/// </summary>
/// <returns></returns>
public string GetIP()
{
string ip = string.Empty;
if (!string.IsNullOrEmpty(System.Web.HttpContext.Current.Request.ServerVariables["HTTP_VIA"]))
ip = Convert.ToString(System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]);
if (string.IsNullOrEmpty(ip))
ip = Convert.ToString(System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]);
return ip;
} }
2、监控程序
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class WebApiTrackerAttribute : ActionFilterAttribute//, ExceptionFilterAttribute
{
private readonly string Key = "_thisWebApiOnActionMonitorLog_";
public override void OnActionExecuting(HttpActionContext actionContext)
{
base.OnActionExecuting(actionContext);
WebApiMonitorLog MonLog = new WebApiMonitorLog();
MonLog.ExecuteStartTime = DateTime.Now;
//获取Action 参数
MonLog.ActionParams = actionContext.ActionArguments;
MonLog.HttpRequestHeaders = actionContext.Request.Headers.ToString();
MonLog.HttpMethod = actionContext.Request.Method.Method; actionContext.Request.Properties[Key] = MonLog;
var form=System.Web.HttpContext.Current.Request.Form;
#region 如果参数是实体对象,获取序列化后的数据
Stream stream = actionContext.Request.Content.ReadAsStreamAsync().Result;
Encoding encoding = Encoding.UTF8;
stream.Position = ;
string responseData = "";
using (StreamReader reader = new StreamReader(stream, encoding))
{
responseData = reader.ReadToEnd().ToString();
}
if (!string.IsNullOrWhiteSpace(responseData) && !MonLog.ActionParams.ContainsKey("__EntityParamsList__"))
{
MonLog.ActionParams["__EntityParamsList__"] = responseData;
}
#endregion
} public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
WebApiMonitorLog MonLog = actionExecutedContext.Request.Properties[Key] as WebApiMonitorLog;
MonLog.ExecuteEndTime = DateTime.Now;
MonLog.ActionName = actionExecutedContext.ActionContext.ActionDescriptor.ActionName;
MonLog.ControllerName = actionExecutedContext.ActionContext.ActionDescriptor.ControllerDescriptor.ControllerName;
Log.Info(MonLog.GetLoginfo());
if (actionExecutedContext.Exception != null)
{
string Msg = string.Format(@"
请求【{0}Controller】的【{1}】产生异常:
Action参数:{2}
Http请求头:{3}
客户端IP:{4},
HttpMethod:{5}
", MonLog.ControllerName, MonLog.ActionName, MonLog.GetCollections(MonLog.ActionParams), MonLog.HttpRequestHeaders, MonLog.GetIP(), MonLog.HttpMethod);
Log.Error(Msg, actionExecutedContext.Exception);
}
} }
3、引用监控

我们可以在每个WebApiController类上或Action上直接引用 [WebApiTracker]即可完成对该WebApiController或Action的监控。

我们也可以在Global.asax中注册全局监控,这样我们就可以监控每一个WebApiController中的Action,代码如下:

 protected void Application_Start()
{ GlobalConfiguration.Configuration.Filters.Add(new WebApiTrackerAttribute());
AreaRegistration.RegisterAllAreas();
}

LoggerHelper 参考下面文章

MVC监控:http://www.cnblogs.com/lc-chenlong/p/4228639.html

WebApi 服务监控的更多相关文章

  1. 学习总结 之 WebApi服务监控 log4net记录监控日志

    在请求WebApi 的时候,我们更想知道在请求数据的时候,调用了哪个接口传了什么参数过来,调用这个Action花了多少时间,有没有人恶意请求.我们可以通过记录日志,对Action进行优化,可以通过日志 ...

  2. Self Host WebApi服务传输层SSL加密(服务器端+客户端调用)

    接上篇<WebApi服务URI加密及验证的两种方式>,在实际开发中,仅对URI进行加密是不够的,在传输层采用SSL加密也是必须的. 如果服务寄宿于IIS,那对传输层加密非常简单仅需要配置一 ...

  3. AJAX跨域调用ASP.NET MVC或者WebAPI服务

    关于AJAX跨域调用ASP.NET MVC或者WebAPI服务的问题及解决方案 作者:陈希章 时间:2014-7-3 问题描述 当跨域(cross domain)调用ASP.NET MVC或者ASP. ...

  4. 运维架构服务监控Open-Falcon

    一. 介绍 监控系统是整个运维环节,乃至整个产品生命周期中最重要的一环,事前及时预警发现故障,事后提供翔实的数据用于追查定位问题.监控系统作为一个成熟的运维产品,业界有很多开源的实现可供选择.当公司刚 ...

  5. wamp 服务监控和启动

    近日我的 wamp 莫名其妙的崩溃重启,apache 能自动起来, mysql 却悲剧了. 于是有了下面的wamp服务监控和启动的批处理文件 @echo off rem define loop tim ...

  6. SpringCloud系列七:Hystrix 熔断机制(Hystrix基本配置、服务降级、HystrixDashboard服务监控、Turbine聚合监控)

    1.概念:Hystrix 熔断机制 2.具体内容 所谓的熔断机制和日常生活中见到电路保险丝是非常相似的,当出现了问题之后,保险丝会自动烧断,以保护我们的电器, 那么如果换到了程序之中呢? 当现在服务的 ...

  7. C#使用Owin技术部署轻量级webApi服务

    写在前面: 除了使用IIS可以启用WebApi之外,微软还提供了Owin技术,免除了IIS繁琐的部署配置,只需要运行编写好的程序,即可启用webApi服务,是不是很爽呢? 对于Owin技术的详细介绍这 ...

  8. ASP.NET WebApi服务接口如何防止重复请求实现HTTP幂等性

    一.背景描述与课程介绍 明人不说暗话,跟着阿笨一起玩WebApi.在我们平时开发项目中可能会出现下面这些情况; 1).由于用户误操作,多次点击网页表单提交按钮.由于网速等原因造成页面卡顿,用户重复刷新 ...

  9. 如何做自己的服务监控?spring boot 2.x服务监控揭秘

    Actuator是spring boot项目中非常强大一个功能,有助于对应用程序进行监视和管理,通过 restful api请求来监管.审计.收集应用的运行情况,针对微服务而言它是必不可少的一个环节. ...

随机推荐

  1. windows下gethostbyname 调用失败

    gethostbyname()函数属于WinSock API库,而在使用WinSock API之前,必须调用WSAStartup函数,只有该函数成功返回(表示应用程序与WinSock库成功地建立起连接 ...

  2. jQuery Mobile 脚本加载问题

    刚开始使用jQuery Mobile,发现很多问题需要重新考虑,比如脚本加载问题. 在普通html中,如果a.html中有链接到b.html,b.html中有类似代码: $(document).rea ...

  3. webForm练习1(地区导航)

    使用LINQ TO SQL类连接数据库. create database mydb go use mydb go CREATE TABLE [dbo].[ChinaStates] ( ) COLLAT ...

  4. Hibernate对象的状态

    站在持久化的角度, Hibernate 把对象分为 4 种状态: 1. 持久化状态 2. 临时状态 3. 游离状态 4. 删除状态 Session 的特定方法能使对象从一个状态转换到另一个状态. 下面 ...

  5. 数据库中int类型存在空数据开发过程中model和dal层处理方法

    model层 public Int32? IsFullAttendance { get; set; } dal层  if (dr["IsFullAttendance"] + &qu ...

  6. JSON中的日期格式化

    Json字符串中的日期格式化函数 ConvertJsonDate: function (jd) { var d = new Date(parseInt(jd.replace("/Date(& ...

  7. 用Python玩转词云

    第一步:引入相关的库包: #coding:utf-8 __author__ = 'Administrator' import jieba #分词包 import numpy #numpy计算包 imp ...

  8. Selenium2+python自动化4-Pycharm使用

    前言 在写脚本之前,先要找个顺手的写脚本工具.python是一门解释性编程语言,所以一般把写python的工具叫解释器.写python脚本的工具很多,小编这里就不一一列举的,只要自己用着顺手就可以的, ...

  9. background-orgin属性

    重点内容是:背景的显示范围是在元素的内边距之内的,如果要想改变显示范围,可以使用background-orgin和background-clip进行调整. (1)background-orgin有三个 ...

  10. JSON.parse()和JSON.stringify()(转载)

    parse用于从一个字符串中解析出json对象,如 var str = '{"name":"huangxiaojian","age":&qu ...