]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_log.h
import ceph 16.2.7
[ceph.git] / ceph / src / rgw / rgw_log.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
3
4 #ifndef CEPH_RGW_LOG_H
5 #define CEPH_RGW_LOG_H
6
7 #include <boost/container/flat_map.hpp>
8 #include "rgw_common.h"
9 #include "common/OutputDataSocket.h"
10 #include <vector>
11 #include <fstream>
12
13 #define dout_subsys ceph_subsys_rgw
14
15 class RGWRados;
16
17 struct rgw_log_entry {
18
19 using headers_map = boost::container::flat_map<std::string, std::string>;
20 using Clock = req_state::Clock;
21
22 rgw_user object_owner;
23 rgw_user bucket_owner;
24 string bucket;
25 Clock::time_point time;
26 string remote_addr;
27 string user;
28 rgw_obj_key obj;
29 string op;
30 string uri;
31 string http_status;
32 string error_code;
33 uint64_t bytes_sent = 0;
34 uint64_t bytes_received = 0;
35 uint64_t obj_size = 0;
36 Clock::duration total_time{};
37 string user_agent;
38 string referrer;
39 string bucket_id;
40 headers_map x_headers;
41 string trans_id;
42 std::vector<string> token_claims;
43
44 void encode(bufferlist &bl) const {
45 ENCODE_START(11, 5, bl);
46 encode(object_owner.id, bl);
47 encode(bucket_owner.id, bl);
48 encode(bucket, bl);
49 encode(time, bl);
50 encode(remote_addr, bl);
51 encode(user, bl);
52 encode(obj.name, bl);
53 encode(op, bl);
54 encode(uri, bl);
55 encode(http_status, bl);
56 encode(error_code, bl);
57 encode(bytes_sent, bl);
58 encode(obj_size, bl);
59 encode(total_time, bl);
60 encode(user_agent, bl);
61 encode(referrer, bl);
62 encode(bytes_received, bl);
63 encode(bucket_id, bl);
64 encode(obj, bl);
65 encode(object_owner, bl);
66 encode(bucket_owner, bl);
67 encode(x_headers, bl);
68 encode(trans_id, bl);
69 encode(token_claims, bl);
70 ENCODE_FINISH(bl);
71 }
72 void decode(bufferlist::const_iterator &p) {
73 DECODE_START_LEGACY_COMPAT_LEN(11, 5, 5, p);
74 decode(object_owner.id, p);
75 if (struct_v > 3)
76 decode(bucket_owner.id, p);
77 decode(bucket, p);
78 decode(time, p);
79 decode(remote_addr, p);
80 decode(user, p);
81 decode(obj.name, p);
82 decode(op, p);
83 decode(uri, p);
84 decode(http_status, p);
85 decode(error_code, p);
86 decode(bytes_sent, p);
87 decode(obj_size, p);
88 decode(total_time, p);
89 decode(user_agent, p);
90 decode(referrer, p);
91 if (struct_v >= 2)
92 decode(bytes_received, p);
93 else
94 bytes_received = 0;
95
96 if (struct_v >= 3) {
97 if (struct_v <= 5) {
98 uint64_t id;
99 decode(id, p);
100 char buf[32];
101 snprintf(buf, sizeof(buf), "%" PRIu64, id);
102 bucket_id = buf;
103 } else {
104 decode(bucket_id, p);
105 }
106 } else {
107 bucket_id = "";
108 }
109 if (struct_v >= 7) {
110 decode(obj, p);
111 }
112 if (struct_v >= 8) {
113 decode(object_owner, p);
114 decode(bucket_owner, p);
115 }
116 if (struct_v >= 9) {
117 decode(x_headers, p);
118 }
119 if (struct_v >= 10) {
120 decode(trans_id, p);
121 }
122 if (struct_v >= 11) {
123 decode(token_claims, p);
124 }
125 DECODE_FINISH(p);
126 }
127 void dump(ceph::Formatter *f) const;
128 static void generate_test_instances(list<rgw_log_entry*>& o);
129 };
130 WRITE_CLASS_ENCODER(rgw_log_entry)
131
132 class OpsLogSink {
133 public:
134 virtual int log(struct req_state* s, struct rgw_log_entry& entry) = 0;
135 virtual ~OpsLogSink() = default;
136 };
137
138 class OpsLogManifold: public OpsLogSink {
139 std::vector<OpsLogSink*> sinks;
140 public:
141 ~OpsLogManifold() override;
142 void add_sink(OpsLogSink* sink);
143 int log(struct req_state* s, struct rgw_log_entry& entry) override;
144 };
145
146 class JsonOpsLogSink : public OpsLogSink {
147 ceph::Formatter *formatter;
148 ceph::mutex lock = ceph::make_mutex("JsonOpsLogSink");
149
150 void formatter_to_bl(bufferlist& bl);
151 protected:
152 virtual int log_json(struct req_state* s, bufferlist& bl) = 0;
153 public:
154 JsonOpsLogSink();
155 ~JsonOpsLogSink() override;
156 int log(struct req_state* s, struct rgw_log_entry& entry) override;
157 };
158
159 class OpsLogFile : public JsonOpsLogSink, public Thread, public DoutPrefixProvider {
160 CephContext* cct;
161 ceph::mutex log_mutex = ceph::make_mutex("OpsLogFile_log");
162 ceph::mutex flush_mutex = ceph::make_mutex("OpsLogFile_flush");
163 std::vector<bufferlist> log_buffer;
164 std::vector<bufferlist> flush_buffer;
165 ceph::condition_variable cond_flush;
166 std::ofstream file;
167 bool stopped;
168 uint64_t data_size;
169 uint64_t max_data_size;
170
171 void flush();
172 protected:
173 int log_json(struct req_state* s, bufferlist& bl) override;
174 void *entry() override;
175 public:
176 OpsLogFile(CephContext* cct, std::string& path, uint64_t max_data_size);
177 ~OpsLogFile() override;
178 CephContext *get_cct() const override { return cct; }
179 unsigned get_subsys() const override { return dout_subsys; }
180 std::ostream& gen_prefix(std::ostream& out) const override { return out << "rgw OpsLogFile: "; }
181 void start();
182 void stop();
183 };
184
185 class OpsLogSocket : public OutputDataSocket, public JsonOpsLogSink {
186 protected:
187 int log_json(struct req_state* s, bufferlist& bl) override;
188 void init_connection(bufferlist& bl) override;
189
190 public:
191 OpsLogSocket(CephContext *cct, uint64_t _backlog);
192 };
193
194 class OpsLogRados : public OpsLogSink {
195 RGWRados* store;
196 public:
197 OpsLogRados(RGWRados* store);
198 int log(struct req_state* s, struct rgw_log_entry& entry) override;
199 };
200
201 class RGWREST;
202
203 int rgw_log_op(RGWREST* const rest, struct req_state* s,
204 const std::string& op_name, OpsLogSink* olog);
205 void rgw_log_usage_init(CephContext *cct, RGWRados *store);
206 void rgw_log_usage_finalize();
207 void rgw_format_ops_log_entry(struct rgw_log_entry& entry,
208 ceph::Formatter *formatter);
209
210 #endif /* CEPH_RGW_LOG_H */
211