andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 5 months ago
Clone

Blame SOURCES/0016-Issue-51165-add-new-access-log-keywords-for-wtime-an.patch

5873fa
From 282edde7950ceb2515d74fdbcc0a188131769d74 Mon Sep 17 00:00:00 2001
5873fa
From: Mark Reynolds <mreynolds@redhat.com>
5873fa
Date: Tue, 23 Jun 2020 16:38:55 -0400
5873fa
Subject: [PATCH] Issue 51165 - add new access log keywords for wtime and
5873fa
 optime
5873fa
5873fa
Description:  In addition to the "etime" stat in the access we can also
5873fa
              add the time the operation spent in the work queue, and
5873fa
              how long the actual operation took.  We now have "wtime"
5873fa
              and "optime" to track these stats in the access log.
5873fa
5873fa
              Also updated logconf for notes=F (related to a different
5873fa
              ticket), and stats for wtime and optime.
5873fa
5873fa
relates: https://pagure.io/389-ds-base/issue/51165
5873fa
5873fa
Reviewed by: ?
5873fa
---
5873fa
 ldap/admin/src/logconv.pl         | 187 +++++++++++++++++++++++++++---
5873fa
 ldap/servers/slapd/add.c          |   3 +
5873fa
 ldap/servers/slapd/bind.c         |   4 +
5873fa
 ldap/servers/slapd/delete.c       |   3 +
5873fa
 ldap/servers/slapd/modify.c       |   3 +
5873fa
 ldap/servers/slapd/modrdn.c       |   3 +
5873fa
 ldap/servers/slapd/operation.c    |  24 ++++
5873fa
 ldap/servers/slapd/opshared.c     |   3 +
5873fa
 ldap/servers/slapd/result.c       |  49 ++++----
5873fa
 ldap/servers/slapd/slap.h         |  13 ++-
5873fa
 ldap/servers/slapd/slapi-plugin.h |  26 ++++-
5873fa
 11 files changed, 269 insertions(+), 49 deletions(-)
5873fa
5873fa
diff --git a/ldap/admin/src/logconv.pl b/ldap/admin/src/logconv.pl
5873fa
index f4808a101..1ed44a888 100755
5873fa
--- a/ldap/admin/src/logconv.pl
5873fa
+++ b/ldap/admin/src/logconv.pl
5873fa
@@ -3,7 +3,7 @@
5873fa
 #
5873fa
 # BEGIN COPYRIGHT BLOCK
5873fa
 # Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
5873fa
-# Copyright (C) 2013 Red Hat, Inc.
5873fa
+# Copyright (C) 2020 Red Hat, Inc.
5873fa
 # All rights reserved.
5873fa
 #
5873fa
 # License: GPL (version 3 or any later version).
5873fa
@@ -55,7 +55,7 @@ my $reportStats = "";
5873fa
 my $dataLocation = "/tmp";
5873fa
 my $startTLSoid = "1.3.6.1.4.1.1466.20037";
5873fa
 my @statnames=qw(last last_str results srch add mod modrdn moddn cmp del abandon
5873fa
-                 conns sslconns bind anonbind unbind notesA notesU etime);
5873fa
+                 conns sslconns bind anonbind unbind notesA notesU notesF etime);
5873fa
 my $s_stats;
5873fa
 my $m_stats;
5873fa
 my $verb = "no";
5873fa
@@ -211,6 +211,7 @@ my $sslClientBindCount = 0;
5873fa
 my $sslClientFailedCount = 0;
5873fa
 my $objectclassTopCount= 0;
5873fa
 my $pagedSearchCount = 0;
5873fa
+my $invalidFilterCount = 0;
5873fa
 my $bindCount = 0;
5873fa
 my $filterCount = 0;
5873fa
 my $baseCount = 0;
5873fa
@@ -258,7 +259,7 @@ map {$conn{$_} = $_} @conncodes;
5873fa
 # hash db-backed hashes
