Share via


타임스탬프 수정

이 항목의 예에서는 연산자를 사용하여 이벤트의 타임스탬프를 수정하는 방법을 보여 줍니다. 이벤트 타임스탬프를 변경하면 조인, 기간에 대한 집계 등의 후속 연산에 대한 이벤트의 영향을 변경할 수 있습니다. 다음 LINQ 확장 메서드에서 이 기능을 제공합니다.

이벤트 시간 이동

ShiftEventTime() 연산자는 지정된 식에 따라 스트림의 각 이벤트 시작 시간을 변경합니다.

다음 예에서는 스트림의 각 이벤트 시간을 15분 후로 이동합니다.

// shift events by 15 minutes into the future.
var shifted = inputStream.ShiftEventTime(e => TimeSpan.FromMinutes(15)); 

다음 예에서는 스트림의 각 이벤트 시간을 1시간 전으로 이동합니다.

// shift events by 1 hour into the past.
var shifted = inputStream.ShiftEventTime(e => TimeSpan.FromHours(-1));

시간 이동을 지정하는 식은 현재 이벤트 시작 시간을 참조할 수는 있지만 이벤트 종료 시간이나 페이로드를 참조할 수는 없습니다. 시간 이동은 이벤트의 수명이나 페이로드에 영향을 주지 않습니다.

마이너스 무한대의 시간 값을 인코딩하기 위해 DateTime.MinValue 값이 고려됩니다. 이벤트 시작 시간에 이 값이 있고 상수와 반대로 지정된 식에서 이벤트 시작 시간이 참조될 경우 식은 평가되지 않고 시작 시간은 DateTime.MinValue로 유지됩니다. 그렇지 않은 경우 식은 런타임에 평가되고 계속해서 오버플로 예외가 발생합니다.

ShiftEventTime은 스트림에서 모든 이벤트의 시작 시간에 영향을 주기 때문에 지정된 시간 이동은 이 연산자를 통과하는 CTI 이벤트에도 적용됩니다.

이벤트 기간 변경

AlterEventDuration() 연산자는 이벤트 수명을 변경합니다. 이벤트 수명은 이벤트가 유효한 시간 간격을 지정합니다. 기간은 이벤트에 대한 함수로 정의되므로 이벤트 시작 시간, 종료 시간 또는 페이로드에서 기간을 계산할 수 있습니다.

다음 예에서는 이벤트 기간을 1시간으로 설정합니다.

// set event duration to 1 hour.
var onehour = inputStream.AlterEventDuration(e => TimeSpan.FromHours(1));

다음 예에서는 이벤트 기간을 현재 수명의 2배로 설정합니다.

// double event duration. 
var doubled = inputStream.AlterEventDuration(e => (e.EndTime - e.StartTime) * 2);

플러스 무한대의 시간 값을 인코딩하기 위해 DateTime.MaxValue 값이 고려됩니다. 이벤트 종료 시간에 이 값이 있고 지정된 식에서 이벤트 종료 시간이 참조될 경우 식은 평가되지 않고 종료 시간은 DateTime.MaxValue로 유지됩니다.

이벤트 기간 및 이동 변경

AlterEventLifetime() 연산자는 표현을 최대화하기 위해 AlterEventDuration 및 ShiftEventTime 함수를 결합합니다.

AlterEventLifeTime() 메서드에 대한 첫 번째 매개 변수는 새 시작 타임스탬프를 지정하며 현재 이벤트의 시작 시간을 참조할 수 있습니다. 이 매개 변수는 UTC 시간으로 지정해야 합니다. 두 번째 매개 변수는 새 수명을 지정하며 현재 이벤트의 시작 시간, 종료 시간 및 페이로드 필드를 참조할 수 있습니다.

다음 예에서는 새 수명을 두 번째 매개 변수로 지정할 때 이벤트 시간을 1분 전으로 이동하되 원래 수명에 1분을 추가해 이벤트 종료 시간은 그대로 유지합니다.

// shift event 1 minute into the past, but leave the end time (event duration) unchanged.
var newStream = inputStream.AlterEventLifetime(e => e.StartTime - TimeSpan.FromMinutes(1),
                                               e => e.EndTime - e.StartTime + TimeSpan.FromMinutes(1));]

지정한 시작 시간 이동은 이 연산자를 통과하는 CTI 이벤트에도 적용된다는 점에 유의하십시오.

