使用OData协议查询Windows日志

OData开放数据协议是微软针对Google的GData推出的,旨在推广Web程序数据库格式标准化的开放数据协议,微软将 OData 定义为基于 HTTP、AtomPub 和 JSON 的协议,增强各种网页应用程序之间的数据兼容性,以提供多种应用、服务和数据商店的信息访问。并且,微软已经正式推出了 OData SDK,包含了 .NET、Java、PHP、Palm WebOS 和 iPhone 的支持。其中 .Net OData 客户端基于 Apache 授权开源。微软多款产品已经支持 OData 包括 SharePoint Server 2010, Excel 2010, Dynamics 等。

   微软第一代数据交换协议叫ODBC(开放数据库联接 Open Database Connectivity),目前仍旧可见于window和linux的原生程序开发之中,其目的是为操作系统下的应用程序之间提供统一的数据交互的API,是函数式的。之后,微软推出了第二代:OLE DB,带来了OOP式样的交互API,以及跨网络的数据交互的可能性(通过DCOM),OLE DB 标准的具体实现是一组C++ API 函数,就像ODBC 标准中的ODBC API 一样,不同的是,OLE DB 的API 是符合COM 标准、基于对象的(ODBC API 则是简单的C API)。使用OLE DB API,可以编写能够访问符合OLE DB 标准的任何数据源的应用程序,也可以编写针对某种特定数据存储的查询处理程序(Query Processor)和游标引擎(Cursor Engine),因此OLE DB 标准实际上是规定了数据使用者和提供者之间的一种应用层的协议(Application-Level Protocol)。在云计算时代,web应用已经是主流,程序主要通过HTTP Request来表达需求,通过HTTP Response来获取结果,ODBC和OLE DB都已无法使用。微软于是开发了其第三代数据交互协议:OData开放数据协议

   在SOA的世界中,最重要的一个概念就是契约(contract)。在云计算的世界中,有关通信的最重要的概念也是契约。XML具有强大对数据的描述能力,Atom格式和AtomPub都建立在XML之上,在Google和微软的推动下,也已经成为标准。但是,Atom/AtomPub和ODBC/OLEDB这样的真正数据交互协议相比较,还有着根本上的欠缺:缺乏数据类型的具体描述,降低了交互性能。缺乏对数据查询的控制能力,比如返回特定的数据集合的区间,或者说分页能力等等。微软基于EDM模型释出了:OData,这里也可以看出Entity Framework对于NHibernate这样的ORM的工具不同的战略考虑。

    在PDC大会上,微软宣布了一个代号为 “Dallas”的社区技术预览(CTP),由Windows Azure 和SQL Azure构建的信息服务,能够让开发者与信息工作者在任何平台上使用优质的第三方数据集和内容。“Dallas”也可以通过使用微软技术自助的商务智能与分析存储的数据集。Dallas所使用的数据交互协议就是OData。

   在微软的解决方案中,是用WCF来处理所有程序间的通信,针对数据通信,WCF Data Services自然是最好的选择。首先,WCF Data Services是WCF服务,所以你可以使用所有现有的WCF知识。其次,WCF Data Services已经实现了OData拓扑,于是你可以致力于你的数据格式在你的程序中的表示,而不是AtomPub/JSON这些真正在网络上传递的数据格式。再有,WCF Data Services致力于数据传输,而不是数据存储。你的数据可以存放在任何位置:本地的数据库,云端的数据库,外部的web services,xml文件,等等。无论数据是怎么来的,你都可以用同样的方式来发布/使用它们。

   下面我们就使用WCF Data Service将服务器的Windows应用程序日志向外发布。我们的应用程序可以把日志直接就写在Windows的日志里,然后通过使用WCF Data Service非常容易的就将日志想其他需要的用户公开。WCF Data Service默认使用的是Entity Framework,使用Entity Framework参看文章WCF Data Service QuickStart,还有一个Reflection Provider,可以支持只读的数据服务,这个例子就是演示使用Reflection Provider,资料参看MSDN:http://msdn.microsoft.com/en-us/library/dd723653(VS.100).aspx,还可以自定义实现一个Provider,参看文章自定义Data Service Providers

首先定义一个Windows日志的实体,类似于WCF的DataContract,这里使用的是EDM的映射:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Data.Services.Common; 
namespace ReflectionDataServiceDemo 
{ 
    [EntityPropertyMappingAttribute("Source", 
         SyndicationItemProperty.Title, 
         SyndicationTextContentKind.Plaintext, true)] 
    [EntityPropertyMapping("Message", 
        SyndicationItemProperty.Summary, 
        SyndicationTextContentKind.Plaintext, true)] 
    [EntityPropertyMapping("TimeGenerated", 
        SyndicationItemProperty.Updated, 
        SyndicationTextContentKind.Plaintext, true)] 
    [DataServiceKey("EventID")] 
    public class LogEntry 
    { 
        public long EventID 
        { 
            get; 
            set; 
        } 
        public string Category 
        { 
            get; 
            set; 
        } 
        public string Message 
        { 
            get; 
            set; 
        } 
        public DateTime TimeGenerated 
        { 
            get; 
            set; 
        } 
        public string Source 
        { 
            get; 
            set; 
        } 
    } 
}

