## SoupLogger

SoupLogger — Debug logging support

## Synopsis

    #include <libsoup/soup.h>

                        SoupLogger;
    enum                SoupLoggerLogLevel;
    SoupLogger *        soup_logger_new                     (SoupLoggerLogLevel level,
                                                             int max_body_size);
    void                soup_logger_attach                  (SoupLogger *logger,
                                                             SoupSession *session);
    void                soup_logger_detach                  (SoupLogger *logger,
                                                             SoupSession *session);

    SoupLoggerLogLevel  (*SoupLoggerFilter)                 (SoupLogger *logger,
                                                             SoupMessage *msg,
                                                             gpointer user_data);
    void                soup_logger_set_request_filter      (SoupLogger *logger,
                                                             SoupLoggerFilter request_filter,
                                                             gpointer filter_data,
                                                             GDestroyNotify destroy);
    void                soup_logger_set_response_filter     (SoupLogger *logger,
                                                             SoupLoggerFilter response_filter,
                                                             gpointer filter_data,
                                                             GDestroyNotify destroy);

    void                (*SoupLoggerPrinter)                (SoupLogger *logger,
                                                             SoupLoggerLogLevel level,
                                                             char direction,
                                                             const char *data,
                                                             gpointer user_data);
    void                soup_logger_set_printer             (SoupLogger *logger,
                                                             SoupLoggerPrinter printer,
                                                             gpointer printer_data,
                                                             GDestroyNotify destroy);

## Object Hierarchy

      GObject
       +----SoupLogger

## Implemented Interfaces

SoupLogger implements SoupSessionFeature.

## Description

SoupLogger watches a SoupSession and logs the HTTP traffic that it generates, for debugging purposes. Many applications use an environment variable to determine whether or not to use SoupLogger, and to determine the amount of debugging output.

To use SoupLogger, first create a logger with `soup_logger_new()`, optionally configure it with `soup_logger_set_request_filter()`, `soup_logger_set_response_filter()`, and `soup_logger_set_printer()`, and then attach it to a session (or multiple sessions) with `soup_session_add_feature()`.

By default, the debugging output is sent to `stdout`, and looks something like:

    > POST /unauth HTTP/1.1
    > Soup-Debug-Timestamp: 1200171744
    > Soup-Debug: SoupSessionAsync 1 (0x612190), SoupMessage 1 (0x617000), SoupSocket 1 (0x612220)
    > Host: localhost
    > Content-Type: text/plain
    > Connection: close
    >
    > This is a test.

    < HTTP/1.1 201 Created
    < Soup-Debug-Timestamp: 1200171744
    < Soup-Debug: SoupMessage 1 (0x617000)
    < Date: Sun, 12 Jan 2008 21:02:24 GMT
    < Content-Length: 0

The `Soup-Debug-Timestamp` line gives the time (as a time_t) when the request was sent, or the response fully received.

The `Soup-Debug` line gives further debugging information about the SoupSession, SoupMessage, and SoupSocket involved; the hex numbers are the addresses of the objects in question (which may be useful if you are running in a debugger). The decimal IDs are simply counters that uniquely identify objects across the lifetime of the SoupLogger. In particular, this can be used to identify when multiple messages are sent across the same connection.

Currently, the request half of the message is logged just before the first byte of the request gets written to the network (from the "request_started" signal), which means that if you have not made the complete request body available at that point, it will not be logged. The response is logged just after the last byte of the response body is read from the network (from the "got_body" or "got_informational" signal), which means that the "got_headers" signal, and anything triggered off it (such as "authenticate") will be emitted before the response headers are actually logged.

## Details

### SoupLogger

    typedef struct _SoupLogger SoupLogger;

### enum SoupLoggerLogLevel

    typedef enum {
    	SOUP_LOGGER_LOG_NONE,
    	SOUP_LOGGER_LOG_MINIMAL,
    	SOUP_LOGGER_LOG_HEADERS,
    	SOUP_LOGGER_LOG_BODY
    } SoupLoggerLogLevel;

Describes the level of logging output to provide.

`SOUP_LOGGER_LOG_NONE` | No logging
`SOUP_LOGGER_LOG_MINIMAL` | Log the Request-Line or Status-Line and the Soup-Debug pseudo-headers
`SOUP_LOGGER_LOG_HEADERS` | Log the full request/response headers
`SOUP_LOGGER_LOG_BODY` | Log the full headers and request/response bodies.

### soup_logger_new ()

    SoupLogger *        soup_logger_new                     (SoupLoggerLogLevel level,
                                                             int max_body_size);

