다음을 통해 공유


사용자 지정 추적 서비스 만들기

Windows Workflow Foundation에는 호스팅 환경에 즉시 연결하여 사용하기 시작할 수 있는 몇 가지 서비스가 포함되어 있습니다. 그러나 경우에 따라 특정 서비스를 사용자 지정하거나 직접 서비스를 만들어야 할 수 있습니다. 추적 서비스를 통해 프로세스 정보를 로그 파일이나 SQL Server 데이터베이스와 같은 저장 매체에 저장할 수 있습니다. 이 항목에서는 사용자 지정된 추적 서비스를 만드는 데 필요한 단계에 대해 설명합니다.

사용자 지정 추적 서비스 클래스 만들기

추적 데이터를 받는 모든 구성 요소는 TrackingService 기본 클래스에서 파생되어야 합니다. 호스트는 다른 Windows Workflow Foundation 서비스와 마찬가지로 Windows Workflow Foundation 런타임에 추적 서비스를 등록합니다. 추적 서비스가 등록된 후 추적 프레임워크는 추적 서비스를 인식하고 추적 서비스에서 워크플로 인스턴스 실행을 추적할 수 있도록 허용합니다. 서비스를 등록하는 방법에 대한 자세한 내용은 방법: 워크플로 서비스 추가 및 제거를 참조하십시오.

사용자 지정 추적 서비스는 추상 TrackingService 클래스에서 파생되는 클래스 개체입니다. TrackingService 클래스에는 사용자 지정 추적 서비스 동작을 제공하기 위해 재정의해야 하는 몇 가지 추상 메서드가 포함되어 있습니다.

예를 들어, 시스템 이벤트 로그를 사용하여 추적 정보를 출력하는 사용자 지정 추적 서비스를 만들려면 프로젝트에서 새 클래스를 만들고 이름을 EventLogTrackingService로 지정한 다음 TrackingService 기본 클래스에서 클래스를 파생시킵니다.

추상 기본 클래스 메서드를 재정의해야 하는 메서드를 생성하려면 TrackingService 클래스 이름을 마우스 오른쪽 단추로 클릭하고 바로 가기 메뉴에서 추상 클래스 'TrackingService' 구현을 선택합니다. 이렇게 하면 사용자 지정 추적 서비스를 구현하는 데 사용되는 메서드 정의가 생성됩니다.

코드는 다음 코드 예제와 유사합니다.

using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Workflow.ComponentModel;
using System.Workflow.Runtime;
using System.Workflow.Runtime.Tracking;

namespace CustomTrackingService
{
    public class EventLogTrackingService : TrackingService
    {
        protected override TrackingProfile GetProfile(Guid workflowInstanceId)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        protected override TrackingProfile GetProfile(Type workflowType, Version profileVersionId)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        protected override TrackingChannel GetTrackingChannel(TrackingParameters parameters)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        protected override bool TryGetProfile(Type workflowType, out TrackingProfile profile)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        protected override bool TryReloadProfile(Type workflowType, Guid workflowInstanceId, out TrackingProfile profile)
        {
            throw new Exception("The method or operation is not implemented.");
        }
    }
}
Imports System
Imports System.Diagnostics
Imports System.Collections.Generic
Imports System.Text
Imports System.Threading
Imports System.Workflow.ComponentModel
Imports System.Workflow.Runtime
Imports System.Workflow.Runtime.Tracking

Public Class EventLogTrackingService
    Inherits TrackingService

    Protected Overloads Overrides Function GetProfile(ByVal workflowInstanceId As System.Guid) As System.Workflow.Runtime.Tracking.TrackingProfile

    End Function

    Protected Overloads Overrides Function GetProfile(ByVal workflowType As System.Type, ByVal profileVersionId As System.Version) As System.Workflow.Runtime.Tracking.TrackingProfile

    End Function

    Protected Overrides Function GetTrackingChannel(ByVal parameters As System.Workflow.Runtime.Tracking.TrackingParameters) As System.Workflow.Runtime.Tracking.TrackingChannel

    End Function

    Protected Overrides Function TryGetProfile(ByVal workflowType As System.Type, ByRef profile As System.Workflow.Runtime.Tracking.TrackingProfile) As Boolean
    End Function

    Protected Overrides Function TryReloadProfile(ByVal workflowType As System.Type, ByVal workflowInstanceId As System.Guid, ByRef profile As System.Workflow.Runtime.Tracking.TrackingProfile) As Boolean

    End Function