5873fa
 my @hashnames = qw(attr rc src rsrc excount conn_hash ip_hash conncount nentries
5873fa
                    filter base ds6xbadpwd saslmech saslconnop bindlist etime oid
5873fa
-                   start_time_of_connection end_time_of_connection
5873fa
+                   start_time_of_connection end_time_of_connection notesf_conn_op
5873fa
                    notesa_conn_op notesu_conn_op etime_conn_op nentries_conn_op
5873fa
                    optype_conn_op time_conn_op srch_conn_op del_conn_op mod_conn_op
5873fa
                    mdn_conn_op cmp_conn_op bind_conn_op unbind_conn_op ext_conn_op
5873fa
@@ -926,7 +927,7 @@ if ($verb eq "yes" || $usage =~ /u/ || $usage =~ /U/){
5873fa
 			}
5873fa
 			while($op > 0){
5873fa
 				# The bind op is not the same as the search op that triggered the notes=A.
5873fa
-				# We have adjust the key by decrementing the op count until we find the last bind op.
5873fa
+				# We have to adjust the key by decrementing the op count until we find the last bind op.
5873fa
 				$op--;
5873fa
 				$binddn_key = "$srvRstCnt,$conn,$op";
5873fa
 				if (exists($bind_conn_op->{$binddn_key}) && defined($bind_conn_op->{$binddn_key})) {
5873fa
@@ -1049,9 +1050,60 @@ if ($verb eq "yes" || $usage =~ /u/ || $usage =~ /U/){
5873fa
 			}
5873fa
 		}
5873fa
 	}
5873fa
-} # end of unindexed search report
5873fa
+    print "\n";
5873fa
+}
5873fa
+
5873fa
+print "Invalid Attribute Filters:    $invalidFilterCount\n";
5873fa
+if ($invalidFilterCount > 0 && $verb eq "yes"){
5873fa
+    my $conn_hash = $hashes->{conn_hash};
5873fa
+    my $notesf_conn_op = $hashes->{notesf_conn_op};
5873fa
+    my $time_conn_op = $hashes->{time_conn_op};
5873fa
+    my $etime_conn_op = $hashes->{etime_conn_op};
5873fa
+    my $nentries_conn_op = $hashes->{nentries_conn_op};
5873fa
+    my $filter_conn_op = $hashes->{filter_conn_op};
5873fa
+    my $bind_conn_op = $hashes->{bind_conn_op};
5873fa
+    my $notesCount = 1;
5873fa
+    my $unindexedIp;
5873fa
+    my $binddn_key;
5873fa
+    my %uniqFilt = (); # hash of unique filters
5873fa
+    my %uniqFilter = (); # hash of unique filters bind dn
5873fa
+    my %uniqBindDNs = (); # hash of unique bind dn's
5873fa
+    my %uniqBindFilters = (); # hash of filters for a bind DN
5873fa
+
5873fa
+    while (my ($srcnt_conn_op, $count) = each %{$notesf_conn_op}) {
5873fa
+        my ($srvRstCnt, $conn, $op) = split(",", $srcnt_conn_op);
5873fa
+        my $attrIp = getIPfromConn($conn, $srvRstCnt);
5873fa
+        print "\n  Invalid Attribute Filter #".$notesCount." (notes=F)\n";
5873fa
+        print "  -  Date/Time:             $time_conn_op->{$srcnt_conn_op}\n";
5873fa
+        print "  -  Connection Number:     $conn\n";
5873fa
+        print "  -  Operation Number:      $op\n";
5873fa
+        print "  -  Etime:                 $etime_conn_op->{$srcnt_conn_op}\n";
5873fa
+        print "  -  Nentries:              $nentries_conn_op->{$srcnt_conn_op}\n";
5873fa
+        print "  -  IP Address:            $attrIp\n";
5873fa
+        if (exists($filter_conn_op->{$srcnt_conn_op}) && defined($filter_conn_op->{$srcnt_conn_op})) {
5873fa
+            print "  -  Search Filter:         $filter_conn_op->{$srcnt_conn_op}\n";
5873fa
+            $uniqFilt{$filter_conn_op->{$srcnt_conn_op}}++;
5873fa
+        }
5873fa
+        while($op > 0){
5873fa
+            # The bind op is not the same as the search op that triggered the notes=A.
5873fa
+            # We have to adjust the key by decrementing the op count until we find the last bind op.
5873fa
+            $op--;
5873fa
+            $binddn_key = "$srvRstCnt,$conn,$op";
5873fa
+            if (exists($bind_conn_op->{$binddn_key}) && defined($bind_conn_op->{$binddn_key})) {
5873fa
+                print "  -  Bind DN:               $bind_conn_op->{$binddn_key}\n";
5873fa
+                $uniqBindDNs{$bind_conn_op->{$binddn_key}}++;
5873fa
+                if( $uniqFilt{$filter_conn_op->{$srcnt_conn_op}} && defined($filter_conn_op->{$srcnt_conn_op})) {
5873fa
+                    $uniqBindFilters{$bind_conn_op->{$binddn_key}}{$filter_conn_op->{$srcnt_conn_op}}++;
5873fa
+                    $uniqFilter{$filter_conn_op->{$srcnt_conn_op}}{$bind_conn_op->{$binddn_key}}++;
5873fa
+                }
5873fa
+                last;
5873fa
+            }
5873fa
+        }
5873fa
+        $notesCount++;
5873fa
+    }
5873fa
+    print "\n";
5873fa
+}
5873fa
 
5873fa
-print "\n";
5873fa
 print "FDs Taken:                    $fdTaken\n";
5873fa
 print "FDs Returned:                 $fdReturned\n";
5873fa
 print "Highest FD Taken:             $highestFdTaken\n\n";
5873fa
@@ -1386,20 +1438,20 @@ if ($usage =~ /l/ || $verb eq "yes"){
5873fa
 	}
5873fa
 }
5873fa
 
5873fa
-#########################################
5873fa
-#                                       #
5873fa
-# Gather and Process the unique etimes  #
5873fa
-#                                       #
5873fa
-#########################################
5873fa
+##############################################################
5873fa
+#                                                            #
5873fa
+# Gather and Process the unique etimes, wtimes, and optimes  #
5873fa
+#                                                            #
5873fa
+##############################################################
5873fa
 
5873fa
 my $first;
