1
#pragma once
2

            
3
#include <string>
4

            
5
#include "envoy/http/async_client.h"
6

            
7
#include "source/common/common/logger.h"
8
#include "source/common/upstream/cluster_update_tracker.h"
9

            
10
#include "absl/container/flat_hash_map.h"
11
#include "datadog/http_client.h"
12
#include "nlohmann/json.hpp"
13

            
14
namespace Envoy {
15
namespace Extensions {
16
namespace Tracers {
17
namespace Datadog {
18

            
19
struct TracerStats;
20

            
21
/**
22
 * \c datadog::tracing::HTTPClient implementation that uses Envoy's
23
 * \c Http::AsyncClient. The class is called \c AgentHTTPClient because it is
24
 * not a general-purpose HTTP client. Instead, it sends requests to a specified
25
 * cluster only. The idea is that the cluster is configured to point to a
26
 * Datadog Agent instance.
27
 */
28
class AgentHTTPClient : public datadog::tracing::HTTPClient,
29
                        public Http::AsyncClient::Callbacks,
30
                        private Logger::Loggable<Logger::Id::tracing> {
31
public:
32
  struct Handlers {
33
    ResponseHandler on_response;
34
    ErrorHandler on_error;
35
  };
36

            
37
public:
38
  /**
39
   * Create an  \c AgentHTTPClient that uses the specified \p cluster_manager
40
   * to make requests to the specified \p cluster, where requests include the
41
   * specified \p reference_host as the "Host" header. Use the specified
42
   * \p stats to keep track of usage statistics.
43
   * @param cluster_manager cluster manager from which the thread local cluster
44
   * is retrieved in order to make HTTP requests
45
   * @param cluster the name of the cluster to which HTTP requests are made
46
   * @param reference_host the value to use for the "Host" HTTP request header
47
   * @param stats a collection of counters used to keep track of events, such as
48
   * when a request fails
49
   * @param time_source clocks used for calculating request timeouts
50
   */
51
  AgentHTTPClient(Upstream::ClusterManager& cluster_manager, const std::string& cluster,
52
                  const std::string& reference_host, TracerStats& stats, TimeSource& time_source);
53
  ~AgentHTTPClient() override;
54

            
55
  // datadog::tracing::HTTPClient
56

            
57
  /**
58
   * Send an HTTP POST request to the cluster, where the requested resource is
59
   * \p url.path. Invoke \p set_headers immediately to obtain the HTTP request
60
   * headers. Send \p body as the request body. Return a
61
   * \c datadog::tracing::Error if one occurs, otherwise return
62
   * \c datadog::tracing::nullopt. When a complete response is received,
63
   * invoke \p on_response with the response status, response headers, and
64
   * response body. If an error occurs before a complete response is received,
65
   * invoke \p on_error with a \c datadog::tracing::Error.
66
   * @param url URL from which the request path is taken
67
   * @param set_headers callback invoked immediately to obtain request headers
68
   * @param body data to send as POST request body
69
   * @param on_response callback to invoke when a complete response is received
70
   * @param on_error callback to invoke when an error occurs before a complete
71
   * response is received
72
   * @param deadline time after which a response is not expected
73
   * @return \c datadog::tracing::Error if an error occurs, or
74
   * \c datadog::tracing::nullopt otherwise
75
   */
76
  datadog::tracing::Expected<void> post(const URL& url, HeadersSetter set_headers, std::string body,
77
                                        ResponseHandler on_response, ErrorHandler on_error,
78
                                        std::chrono::steady_clock::time_point deadline) override;
79

            
80
  /**
81
   * \c drain has no effect. It's a part of the \c datadog::tracing::HTTPClient
82
   * that we do not need.
83
   */
84
  void drain(std::chrono::steady_clock::time_point) override;
85

            
86
  /**
87
   * Implementation of the required config() method from datadog::tracing::HTTPClient.
88
   */
89
  std::string config() const override;
90

            
91
  /**
92
   * Return a JSON representation of this object's configuration. This function
93
   * is used in the startup banner logged by \c dd-trace-cpp.
94
   */
95
  const nlohmann::json& config_json() const;
96

            
97
  // Http::AsyncClient::Callbacks
98

            
99
  void onSuccess(const Http::AsyncClient::Request&, Http::ResponseMessagePtr&&) override;
100
  void onFailure(const Http::AsyncClient::Request&, Http::AsyncClient::FailureReason) override;
101
  void onBeforeFinalizeUpstreamSpan(Tracing::Span&, const Http::ResponseHeaderMap*) override;
102

            
103
private:
104
  absl::flat_hash_map<Http::AsyncClient::Request*, Handlers> handlers_;
105
  Upstream::ClusterUpdateTracker collector_cluster_;
106
  const std::string cluster_;
107
  const std::string reference_host_;
108
  TracerStats& stats_;
109
  TimeSource& time_source_;
110
};
111

            
112
} // namespace Datadog
113
} // namespace Tracers
114
} // namespace Extensions
115
} // namespace Envoy