End Class

추적 프로필

TrackingService 기본 클래스에서 재정의해야 하는 추상 메서드에는 TrackingProfiles와 TrackingChannels를 사용한 작업이 포함됩니다. TrackingProfiles를 사용하는 방법에 대한 자세한 내용은 추적 프로필 만들기 및 사용을 참조하십시오. TrackingService 클래스에 대한 자세한 내용은 TrackingService를 참조하십시오.

추적 서비스에 추적 데이터를 전송하기 위해 채널을 열기 전에 프로필을 제공해야 합니다. 이 프로필에서는 추적 서비스가 런타임 엔진에서 받을 추적 데이터의 형식에 대해 설명합니다. 이렇게 하려면 새 TrackingProfile 개체를 만들고 프로필을 ActivityTrackPointActivityTrackingLocation 개체와 연결합니다. 워크플로 런타임 엔진은 다음 예제와 같이 개체의 TryGetProfile 메서드를 호출하여 워크플로 형식을 추적 프로필과 연결합니다. 이 예제에서 GetDefaultProfile이라는 단일 정적 메서드는 기본 추적 프로필을 만드는 데 사용됩니다.

참고

GetProfile 메서드를 호출할 때 메서드에 전달하는 버전 번호는 사용할 추적 프로필의 버전 번호와 일치해야 합니다. 또한 버전 번호는 SqlTrackingService 서비스에서 사용되는 UpdateTrackingProfile 저장 프로시저와 추적 프로필 간에 일치해야 합니다.

참고

GetTrackingChannel 메서드의 구현 예는 다음 단원 끝에서 제공됩니다.

// Add in a local variable and overloaded constructor methods.
protected WorkflowRuntime runtimeContainer = null;
public EventLogTrackingService()
{
}

public EventLogTrackingService (WorkflowRuntime container)
{
    runtimeContainer = container;
}

// Implement the TrackingService abstract methods.
protected override TrackingProfile GetProfile(Guid workflowInstanceId)
{
    // Instance profiles not implemented.
    throw new NotImplementedException("The method or operation is not implemented.");
}

protected override TrackingProfile GetProfile(Type workflowType, Version profileVersionId)
{
    return GetDefaultProfile();
}

protected override bool TryGetProfile(Type workflowType, out TrackingProfile profile)
{
    // Depending on the workflowType, service can return different 
    // tracking profiles. In this sample, the same profile is returned 
    // for all running types.
    profile = GetDefaultProfile();
    return true;
}

protected override bool TryReloadProfile(Type workflowType, Guid workflowInstanceId, out TrackingProfile profile)
{
    // Reloading profiles not implemented.
    profile = null;
    return false;
}

// Create the profile.
private static TrackingProfile GetDefaultProfile()
{
    TrackingProfile profile = new TrackingProfile();
    profile.Version = new Version("3.0.0");

    // Add activity track points.
    ActivityTrackPoint atp = new ActivityTrackPoint();
    ActivityTrackingLocation location = new ActivityTrackingLocation(typeof(Activity));
    location.MatchDerivedTypes = true;
    foreach (ActivityExecutionStatus s in Enum.GetValues(typeof(ActivityExecutionStatus)))
    {
        location.ExecutionStatusEvents.Add(s);
    }
    atp.MatchingLocations.Add(location);
    profile.ActivityTrackPoints.Add(atp);

    // Add instance track points.
    WorkflowTrackPoint wtp = new WorkflowTrackPoint();
    WorkflowTrackingLocation workflowLocation = new WorkflowTrackingLocation();
    wtp.MatchingLocation = workflowLocation;

    foreach (TrackingWorkflowEvent workflowEvent in Enum.GetValues(typeof(TrackingWorkflowEvent)))
    {
        wtp.MatchingLocation.Events.Add(workflowEvent);
    }
    profile.WorkflowTrackPoints.Add(wtp);

    return profile;
}
' Add in a local variable and overloaded constructor methods.
Protected runtimeContainer As WorkflowRuntime = Nothing