5873fa
 if ($usage =~ /t/i || $verb eq "yes"){
5873fa
+	# Print the elapsed times (etime)
5873fa
+
5873fa
 	my $etime = $hashes->{etime};
5873fa
 	my @ekeys = keys %{$etime};
5873fa
-	#
5873fa
 	# print most often etimes
5873fa
-	#
5873fa
-	print "\n\n----- Top $sizeCount Most Frequent etimes -----\n\n";
5873fa
+	print "\n\n----- Top $sizeCount Most Frequent etimes (elapsed times) -----\n\n";
5873fa
 	my $eloop = 0;
5873fa
 	my $retime = 0;
5873fa
 	foreach my $et (sort { $etime->{$b} <=> $etime->{$a} } @ekeys) {
5873fa
@@ -1411,16 +1463,84 @@ if ($usage =~ /t/i || $verb eq "yes"){
5873fa
 		printf "%-8s        %-12s\n", $etime->{ $et }, "etime=$et";
5873fa
 		$eloop++;
5873fa
 	}
5873fa
-	#
5873fa
+	if ($eloop == 0) {
5873fa
+		print "None";
5873fa
+	}
5873fa
 	# print longest etimes
5873fa
-	#
5873fa
-	print "\n\n----- Top $sizeCount Longest etimes -----\n\n";
5873fa
+	print "\n\n----- Top $sizeCount Longest etimes (elapsed times) -----\n\n";
5873fa
 	$eloop = 0;
5873fa
 	foreach my $et (sort { $b <=> $a } @ekeys) {
5873fa
 		if ($eloop == $sizeCount) { last; }
5873fa
 		printf "%-12s    %-10s\n","etime=$et",$etime->{ $et };
5873fa
 		$eloop++;
5873fa
 	}
5873fa
+	if ($eloop == 0) {
5873fa
+		print "None";
5873fa
+	}
5873fa
+
5873fa
+	# Print the wait times (wtime)
5873fa
+
5873fa
+	my $wtime = $hashes->{wtime};
5873fa
+	my @wkeys = keys %{$wtime};
5873fa
+	# print most often wtimes
5873fa
+	print "\n\n----- Top $sizeCount Most Frequent wtimes (wait times) -----\n\n";
5873fa
+	$eloop = 0;
5873fa
+	$retime = 0;
5873fa
+	foreach my $et (sort { $wtime->{$b} <=> $wtime->{$a} } @wkeys) {
5873fa
+		if ($eloop == $sizeCount) { last; }
5873fa
+		if ($retime ne "2"){
5873fa
+			$first = $et;
5873fa
+			$retime = "2";
5873fa
+		}
5873fa
+		printf "%-8s        %-12s\n", $wtime->{ $et }, "wtime=$et";
5873fa
+		$eloop++;
5873fa
+	}
5873fa
+	if ($eloop == 0) {
5873fa
+		print "None";
5873fa
+	}
5873fa
+	# print longest wtimes
5873fa
+	print "\n\n----- Top $sizeCount Longest wtimes (wait times) -----\n\n";
5873fa
+	$eloop = 0;
5873fa
+	foreach my $et (sort { $b <=> $a } @wkeys) {
5873fa
+		if ($eloop == $sizeCount) { last; }
5873fa
+		printf "%-12s    %-10s\n","wtime=$et",$wtime->{ $et };
5873fa
+		$eloop++;
5873fa
+	}
5873fa
+	if ($eloop == 0) {
5873fa
+		print "None";
5873fa
+	}
5873fa
+
5873fa
+	# Print the operation times (optime)
5873fa
+
5873fa
+	my $optime = $hashes->{optime};
5873fa
+	my @opkeys = keys %{$optime};
5873fa
+	# print most often optimes
5873fa
+	print "\n\n----- Top $sizeCount Most Frequent optimes (actual operation times) -----\n\n";
5873fa
+	$eloop = 0;
5873fa
+	$retime = 0;
5873fa
+	foreach my $et (sort { $optime->{$b} <=> $optime->{$a} } @opkeys) {
5873fa
+		if ($eloop == $sizeCount) { last; }
5873fa
+		if ($retime ne "2"){
5873fa
+			$first = $et;
5873fa
+			$retime = "2";
5873fa
+		}
5873fa
+		printf "%-8s        %-12s\n", $optime->{ $et }, "optime=$et";
5873fa
+		$eloop++;
5873fa
+	}
5873fa
+	if ($eloop == 0) {
5873fa
+		print "None";
5873fa
+	}
5873fa
+	# print longest optimes
5873fa
+	print "\n\n----- Top $sizeCount Longest optimes (actual operation times) -----\n\n";
5873fa
+	$eloop = 0;
5873fa
+	foreach my $et (sort { $b <=> $a } @opkeys) {
5873fa
+		if ($eloop == $sizeCount) { last; }
5873fa
+		printf "%-12s    %-10s\n","optime=$et",$optime->{ $et };
5873fa
+		$eloop++;
5873fa
+	}
5873fa
+	if ($eloop == 0) {
5873fa
+		print "None";
5873fa
+	}
5873fa
 }
5873fa
 
5873fa
 #######################################
5873fa
@@ -2152,6 +2272,26 @@ sub parseLineNormal
5873fa
 	if (m/ RESULT err=/ && m/ notes=[A-Z,]*P/){
5873fa
 		$pagedSearchCount++;
5873fa
 	}
5873fa
+	if (m/ RESULT err=/ && m/ notes=[A-Z,]*F/){
5873fa
+		$invalidFilterCount++;
5873fa
+		$con = "";
5873fa
+		if ($_ =~ /conn= *([0-9A-Z]+)/i){
5873fa
+			$con = $1;
5873fa
+			if ($_ =~ /op= *([0-9\-]+)/i){ $op = $1;}
5873fa
+		}
5873fa
+
5873fa
+		if($reportStats){ inc_stats('notesF',$s_stats,$m_stats); }
5873fa
+        if ($usage =~ /u/ || $usage =~ /U/ || $verb eq "yes"){
5873fa
+            if($_ =~ /etime= *([0-9.]+)/i ){
5873fa
+                if($1 >= $minEtime){
5873fa
+                    $hashes->{etime_conn_op}->{"$serverRestartCount,$con,$op"} = $1;
5873fa
+                    $hashes->{notesf_conn_op}->{"$serverRestartCount,$con,$op"}++;
5873fa
+                    if ($_ =~ / *([0-9a-z:\/]+)/i){ $hashes->{time_conn_op}->{"$serverRestartCount,$con,$op"} = $1; }
5873fa
+                    if ($_ =~ /nentries= *([0-9]+)/i ){ $hashes->{nentries_conn_op}->{"$serverRestartCount,$con,$op"} = $1; }
5873fa
+                }
5873fa
+            }
5873fa
+        }
5873fa
+	}
5873fa
 	if (m/ notes=[A-Z,]*A/){
5873fa
 		$con = "";
5873fa
 		if ($_ =~ /conn= *([0-9A-Z]+)/i){
5873fa
@@ -2435,6 +2575,16 @@ sub parseLineNormal
5873fa
 		if ($usage =~ /t/i || $verb eq "yes"){ $hashes->{etime}->{$etime_val}++; }
5873fa
 		if ($reportStats){ inc_stats_val('etime',$etime_val,$s_stats,$m_stats); }
5873fa
 	}
5873fa
+	if ($_ =~ /wtime= *([0-9.]+)/ ) {
5873fa
+		my $wtime_val = $1;
5873fa
+		if ($usage =~ /t/i || $verb eq "yes"){ $hashes->{wtime}->{$wtime_val}++; }
5873fa
+		if ($reportStats){ inc_stats_val('wtime',$wtime_val,$s_stats,$m_stats); }
5873fa
+	}
5873fa
+	if ($_ =~ /optime= *([0-9.]+)/ ) {
5873fa
+		my $optime_val = $1;
5873fa
+		if ($usage =~ /t/i || $verb eq "yes"){ $hashes->{optime}->{$optime_val}++; }
5873fa
+		if ($reportStats){ inc_stats_val('optime',$optime_val,$s_stats,$m_stats); }
5873fa
+	}
5873fa
 	if ($_ =~ / tag=101 / || $_ =~ / tag=111 / || $_ =~ / tag=100 / || $_ =~ / tag=115 /){
5873fa
 		if ($_ =~ / nentries= *([0-9]+)/i ){ 
5873fa
 			my $nents = $1;
5873fa
@@ -2555,7 +2705,7 @@ sub parseLineNormal
5873fa
 			}
5873fa
 		}
5873fa
 	}
5873fa
-	if (/ RESULT err=/ && / tag=97 nentries=0 etime=/ && $_ =~ /dn=\"(.*)\"/i){
5873fa
+	if (/ RESULT err=/ && / tag=97 nentries=0 / && $_ =~ /dn=\"(.*)\"/i){
5873fa
 		# Check if this is a sasl bind, if see we need to add the RESULT's dn as a bind dn
5873fa
 		my $binddn = $1;
5873fa
 		my ($conn, $op);
5873fa
@@ -2680,6 +2830,7 @@ print_stats_block
5873fa
 						 $stats->{'unbind'},
5873fa
 						 $stats->{'notesA'},
5873fa
 						 $stats->{'notesU'},
5873fa
+						 $stats->{'notesF'},
5873fa
 						 $stats->{'etime'}),
5873fa
 					"\n" );
5873fa
 			} else {
5873fa
diff --git a/ldap/servers/slapd/add.c b/ldap/servers/slapd/add.c
5873fa
index 06ca1ee79..52c64fa3c 100644
5873fa
--- a/ldap/servers/slapd/add.c
5873fa
+++ b/ldap/servers/slapd/add.c
5873fa
@@ -441,6 +441,9 @@ op_shared_add(Slapi_PBlock *pb)
5873fa
     internal_op = operation_is_flag_set(operation, OP_FLAG_INTERNAL);
5873fa
     pwpolicy = new_passwdPolicy(pb, slapi_entry_get_dn(e));
5873fa
 
5873fa
+    /* Set the time we actually started the operation */
5873fa
+    slapi_operation_set_time_started(operation);
5873fa
+
5873fa
     /* target spec is used to decide which plugins are applicable for the operation */
5873fa
     operation_set_target_spec(operation, slapi_entry_get_sdn(e));
5873fa
 
5873fa
diff --git a/ldap/servers/slapd/bind.c b/ldap/servers/slapd/bind.c
5873fa
index 310216e89..55f865077 100644
5873fa
--- a/ldap/servers/slapd/bind.c
5873fa
+++ b/ldap/servers/slapd/bind.c
5873fa
@@ -87,6 +87,10 @@ do_bind(Slapi_PBlock *pb)
5873fa
         send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL);
