[libsoup/carlosgc/metrics: 23/24] Add support for collecting metrics
- From: Carlos Garcia Campos <carlosgc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libsoup/carlosgc/metrics: 23/24] Add support for collecting metrics
- Date: Wed, 14 Apr 2021 09:45:34 +0000 (UTC)
commit d7ff300311ac239e3a5123a1df9cbc1cca98fbdf
Author: Carlos Garcia Campos <cgarcia igalia com>
Date: Fri Mar 26 15:30:59 2021 +0100
Add support for collecting metrics
docs/reference/libsoup-3.0-docs.xml | 4 +
docs/reference/libsoup-3.0-sections.txt | 23 +++
docs/reference/meson.build | 1 +
libsoup/cache/soup-cache.c | 4 +
libsoup/include/soup-installed.h | 1 +
libsoup/meson.build | 2 +
libsoup/soup-message-io.c | 13 +-
libsoup/soup-message-metrics-private.h | 26 ++++
libsoup/soup-message-metrics.c | 245 ++++++++++++++++++++++++++++++++
libsoup/soup-message-metrics.h | 53 +++++++
libsoup/soup-message-private.h | 15 ++
libsoup/soup-message.c | 110 ++++++++++++++
libsoup/soup-message.h | 7 +-
libsoup/soup-session.c | 11 ++
libsoup/soup-types.h | 1 +
libsoup/soup.h | 1 +
tests/cache-test.c | 110 ++++++++++++++
tests/connection-test.c | 210 +++++++++++++++++++++++++--
18 files changed, 827 insertions(+), 10 deletions(-)
---
diff --git a/docs/reference/libsoup-3.0-docs.xml b/docs/reference/libsoup-3.0-docs.xml
index 3130a35b..b1fa54d6 100644
--- a/docs/reference/libsoup-3.0-docs.xml
+++ b/docs/reference/libsoup-3.0-docs.xml
@@ -76,6 +76,10 @@
<xi:include href="xml/soup-hsts-enforcer-db.xml"/>
<xi:include href="xml/soup-hsts-policy.xml"/>
</section>
+ <section>
+ <title>Metrics</title>
+ <xi:include href="xml/soup-message-metrics.xml"/>
+ </section>
</chapter>
<chapter>
diff --git a/docs/reference/libsoup-3.0-sections.txt b/docs/reference/libsoup-3.0-sections.txt
index 26775111..cc5b5710 100644
--- a/docs/reference/libsoup-3.0-sections.txt
+++ b/docs/reference/libsoup-3.0-sections.txt
@@ -55,6 +55,8 @@ soup_message_get_site_for_cookies
soup_message_set_site_for_cookies
soup_message_get_is_top_level_navigation
soup_message_set_is_top_level_navigation
+<SUBSECTION>
+soup_message_get_metrics
<SUBSECTION Standard>
SOUP_MESSAGE
SOUP_IS_MESSAGE
@@ -991,3 +993,24 @@ SOUP_IS_HSTS_ENFORCER_DB
SOUP_IS_HSTS_ENFORCER_DB_CLASS
soup_hsts_enforcer_db_get_type
</SECTION>
+
+<SECTION>
+<FILE>soup-message-metrics</FILE>
+<TITLE>SoupMessageMetrics</TITLE>
+SoupMessageMetrics
+soup_message_metrics_copy
+soup_message_metrics_free
+<SUBSECTION>
+soup_message_metrics_get_fetch_start
+soup_message_metrics_get_dns_start
+soup_message_metrics_get_dns_end
+soup_message_metrics_get_connect_start
+soup_message_metrics_get_connect_end
+soup_message_metrics_get_tls_start
+soup_message_metrics_get_request_start
+soup_message_metrics_get_response_start
+soup_message_metrics_get_response_end
+<SUBSECTION Standard>
+SOUP_TYPE_MESSAGE_METRICS
+soup_message_metrics_get_type
+</SECTION>
diff --git a/docs/reference/meson.build b/docs/reference/meson.build
index 40a98944..de67bb20 100644
--- a/docs/reference/meson.build
+++ b/docs/reference/meson.build
@@ -36,6 +36,7 @@ ignore_headers = [
'soup-message-io-data.h',
'soup-uri-utils-private.h',
'soup-session-feature-private.h',
+ 'soup-message-metrics-private.h',
]
mkdb_args = [
diff --git a/libsoup/cache/soup-cache.c b/libsoup/cache/soup-cache.c
index f9303cec..969b3a4d 100644
--- a/libsoup/cache/soup-cache.c
+++ b/libsoup/cache/soup-cache.c
@@ -692,6 +692,8 @@ soup_cache_send_response (SoupCache *cache, SoupMessage *msg)
g_return_val_if_fail (SOUP_IS_CACHE (cache), NULL);
g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
+ soup_message_set_metrics_timestamp (msg, SOUP_MESSAGE_METRICS_REQUEST_START);
+
entry = soup_cache_entry_lookup (cache, msg);
g_return_val_if_fail (entry, NULL);
@@ -716,6 +718,8 @@ soup_cache_send_response (SoupCache *cache, SoupMessage *msg)
/* Message starting */
soup_message_starting (msg);
+ soup_message_set_metrics_timestamp (msg, SOUP_MESSAGE_METRICS_RESPONSE_START);
+
/* Status */
soup_message_set_status (msg, entry->status_code, NULL);
diff --git a/libsoup/include/soup-installed.h b/libsoup/include/soup-installed.h
index 85ad6eb5..99954228 100644
--- a/libsoup/include/soup-installed.h
+++ b/libsoup/include/soup-installed.h
@@ -30,6 +30,7 @@ extern "C" {
#include <libsoup/soup-hsts-policy.h>
#include <libsoup/soup-logger.h>
#include <libsoup/soup-message.h>
+#include <libsoup/soup-message-metrics.h>
#include <libsoup/soup-method.h>
#include <libsoup/soup-multipart.h>
#include <libsoup/soup-multipart-input-stream.h>
diff --git a/libsoup/meson.build b/libsoup/meson.build
index 827c4a3b..adcccc3e 100644
--- a/libsoup/meson.build
+++ b/libsoup/meson.build
@@ -64,6 +64,7 @@ soup_sources = [
'soup-message-headers.c',
'soup-message-io.c',
'soup-message-io-data.c',
+ 'soup-message-metrics.c',
'soup-message-queue-item.c',
'soup-method.c',
'soup-misc.c',
@@ -120,6 +121,7 @@ soup_introspection_headers = [
'soup-logger.h',
'soup-message.h',
'soup-message-headers.h',
+ 'soup-message-metrics.h',
'soup-method.h',
'soup-multipart.h',
'soup-multipart-input-stream.h',
diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c
index 8aef3170..9eab3ef2 100644
--- a/libsoup/soup-message-io.c
+++ b/libsoup/soup-message-io.c
@@ -510,12 +510,19 @@ io_read (SoupMessage *msg, gboolean blocking,
SoupClientMessageIOData *client_io = soup_message_get_io_data (msg);
SoupMessageIOData *io = &client_io->base;
gboolean succeeded;
+ gboolean is_first_read;
switch (io->read_state) {
case SOUP_MESSAGE_IO_STATE_HEADERS:
+ is_first_read = io->read_header_buf->len == 0 &&
+ soup_message_get_status (msg) == SOUP_STATUS_NONE;
+
if (!soup_message_io_data_read_headers (io, blocking, cancellable, error))
return FALSE;
+ if (is_first_read)
+ soup_message_set_metrics_timestamp (msg, SOUP_MESSAGE_METRICS_RESPONSE_START);
+
succeeded = parse_headers (msg,
(char *)io->read_header_buf->data,
io->read_header_buf->len,
@@ -533,6 +540,7 @@ io_read (SoupMessage *msg, gboolean blocking,
*/
soup_message_headers_append (soup_message_get_request_headers (msg),
"Connection", "close");
+ soup_message_set_metrics_timestamp (msg, SOUP_MESSAGE_METRICS_RESPONSE_END);
io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
break;
}
@@ -639,6 +647,7 @@ io_read (SoupMessage *msg, gboolean blocking,
case SOUP_MESSAGE_IO_STATE_BODY_DONE:
io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
+ soup_message_set_metrics_timestamp (msg, SOUP_MESSAGE_METRICS_RESPONSE_END);
soup_message_got_body (msg);
break;
@@ -771,7 +780,9 @@ soup_message_io_finish (SoupMessage *msg,
/* Connection got closed, but we can safely try again. */
io->item->state = SOUP_MESSAGE_RESTARTING;
- }
+ } else if (error) {
+ soup_message_set_metrics_timestamp (msg, SOUP_MESSAGE_METRICS_RESPONSE_END);
+ }
soup_message_io_finished (msg);
}
diff --git a/libsoup/soup-message-metrics-private.h b/libsoup/soup-message-metrics-private.h
new file mode 100644
index 00000000..03d62ad1
--- /dev/null
+++ b/libsoup/soup-message-metrics-private.h
@@ -0,0 +1,26 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright 2021 Igalia S.L.
+ */
+
+#pragma once
+
+#include "soup-message-metrics.h"
+
+G_BEGIN_DECLS
+
+struct _SoupMessageMetrics {
+ guint64 fetch_start;
+ guint64 dns_start;
+ guint64 dns_end;
+ guint64 connect_start;
+ guint64 connect_end;
+ guint64 tls_start;
+ guint64 request_start;
+ guint64 response_start;
+ guint64 response_end;
+};
+
+SoupMessageMetrics *soup_message_metrics_new (void);
+
+G_END_DECLS
diff --git a/libsoup/soup-message-metrics.c b/libsoup/soup-message-metrics.c
new file mode 100644
index 00000000..e3b642c3
--- /dev/null
+++ b/libsoup/soup-message-metrics.c
@@ -0,0 +1,245 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * soup-message-metrics.c
+ *
+ * Copyright (C) 2021 Igalia S.L.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "soup-message-metrics-private.h"
+
+/**
+ * SECTION:soup-message-metrics
+ * @short_description: Message metrics
+ * @see_also: #SoupMessage
+ *
+ * Metrics collected while loading a #SoupMessage.
+ *
+ * Metrics are not collected by default for a #SoupMessage, you need to add the
+ * flag %SOUP_MESSAGE_COLLECT_METRICS to enable the feature.
+ */
+
+/**
+ * SoupMessageMetrics:
+ *
+ * SoupMessageMetrics contains metrics collected while loading a #SoupMessage
+ * either from the network or the disk cache.
+ *
+ * Temporal metrics are expressed as a monotonic time and always start with a
+ * fetch start event and finish with response end. All other events are optional.
+ * An event can be 0 because it hasn't happened yet, because it's optional or
+ * because the load failed before the event reached.
+ */
+
+G_DEFINE_BOXED_TYPE (SoupMessageMetrics, soup_message_metrics, soup_message_metrics_copy,
soup_message_metrics_free)
+
+SoupMessageMetrics *
+soup_message_metrics_new (void)
+{
+ return g_slice_new0 (SoupMessageMetrics);
+}
+
+/**
+ * soup_message_metrics_copy:
+ * @metrics: a #SoupMessageMetrics
+ *
+ * Copies @metrics.
+ *
+ * Returns: a copy of @metrics
+ *
+ **/
+SoupMessageMetrics *
+soup_message_metrics_copy (SoupMessageMetrics *metrics)
+{
+ SoupMessageMetrics *copy;
+
+ g_return_val_if_fail (metrics != NULL, NULL);
+
+ copy = soup_message_metrics_new ();
+ *copy = *metrics;
+
+ return copy;
+}
+
+/**
+ * soup_message_metrics_free:
+ * @metrics: a #SoupMessageMetrics
+ *
+ * Frees @metrics
+ */
+void
+soup_message_metrics_free (SoupMessageMetrics *metrics)
+{
+ g_return_if_fail (metrics != NULL);
+
+ g_slice_free (SoupMessageMetrics, metrics);
+}
+
+/**
+ * soup_message_metrics_get_fetch_start:
+ * @metrics: a #SoupMessageMetrics
+ *
+ * Get the time immediately before the #SoupMessage started to
+ * fetch a resource either from a remote server or local disk cache.
+ *
+ * Returns: the fetch start time
+ */
+guint64
+soup_message_metrics_get_fetch_start (SoupMessageMetrics *metrics)
+{
+ g_return_val_if_fail (metrics != NULL, 0);
+
+ return metrics->fetch_start;
+}
+
+/**
+ * soup_message_metrics_get_dns_start:
+ * @metrics: a #SoupMessageMetrics
+ *
+ * Get the time immediately before the #SoupMessage started the
+ * domain lookup name for the resource. It will be 0 if no domain
+ * lookup was required to fetch the resource (a persistent connection
+ * was used or resource was loaded from the local disk cache).
+ *
+ * Returns: the domain lookup start time
+ */
+guint64
+soup_message_metrics_get_dns_start (SoupMessageMetrics *metrics)
+{
+ g_return_val_if_fail (metrics != NULL, 0);
+
+ return metrics->dns_start;
+}
+
+/**
+ * soup_message_metrics_get_dns_end:
+ * @metrics: a #SoupMessageMetrics
+ *
+ * Get the time immediately after the #SoupMessage completed the
+ * domain lookup name for the resource. It will be 0 if no domain
+ * lookup was required to fetch the resource (a persistent connection
+ * was used or resource was loaded from the local disk cache).
+ *
+ * Returns: the domain lookup end time
+ */
+guint64
+soup_message_metrics_get_dns_end (SoupMessageMetrics *metrics)
+{
+ g_return_val_if_fail (metrics != NULL, 0);
+
+ return metrics->dns_end;
+}
+
+/**
+ * soup_message_metrics_get_connect_start:
+ * @metrics: a #SoupMessageMetrics
+ *
+ * Get the time immediately before the #SoupMessage started to
+ * establish the connection to the server. It will be 0 if no
+ * network connection was required to fetch the resource (a persistent
+ * connection was used or resource was loaded from the local disk cache).
+ *
+ * Returns: the connection start time
+ */
+guint64
+soup_message_metrics_get_connect_start (SoupMessageMetrics *metrics)
+{
+ g_return_val_if_fail (metrics != NULL, 0);
+
+ return metrics->connect_start;
+}
+
+/**
+ * soup_message_metrics_get_connect_end:
+ * @metrics: a #SoupMessageMetrics
+ *
+ * Get the time immediately after the #SoupMessage completed the
+ * connection to the server. This includes the time for the proxy
+ * negotiation and TLS handshake. It will be 0 if no network connection
+ * was required to fetch the resource (a persistent connection was used
+ * or resource was loaded from the local disk cache).
+ *
+ * Returns: the connection end time
+ */
+guint64
+soup_message_metrics_get_connect_end (SoupMessageMetrics *metrics)
+{
+ g_return_val_if_fail (metrics != NULL, 0);
+
+ return metrics->connect_end;
+}
+
+/**
+ * soup_message_metrics_get_tls_start:
+ * @metrics: a #SoupMessageMetrics
+ *
+ * Get the time immediately before the #SoupMessage started the
+ * TLS handshake. It will be 0 if no TLS handshake was required
+ * to fetch the resource (connection was not secure, a persistent
+ * connection was used or resource was loaded from the local disk cache).
+ *
+ * Returns: the tls start time
+ */
+guint64
+soup_message_metrics_get_tls_start (SoupMessageMetrics *metrics)
+{
+ g_return_val_if_fail (metrics != NULL, 0);
+
+ return metrics->tls_start;
+}
+
+/**
+ * soup_message_metrics_get_request_start:
+ * @metrics: a #SoupMessageMetrics
+ *
+ * Get the time immediately before the #SoupMessage started the
+ * request of the resource from the server or the local disk cache.
+ *
+ * Returns: the request start time
+ */
+guint64
+soup_message_metrics_get_request_start (SoupMessageMetrics *metrics)
+{
+ g_return_val_if_fail (metrics != NULL, 0);
+
+ return metrics->request_start;
+}
+
+/**
+ * soup_message_metrics_get_response_start:
+ * @metrics: a #SoupMessageMetrics
+ *
+ * Get the time immediately after the #SoupMessage received the first
+ * bytes of the response from the server or the local disk cache.
+ *
+ * Returns: the response start time
+ */
+guint64
+soup_message_metrics_get_response_start (SoupMessageMetrics *metrics)
+{
+ g_return_val_if_fail (metrics != NULL, 0);
+
+ return metrics->response_start;
+}
+
+/**
+ * soup_message_metrics_get_response_end:
+ * @metrics: a #SoupMessageMetrics
+ *
+ * Get the time immediately after the #SoupMessage received the last
+ * bytes of the response from the server or the local disk cache.
+ * In case of load failure, this returns the time immediately before the
+ * fetch is aborted.
+ *
+ * Returns: the response end time
+ */
+guint64
+soup_message_metrics_get_response_end (SoupMessageMetrics *metrics)
+{
+ g_return_val_if_fail (metrics != NULL, 0);
+
+ return metrics->response_end;
+}
diff --git a/libsoup/soup-message-metrics.h b/libsoup/soup-message-metrics.h
new file mode 100644
index 00000000..b5d3f9fb
--- /dev/null
+++ b/libsoup/soup-message-metrics.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright 2021 Igalia S.L.
+ */
+
+#pragma once
+
+#include "soup-types.h"
+
+G_BEGIN_DECLS
+
+typedef struct _SoupMessageMetrics SoupMessageMetrics;
+
+SOUP_AVAILABLE_IN_ALL
+GType soup_message_metrics_get_type (void);
+#define SOUP_TYPE_MESSAGE_METRICS (soup_message_metrics_get_type())
+
+SOUP_AVAILABLE_IN_ALL
+SoupMessageMetrics *soup_message_metrics_copy (SoupMessageMetrics *metrics);
+
+SOUP_AVAILABLE_IN_ALL
+void soup_message_metrics_free (SoupMessageMetrics *metrics);
+
+SOUP_AVAILABLE_IN_ALL
+guint64 soup_message_metrics_get_fetch_start (SoupMessageMetrics *metrics);
+
+SOUP_AVAILABLE_IN_ALL
+guint64 soup_message_metrics_get_dns_start (SoupMessageMetrics *metrics);
+
+SOUP_AVAILABLE_IN_ALL
+guint64 soup_message_metrics_get_dns_end (SoupMessageMetrics *metrics);
+
+SOUP_AVAILABLE_IN_ALL
+guint64 soup_message_metrics_get_connect_start (SoupMessageMetrics *metrics);
+
+SOUP_AVAILABLE_IN_ALL
+guint64 soup_message_metrics_get_connect_end (SoupMessageMetrics *metrics);
+
+SOUP_AVAILABLE_IN_ALL
+guint64 soup_message_metrics_get_tls_start (SoupMessageMetrics *metrics);
+
+SOUP_AVAILABLE_IN_ALL
+guint64 soup_message_metrics_get_request_start (SoupMessageMetrics *metrics);
+
+SOUP_AVAILABLE_IN_ALL
+guint64 soup_message_metrics_get_response_start (SoupMessageMetrics *metrics);
+
+SOUP_AVAILABLE_IN_ALL
+guint64 soup_message_metrics_get_response_end (SoupMessageMetrics *metrics);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(SoupMessageMetrics, soup_message_metrics_free)
+
+G_END_DECLS
diff --git a/libsoup/soup-message-private.h b/libsoup/soup-message-private.h
index 93e45d9e..05e0dcc9 100644
--- a/libsoup/soup-message-private.h
+++ b/libsoup/soup-message-private.h
@@ -143,4 +143,19 @@ void soup_message_set_method (SoupMessage *ms
void soup_message_set_http_version (SoupMessage *msg,
SoupHTTPVersion version);
+typedef enum {
+ SOUP_MESSAGE_METRICS_FETCH_START,
+ SOUP_MESSAGE_METRICS_DNS_START,
+ SOUP_MESSAGE_METRICS_DNS_END,
+ SOUP_MESSAGE_METRICS_CONNECT_START,
+ SOUP_MESSAGE_METRICS_CONNECT_END,
+ SOUP_MESSAGE_METRICS_TLS_START,
+ SOUP_MESSAGE_METRICS_REQUEST_START,
+ SOUP_MESSAGE_METRICS_RESPONSE_START,
+ SOUP_MESSAGE_METRICS_RESPONSE_END
+} SoupMessageMetricsType;
+
+void soup_message_set_metrics_timestamp (SoupMessage *msg,
+ SoupMessageMetricsType type);
+
#endif /* __SOUP_MESSAGE_PRIVATE_H__ */
diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c
index d9e9e4f3..87adc6f4 100644
--- a/libsoup/soup-message.c
+++ b/libsoup/soup-message.c
@@ -15,6 +15,7 @@
#include "soup.h"
#include "soup-connection.h"
#include "soup-message-private.h"
+#include "soup-message-metrics-private.h"
#include "soup-uri-utils-private.h"
/**
@@ -93,6 +94,8 @@ typedef struct {
gboolean is_top_level_navigation;
gboolean is_options_ping;
guint last_connection_id;
+
+ SoupMessageMetrics *metrics;
} SoupMessagePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (SoupMessage, soup_message, G_TYPE_OBJECT)
@@ -168,6 +171,7 @@ soup_message_finalize (GObject *object)
g_clear_pointer (&priv->uri, g_uri_unref);
g_clear_pointer (&priv->first_party, g_uri_unref);
g_clear_pointer (&priv->site_for_cookies, g_uri_unref);
+ g_clear_pointer (&priv->metrics, soup_message_metrics_free);
g_clear_object (&priv->auth);
g_clear_object (&priv->proxy_auth);
@@ -1313,11 +1317,43 @@ soup_message_get_connection (SoupMessage *msg)
return priv->connection;
}
+static void
+soup_message_set_metrics_timestamp_for_network_event (SoupMessage *msg,
+ GSocketClientEvent event)
+{
+ switch (event) {
+ case G_SOCKET_CLIENT_RESOLVING:
+ soup_message_set_metrics_timestamp (msg, SOUP_MESSAGE_METRICS_DNS_START);
+ break;
+ case G_SOCKET_CLIENT_RESOLVED:
+ soup_message_set_metrics_timestamp (msg, SOUP_MESSAGE_METRICS_DNS_END);
+ break;
+ case G_SOCKET_CLIENT_CONNECTING:
+ soup_message_set_metrics_timestamp (msg, SOUP_MESSAGE_METRICS_CONNECT_START);
+ break;
+ case G_SOCKET_CLIENT_CONNECTED:
+ /* connect_end happens after proxy and tls */
+ case G_SOCKET_CLIENT_PROXY_NEGOTIATING:
+ case G_SOCKET_CLIENT_PROXY_NEGOTIATED:
+ break;
+ case G_SOCKET_CLIENT_TLS_HANDSHAKING:
+ soup_message_set_metrics_timestamp (msg, SOUP_MESSAGE_METRICS_TLS_START);
+ break;
+ case G_SOCKET_CLIENT_TLS_HANDSHAKED:
+ break;
+ case G_SOCKET_CLIENT_COMPLETE:
+ soup_message_set_metrics_timestamp (msg, SOUP_MESSAGE_METRICS_CONNECT_END);
+ break;
+ }
+}
+
static void
re_emit_connection_event (SoupMessage *msg,
GSocketClientEvent event,
GIOStream *connection)
{
+ soup_message_set_metrics_timestamp_for_network_event (msg, event);
+
g_signal_emit (msg, signals[NETWORK_EVENT], 0,
event, connection);
}
@@ -1428,6 +1464,7 @@ soup_message_cleanup_response (SoupMessage *msg)
* and proxy authentication. Note that #SoupMessage::authenticate signal will
* be emitted, if you want to disable authentication for a message use
* soup_message_disable_feature() passing #SOUP_TYPE_AUTH_MANAGER instead.
+ * @SOUP_MESSAGE_COLLECT_METRICS: Metrics will be collected for this message.
*
* Various flags that can be set on a #SoupMessage to alter its
* behavior.
@@ -2335,3 +2372,76 @@ soup_message_get_connection_id (SoupMessage *msg)
return priv->last_connection_id;
}
+
+/**
+ * soup_message_get_metrics:
+ * @msg: The #SoupMessage
+ *
+ * Get the #SoupMessageMetrics of @msg. If the flag %SOUP_MESSAGE_COLLECT_METRICS is not
+ * enabled for @msg this will return %NULL.
+ *
+ * Returns: (transfer none) (nullable): a #SoupMessageMetrics, or %NULL
+ */
+SoupMessageMetrics *
+soup_message_get_metrics (SoupMessage *msg)
+{
+ SoupMessagePrivate *priv;
+
+ g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
+
+ priv = soup_message_get_instance_private (msg);
+ if (priv->metrics)
+ return priv->metrics;
+
+ if (priv->msg_flags & SOUP_MESSAGE_COLLECT_METRICS)
+ priv->metrics = soup_message_metrics_new ();
+
+ return priv->metrics;
+}
+
+void
+soup_message_set_metrics_timestamp (SoupMessage *msg,
+ SoupMessageMetricsType type)
+{
+ SoupMessageMetrics *metrics = soup_message_get_metrics (msg);
+ guint64 timestamp;
+
+ if (!metrics)
+ return;
+
+ timestamp = g_get_monotonic_time ();
+ switch (type) {
+ case SOUP_MESSAGE_METRICS_FETCH_START:
+ memset (metrics, 0, sizeof (SoupMessageMetrics));
+ metrics->fetch_start = timestamp;
+ break;
+ case SOUP_MESSAGE_METRICS_DNS_START:
+ metrics->dns_start = timestamp;
+ break;
+ case SOUP_MESSAGE_METRICS_DNS_END:
+ metrics->dns_end = timestamp;
+ break;
+ case SOUP_MESSAGE_METRICS_CONNECT_START:
+ metrics->connect_start = timestamp;
+ break;
+ case SOUP_MESSAGE_METRICS_CONNECT_END:
+ metrics->connect_end = timestamp;
+ break;
+ case SOUP_MESSAGE_METRICS_TLS_START:
+ metrics->tls_start = timestamp;
+ break;
+ case SOUP_MESSAGE_METRICS_REQUEST_START:
+ metrics->request_start = timestamp;
+ break;
+ case SOUP_MESSAGE_METRICS_RESPONSE_START:
+ /* In case of multiple requests due to a informational response
+ * the response start is the first one.
+ */
+ if (metrics->response_start == 0)
+ metrics->response_start = timestamp;
+ break;
+ case SOUP_MESSAGE_METRICS_RESPONSE_END:
+ metrics->response_end = timestamp;
+ break;
+ }
+}
diff --git a/libsoup/soup-message.h b/libsoup/soup-message.h
index 99ebb766..a6ebf57d 100644
--- a/libsoup/soup-message.h
+++ b/libsoup/soup-message.h
@@ -77,7 +77,8 @@ typedef enum {
SOUP_MESSAGE_NO_REDIRECT = (1 << 1),
SOUP_MESSAGE_NEW_CONNECTION = (1 << 2),
SOUP_MESSAGE_IDEMPOTENT = (1 << 3),
- SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE = (1 << 4)
+ SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE = (1 << 4),
+ SOUP_MESSAGE_COLLECT_METRICS = (1 << 5)
} SoupMessageFlags;
SOUP_AVAILABLE_IN_ALL
@@ -171,4 +172,8 @@ void soup_message_set_is_options_ping (SoupMessage *msg,
SOUP_AVAILABLE_IN_ALL
guint64 soup_message_get_connection_id (SoupMessage *msg);
+SOUP_AVAILABLE_IN_ALL
+SoupMessageMetrics *soup_message_get_metrics (SoupMessage *msg);
+
+
G_END_DECLS
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index 06374dd5..521d32cb 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -1343,6 +1343,7 @@ soup_session_append_queue_item (SoupSession *session,
SoupSessionHost *host;
GSList *f;
+ soup_message_set_metrics_timestamp (msg, SOUP_MESSAGE_METRICS_FETCH_START);
soup_message_cleanup_response (msg);
item = soup_message_queue_item_new (session, msg, async, cancellable, callback, user_data);
@@ -1701,6 +1702,7 @@ tunnel_connect (SoupMessageQueueItem *item)
msg = soup_message_new_from_uri (SOUP_METHOD_CONNECT, soup_message_get_uri (item->msg));
soup_message_add_flags (msg, SOUP_MESSAGE_NO_REDIRECT);
+ soup_message_remove_flags (msg, SOUP_MESSAGE_COLLECT_METRICS);
tunnel_item = soup_session_append_queue_item (session, msg,
item->async,
@@ -1727,6 +1729,8 @@ connect_complete (SoupMessageQueueItem *item, SoupConnection *conn, GError *erro
return;
}
+ soup_message_set_metrics_timestamp (item->msg, SOUP_MESSAGE_METRICS_RESPONSE_END);
+
item->error = error;
soup_connection_disconnect (conn);
if (item->state == SOUP_MESSAGE_CONNECTING) {
@@ -2003,6 +2007,8 @@ soup_session_process_queue_item (SoupSession *session,
item->state = SOUP_MESSAGE_RUNNING;
+ soup_message_set_metrics_timestamp (item->msg, SOUP_MESSAGE_METRICS_REQUEST_START);
+
soup_session_send_queue_item (session, item,
(SoupMessageIOCompletionFn)message_completed);
@@ -2025,6 +2031,8 @@ soup_session_process_queue_item (SoupSession *session,
case SOUP_MESSAGE_RESTARTING:
item->state = SOUP_MESSAGE_STARTING;
soup_message_restarted (item->msg);
+ soup_message_set_metrics_timestamp (item->msg, SOUP_MESSAGE_METRICS_FETCH_START);
+
break;
case SOUP_MESSAGE_FINISHING:
@@ -3040,6 +3048,8 @@ static void
cache_stream_finished (GInputStream *stream,
SoupMessageQueueItem *item)
{
+ soup_message_set_metrics_timestamp (item->msg, SOUP_MESSAGE_METRICS_RESPONSE_END);
+
g_signal_handlers_disconnect_matched (stream, G_SIGNAL_MATCH_DATA,
0, 0, NULL, NULL, item);
item->state = SOUP_MESSAGE_FINISHING;
@@ -3175,6 +3185,7 @@ async_respond_from_cache (SoupSession *session,
/* Cached file was deleted? */
return FALSE;
}
+
g_object_set_data_full (G_OBJECT (item->task), "SoupSession:istream",
stream, g_object_unref);
diff --git a/libsoup/soup-types.h b/libsoup/soup-types.h
index 5e8d4862..8ce0505f 100644
--- a/libsoup/soup-types.h
+++ b/libsoup/soup-types.h
@@ -22,6 +22,7 @@ typedef struct _SoupCookieJar SoupCookieJar;
typedef struct _SoupHSTSEnforcer SoupHSTSEnforcer;
typedef struct _SoupHSTSPolicy SoupHSTSPolicy;
typedef struct _SoupMessage SoupMessage;
+typedef struct _SoupMessageMetrics SoupMessageMetrics;
typedef struct _SoupServer SoupServer;
typedef struct _SoupServerMessage SoupServerMessage;
typedef struct _SoupSession SoupSession;
diff --git a/libsoup/soup.h b/libsoup/soup.h
index 73c7f9c4..42d758a7 100644
--- a/libsoup/soup.h
+++ b/libsoup/soup.h
@@ -30,6 +30,7 @@ extern "C" {
#include "hsts/soup-hsts-policy.h"
#include "soup-logger.h"
#include "soup-message.h"
+#include "soup-message-metrics.h"
#include "soup-method.h"
#include "soup-multipart.h"
#include "soup-multipart-input-stream.h"
diff --git a/tests/cache-test.c b/tests/cache-test.c
index 97710047..517201ea 100644
--- a/tests/cache-test.c
+++ b/tests/cache-test.c
@@ -738,6 +738,115 @@ do_leaks_test (gconstpointer data)
g_free (cache_dir);
}
+static void
+do_metrics_test (gconstpointer data)
+{
+ GUri *base_uri = (GUri *)data;
+ SoupSession *session;
+ SoupCache *cache;
+ char *cache_dir;
+ char *body;
+ GUri *uri;
+ SoupMessage *msg;
+ SoupMessageHeaders *request_headers;
+ GInputStream *stream;
+ char buffer[256];
+ gsize nread;
+ SoupMessageMetrics *metrics;
+
+ cache_dir = g_dir_make_tmp ("cache-test-XXXXXX", NULL);
+ debug_printf (2, " Caching to %s\n", cache_dir);
+ cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER);
+ session = soup_test_session_new (NULL);
+ soup_session_add_feature (session, SOUP_SESSION_FEATURE (cache));
+
+ g_signal_connect (session, "request-queued",
+ G_CALLBACK (request_queued), NULL);
+ g_signal_connect (session, "request-unqueued",
+ G_CALLBACK (request_unqueued), NULL);
+
+ body = do_request (session, base_uri, "GET", "/1", NULL,
+ "Test-Set-Expires", "Fri, 01 Jan 2100 00:00:00 GMT",
+ NULL);
+ g_free (body);
+
+ last_request_validated = last_request_hit_network = last_request_unqueued = FALSE;
+ uri = g_uri_parse_relative (base_uri, "/1", SOUP_HTTP_URI_FLAGS, NULL);
+ msg = soup_message_new_from_uri ("GET", uri);
+ g_uri_unref (uri);
+
+ soup_message_add_flags (msg, SOUP_MESSAGE_COLLECT_METRICS);
+ metrics = soup_message_get_metrics (msg);
+ g_assert_nonnull (metrics);
+ g_assert_cmpuint (soup_message_metrics_get_fetch_start (metrics), ==, 0);
+
+ stream = soup_test_request_send (session, msg, NULL, 0, NULL);
+ g_assert_true (G_IS_INPUT_STREAM (stream));
+ g_assert_false (is_network_stream (stream));
+
+ g_assert_cmpuint (soup_message_metrics_get_fetch_start (metrics), >, 0);
+ g_assert_cmpuint (soup_message_metrics_get_dns_start (metrics), ==, 0);
+ g_assert_cmpuint (soup_message_metrics_get_dns_end (metrics), ==, 0);
+ g_assert_cmpuint (soup_message_metrics_get_connect_start (metrics), ==, 0);
+ g_assert_cmpuint (soup_message_metrics_get_tls_start (metrics), ==, 0);
+ g_assert_cmpuint (soup_message_metrics_get_connect_end (metrics), ==, 0);
+ g_assert_cmpuint (soup_message_metrics_get_request_start (metrics), >=,
soup_message_metrics_get_fetch_start (metrics));
+ g_input_stream_read_all (stream, buffer, sizeof (buffer), &nread, NULL, NULL);
+ g_assert_cmpuint (soup_message_metrics_get_response_start (metrics), >=,
soup_message_metrics_get_request_start (metrics));
+ soup_test_request_close_stream (stream, NULL, NULL);
+ g_object_unref (stream);
+ g_assert_cmpuint (soup_message_metrics_get_response_end (metrics), >=,
soup_message_metrics_get_response_start (metrics));
+ g_object_unref (msg);
+
+ body = do_request (session, base_uri, "GET", "/2", NULL,
+ "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT",
+ "Test-Set-Expires", "Sat, 02 Jan 2011 00:00:00 GMT",
+ "Test-Set-Cache-Control", "must-revalidate",
+ NULL);
+ g_free (body);
+
+ last_request_validated = last_request_hit_network = last_request_unqueued = FALSE;
+ uri = g_uri_parse_relative (base_uri, "/2", SOUP_HTTP_URI_FLAGS, NULL);
+ msg = soup_message_new_from_uri ("GET", uri);
+ g_uri_unref (uri);
+
+ request_headers = soup_message_get_request_headers (msg);
+ soup_message_headers_append (request_headers,
+ "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT");
+ soup_message_headers_append (request_headers,
+ "Test-Set-Expires", "Sat, 02 Jan 2011 00:00:00 GMT");
+ soup_message_headers_append (request_headers,
+ "Test-Set-Cache-Control", "must-revalidate");
+
+ soup_message_add_flags (msg, SOUP_MESSAGE_COLLECT_METRICS);
+ metrics = soup_message_get_metrics (msg);
+ g_assert_nonnull (metrics);
+ g_assert_cmpuint (soup_message_metrics_get_fetch_start (metrics), ==, 0);
+
+ stream = soup_test_request_send (session, msg, NULL, 0, NULL);
+ g_assert_true (G_IS_INPUT_STREAM (stream));
+ g_assert_false (is_network_stream (stream));
+ g_assert_true (last_request_validated);
+
+ g_assert_cmpuint (soup_message_metrics_get_fetch_start (metrics), >, 0);
+ g_assert_cmpuint (soup_message_metrics_get_dns_start (metrics), ==, 0);
+ g_assert_cmpuint (soup_message_metrics_get_dns_end (metrics), ==, 0);
+ g_assert_cmpuint (soup_message_metrics_get_connect_start (metrics), ==, 0);
+ g_assert_cmpuint (soup_message_metrics_get_tls_start (metrics), ==, 0);
+ g_assert_cmpuint (soup_message_metrics_get_connect_end (metrics), ==, 0);
+ g_assert_cmpuint (soup_message_metrics_get_request_start (metrics), >=,
soup_message_metrics_get_fetch_start (metrics));
+ g_input_stream_read_all (stream, buffer, sizeof (buffer), &nread, NULL, NULL);
+ g_assert_cmpuint (soup_message_metrics_get_response_start (metrics), >=,
soup_message_metrics_get_request_start (metrics));
+ soup_test_request_close_stream (stream, NULL, NULL);
+ g_object_unref (stream);
+ g_assert_cmpuint (soup_message_metrics_get_response_end (metrics), >=,
soup_message_metrics_get_response_start (metrics));
+ g_object_unref (msg);
+
+ soup_test_session_abort_unref (session);
+ g_object_unref (cache);
+ g_free (cache_dir);
+}
+
int
main (int argc, char **argv)
{
@@ -756,6 +865,7 @@ main (int argc, char **argv)
g_test_add_data_func ("/cache/refcounting", base_uri, do_refcounting_test);
g_test_add_data_func ("/cache/headers", base_uri, do_headers_test);
g_test_add_data_func ("/cache/leaks", base_uri, do_leaks_test);
+ g_test_add_data_func ("/cache/metrics", base_uri, do_metrics_test);
ret = g_test_run ();
diff --git a/tests/connection-test.c b/tests/connection-test.c
index b307cb88..ec40bc5b 100644
--- a/tests/connection-test.c
+++ b/tests/connection-test.c
@@ -863,17 +863,92 @@ network_event (SoupMessage *msg, GSocketClientEvent event,
}
}
+ if (soup_message_query_flags (msg, SOUP_MESSAGE_COLLECT_METRICS)) {
+ SoupMessageMetrics *metrics = soup_message_get_metrics (msg);
+
+ g_assert_cmpuint (soup_message_metrics_get_fetch_start (metrics), >, 0);
+
+ switch (event) {
+ case G_SOCKET_CLIENT_RESOLVING:
+ g_assert_cmpuint (soup_message_metrics_get_dns_start (metrics), >, 0);
+ break;
+ case G_SOCKET_CLIENT_RESOLVED:
+ g_assert_cmpuint (soup_message_metrics_get_dns_end (metrics), >, 0);
+ g_assert_cmpuint (soup_message_metrics_get_dns_end (metrics), >=,
soup_message_metrics_get_dns_start (metrics));
+ break;
+ case G_SOCKET_CLIENT_CONNECTING:
+ g_assert_cmpuint (soup_message_metrics_get_connect_start (metrics), >, 0);
+ g_assert_cmpuint (soup_message_metrics_get_connect_start (metrics), >=,
soup_message_metrics_get_dns_end (metrics));
+ break;
+ case G_SOCKET_CLIENT_TLS_HANDSHAKING:
+ g_assert_cmpuint (soup_message_metrics_get_tls_start (metrics), >, 0);
+ g_assert_cmpuint (soup_message_metrics_get_tls_start (metrics), >=,
soup_message_metrics_get_connect_start (metrics));
+ break;
+ case G_SOCKET_CLIENT_COMPLETE:
+ g_assert_cmpuint (soup_message_metrics_get_connect_end (metrics), >, 0);
+ g_assert_cmpuint (soup_message_metrics_get_connect_end (metrics), >=,
soup_message_metrics_get_connect_start (metrics));
+ if (soup_message_metrics_get_tls_start (metrics))
+ g_assert_cmpuint (soup_message_metrics_get_connect_end (metrics), >=,
soup_message_metrics_get_tls_start (metrics));
+ break;
+ default:
+ break;
+ }
+ }
+
*events = *events + 1;
}
static void
-do_one_connection_event_test (SoupSession *session, const char *uri,
- const char *events)
+metrics_test_message_starting_cb (SoupMessage *msg)
+{
+ SoupMessageMetrics *metrics = soup_message_get_metrics (msg);
+
+ g_assert_cmpuint (soup_message_metrics_get_request_start (metrics), >, 0);
+ g_assert_cmpuint (soup_message_metrics_get_request_start (metrics), >=,
soup_message_metrics_get_fetch_start (metrics));
+}
+
+static void
+metrics_test_status_changed_cb (SoupMessage *msg)
+{
+ SoupMessageMetrics *metrics;
+
+ metrics = soup_message_get_metrics (msg);
+ g_assert_cmpuint (soup_message_metrics_get_response_start (metrics), >, 0);
+ g_assert_cmpuint (soup_message_metrics_get_response_start (metrics), >=,
soup_message_metrics_get_request_start (metrics));
+}
+
+static void
+metrics_test_got_body_cb (SoupMessage *msg)
+{
+ SoupMessageMetrics *metrics = soup_message_get_metrics (msg);
+
+ g_assert_cmpuint (soup_message_metrics_get_response_end (metrics), >, 0);
+ g_assert_cmpuint (soup_message_metrics_get_response_end (metrics), >=,
soup_message_metrics_get_response_start (metrics));
+}
+
+static void
+do_one_connection_event_test (SoupSession *session,
+ const char *uri,
+ gboolean collect_metrics,
+ const char *events)
{
SoupMessage *msg;
GBytes *body;
+ SoupMessageMetrics *metrics;
msg = soup_message_new ("GET", uri);
+ if (collect_metrics) {
+ soup_message_add_flags (msg, SOUP_MESSAGE_COLLECT_METRICS);
+ g_signal_connect (msg, "starting",
+ G_CALLBACK (metrics_test_message_starting_cb),
+ NULL);
+ g_signal_connect (msg, "notify::status-code",
+ G_CALLBACK (metrics_test_status_changed_cb),
+ NULL);
+ g_signal_connect (msg, "got-body",
+ G_CALLBACK (metrics_test_got_body_cb),
+ NULL);
+ }
g_signal_connect (msg, "network-event",
G_CALLBACK (network_event),
&events);
@@ -886,22 +961,128 @@ do_one_connection_event_test (SoupSession *session, const char *uri,
events++;
}
+ metrics = soup_message_get_metrics (msg);
+ if (collect_metrics) {
+ g_assert_nonnull (metrics);
+
+ g_assert_cmpuint (soup_message_metrics_get_fetch_start (metrics), >, 0);
+ g_assert_cmpuint (soup_message_metrics_get_dns_start (metrics), >, 0);
+ g_assert_cmpuint (soup_message_metrics_get_dns_end (metrics), >, 0);
+ g_assert_cmpuint (soup_message_metrics_get_connect_start (metrics), >, 0);
+ if (g_str_equal (uri, HTTPS_SERVER))
+ g_assert_cmpuint (soup_message_metrics_get_tls_start (metrics), >, 0);
+ g_assert_cmpuint (soup_message_metrics_get_connect_end (metrics), >, 0);
+ g_assert_cmpuint (soup_message_metrics_get_request_start (metrics), >, 0);
+ g_assert_cmpuint (soup_message_metrics_get_response_start (metrics), >, 0);
+ g_assert_cmpuint (soup_message_metrics_get_response_end (metrics), >, 0);
+ } else {
+ g_assert_null (metrics);
+ }
+
g_bytes_unref (body);
g_object_unref (msg);
soup_session_abort (session);
}
static void
-do_connection_event_test_for_session (SoupSession *session)
+do_one_connection_event_fail_test (SoupSession *session,
+ const char *uri,
+ gboolean collect_metrics,
+ GQuark domain,
+ gint code,
+ const char *events)
+{
+ SoupMessage *msg;
+ GBytes *body;
+ SoupMessageMetrics *metrics;
+ GError *error = NULL;
+ GTlsDatabase *previous_tlsdb = NULL;
+
+ if (tls_available) {
+ GTlsDatabase *tlsdb;
+
+ previous_tlsdb = g_object_ref (soup_session_get_tls_database (session));
+ tlsdb = g_tls_backend_get_default_database (g_tls_backend_get_default ());
+ soup_session_set_tls_database (session, tlsdb);
+ g_object_unref (tlsdb);
+ }
+
+ msg = soup_message_new ("GET", uri);
+ if (collect_metrics) {
+ soup_message_add_flags (msg, SOUP_MESSAGE_COLLECT_METRICS);
+ g_signal_connect (msg, "starting",
+ G_CALLBACK (metrics_test_message_starting_cb),
+ NULL);
+ g_signal_connect (msg, "notify::status-code",
+ G_CALLBACK (metrics_test_status_changed_cb),
+ NULL);
+ g_signal_connect (msg, "got-body",
+ G_CALLBACK (metrics_test_got_body_cb),
+ NULL);
+ }
+ g_signal_connect (msg, "network-event",
+ G_CALLBACK (network_event),
+ &events);
+ body = soup_session_send_and_read (session, msg, NULL, &error);
+ soup_test_assert_message_status (msg, SOUP_STATUS_NONE);
+ g_assert_error (error, domain, code);
+ g_error_free (error);
+
+ while (*events) {
+ soup_test_assert (!*events,
+ "Expected %s",
+ event_name_from_abbrev (*events));
+ events++;
+ }
+
+ metrics = soup_message_get_metrics (msg);
+ if (collect_metrics) {
+ g_assert_nonnull (metrics);
+
+ g_assert_cmpuint (soup_message_metrics_get_fetch_start (metrics), >, 0);
+ g_assert_cmpuint (soup_message_metrics_get_dns_start (metrics), >, 0);
+ g_assert_cmpuint (soup_message_metrics_get_dns_end (metrics), >, 0);
+ if (g_str_equal (uri, HTTPS_SERVER))
+ g_assert_cmpuint (soup_message_metrics_get_tls_start (metrics), >, 0);
+ g_assert_cmpuint (soup_message_metrics_get_connect_end (metrics), ==, 0);
+ g_assert_cmpuint (soup_message_metrics_get_request_start (metrics), ==, 0);
+ g_assert_cmpuint (soup_message_metrics_get_response_start (metrics), ==, 0);
+ g_assert_cmpuint (soup_message_metrics_get_response_end (metrics), >, 0);
+ } else {
+ g_assert_null (metrics);
+ }
+
+ g_bytes_unref (body);
+ g_object_unref (msg);
+ soup_session_abort (session);
+
+ if (tls_available) {
+ soup_session_set_tls_database (session, previous_tlsdb);
+ g_object_unref (previous_tlsdb);
+ }
+}
+
+static void
+do_connection_event_test_for_session (SoupSession *session,
+ gboolean collect_metrics)
{
GProxyResolver *resolver;
debug_printf (1, " http\n");
- do_one_connection_event_test (session, HTTP_SERVER, "rRcCx");
+ do_one_connection_event_test (session, HTTP_SERVER, collect_metrics, "rRcCx");
+
+ debug_printf (1, " wrong http (invalid port)\n");
+ do_one_connection_event_fail_test (session, HTTP_SERVER_BAD_PORT, collect_metrics,
+ G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED,
+ "rRc");
if (tls_available) {
debug_printf (1, " https\n");
- do_one_connection_event_test (session, HTTPS_SERVER, "rRcCtTx");
+ do_one_connection_event_test (session, HTTPS_SERVER, collect_metrics, "rRcCtTx");
+ debug_printf (1, " wrong https (invalid certificate)\n");
+ do_one_connection_event_fail_test (session, HTTPS_SERVER, collect_metrics,
+ G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
+ "rRcCt");
} else
debug_printf (1, " https -- SKIPPING\n");
@@ -910,11 +1091,11 @@ do_connection_event_test_for_session (SoupSession *session)
g_object_unref (resolver);
debug_printf (1, " http with proxy\n");
- do_one_connection_event_test (session, HTTP_SERVER, "rRcCx");
+ do_one_connection_event_test (session, HTTP_SERVER, collect_metrics, "rRcCx");
if (tls_available) {
debug_printf (1, " https with proxy\n");
- do_one_connection_event_test (session, HTTPS_SERVER, "rRcCpPtTx");
+ do_one_connection_event_test (session, HTTPS_SERVER, collect_metrics, "rRcCpPtTx");
} else
debug_printf (1, " https with proxy -- SKIPPING\n");
}
@@ -927,7 +1108,7 @@ do_connection_event_test (void)
SOUP_TEST_SKIP_IF_NO_APACHE;
session = soup_test_session_new (NULL);
- do_connection_event_test_for_session (session);
+ do_connection_event_test_for_session (session, FALSE);
soup_test_session_abort_unref (session);
}
@@ -1261,6 +1442,18 @@ do_connection_preconnect_test (void)
debug_printf (1, " https -- SKIPPING\n");
}
+static void
+do_connection_metrics_test (void)
+{
+ SoupSession *session;
+
+ SOUP_TEST_SKIP_IF_NO_APACHE;
+
+ session = soup_test_session_new (NULL);
+ do_connection_event_test_for_session (session, TRUE);
+ soup_test_session_abort_unref (session);
+}
+
int
main (int argc, char **argv)
{
@@ -1283,6 +1476,7 @@ main (int argc, char **argv)
g_test_add_func ("/connection/state", do_connection_state_test);
g_test_add_func ("/connection/event", do_connection_event_test);
g_test_add_func ("/connection/preconnect", do_connection_preconnect_test);
+ g_test_add_func ("/connection/metrics", do_connection_metrics_test);
ret = g_test_run ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]