또한 이 항목의 앞부분에서 DateTime.MinValue 및 DateTime.MaxValue에 대한 설명을 참조하십시오.

스트림을 시점 이벤트 스트림으로 변환

ToPointEventStream 연산자는 다음 예와 같이 이벤트 수명을 이벤트 시작 시간 전의 단일 틱으로 변경하여 가장자리 이벤트 및 간격 이벤트를 시점 이벤트로 변환하는 데 사용할 수 있는 편리한 함수입니다.

var pointStream = inputStream.ToPointEventStream();

간격 이벤트가 시점 이벤트로 변환될 때 이벤트의 시작 시간만 유지됩니다.

이벤트 기간 자르기

ClipEventDuration 연산자는 두 개의 스트림을 매개 변수로 사용하며 두 번째 스트림에 있는 일치하는 다음 이벤트의 시작 시간에 따라 첫 번째 스트림에 있는 각 이벤트의 수명을 변경합니다.

지금까지는 이벤트의 수명을 고정된 기간만큼 변경하는 데 사용할 수 있는 연산자에 대해 살펴봤습니다. ClipEventDuration 연산자는 다른 이벤트에 따라 이벤트의 수명을 조정하는 매우 융통성 있는 방법을 제공합니다. 일반적으로 이 연산자는 한 스트림에서 지정되며 일치 조건과 함께 또 다른 스트림을 매개 변수로 사용합니다. 이 연산자는 첫 번째 스트림에 있는 각 이벤트의 수명을 다른 스트림에 있는 일치 조건을 충족하는 "다음" 이벤트의 시작 시간(응용 프로그램 시간)으로 자릅니다.

예를 들어 stream1과 stream2라는 두 개의 스트림에서 "id"라는 페이로드 필드와 함께 이벤트가 전송된다고 가정해 보십시오. 다음 문은 stream1의 모든 이벤트를 "id" 값이 동일한 stream2의 다음 이벤트로 자릅니다.

var clipped = stream1.ClipEventDuration(stream2, (e1, e2) => e1.Id == e2.Id);

일치 조건은 두 입력 페이로드 모두에 대해 식으로 제공됩니다. 다음 다이어그램에서는 이 문의 의미를 보여 줍니다.

ClipEventDuration의 의미 체계

이 다이어그램은 stream1의 Id가 A인 첫 번째 이벤트가 stream2의 Id가 A인 다음 이벤트로 잘리는 방법을 보여 줍니다. Id가 B인 stream1의 다른 이벤트는 잘리지 않는데 stream2의 일치하는 다음 이벤트는 stream1의 이벤트가 종료된 후에만 발생하기 때문입니다.

이 자르기 동작은 다양한 응용 프로그램을 엽니다. 이 동작을 통해 지점 스트림을 연속된 간격 스트림 또는 "신호"로 변환하는 일반적인 요구 사항을 해결할 수 있습니다.

지점에서 신호로 변환

이 경우 먼저 모든 시점 이벤트를 연장하여 이벤트가 실제로 다음 이벤트에 도달하도록 해야 합니다. 다시 말해 다음 이벤트가 발생하기 전까지 한 이벤트가 지속되는 기간을 결정하는 제한 시간을 적용해야 합니다. 이 제한 시간은 유한 또는 무한 시간일 수 있습니다. 제한 시간이 60초라고 가정해 보겠습니다.

var extended = input.AlterEventDuration(e => TimeSpan.FromSeconds(60));

이 작업을 준비할 때 스트림 자체를 매개 변수로 지정하여 ClipEventDuration 연산자를 사용할 수 있습니다. 이렇게 하면 각 이벤트가 동일한 스트림에 있는 다음 이벤트로 잘려 연속된 일련의 간격 이벤트가 만들어집니다. 자르기 작업에서는 두 번째 스트림의 시작 시간만 의미가 있으므로 원래 지점 스트림도 사용할 수 있습니다.

var signal = extended.ClipEventDuration(input, (e1, e2) => true);

여기서는 단일 논리적 스트림을 사용한다고 가정하므로, 즉 스트림의 모든 이벤트에 단일 데이터 원본이 연결되어 있으므로 일치 조건이 항상 true로 평가됩니다.

다음 다이어그램은 ClipEventDuration 연산자를 통한 시점에서 신호로의 변환의 결과를 보여 줍니다.