5873fa
         goto free_and_return;
5873fa
     }
5873fa
+
5873fa
+    /* Set the time we actually started the operation */
5873fa
+    slapi_operation_set_time_started(pb_op);
5873fa
+
5873fa
     ber = pb_op->o_ber;
5873fa
 
5873fa
     /*
5873fa
diff --git a/ldap/servers/slapd/delete.c b/ldap/servers/slapd/delete.c
5873fa
index c0e61adf1..1a7209317 100644
5873fa
--- a/ldap/servers/slapd/delete.c
5873fa
+++ b/ldap/servers/slapd/delete.c
5873fa
@@ -236,6 +236,9 @@ op_shared_delete(Slapi_PBlock *pb)
5873fa
     slapi_pblock_get(pb, SLAPI_OPERATION, &operation);
5873fa
     internal_op = operation_is_flag_set(operation, OP_FLAG_INTERNAL);
5873fa
 
5873fa
+    /* Set the time we actually started the operation */
5873fa
+    slapi_operation_set_time_started(operation);
5873fa
+
5873fa
     sdn = slapi_sdn_new_dn_byval(rawdn);
5873fa
     dn = slapi_sdn_get_dn(sdn);
5873fa
     slapi_pblock_set(pb, SLAPI_DELETE_TARGET_SDN, (void *)sdn);