Public Sub New()
End Sub

Public Sub New(ByVal container As WorkflowRuntime)
        runtimeContainer = container
End Sub

' Implement the TrackingService abstract methods.
Protected Overloads Overrides Function GetProfile(ByVal workflowInstanceId As Guid) As TrackingProfile
    ' Instance profiles not implemented
    Throw New NotImplementedException("The method or operation is not implemented.")
End Function

Protected Overloads Overrides Function GetProfile(ByVal workflowType As Type, ByVal profileVersionId As Version) As TrackingProfile
    Return GetDefaultProfile()
End Function

Protected Overrides Function TryGetProfile(ByVal workflowType As Type, ByRef profile As TrackingProfile) As Boolean
    ' Depending on the workflowType, service can return different 
    ' tracking profiles. In this sample, the same profile is returned 
    ' for all running types.
    profile = GetDefaultProfile()
    Return True
End Function

Protected Overrides Function TryReloadProfile(ByVal workflowType As Type, ByVal workflowInstanceId As Guid, ByRef profile As TrackingProfile) As Boolean
    ' Reloading profiles not implemented.
    profile = Nothing
    Return False
End Function

' Create the profile.
Private Shared Function GetDefaultProfile() As TrackingProfile
    Dim profile As New TrackingProfile()
    profile.Version = New Version("3.0.0")

    ' Add activity track points.
    Dim atp As New ActivityTrackPoint()
    Dim location As New ActivityTrackingLocation(GetType(Activity))
    location.MatchDerivedTypes = True
    Dim s As ActivityExecutionStatus
    For Each s In System.Enum.GetValues(GetType(ActivityExecutionStatus))
        location.ExecutionStatusEvents.Add(s)
    Next s
    atp.MatchingLocations.Add(location)
    profile.ActivityTrackPoints.Add(atp)

    ' Add instance track points.
    Dim wtp As New WorkflowTrackPoint()
    Dim workflowLocation As New WorkflowTrackingLocation()
    wtp.MatchingLocation = workflowLocation

    Dim workflowEvent As TrackingWorkflowEvent
    For Each workflowEvent In System.Enum.GetValues(GetType(TrackingWorkflowEvent))
        wtp.MatchingLocation.Events.Add(workflowEvent)
    Next workflowEvent
    profile.WorkflowTrackPoints.Add(wtp)
    Return profile
End Function

TrackingChannel 구현

TrackingChannel 추상 클래스는 단일 워크플로 인스턴스에 대한 추적 이벤트와 데이터를 받는 통로 역할을 합니다. TrackingChannel의 목적은 추적 서비스 작성기가 스레드 안전을 고려할 필요 없이 추적 정보를 받는 메커니즘을 제공하는 것입니다. 각 워크플로 인스턴스에 실행 스레드가 하나만 있기 때문에 TrackingChannel 개체에서는 한 번에 둘 이상의 스레드가 활성화되지 않습니다. 이에 따라 데이터 동기화의 필요성이 줄어듭니다.

TrackingChannel은 워크플로와 추적 서비스 간의 통신에 사용되는 개체입니다. EventLogTrackingService에 대한 TrackingChannel을 만들려면 이전 단원에서 TrackingService 추상 클래스에 대해 수행한 것처럼 EventLogTrackingChannel 클래스를 만들고 TrackingChannel 기본 클래스에서 클래스를 파생시킨 다음 필요한 추상 메서드를 구현합니다.

워크플로는 추적 정보를 보낼 때 TrackingChannel 클래스에 정의된 Send 메서드를 통해 보냅니다. TrackingRecord가 추적 정보를 추출할 수 있는 매개 변수로 전달됩니다. 다음 코드 예제에서는 ActivityRecord 매개 변수에서 데이터를 추출하고 해당 정보를 이벤트 로그에 출력하는 방법을 보여 줍니다.