上面使用一个新特性Friendly feeds 将数据映射到标准ATOM元素,其中DataServiceKey是唯一一个必须的标记,然后使用Reflection Provider实现一个IQueryable接口的数据源:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Diagnostics; 
namespace ReflectionDataServiceDemo 
{ 
    public class LogDataSource 
    { 
        string source; 
        public LogDataSource(string source) 
        { 
            this.source = source; 
        } 
        public LogDataSource() 
        { 
        } 
        public IQueryable<LogEntry> LogEntries 
        { 
            get { return GetEntries().AsQueryable().OrderBy(e => e.TimeGenerated); } 
        } 
        private IEnumerable<LogEntry> GetEntries() 
        { 
            var applicationLog = System.Diagnostics.EventLog.GetEventLogs().Where(e => e.Log == "Application") 
                .FirstOrDefault(); 
            var entries = new List<LogEntry>(); 
            if (applicationLog != null) 
            { 
                foreach (EventLogEntry entry in applicationLog.Entries) 
                { 
                    if (source == null || entry.Source.Equals(source, StringComparison.InvariantCultureIgnoreCase)) 
                    { 
                        entries.Add(new LogEntry 
                        { 
                            Category = entry.Category, 
                            EventID = entry.InstanceId, 
                            Message = entry.Message, 
                            TimeGenerated = entry.TimeGenerated, 
                            Source = entry.Source, 
                        }); 
                    } 
                } 
            } 
            return entries.OrderByDescending(e => e.TimeGenerated) 
                        .Take(200); 
        } 
    } 
}

最后添加一个WCF Data Service,代码非常的简单,主要的工作就是将上述数据源通过WCF Data Service发布出去:

using System; 
using System.Collections.Generic; 
using System.Data.Services; 
using System.Data.Services.Common; 
using System.Linq; 
using System.ServiceModel.Web; 
using System.Web; 
using System.Configuration; 
namespace ReflectionDataServiceDemo 
{ 
    public class LogDataService : DataService<LogDataSource > 
    { 
        // This method is called only once to initialize service-wide policies. 
        public static void InitializeService(DataServiceConfiguration config) 
        { 
            // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc. 
            // Examples: 
            config.SetEntitySetAccessRule("*", EntitySetRights.AllRead); 
            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All); 
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2; 
        } 
        protected override LogDataSource CreateDataSource() 
        { 
            string source = ConfigurationManager.AppSettings["EventLogSource"]; 
            if (source == null) 
            { 
                throw new ApplicationException("The EventLogSource appsetting is missing in the configuration file"); 
            } 
            return new LogDataSource(source); 
        } 
    } 
}

我们再来写个简单控制台客户端消费这个Service,通过Visual Studio的添加服务引用生成服务的客户端代码,还可以使用一个插件Open Data Protocol Visualizer查看服务返回的OData数据数据,这个工具的获取和安装可以参看VS2010的扩展。可以通过服务引用的“View in Diagram”进行查看。

客户端的代码也非常简单;

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
namespace ClientDemo 
{ 
    class Program 
    { 
        static void Main(string[] args) 
        { 
            LogDataService.LogDataSource logSource = new LogDataService.LogDataSource(new Uri("http://localhost:3399/LogDataService.svc/")); 
            foreach (var item in logSource.LogEntries) 
            { 
                Console.WriteLine(string.Format("来自{0}事件{1},内容{2}", item.Source, item.EventID, item.Message)); 
            } 
            Console.Read(); 
        } 
    } 
}

项目代码可以到这里获取 http://cid-33478a966734670f.skydrive.live.com/self.aspx/.Public/ReflectionDataServiceDemo.zip

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏葡萄城控件技术团队

如何在 ASP.NET MVC 中集成 AngularJS(3)

今天来为大家介绍如何在 ASP.NET MVC 中集成 AngularJS 的最后一部分内容。 调试路由表 - HTML 缓存清除 就在我以为示例应用程序完成之...

232100
来自专栏猛牛哥的博客

集结号抢座挂的制作分析过程(一):座位内存的分析

27260
来自专栏程序猿DD

极大提高工作效率的几十种神兵利器

来源:https://www.liutf.com/posts/3720794851.html

24130
来自专栏FreeBuf

浅谈拒绝服务攻击的原理与防御(2) :反射型DDOS

0×01 前言 前几天提交了一篇关于DDOS攻击的文章到今天下午才审核通过发表出来,所以晚上闲来无事在接着写下面的内容,今天我就不多说废话了直接来干货。 目前来...

31160
来自专栏Albert陈凯

2018-05-17 架构师技能图谱,搞懂这些找工作无敌数据结构常用算法并发操作系统设计模式运维 & 统计 & 技术支持中间件网络数据库搜索引擎性能大数据安全常用开源框架分布式设计设计思想 & 开发模

1.3K50
来自专栏架构师之路

1分钟实现“延迟消息”功能

一、缘起 很多时候,业务有“在一段时间之后,完成一个工作任务”的需求。 例如:滴滴打车订单完成后,如果用户一直不评价,48小时后会将自动评价为5星。 一般来说怎...

56060
来自专栏企鹅号快讯

httpclient接口测试完整用例

本人是在使用httpclient做接口测试的过程中,总结了一些方法,写了一个基本的测试框架。用例的管理和测试结果的保存都放在数据库中,今天算是基本完成和健全了用...

28750
来自专栏林德熙的博客

VisualStduio 打断点调试和不打断点调试有什么区别 随机数

最近小伙伴告诉我,他的代码在打断点的时候,运行到断点,之后就可以运行。如果没有断点,他的代码就无法运行,经过了一段时间的研究才发现,原来打断点和不打断点是有一些...

20920
来自专栏函数式编程语言及工具

Akka(28): Http:About Akka-Http

  众所周知,Akka系统是基于Actor模式的分布式运算系统,非常适合构建大数据平台。所以,无可避免地会出现独立系统之间、与异类系统、与移动系统集成的需求。由...

27670
来自专栏漏斗社区

黑客游戏| Owasp juice shop (一)

0x01 前言 最近看到一篇关于owasp juice shop的文章,觉的很有意思,斗哥就自己撸了个环境,上手后深深觉的这是一个很棒的漏洞靶场,所以就把该...

52680

扫码关注云+社区

领取腾讯云代金券