次の方法で共有


HOWTO: Get Field Data for Custom Logging with ISAPI Filter

Question:

I'm trying to write a Filter that handles writing a W3C-compliant log file based on a special set of criteria. I have found most of the needed information in GetServerVariables(), but I still need the following things:

sc-status: The status code returned by the server on the request (i.e. 200 if the HTTP request was OK)

sc-substatus: Substatus code, it's an entry in the current IIS log files and I'd like to keep it

sc-win32-status: Appears to always be 0, but I'll keep it if I can.

sc-bytes: The number of bytes sent back to the client as the response.

time-taken: The amount of time it took IIS internally to process and complete the request.

If anyone can help me with the necessary calls to get these values, that would be wonderful. They are values in the normal IIS log files when W3C is selected, so I feel like they must be available.

Thanks,

Answer:

You can do it the EASY way or the HARD way. :-) I'll provide you the info; you pick.

Easy Way

The info you want can be found in the HTTP_FILTER_LOG structure available in the SF_NOTIFY_LOG ISAPI Filter event.

 typedef struct _HTTP_FILTER_LOG
{
    const CHAR * pszClientHostName;
    const CHAR * pszClientUserName;
    const CHAR * pszServerName;
    const CHAR * pszOperation;
    const CHAR * pszTarget;
    const CHAR * pszParameters;

    DWORD  dwHttpStatus;
    DWORD  dwWin32Status;

    DWORD  dwBytesSent;             
    DWORD  dwBytesRecvd;            
    DWORD  msTimeForProcessing;     

} HTTP_FILTER_LOG, *PHTTP_FILTER_LOG;

The SF_NOTIFY_LOG event happens right before IIS is about to write the log entry for that request. The members of HTTP_FILTER_LOG are read/write, so it should be trivial for you to use it for custom logging purposes.

What are the benefits of using HTTP_FILTER_LOG?

  1. You do not need to call GetServerVariable() and [re]-allocate a buffer (see this blog entry for an example)
  2. You can even alter what IIS will log by changing the fields of this structure (see this blog entry for an example) - so you can modify pszParameters, have IIS keep the merged log files of all your subdomains (for analysis purposes), and still know which request went to which subdomain

The only thing that is missing is sc-substatus, and it cannot be retrieved in ISAPI Filter.

Hard Way

If you insist on doing it the hard way:

  • sc-status can be obtained from SF_NOTIFY_SEND_RESPONSE, in the HTTP_FILTER_SEND_RESPONSE.HttpStatus member. This only works for structured responses... for raw responses, you have to buffer and parse SF_NOTIFY_SEND_RAW_DATA.

  • sc-substatus and sc-win32-status:

    The only way on IIS6 to get sc-substatus and sc-win32-status for the response is in the async completion function of an HSE_REQ_EXEC_URL ServerSupportFunction call by calling HSE_REQ_GET_EXEC_URL_STATUS.

    Nowhere else in ISAPI Filter/Extension API do you have access to that value, even though we added sc-substatus in IIS6, because we would break binary compatibility by changing existing structures where it logically belongs:

    • You can't read/set it in ISAPI Filter
    • You can't set it in ISAPI Extension
    • You can read it in ISAPI Extension in async completion function HSE_REQ_EXEC_URL
  • sc-bytes - listen on SF_NOTIFY_SEND_RAW_DATA and track HTTP_FILTER_RAW_DATA.cbInData to count number of bytes transferred. Hard part is figuring out how to do this on a per-request basis because pFilterContext is per-connection.

  • time-taken - Set timer between SF_NOTIFY_READ_RAW_DATA and SF_NOTIFY_END_OF_NET_SESSION. This is not compatible with IIS6 Worker Process Isolation Mode.

//David

Comments

  • Anonymous
    April 16, 2006
    Ok, so question about that.  You said that I should be able to get everything I need out of parameters, but I think I may not be understanding that exactly as you meant it.  I need user agent and referer for example;  am I correct in thinking that data is not in pszParameters?  I output-ed pszParameters and it looks like garbage to me on the request.  To get user_agent and referer I will still have to call GetServerVariables correct?

  • Anonymous
    April 16, 2006
    The comment has been removed

  • Anonymous
    April 16, 2006
    Ok, I thought that was what you meant, I just wanted to make sure that information wasn't somehow available out of the parameters field with some processing.  Thanks for all of your help, I think I have everything I need to know.  I'll let you know how it turns out.

    Jacob

  • Anonymous
    June 12, 2006
    David - Apologies if this is addressed elsewhere but I didn't see it.

    Our web server is protected by SiteMinder.  IIS 6.0 is running anonymous and SM handles the authentication.  I'm trying to create an add'l ISAPI that does an extra lookup in Active Directory to check if the user is a member of a particular group.

    I started with the AuthFilter example and am trying to use GetServerVariable to retrieve the user's id, but I'm finding that REMOTE_USER, LOGON_USER, etc are all blank.  Is there a way to get the user's id if IIS is running anonymous?

    Bret

  • Anonymous
    June 12, 2006
    The comment has been removed

  • Anonymous
    December 20, 2007
    We have a web application that creates PDF's.   We are seeing in our IIS logs records where the sc-win32-status equals 64 but the sc-status equals 200.    The PDF's are NOT being created.   I have seen a number of postings that appear to be same as this issue but not definitive answers.    Can someone explain what is going on?

  • Anonymous
    February 21, 2008
    Hi, I have a question about custom Logging data. A client requests a file (1MB) and IIS send the file. If some error occurs, then sending file would not be completed. At this time, IIS has log

  • Anonymous
    February 22, 2008
    newro - Logging has to happen regardless if the request succeeds or fails. Use the dwWin32Status and dwHttpStatus fields to distinguish between successful and failing requests. //David

  • Anonymous
    February 22, 2008
    john.corbett - Many things can result in that status code. One common cause is the client disconnecting, such as a user hitting F5 to refresh because your web application took too long to create the PDF. //David

  • Anonymous
    August 13, 2010
    Is there an equivalent way to get the "bytes sent" using the managed modules?