Creates a new SoupLogger with the given debug level. If `level` is `SOUP_LOGGER_LOG_BODY`, `max_body_size` gives the maximum number of bytes of the body that will be logged. (-1 means "no limit".)

If you need finer control over what message parts are and aren't logged, use `soup_logger_set_request_filter()` and `soup_logger_set_response_filter()`.

`level` : | the debug level
`max_body_size` : | the maximum body size to output, or -1
Returns : | a new SoupLogger

### soup_logger_attach ()

    void                soup_logger_attach                  (SoupLogger *logger,
                                                             SoupSession *session);

### Warning

`soup_logger_attach` is deprecated and should not be used in newly-written code. Use `soup_session_add_feature()` instead.

Sets `logger` to watch `session` and print debug information for its messages.

(The session will take a reference on `logger`, which will be removed when you call `soup_logger_detach()`, or when the session is destroyed.)

`logger` : | a SoupLogger
`session` : | a SoupSession

### soup_logger_detach ()

    void                soup_logger_detach                  (SoupLogger *logger,
                                                             SoupSession *session);

### Warning

`soup_logger_detach` is deprecated and should not be used in newly-written code. Use `soup_session_remove_feature()` instead.

Stops `logger` from watching `session`.

`logger` : | a SoupLogger
`session` : | a SoupSession

### SoupLoggerFilter ()

    SoupLoggerLogLevel  (*SoupLoggerFilter)                 (SoupLogger *logger,
                                                             SoupMessage *msg,
                                                             gpointer user_data);

The prototype for a logging filter. The filter callback will be invoked for each request or response, and should analyze it and return a SoupLoggerLogLevel value indicating how much of the message to log. Eg, it might choose between `SOUP_LOGGER_LOG_BODY` and `SOUP_LOGGER_LOG_HEADERS` depending on the Content-Type.

`logger` : | the SoupLogger
`msg` : | the message being logged
`user_data` : | the data passed to `soup_logger_set_request_filter()` or `soup_logger_set_response_filter()`
Returns : | a SoupLoggerLogLevel value indicating how much of the message to log

### soup_logger_set_request_filter ()

    void                soup_logger_set_request_filter      (SoupLogger *logger,
                                                             SoupLoggerFilter request_filter,
                                                             gpointer filter_data,
                                                             GDestroyNotify destroy);

Sets up a filter to determine the log level for a given request. For each HTTP request `logger` will invoke `request_filter` to determine how much (if any) of that request to log. (If you do not set a request filter, `logger` will just always log requests at the level passed to `soup_logger_new()`.)

`logger` : | a SoupLogger
`request_filter` : | the callback for request debugging
`filter_data` : | data to pass to the callback
`destroy` : | a GDestroyNotify to free `filter_data`

### soup_logger_set_response_filter ()

    void                soup_logger_set_response_filter     (SoupLogger *logger,
                                                             SoupLoggerFilter response_filter,
                                                             gpointer filter_data,
                                                             GDestroyNotify destroy);

Sets up a filter to determine the log level for a given response. For each HTTP response `logger` will invoke `response_filter` to determine how much (if any) of that response to log. (If you do not set a response filter, `logger` will just always log responses at the level passed to `soup_logger_new()`.)

`logger` : | a SoupLogger
`response_filter` : | the callback for response debugging
`filter_data` : | data to pass to the callback
`destroy` : | a GDestroyNotify to free `filter_data`

### SoupLoggerPrinter ()

    void                (*SoupLoggerPrinter)                (SoupLogger *logger,
                                                             SoupLoggerLogLevel level,
                                                             char direction,
                                                             const char *data,
                                                             gpointer user_data);

The prototype for a custom printing callback.

`level` indicates what kind of information is being printed. Eg, it will be `SOUP_LOGGER_LOG_HEADERS` if `data` is header data.

`direction` is either '<', '>', or ' ', and `data` is the single line to print; the printer is expected to add a terminating newline.

To get the effect of the default printer, you would do:

    printf ("%c %s\n", direction, data);

`logger` : | the SoupLogger
`level` : | the level of the information being printed.
`direction` : | a single-character prefix to `data`
`data` : | data to print
`user_data` : | the data passed to `soup_logger_set_printer()`

### soup_logger_set_printer ()

    void                soup_logger_set_printer             (SoupLogger *logger,
                                                             SoupLoggerPrinter printer,
                                                             gpointer printer_data,
                                                             GDestroyNotify destroy);

Sets up an alternate log printing routine, if you don't want the log to go to `stdout`.

`logger` : | a SoupLogger
`printer` : | the callback for printing logging output
`printer_data` : | data to pass to the callback
`destroy` : | a GDestroyNotify to free `printer_data`