public class EventLogTrackingChannel : TrackingChannel
{
    // Add in a local variable and constructor method.
    private TrackingParameters parameters = null;

    public EventLogTrackingChannel(TrackingParameters parameters)
    {
        this.parameters = parameters;
    }

    // InstanceCompletedOrTerminated is called by Tracking runtime to 
    // indicate that the Workflow instance finished running.
    protected override void InstanceCompletedOrTerminated()
    {
        System.Diagnostics.EventLog.WriteEntry("EventLogTrackingService", "Workflow Instance Completed or Terminated");
    }

    // Implement the TrackingChannel abstract methods.
    protected override void Send(TrackingRecord record)
    {
        if (record is ActivityTrackingRecord)
        {
            ActivityTrackingRecord act = (ActivityTrackingRecord)record;

            System.Diagnostics.EventLog.WriteEntry("EventLogTrackingService", "Activity: " + act.QualifiedName + " - " +  act.ExecutionStatus );
        }
        else if (record is WorkflowTrackingRecord)
        {
            if (TrackingWorkflowEvent.Changed == ((WorkflowTrackingRecord)record).TrackingWorkflowEvent)
            {
                System.Diagnostics.EventLog.WriteEntry("EventLogTrackingService", "Workflow changes have been applied");
            }
        }
    }
}
Public Class EventLogTrackingChannel
    Inherits TrackingChannel

    ' Add in a local variable and constructor method.
    Private parameters As TrackingParameters = Nothing

    Public Sub New(ByVal parameters As TrackingParameters)
        Me.parameters = parameters
    End Sub

    ' InstanceCompletedOrTerminated is called by Tracking runtime to 
    ' indicate that the Workflow instance finished running.
    Protected Overrides Sub InstanceCompletedOrTerminated()
        System.Diagnostics.EventLog.WriteEntry("EventLogTrackingService", "Workflow Instance Completed or Terminated")
    End Sub

    ' Implement the TrackingChannel abstract methods.
    Protected Overrides Sub Send(ByVal record As System.Workflow.Runtime.Tracking.TrackingRecord)
        If TypeOf record Is ActivityTrackingRecord Then
            Dim act As ActivityTrackingRecord = CType(record, ActivityTrackingRecord)
            System.Diagnostics.EventLog.WriteEntry("EventLogTrackingService", "Activity: " & act.QualifiedName & " - " & act.ExecutionStatus)
        ElseIf TypeOf record Is WorkflowTrackingRecord Then
            If TrackingWorkflowEvent.Changed = CType(record, WorkflowTrackingRecord).TrackingWorkflowEvent Then
                System.Diagnostics.EventLog.WriteEntry("EventLogTrackingService", "Workflow changes have been applied")
            End If
        End If
    End Sub
End Class

워크플로 런타임 엔진은 EventLogTrackingService 클래스에 정의된 GetTrackingChannel 메서드를 호출하여 EventLogTrackingChannel에 대한 참조를 가져옵니다. 다음 코드 예제와 같이 새 EventLogTrackingChannel 개체를 만들고 GetTrackingChannel 메서드에서 해당 개체를 반환합니다.

protected override TrackingChannel GetTrackingChannel(TrackingParameters parameters)
{
    return new EventLogTrackingChannel(parameters);
}
Protected Overrides Function GetTrackingChannel(ByVal parameters As TrackingParameters) As TrackingChannel
    Return New EventLogTrackingChannel(parameters)
End Function

참고 항목

참조

TrackingService
TrackingChannel
TrackingProfile

개념

방법: 워크플로 서비스 추가 및 제거
추적 프로필 만들기 및 사용

기타 리소스

ConsoleTrackingService Sample
Tracking Profile Designer Sample
Windows Workflow Foundation 서비스 개발

Footer image

Copyright © 2007 by Microsoft Corporation. All rights reserved.