전체 요청 및 응답 본문을 포함하여 서비스 참조로 이동하는 모든 아웃 바운드 요청을 기록하려고합니다. behaviorExtensions를 사용하는 솔루션이 있다고 생각했지만 배포 한 후에 확장이 여러 요청간에 공유 되었음이 분명해졌습니다.IEndpointBehavior 수명주기/로깅 서비스 호출
여기 내 현재 코드입니다 : 내가 로그인 할 수있는 지점에 도달 할 때, 나는 행동을 추출, 그리고
public class LoggingBehaviorExtender : BehaviorExtensionElement
{
public override Type BehaviorType => typeof(LoggingRequestExtender);
protected override object CreateBehavior() { return new LoggingRequestExtender(); }
}
public class LoggingRequestExtender : IClientMessageInspector, IEndpointBehavior
{
public string Request { get; private set; }
public string Response { get; private set; }
#region IClientMessageInspector
public virtual object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
Request = request.ToString();
Response = null;
return null;
}
public virtual void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
Response = reply.ToString();
}
#endregion
#region IEndpointBehavior
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(this);
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { }
public void Validate(ServiceEndpoint endpoint) { }
#endregion
}
... LoggingRequestExtender에 디버그 로깅을 추가
var lre = client.Endpoint.Behaviors.OfType<LoggingRequestExtender>().FirstOrDefault();
var req = lre?.Request;
var resp = lre?.Response;
, 나는 그것을 발견 여러 요청에 대해 한 번만 인스턴스화되었습니다.
이 동작 클래스가 각 스레드에 대해 새로 인스턴스화되었는지 확인하는 방법이 있습니까? 아니면 서비스 호출을 할 때 전체 요청/응답 본문을 얻는 더 좋은 방법이 있습니까?
편집/부분적인 대답 :
내가 GUID를 사용하여 요청 및 응답을 연결할 수 correlationState으로 내가 BeforeSendRequest에 의해 반환되는 값이 AfterReceiveReply로 전달되는 것을 발견했다이 작성 가입일 :
public virtual object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
var guid = Guid.NewGuid();
WebServiceLog.LogCallStart(guid, channel.RemoteAddress.ToString(), request.ToString());
return guid;
}
public virtual void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
Guid guid = (Guid)correlationState;
WebServiceLog.LogCallEnd(guid, reply.ToString());
}
을
이 접근 방식에는 두 가지 결함이 있습니다. 살만한 것은 하나의 삽입물이 아니라 로그 삽입과 업데이트가 필요하다는 것입니다.
두 번째 문제가 더 많습니다. 예외 (예 : 시간 초과)의 경우 우리는 결코 AfterRecieveSupply를 누르지 않으므로 로그에 어떤 일이 발생했는지 알 수 없습니다. 내가 따로 ...
try
{
response = client.SomeFunction(request);
}
catch (Exception ex)
{
AppLog.Error("Some function failed", ex);
}
를 예외를 로그인 할 수 있습니다 ...하지만 나는 BeforeSendRequest 외부 GUID를 액세스하는 방법을 볼 수 없습니다/AfterReceiveReply 그래서 서비스 요청 로그에 예외 로그를 묶는 게 없다 .