5873fa
diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c
5873fa
index 259bedfff..a186dbde3 100644
5873fa
--- a/ldap/servers/slapd/modify.c
5873fa
+++ b/ldap/servers/slapd/modify.c
5873fa
@@ -626,6 +626,9 @@ op_shared_modify(Slapi_PBlock *pb, int pw_change, char *old_pw)
5873fa
     slapi_pblock_get(pb, SLAPI_SKIP_MODIFIED_ATTRS, &skip_modified_attrs);
5873fa
     slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
5873fa
 
5873fa
+    /* Set the time we actually started the operation */
5873fa
+    slapi_operation_set_time_started(operation);
5873fa
+
5873fa
     if (sdn) {
5873fa
         passin_sdn = 1;
5873fa
     } else {
5873fa
diff --git a/ldap/servers/slapd/modrdn.c b/ldap/servers/slapd/modrdn.c
5873fa
index 3efe584a7..e04916b83 100644
5873fa
--- a/ldap/servers/slapd/modrdn.c
5873fa
+++ b/ldap/servers/slapd/modrdn.c
5873fa
@@ -417,6 +417,9 @@ op_shared_rename(Slapi_PBlock *pb, int passin_args)
5873fa
     internal_op = operation_is_flag_set(operation, OP_FLAG_INTERNAL);
5873fa
     slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
5873fa
 
5873fa
+    /* Set the time we actually started the operation */
5873fa
+    slapi_operation_set_time_started(operation);
5873fa
+
5873fa
     /*
5873fa
      * If ownership has not been passed to this function, we replace the
5873fa
      * string input fields within the pblock with strdup'd copies.  Why?
5873fa
diff --git a/ldap/servers/slapd/operation.c b/ldap/servers/slapd/operation.c
5873fa
index ff16cd906..4dd3481c7 100644
5873fa
--- a/ldap/servers/slapd/operation.c
5873fa
+++ b/ldap/servers/slapd/operation.c
5873fa
@@ -651,3 +651,27 @@ slapi_operation_time_expiry(Slapi_Operation *o, time_t timeout, struct timespec
5873fa
 {
5873fa
     slapi_timespec_expire_rel(timeout, &(o->o_hr_time_rel), expiry);
5873fa
 }
5873fa
+
5873fa
+/* Set the time the operation actually started */
5873fa
+void
5873fa
+slapi_operation_set_time_started(Slapi_Operation *o)
5873fa
+{
5873fa
+	clock_gettime(CLOCK_MONOTONIC, &(o->o_hr_time_started_rel));
5873fa
+}
5873fa
+
5873fa
+/* The time diff of how long the operation took once it actually started */
5873fa
+void
5873fa
+slapi_operation_op_time_elapsed(Slapi_Operation *o, struct timespec *elapsed)
5873fa
+{
5873fa
+    struct timespec o_hr_time_now;
5873fa
+    clock_gettime(CLOCK_MONOTONIC, &o_hr_time_now);
5873fa
+
5873fa
+    slapi_timespec_diff(&o_hr_time_now, &(o->o_hr_time_started_rel), elapsed);
5873fa
+}
5873fa
+
5873fa
+/* The time diff the operation waited in the work queue */
5873fa
+void
5873fa
+slapi_operation_workq_time_elapsed(Slapi_Operation *o, struct timespec *elapsed)
5873fa
+{
5873fa
+    slapi_timespec_diff(&(o->o_hr_time_started_rel), &(o->o_hr_time_rel), elapsed);
5873fa
+}
5873fa
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
5873fa
index 9fe78655c..c0bc5dcd0 100644
5873fa
--- a/ldap/servers/slapd/opshared.c
5873fa
+++ b/ldap/servers/slapd/opshared.c
5873fa
@@ -284,6 +284,9 @@ op_shared_search(Slapi_PBlock *pb, int send_result)
5873fa
     slapi_pblock_get(pb, SLAPI_SEARCH_TARGET_SDN, &sdn;;
5873fa
     slapi_pblock_get(pb, SLAPI_OPERATION, &operation);
5873fa
 
5873fa
+    /* Set the time we actually started the operation */
5873fa
+    slapi_operation_set_time_started(operation);
5873fa
+
5873fa
     if (NULL == sdn) {
5873fa
         sdn = slapi_sdn_new_dn_byval(base);
5873fa
         slapi_pblock_set(pb, SLAPI_SEARCH_TARGET_SDN, sdn);
5873fa
diff --git a/ldap/servers/slapd/result.c b/ldap/servers/slapd/result.c
5873fa
index 0b13c30e9..61efb6f8d 100644
5873fa
--- a/ldap/servers/slapd/result.c
5873fa
+++ b/ldap/servers/slapd/result.c
5873fa
@@ -1975,6 +1975,8 @@ log_result(Slapi_PBlock *pb, Operation *op, int err, ber_tag_t tag, int nentries
5873fa
     CSN *operationcsn = NULL;
5873fa
     char csn_str[CSN_STRSIZE + 5];
5873fa
     char etime[ETIME_BUFSIZ] = {0};
5873fa
+    char wtime[ETIME_BUFSIZ] = {0};
5873fa
+    char optime[ETIME_BUFSIZ] = {0};
5873fa
     int pr_idx = -1;
5873fa
     int pr_cookie = -1;
5873fa
     uint32_t operation_notes;
5873fa
@@ -1982,19 +1984,26 @@ log_result(Slapi_PBlock *pb, Operation *op, int err, ber_tag_t tag, int nentries
5873fa
     int32_t op_id;
5873fa
     int32_t op_internal_id;
5873fa
     int32_t op_nested_count;
5873fa
+    struct timespec o_hr_time_end;
5873fa
 
5873fa
     get_internal_conn_op(&connid, &op_id, &op_internal_id, &op_nested_count);
5873fa
-
5873fa
     slapi_pblock_get(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx);
5873fa
     slapi_pblock_get(pb, SLAPI_PAGED_RESULTS_COOKIE, &pr_cookie);
5873fa
-
5873fa
     internal_op = operation_is_flag_set(op, OP_FLAG_INTERNAL);
5873fa
 
5873fa
-    struct timespec o_hr_time_end;
5873fa
+    /* total elapsed time */
5873fa
     slapi_operation_time_elapsed(op, &o_hr_time_end);
5873fa
+    snprintf(etime, ETIME_BUFSIZ, "%" PRId64 ".%.09" PRId64 "", (int64_t)o_hr_time_end.tv_sec, (int64_t)o_hr_time_end.tv_nsec);
5873fa
+
5873fa
+    /* wait time */
5873fa
+    slapi_operation_workq_time_elapsed(op, &o_hr_time_end);
5873fa
+    snprintf(wtime, ETIME_BUFSIZ, "%" PRId64 ".%.09" PRId64 "", (int64_t)o_hr_time_end.tv_sec, (int64_t)o_hr_time_end.tv_nsec);
5873fa
+
5873fa
+    /* op time */
5873fa
+    slapi_operation_op_time_elapsed(op, &o_hr_time_end);
5873fa
+    snprintf(optime, ETIME_BUFSIZ, "%" PRId64 ".%.09" PRId64 "", (int64_t)o_hr_time_end.tv_sec, (int64_t)o_hr_time_end.tv_nsec);
5873fa
 
5873fa
 
5873fa
-    snprintf(etime, ETIME_BUFSIZ, "%" PRId64 ".%.09" PRId64 "", (int64_t)o_hr_time_end.tv_sec, (int64_t)o_hr_time_end.tv_nsec);
5873fa
 
5873fa
     operation_notes = slapi_pblock_get_operation_notes(pb);
5873fa
 
5873fa
@@ -2025,16 +2034,16 @@ log_result(Slapi_PBlock *pb, Operation *op, int err, ber_tag_t tag, int nentries
5873fa
         if (!internal_op) {
5873fa
             slapi_log_access(LDAP_DEBUG_STATS,
5873fa
                              "conn=%" PRIu64 " op=%d RESULT err=%d"
5873fa
-                             " tag=%" BERTAG_T " nentries=%d etime=%s%s%s"
5873fa
+                             " tag=%" BERTAG_T " nentries=%d wtime=%s optime=%s etime=%s%s%s"
5873fa
                              ", SASL bind in progress\n",
5873fa
                              op->o_connid,
5873fa
                              op->o_opid,
5873fa
                              err, tag, nentries,
5873fa
-                             etime,
5873fa
+                             wtime, optime, etime,
5873fa
                              notes_str, csn_str);
5873fa
         } else {
5873fa
 
5873fa
-#define LOG_SASLMSG_FMT " tag=%" BERTAG_T " nentries=%d etime=%s%s%s, SASL bind in progress\n"
5873fa
+#define LOG_SASLMSG_FMT " tag=%" BERTAG_T " nentries=%d wtime=%s optime=%s etime=%s%s%s, SASL bind in progress\n"
5873fa
             slapi_log_access(LDAP_DEBUG_ARGS,
5873fa
                              connid == 0 ? LOG_CONN_OP_FMT_INT_INT LOG_SASLMSG_FMT :
5873fa
                                            LOG_CONN_OP_FMT_EXT_INT LOG_SASLMSG_FMT,
5873fa
@@ -2043,7 +2052,7 @@ log_result(Slapi_PBlock *pb, Operation *op, int err, ber_tag_t tag, int nentries
5873fa
                              op_internal_id,
5873fa
                              op_nested_count,
5873fa
                              err, tag, nentries,
5873fa
-                             etime,
5873fa
+                             wtime, optime, etime,
5873fa
                              notes_str, csn_str);
5873fa
         }
5873fa
     } else if (op->o_tag == LDAP_REQ_BIND && err == LDAP_SUCCESS) {
5873fa
@@ -2057,15 +2066,15 @@ log_result(Slapi_PBlock *pb, Operation *op, int err, ber_tag_t tag, int nentries
5873fa
         if (!internal_op) {
5873fa
             slapi_log_access(LDAP_DEBUG_STATS,
5873fa
                              "conn=%" PRIu64 " op=%d RESULT err=%d"
5873fa
-                             " tag=%" BERTAG_T " nentries=%d etime=%s%s%s"
5873fa
+                             " tag=%" BERTAG_T " nentries=%d wtime=%s optime=%s etime=%s%s%s"
5873fa
                              " dn=\"%s\"\n",
5873fa
                              op->o_connid,
5873fa
                              op->o_opid,
5873fa
                              err, tag, nentries,
5873fa
-                             etime,
5873fa
+                             wtime, optime, etime,
5873fa
                              notes_str, csn_str, dn ? dn : "");
5873fa
         } else {
5873fa
-#define LOG_BINDMSG_FMT " tag=%" BERTAG_T " nentries=%d etime=%s%s%s dn=\"%s\"\n"
5873fa
+#define LOG_BINDMSG_FMT " tag=%" BERTAG_T " nentries=%d wtime=%s optime=%s etime=%s%s%s dn=\"%s\"\n"
5873fa
             slapi_log_access(LDAP_DEBUG_ARGS,
5873fa
                              connid == 0 ? LOG_CONN_OP_FMT_INT_INT LOG_BINDMSG_FMT :
5873fa
                                            LOG_CONN_OP_FMT_EXT_INT LOG_BINDMSG_FMT,
5873fa
@@ -2074,7 +2083,7 @@ log_result(Slapi_PBlock *pb, Operation *op, int err, ber_tag_t tag, int nentries
5873fa
                              op_internal_id,
5873fa
                              op_nested_count,
5873fa
                              err, tag, nentries,
5873fa
-                             etime,
5873fa
+                             wtime, optime, etime,
5873fa
                              notes_str, csn_str, dn ? dn : "");
5873fa
         }
5873fa
         slapi_ch_free((void **)&dn;;
5873fa
@@ -2083,15 +2092,15 @@ log_result(Slapi_PBlock *pb, Operation *op, int err, ber_tag_t tag, int nentries
5873fa
             if (!internal_op) {
5873fa
                 slapi_log_access(LDAP_DEBUG_STATS,
5873fa
                                  "conn=%" PRIu64 " op=%d RESULT err=%d"
5873fa
-                                 " tag=%" BERTAG_T " nentries=%d etime=%s%s%s"
5873fa
+                                 " tag=%" BERTAG_T " nentries=%d wtime=%s optime=%s etime=%s%s%s"
5873fa
                                  " pr_idx=%d pr_cookie=%d\n",
5873fa
                                  op->o_connid,
5873fa
                                  op->o_opid,
5873fa
                                  err, tag, nentries,
5873fa
-                                 etime,
5873fa
+                                 wtime, optime, etime,
5873fa
                                  notes_str, csn_str, pr_idx, pr_cookie);
5873fa
             } else {
5873fa
-#define LOG_PRMSG_FMT " tag=%" BERTAG_T " nentries=%d etime=%s%s%s pr_idx=%d pr_cookie=%d \n"
5873fa
+#define LOG_PRMSG_FMT " tag=%" BERTAG_T " nentries=%d wtime=%s optime=%s etime=%s%s%s pr_idx=%d pr_cookie=%d \n"
5873fa
                 slapi_log_access(LDAP_DEBUG_ARGS,
5873fa
                                  connid == 0 ? LOG_CONN_OP_FMT_INT_INT LOG_PRMSG_FMT :
5873fa
                                                LOG_CONN_OP_FMT_EXT_INT LOG_PRMSG_FMT,
5873fa
@@ -2100,7 +2109,7 @@ log_result(Slapi_PBlock *pb, Operation *op, int err, ber_tag_t tag, int nentries
5873fa
                                  op_internal_id,
5873fa
                                  op_nested_count,
5873fa
                                  err, tag, nentries,
5873fa
-                                 etime,
5873fa
+                                 wtime, optime, etime,
5873fa
                                  notes_str, csn_str, pr_idx, pr_cookie);
5873fa
             }
5873fa
         } else if (!internal_op) {
5873fa
@@ -2114,11 +2123,11 @@ log_result(Slapi_PBlock *pb, Operation *op, int err, ber_tag_t tag, int nentries
5873fa
             }
5873fa
             slapi_log_access(LDAP_DEBUG_STATS,
5873fa
                              "conn=%" PRIu64 " op=%d RESULT err=%d"
5873fa
-                             " tag=%" BERTAG_T " nentries=%d etime=%s%s%s%s\n",
5873fa
+                             " tag=%" BERTAG_T " nentries=%d wtime=%s optime=%s etime=%s%s%s%s\n",
5873fa
                              op->o_connid,
5873fa
                              op->o_opid,
5873fa
                              err, tag, nentries,
5873fa
-                             etime,
5873fa
+                             wtime, optime, etime,
5873fa
                              notes_str, csn_str, ext_str);
5873fa
             if (pbtxt) {
5873fa
                 /* if !pbtxt ==> ext_str == "".  Don't free ext_str. */
5873fa
@@ -2126,7 +2135,7 @@ log_result(Slapi_PBlock *pb, Operation *op, int err, ber_tag_t tag, int nentries
5873fa
             }
5873fa
         } else {
5873fa
             int optype;
5873fa
-#define LOG_MSG_FMT " tag=%" BERTAG_T " nentries=%d etime=%s%s%s\n"
5873fa
+#define LOG_MSG_FMT " tag=%" BERTAG_T " nentries=%d wtime=%s optime=%s etime=%s%s%s\n"
5873fa
             slapi_log_access(LDAP_DEBUG_ARGS,
5873fa
                              connid == 0 ? LOG_CONN_OP_FMT_INT_INT LOG_MSG_FMT :
5873fa
                                            LOG_CONN_OP_FMT_EXT_INT LOG_MSG_FMT,
5873fa
@@ -2135,7 +2144,7 @@ log_result(Slapi_PBlock *pb, Operation *op, int err, ber_tag_t tag, int nentries
5873fa
                              op_internal_id,
5873fa
                              op_nested_count,
5873fa
                              err, tag, nentries,
5873fa
-                             etime,
5873fa
+                             wtime, optime, etime,
5873fa
                              notes_str, csn_str);
5873fa
             /*
5873fa
              *  If this is an unindexed search we should log it in the error log if
5873fa
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
5873fa
index cef8c789c..8e76393c3 100644
5873fa
--- a/ldap/servers/slapd/slap.h
5873fa
+++ b/ldap/servers/slapd/slap.h
5873fa
@@ -1538,16 +1538,17 @@ typedef struct slapi_operation_results
5873fa
  */
5873fa
 typedef struct op
5873fa
 {
5873fa
-    BerElement *o_ber;             /* ber of the request          */
5873fa
-    ber_int_t o_msgid;             /* msgid of the request          */
5873fa
-    ber_tag_t o_tag;               /* tag of the request          */
5873fa
+    BerElement *o_ber;             /* ber of the request */
5873fa
+    ber_int_t o_msgid;             /* msgid of the request */
5873fa
+    ber_tag_t o_tag;               /* tag of the request */
5873fa
     struct timespec o_hr_time_rel; /* internal system time op initiated */
5873fa
     struct timespec o_hr_time_utc; /* utc system time op initiated */
5873fa
-    int o_isroot;                  /* requestor is manager          */
5873fa
+    struct timespec o_hr_time_started_rel; /* internal system time op started */
5873fa
+    int o_isroot;                  /* requestor is manager */
5873fa
     Slapi_DN o_sdn;                /* dn bound when op was initiated */
5873fa
-    char *o_authtype;              /* auth method used to bind dn      */
5873fa
+    char *o_authtype;              /* auth method used to bind dn */
5873fa
     int o_ssf;                     /* ssf for this operation (highest between SASL and TLS/SSL) */
5873fa
-    int o_opid;                    /* id of this operation          */
5873fa
+    int o_opid;                    /* id of this operation */
5873fa
     PRUint64 o_connid;             /* id of conn initiating this op; for logging only */
5873fa
     void *o_handler_data;
5873fa
     result_handler o_result_handler;
5873fa
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
5873fa
index 834a98742..8d9c3fa6a 100644
5873fa
--- a/ldap/servers/slapd/slapi-plugin.h
5873fa
+++ b/ldap/servers/slapd/slapi-plugin.h
5873fa
@@ -8210,13 +8210,29 @@ void slapi_operation_time_elapsed(Slapi_Operation *o, struct timespec *elapsed);
5873fa
  */
5873fa
 void slapi_operation_time_initiated(Slapi_Operation *o, struct timespec *initiated);
5873fa
 /**
5873fa
- * Given an operation and a timeout, return a populate struct with the expiry
5873fa
- * time of the operation suitable for checking with slapi_timespec_expire_check
5873fa
+ * Given an operation, determine the time elapsed since the op
5873fa
+ * was actually started.
5873fa
  *
5873fa
- * \param Slapi_Operation o - the operation that is in progress
5873fa
- * \param time_t timeout the seconds relative to operation initiation to expiry at.
5873fa
- * \param struct timespec *expiry the timespec to popluate with the relative expiry.
5873fa
+ * \param Slapi_Operation o - the operation which is inprogress
5873fa
+ * \param struct timespec *elapsed - location where the time difference will be
5873fa
+ * placed.
5873fa
+ */
5873fa
+void slapi_operation_op_time_elapsed(Slapi_Operation *o, struct timespec *elapsed);
5873fa
+/**
5873fa
+ * Given an operation, determine the time elapsed that the op spent
5873fa
+ * in the work queue before actually being dispatched to a worker thread
5873fa
+ *
5873fa
+ * \param Slapi_Operation o - the operation which is inprogress
5873fa
+ * \param struct timespec *elapsed - location where the time difference will be
5873fa
+ * placed.
5873fa
+ */
5873fa
+void slapi_operation_workq_time_elapsed(Slapi_Operation *o, struct timespec *elapsed);
5873fa
+/**
5873fa
+ * Set the time the operation actually started
5873fa
+ *
5873fa
+ * \param Slapi_Operation o - the operation which is inprogress
5873fa
  */
5873fa
+void slapi_operation_set_time_started(Slapi_Operation *o);
5873fa
 #endif
5873fa
 
5873fa
 /**
5873fa
-- 
5873fa
2.26.2
5873fa