【原创】StreamInsight查询系列(十七)——查询模式之应对瞬变及报警泛滥

上篇文章介绍了查询模式中的左外联接部分,这篇博文将介绍StreamInsight中如何处理报警及瞬变。

瞬变

我们用一个例子来解释如何使用StreamInsight处理瞬变情形,例如:

设定一个特定事件的“报警值”,如果2分钟内没有新事件出现,则产生一个报警?

如下,我们希望为Status为1的事件发生后2分钟内没有没有新事件出现的瞬变进行报警。

var sourceData = new[]
{
    new { Status = 1, TimeStamp = DateTime.Parse("10/23/2009 4:12:00 PM") },
    new { Status = 0, TimeStamp = DateTime.Parse("10/23/2009 4:13:00 PM") },
    new { Status = 1, TimeStamp = DateTime.Parse("10/23/2009 4:14:00 PM") },
    new { Status = 0, TimeStamp = DateTime.Parse("10/23/2009 4:15:00 PM") },
    new { Status = 0, TimeStamp = DateTime.Parse("10/23/2009 4:16:00 PM") },
    new { Status = 1, TimeStamp = DateTime.Parse("10/23/2009 4:30:00 PM") },
    new { Status = 0, TimeStamp = DateTime.Parse("10/23/2009 4:35:00 PM") },
};

var source = sourceData.ToPointStream(Application, ev =>
    PointEvent.CreateInsert(ev.TimeStamp.ToLocalTime(), ev),
    AdvanceTimeSettings.StrictlyIncreasingStartTime);

修改Status为0的事件流生命周期(提前2分钟),并利用左反半部联接与Status为1的事件流进行联接可以找出这些事件:

var result = from alarm in source.Where(e => e.Status == 1)
             where (from nextevent in source
                        .AlterEventLifetime(
                            e => e.StartTime.Subtract(TimeSpan.FromMinutes(2)),
                            e => timeout)
                    where nextevent.Status == 0
                    select nextevent).IsEmpty()
             select alarm;
结果如下:

报警泛滥

所谓报警泛滥是指给定某个特定事件的报警条件,如果报警发生,忽略掉后续一段时间内接下去的报警(例如“我已经知道车门没关好了,请别再告诉我了”)。

在下面的例子中,我们定义Status为0表示正常情况,Status为1表示报警。此外,我们设置10分钟的时间窗口来避免报警泛滥,并且希望最终得到的结果是发生在4:12和4:35的事件而过滤掉其他事件。

var sourceData2 = new[]
{
    new { Status = 0, TimeStamp = DateTime.Parse("10/23/2009 4:00:00 PM") },
    new { Status = 0, TimeStamp = DateTime.Parse("10/23/2009 4:10:00 PM") },
    new { Status = 1, TimeStamp = DateTime.Parse("10/23/2009 4:12:00 PM") },
    new { Status = 1, TimeStamp = DateTime.Parse("10/23/2009 4:13:00 PM") },
    new { Status = 1, TimeStamp = DateTime.Parse("10/23/2009 4:14:00 PM") },
    new { Status = 1, TimeStamp = DateTime.Parse("10/23/2009 4:15:00 PM") },
    new { Status = 0, TimeStamp = DateTime.Parse("10/23/2009 4:20:00 PM") },
    new { Status = 0, TimeStamp = DateTime.Parse("10/23/2009 4:30:00 PM") },
    new { Status = 1, TimeStamp = DateTime.Parse("10/23/2009 4:35:00 PM") },
};

var source2 = sourceData2.ToPointStream(Application, ev =>
    PointEvent.CreateInsert(ev.TimeStamp.ToLocalTime(), ev),
    AdvanceTimeSettings.StrictlyIncreasingStartTime);

要解决这个问题,我们可以:

  1. 过滤出报警事件;
  2. 将报警事件持续时间延伸为10分钟;
  3. 在快照窗口内进行计数;
  4. 将出现次数为1的事件流转变为点类型事件流,并与原有事件流进行联接得到结果。

第1,2,3步可以写在同一个查询中:

// 将报警事件持续时间扩展为10分钟,并且在快照窗口上计数
var counts = from win in source2
                 .Where(e => e.Status == 1)
                 .AlterEventDuration(e => TimeSpan.FromMinutes(10))
                 .SnapshotWindow(SnapshotWindowOutputPolicy.Clip)
             select new { count = win.Count() };

第4步:

// 计数为1的事件中包含了初始报警事件
// 将其转变为点类型事件并与原有流进行联接得到结果
var result2 = from c in counts
                .Where(e => e.count == 1)
                 .ToPointEventStream()
              from e in source2
              select e;

最终结果如下:

下一篇将介绍StreamInsight查询模式中的趋势发现。

posted @ 2011-09-06 09:57  StreamInsight  阅读(1131)  评论(2编辑  收藏  举报