ClipEventDuration을 사용하여 지점에서 신호로 변환

두 LINQ 문을 단일 문으로 결합할 수 있습니다.

var signal = input.AlterEventDuration(e => TimeSpan.FromSeconds(60)).ClipEventDuration(input, (e1, e2) => true);

스트림에 논리적 스트림이 여러 개 포함된 경우, 예를 들어 여러 장치의 측정값 또는 여러 주식의 주가가 포함된 경우에는 부울 식에서 해당 키(장치 ID 또는 주식 기호)가 일치해야 합니다.

var signal = input.AlterEventDuration(e => TimeSpan.FromSeconds(60)).ClipEventDuration(input, (e1, e2) => e1.Symbol == e2.Symbol);

세션 만들기

ClipEventDuration은 세션 중 발생한 이벤트에 주석을 추가하기 위해 세션 이벤트를 만들려는 경우에도 사용할 수 있습니다. 몇 가지 사용자 상호 작용 이벤트에 대해 설명하는 다음과 같은 이벤트 스키마가 있다고 가정해 보겠습니다.

public class EventType
{
    public int UserId;
    public string Type;
    public DateTime Time;
    public byte[] data;
};

이 예에서 페이로드 필드 Type은 각각 사용자 세션의 시작, 세션의 끝 또는 세션 중 발생한 사용자 이벤트에 대해 설명하는 “start”, “end” 또는 “other”일 수 있습니다. Time 필드에는 상호 작용의 타임스탬프가 포함되고 data에는 추가 정보가 포함됩니다. 이는 이벤트가 발생한 세션의 시작 시간을 각 이벤트에 주석으로 추가하기 위한 것입니다. 또한 각 세션은 10분 후에 제한 시간이 초과된다고 가정합니다.

다음 다이어그램에서는 이 시나리오에서 사용된 일련의 이벤트를 예로 보여 줍니다.

ClipEventDuration으로 세션 이벤트 만들기

먼저 제한 시간에 따른 기간 연장이 "start" 유형의 모든 이벤트에 적용됩니다.

var sessionStarts = from e in input
                    where e.Type == “start”
                    select e;
var sessionStartsExt = sessionStarts.AlterEventDuration(e => TimeSpan.FromMinutes(10));

그 다음에는 각 사용자 ID에 대해 이러한 세션 이벤트가 해당 끝까지 잘려야 합니다.

var sessionEnds = from e in input
                  where e.Type == “end”
                  select e;
var sessions = sessionStartsExt.ClipEventDuration(sessionEnds, (e1, e2) => e1.UserId == e2.UserId);

다음 다이어그램에서는 이러한 문을 보여 줍니다.

ClipEventDuration으로 세션 이벤트 자르기

이제 세션 이벤트를 나머지 이벤트에 조인할 수 있습니다.

var sessionActivity = from e in input
                      where e.Type == “other”
                      select e;
var annotated = from s1 in sessions
                join s2 in sessionActivity
                on s1.UserId equals s2.UserId
                select new {
                    s2.UserId,
                    s2.Type,
                    s2.Time,
                    s2.Data,
                    SessionStart = s1.Time
                }

이 조인에서 sessionActivity 이벤트와 세션 이벤트의 필드를 참조하여 주석이 추가된 sessionActivity 이벤트를 어셈블하고 세션 시작 시간을 각 sessionActivity 이벤트로 끌어올 수 있습니다.

다른 이벤트로 세션 이벤트 조인

조인 조건은 UserId와 같으므로 sessionActivity에서 UserId가 Y인 이벤트는 UserId가 X인 이 세션에서 고려되지 않습니다.

LINQ 문을 간단한 집합으로 압축할 수 있습니다.

var sessions = input
                 .Where(e => e.Type == “start”)
                 .AlterEventDuration(e => TimeSpan.FromMinutes(10))
                 .ClipEventDuration(input.Where(e => e.Type == “end”), (e1, e2) => e1.UserId == e2.UserId);
var annotated = from s1 in sessions
                join s2 in input.Where(e => e.Type == “other”)
                on s1.UserId equals s2.UserId
                select new {
                    s2.UserId,
                    s2.Type,
                    s2.Time,
                    s2.Data,
                    SessionStart = s1.Time
                }

참고 항목

개념

StreamInsight 서버 개념