File: report_queue.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (122 lines) | stat: -rw-r--r-- 4,676 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/reporting/client/report_queue.h"

#include <memory>
#include <string>
#include <utility>

#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/json/json_writer.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_functions.h"
#include "base/sequence_checker.h"
#include "base/strings/strcat.h"
#include "base/time/time.h"
#include "base/types/expected.h"
#include "base/values.h"
#include "components/reporting/proto/synced/record.pb.h"
#include "components/reporting/proto/synced/record_constants.pb.h"
#include "components/reporting/util/status.h"
#include "components/reporting/util/status_macros.h"
#include "components/reporting/util/statusor.h"

namespace reporting {

namespace {

StatusOr<std::string> ValueToJson(base::Value::Dict record) {
  std::string json_record;
  if (!base::JSONWriter::Write(record, &json_record)) {
    return base::unexpected(
        Status(error::INVALID_ARGUMENT,
               "Provided record was not convertable to a std::string"));
  }
  return json_record;
}

StatusOr<std::string> ProtoToString(
    std::unique_ptr<const google::protobuf::MessageLite> record) {
  std::string protobuf_record;
  if (!record->SerializeToString(&protobuf_record)) {
    return base::unexpected(
        Status(error::INVALID_ARGUMENT,
               "Unabled to serialize record to string. Most likely due to "
               "unset required fields."));
  }
  return protobuf_record;
}

void EnqueueResponded(ReportQueue::EnqueueCallback callback,
                      Destination destination,
                      Status status) {
  // Log the overall enqueue error status. Gives us insight to how the ERP is
  // performing in general.
  base::UmaHistogramEnumeration(ReportQueue::kEnqueueMetricsName, status.code(),
                                error::Code::MAX_VALUE);

  // Log the type of enqueue error (if any) for this destination. Gives us
  // insights as to what types of errors this destination experiences.
  base::UmaHistogramEnumeration(
      base::StrCat({ReportQueue::kEnqueueMetricsName, ".",
                    Destination_Name(destination)}),
      status.code(), error::Code::MAX_VALUE);

  // Log whether the enqueue succeeded or failed for this destination. Gives us
  // insight as to whether one destination experiences more failures than
  // others. If you find that a destination has more failures than other
  // destinations, it could mean several things:
  //
  // 1. That destination gets much more traffic and is naturally going to
  // experience more errors.
  //
  // 2. The code that enqueues records to that destination may be implemented
  // incorrectly.
  //
  // To dive further, look up the `Browser.ERP.EventEnqueueResult<Destination>`
  // UMA (logged above) to understand what types of errors the destination
  // experiences most often.
  const auto* const enqueue_destination_metrics_name =
      status.ok() ? ReportQueue::kEnqueueSuccessDestinationMetricsName
                  : ReportQueue::kEnqueueFailedDestinationMetricsName;
  base::UmaHistogramExactLinear(enqueue_destination_metrics_name,
                                static_cast<int>(destination),
                                Destination_ARRAYSIZE);
  std::move(callback).Run(std::move(status));
}
}  // namespace

ReportQueue::~ReportQueue() = default;

void ReportQueue::Enqueue(std::string record,
                          Priority priority,
                          ReportQueue::EnqueueCallback callback) const {
  AddProducedRecord(
      base::BindOnce([](std::string record)
                         -> StatusOr<std::string> { return std::move(record); },
                     std::move(record)),
      priority,
      base::BindOnce(&EnqueueResponded, std::move(callback), GetDestination()));
}

void ReportQueue::Enqueue(base::Value::Dict record,
                          Priority priority,
                          ReportQueue::EnqueueCallback callback) const {
  AddProducedRecord(
      base::BindOnce(&ValueToJson, std::move(record)), priority,
      base::BindOnce(&EnqueueResponded, std::move(callback), GetDestination()));
}

void ReportQueue::Enqueue(
    std::unique_ptr<const google::protobuf::MessageLite> record,
    Priority priority,
    ReportQueue::EnqueueCallback callback) const {
  AddProducedRecord(
      base::BindOnce(&ProtoToString, std::move(record)), priority,
      base::BindOnce(&EnqueueResponded, std::move(callback), GetDestination()));
}

}  // namespace reporting