sozu-command-lib 1.1.1

configuration library to command a sozu instance
Documentation
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
syntax = "proto2";
package command;

// A message received by Sōzu to change its state or query information
message Request {
  oneof request_type {
    // This message tells Sōzu to dump the current proxy state (backends,
    // front domains, certificates, etc) as a list of JSON-serialized Requests,
    // separated by a 0 byte, to a file. This file can be used later
    // to bootstrap the proxy. This message is not forwarded to workers.
    // If the specified path is relative, it will be calculated relative to the current
    // working directory of the proxy.
    string save_state = 1;
    // load a state file, given its path
    string load_state = 2;
    // list the workers and their status
    ListWorkers list_workers = 4;
    // list the frontends, filtered by protocol and/or domain
    FrontendFilters list_frontends = 5;
    // list all listeners
    ListListeners list_listeners = 6;
    // launch a new worker
    // never implemented, the tag is unused and probably not needed
    // we may still implement it later with no paramater
    // the main process will automatically assign a new id to a new worker
    string launch_worker = 7;
    // upgrade the main process
    UpgradeMain upgrade_main = 8;
    // upgrade an existing worker, giving its id
    uint32 upgrade_worker = 9;
    // subscribe to proxy events
    SubscribeEvents subscribe_events = 10;
    // reload the configuration from the config file, or a new file
    // CHECK: this used to be an option. None => use the config file, Some(string) => path_to_file
    // make sure it works using "" and "path_to_file"
    string reload_configuration = 11;
    // give status of main process and all workers
    Status status = 12;
    // add a cluster
    Cluster add_cluster = 13;
    // remove a cluster giving its id
    string remove_cluster = 14;
    // add an HTTP frontend
    RequestHttpFrontend add_http_frontend = 15;
    // remove an HTTP frontend
    RequestHttpFrontend remove_http_frontend = 16;
    // add an HTTPS frontend
    RequestHttpFrontend add_https_frontend = 17;
    // remove an HTTPS frontend
    RequestHttpFrontend remove_https_frontend = 18;
    // add a certificate
    AddCertificate add_certificate = 19;
    // replace a certificate
    ReplaceCertificate replace_certificate = 20;
    // remove a certificate
    RemoveCertificate remove_certificate = 21;
    // add a TCP frontend
    RequestTcpFrontend add_tcp_frontend = 22;
    // remove a TCP frontend
    RequestTcpFrontend remove_tcp_frontend = 23;
    // add a backend
    AddBackend add_backend = 24;
    // remove a backend
    RemoveBackend remove_backend = 25;
    // add an HTTP listener
    HttpListenerConfig add_http_listener = 26;
    // add an HTTPS listener
    HttpsListenerConfig add_https_listener = 27;
    // add a TCP listener
    TcpListenerConfig add_tcp_listener = 28;
    // remove a listener
    RemoveListener remove_listener = 29;
    // activate a listener
    ActivateListener activate_listener = 30;
    // deactivate a listener
    DeactivateListener deactivate_listener = 31;
    // query a cluster by id
    string query_cluster_by_id = 35;
    // query clusters with a hostname and optional path
    QueryClusterByDomain query_clusters_by_domain = 36;
    // query clusters hashes
    QueryClustersHashes query_clusters_hashes = 37;
    // query metrics
    QueryMetricsOptions query_metrics = 38;
    // soft stop
    SoftStop soft_stop = 39;
    // hard stop
    HardStop hard_stop = 40;
    // enable, disable or clear the metrics 
    MetricsConfiguration configure_metrics = 41;
    // Change the logging level
    string Logging = 42;
    // Return the listen sockets
    ReturnListenSockets return_listen_sockets = 43;
    // Get certificates from the state (rather than from the workers)
    QueryCertificatesFilters query_certificates_from_the_state = 44;
    // Get certificates from the workers (rather than from the state)
    QueryCertificatesFilters query_certificates_from_workers = 45;
    // query the state about how many requests of each type has been received
    // since startup
    CountRequests count_requests = 46;
  }
}

message ListWorkers {}
message ListListeners {}
message UpgradeMain {}
message SubscribeEvents {}
message Status {}
message QueryClustersHashes {}
message SoftStop {}
message HardStop {}
message ReturnListenSockets {}
message CountRequests {}

// details of an HTTP listener
message HttpListenerConfig {
    required SocketAddress address = 1;
    optional SocketAddress public_address = 2;
    required bool expect_proxy = 5 [default = false];
    required string sticky_name = 6;
    // client inactive time, in seconds
    required uint32 front_timeout = 7 [default = 60];
    // backend server inactive time, in seconds
    required uint32 back_timeout = 8 [default = 30];
    // time to connect to the backend, in seconds
    required uint32 connect_timeout = 9 [default = 3];
    // max time to send a complete request, in seconds
    required uint32 request_timeout = 10 [default = 10];
    // wether the listener is actively listening on its socket
    required bool active = 11 [default = false];
    optional CustomHttpAnswers http_answers = 12;
}

// details of an HTTPS listener
message HttpsListenerConfig {
    required SocketAddress address = 1;
    optional SocketAddress public_address = 2;
    required bool expect_proxy = 5 [default = false];
    required string sticky_name = 6;
    // client inactive time, in seconds
    required uint32 front_timeout = 7 [default = 60];
    // backend server inactive time, in seconds
    required uint32 back_timeout = 8 [default = 30];
    // time to connect to the backend, in seconds
    required uint32 connect_timeout = 9 [default = 3];
    // max time to send a complete request, in seconds
    required uint32 request_timeout = 10 [default = 10];
    // wether the listener is actively listening on its socket
    required bool active = 11 [default = false];
    // TLS versions
    repeated TlsVersion versions = 12;
    repeated string cipher_list = 13;
    repeated string cipher_suites = 14;
    repeated string signature_algorithms = 15;
    repeated string groups_list = 16;
    optional string certificate = 17;
    repeated string certificate_chain = 18;
    optional string key = 19;
    // Number of TLS 1.3 tickets to send to a client when establishing a connection.
    // The tickets allow the client to resume a session. This protects the client
    // agains session tracking. Defaults to 4.
    required uint64 send_tls13_tickets = 20;
    optional CustomHttpAnswers http_answers = 21;
}

// details of an TCP listener
message TcpListenerConfig {
    required SocketAddress address = 1;
    optional SocketAddress public_address = 2;
    required bool expect_proxy = 3 [default = false];
    // client inactive time, in seconds
    required uint32 front_timeout = 4 [default = 60];
    // backend server inactive time, in seconds
    required uint32 back_timeout = 5 [default = 30];
    // time to connect to the backend, in seconds
    required uint32 connect_timeout = 6 [default = 3];
    // wether the listener is actively listening on its socket
    required bool active = 7 [default = false];
}

// custom HTTP answers, useful for 404, 503 pages
message CustomHttpAnswers {
    // MovedPermanently
    optional string answer_301 = 1;
    // BadRequest
    optional string answer_400 = 2;
    // Unauthorized
    optional string answer_401 = 3;
    // NotFound
    optional string answer_404 = 4;
    // RequestTimeout
    optional string answer_408 = 5;
    // PayloadTooLarge
    optional string answer_413 = 6;
    // BadGateway
    optional string answer_502 = 7;
    // ServiceUnavailable
    optional string answer_503 = 8;
    // GatewayTimeout
    optional string answer_504 = 9;
    // InsufficientStorage
    optional string answer_507 = 10;

}

message ActivateListener {
    required SocketAddress address = 1;
    required ListenerType proxy = 2;
    required bool from_scm = 3;
}

message DeactivateListener {
    required SocketAddress address = 1;
    required ListenerType proxy = 2;
    required bool to_scm = 3;
}

message RemoveListener {
    required SocketAddress address = 1;
    required ListenerType proxy = 2;
}

enum ListenerType {
    HTTP = 0;
    HTTPS = 1;
    TCP = 2;
}

// All listeners, listed
message ListenersList {
    // address -> http listener config
    map<string, HttpListenerConfig> http_listeners = 1;
    // address -> https listener config
    map<string, HttpsListenerConfig> https_listeners = 2;
    // address -> tcp listener config
    map<string, TcpListenerConfig> tcp_listeners = 3;
}

// An HTTP or HTTPS frontend, as order to, or received from, Sōzu
message RequestHttpFrontend {
    optional string cluster_id = 1;
    required SocketAddress address = 2;
    required string hostname = 3;
    required PathRule path = 4;
    optional string method = 5;
    required RulePosition position = 6 [default = TREE];
    // custom tags to identify the frontend in the access logs
    map<string, string> tags = 7;
}

message RequestTcpFrontend {
    required string cluster_id = 1;
    // the socket address on which to listen for incoming traffic
    required SocketAddress address = 2;
    // custom tags to identify the frontend in the access logs
    map<string, string> tags = 3;
}

// list the frontends, filtered by protocol and/or domain
message FrontendFilters {
    required bool http = 1;
    required bool https = 2;
    required bool tcp = 3;
    optional string domain = 4;
}

// A filter for the path of incoming requests
message PathRule {
    // The kind of filter used for path rules
    required PathRuleKind kind = 1;
    // the value of the given prefix, regex or equal pathrule
    required string value = 2;
}

// The kind of filter used for path rules
enum PathRuleKind {
    // filters paths that start with a pattern, typically "/api"
    PREFIX = 0;
    // filters paths that match a regex pattern
    REGEX = 1;
    // filters paths that exactly match a pattern, no more, no less
    EQUALS = 2;
}

// TODO: find a proper definition for this
enum RulePosition {
    PRE = 0;
    POST = 1;
    TREE = 2;
}

// Add a new TLS certificate to an HTTPs listener
message AddCertificate {
    required SocketAddress address = 1;
    required CertificateAndKey certificate = 2;
    // A unix timestamp. Overrides certificate expiration.
    optional int64 expired_at = 3;
}

message RemoveCertificate {
    required SocketAddress address = 1;
    // a hex-encoded TLS fingerprint to identify the certificate to remove
    required string fingerprint = 2;
}

message ReplaceCertificate {
    required SocketAddress address = 1;
    required CertificateAndKey new_certificate = 2;
    // a hex-encoded TLS fingerprint to identify the old certificate
    required string old_fingerprint = 3;
    // A unix timestamp. Overrides certificate expiration.
    optional int64 new_expired_at = 4;
}

message CertificateAndKey {
    required string certificate = 1;
    repeated string certificate_chain = 2;
    required string key = 3;
    repeated TlsVersion versions = 4;
    // a list of domain names. Override certificate names
    // if empty, the names of the certificate will be used
    repeated string names = 5;
}

// Should be either a domain name or a fingerprint.
// These filter do not compound, use either one but not both.
// If none of them is specified, all certificates will be returned.
message QueryCertificatesFilters {
    // a domain name to filter certificate results
    optional string domain = 1;
    // a hex-encoded fingerprint of the TLS certificate to find
    optional string fingerprint = 2;
}

// domain name and fingerprint of a certificate
message CertificateSummary {
    required string domain = 1;
    // a hex-encoded TLS fingerprint
    required string fingerprint = 2;
}

// Used by workers to reply to some certificate queries
message ListOfCertificatesByAddress {
    repeated CertificatesByAddress certificates = 1;
}

// Summaries of certificates for a given address
message CertificatesByAddress {
    required SocketAddress address = 1;
    repeated CertificateSummary certificate_summaries = 2;
}

// to reply to several certificate queries
message CertificatesWithFingerprints {
    // a map of fingerprint -> certificate_and_key
    map<string, CertificateAndKey> certs = 1;
}

enum TlsVersion {
    SSL_V2 = 0;
    SSL_V3 = 1;
    TLS_V1_0 = 2;
    TLS_V1_1 = 3;
    TLS_V1_2 = 4;
    TLS_V1_3 = 5;
}

// A cluster is what binds a frontend to backends with routing rules
message Cluster {
    required string cluster_id = 1;
    // wether a connection from a client shall be always redirected to the same backend
    required bool sticky_session = 2;
    required bool https_redirect = 3;
    optional ProxyProtocolConfig proxy_protocol = 4;
    required LoadBalancingAlgorithms load_balancing = 5 [default = ROUND_ROBIN];
    optional string answer_503 = 6;
    optional LoadMetric load_metric = 7;
}

enum LoadBalancingAlgorithms {
    ROUND_ROBIN = 0;
    RANDOM = 1;
    LEAST_LOADED = 2;
    POWER_OF_TWO = 3;
}

enum ProxyProtocolConfig {
    EXPECT_HEADER = 0;
    SEND_HEADER = 1;
    RELAY_HEADER = 2;
}

// how sozu measures which backend is less loaded
enum LoadMetric {
    // number of TCP connections
    CONNECTIONS = 0;
    // number of active HTTP requests
    REQUESTS = 1;
    // time to connect to the backend, weighted by the number of active connections (peak EWMA)
    CONNECTION_TIME = 2;
}

// add a backend
message AddBackend {
    required string cluster_id = 1;
    required string backend_id = 2;
    // the socket address of the backend
    required SocketAddress address = 3;
    optional string sticky_id = 4;
    optional LoadBalancingParams load_balancing_parameters = 5;
    optional bool backup = 6;
}

// remove an existing backend
message RemoveBackend {
    required string cluster_id = 1;
    required string backend_id = 2;
    // the socket address of the backend
    required SocketAddress address = 3 ;
}

message LoadBalancingParams {
    required int32 weight = 1;
}

message QueryClusterByDomain {
    required string hostname = 1;
    optional string path = 2;
}

// Options when querying metrics
message QueryMetricsOptions {
    // query a list of available metrics
    required bool list = 1;
    // query metrics for these clusters
    repeated string cluster_ids = 2;
    // query metrics for these backends
    repeated string backend_ids = 3;
    // query only these metrics
    repeated string metric_names = 4;
    // query only worker and main process metrics (no cluster metrics)
    required bool no_clusters = 5;
    // display metrics of each worker, without flattening (takes more space)
    required bool workers = 6;
}

// options to configure metrics collection
enum MetricsConfiguration {
    // enable metrics collection
    ENABLED = 0;
    // disable metrics collection
    DISABLED = 1;
    // wipe the metrics memory
    CLEAR = 2;
}

// Response to a request
message Response {
    // wether the request was a success, a failure, or is processing
    required ResponseStatus status = 1 [default = FAILURE];
    // a success or error message
    required string message = 2;
    // response data, if any
    optional ResponseContent content = 3;
}


// content of a response
message ResponseContent {
    oneof content_type {
        // a list of workers, with ids, pids, statuses
        WorkerInfos workers = 1;
        // aggregated metrics of main process and workers
        AggregatedMetrics metrics = 2;
        // a collection of worker responses to the same request
        WorkerResponses worker_responses = 3;
        // a proxy event
        Event event = 4;
        // a filtered list of frontend
        ListedFrontends frontend_list = 5;
        // all listeners
        ListenersList listeners_list = 6;
        // contains proxy & cluster metrics
        WorkerMetrics worker_metrics = 7;
        // Lists of metrics that are available
        AvailableMetrics available_metrics = 8;
        // a list of cluster informations
        ClusterInformations clusters = 9;
        // collection of hashes of cluster information, 
        ClusterHashes cluster_hashes = 10;
        // a list of certificates summaries, grouped by socket address
        ListOfCertificatesByAddress certificates_by_address = 11;
        // a map of complete certificates using fingerprints as key
        CertificatesWithFingerprints certificates_with_fingerprints = 12;
        // a census of the types of requests received since startup,
        RequestCounts request_counts = 13;
    }
}

// a map of worker_id -> ResponseContent
message WorkerResponses {
    map<string, ResponseContent> map = 1;
}

// lists of frontends present in the state
message ListedFrontends {
    repeated RequestHttpFrontend http_frontends = 1;
    repeated RequestHttpFrontend https_frontends = 2;
    repeated RequestTcpFrontend tcp_frontends = 3;
}

message ClusterInformations {
    repeated ClusterInformation vec = 1;
}

// Information about a given cluster
// Contains types usually used in requests, because they are readily available in protobuf
message ClusterInformation {
    optional Cluster configuration = 1;
    repeated RequestHttpFrontend http_frontends = 2;
    repeated RequestHttpFrontend https_frontends = 3;
    repeated RequestTcpFrontend tcp_frontends = 4;
    repeated AddBackend backends = 5;
}

// an event produced by a worker to notify about backends status
message Event {
    required EventKind kind = 1;
    optional string cluster_id = 2;
    optional string backend_id = 3;
    optional SocketAddress address = 4;
}

enum EventKind {
    BACKEND_DOWN = 0;
    BACKEND_UP = 1;
    NO_AVAILABLE_BACKENDS = 2;
    REMOVED_BACKEND_HAS_NO_CONNECTIONS = 3;
}

message ClusterHashes {
    // cluster id -> hash of cluster information
    map<string, uint64> map = 1;
}

enum ResponseStatus {
    OK = 0;
    PROCESSING = 1;
    FAILURE = 2;
}

// A list of worker infos
message WorkerInfos {
    repeated WorkerInfo vec = 1;
}

// Information about a worker with id, pid, runstate
message WorkerInfo {
    required uint32 id = 1;
    required int32 pid = 2;
    required RunState run_state = 3;
}

// Runstate of a worker
enum RunState {
    RUNNING = 0;
    STOPPING = 1;
    STOPPED = 2;
    NOT_ANSWERING = 3;
}

// lists of available metrics in a worker, or in the main process (in which case there are no cluster metrics)
message AvailableMetrics {
    repeated string proxy_metrics = 1;
    repeated string cluster_metrics = 2;
}

// Aggregated metrics of main process & workers
message AggregatedMetrics {
    // metrics about the main process.
    // metric_name -> metric_value
    map<string, FilteredMetrics> main = 1;
    // details of worker metrics, with clusters and backends.
    // worker_id -> worker_metrics
    map<string, WorkerMetrics> workers = 2;
    // if present, contains metrics of clusters and their backends, merged across all workers.
    // cluster_id -> cluster_metrics
    map<string, ClusterMetrics> clusters = 3;
    // if present, proxying metrics, merged accross all workers.
    // metric_name -> metric_value
    map<string, FilteredMetrics> proxying = 4;
}

// All metrics of a worker: proxy and clusters
// Populated by Options so partial results can be sent
message WorkerMetrics {
   // Metrics of the worker process, key -> value
    map<string, FilteredMetrics> proxy = 1;
    // cluster_id -> cluster_metrics
    map<string, ClusterMetrics> clusters = 2;
}

// the metrics of a given cluster, with several backends
message ClusterMetrics {
    // metric name -> metric value
    map<string, FilteredMetrics> cluster = 1;
    // list of backends with their metrics
    repeated BackendMetrics backends = 2;
}

message BackendMetrics {
    required string backend_id = 1;
    map<string, FilteredMetrics> metrics = 2;
}

// A metric, in a "filtered" format, which means: sendable to outside programs.
message FilteredMetrics {
    oneof inner {
        // increases or decrease depending on the state
        uint64 gauge = 1;
        // increases only
        int64 count = 2;
        // milliseconds
        uint64 time = 3;
        Percentiles percentiles = 4;
        FilteredTimeSerie time_serie = 5;
        FilteredHistogram histogram = 6;
    }
}

message FilteredTimeSerie {
    required uint32 last_second = 1;
    repeated uint32 last_minute = 2;
    repeated uint32 last_hour = 3;
}

message Percentiles {
    required uint64 samples = 1;
    required uint64 p_50 = 2;
    required uint64 p_90 = 3;
    required uint64 p_99 = 4;
    required uint64 p_99_9 = 5;
    required uint64 p_99_99 = 6;
    required uint64 p_99_999 = 7;
    required uint64 p_100 = 8;
    required uint64 sum = 9;
}

// a histogram meant to be translated to prometheus
message FilteredHistogram {
    required uint64 sum = 1;
    required uint64 count = 2;
    repeated Bucket buckets = 3;
}

// a prometheus histogram bucket
message Bucket {
    required uint64 count = 1;
    // upper range of the bucket (le = less or equal)
    required uint64 le = 2;
}

message RequestCounts {
    map<string, int32> map = 1;
}

// matches std::net::SocketAddr in the Rust library
// beware that the ports are expressed with uint32 here,
// but they should NOT exceed uint16 value
message SocketAddress {
    required IpAddress ip = 1;
    required uint32 port = 2;
}

message IpAddress {
    oneof inner {
        fixed32 v4 = 1;
        Uint128 v6 = 2;
    }
}

// used to represent the 128 bits of an IPv6 address
message Uint128 {
    // higher value, first 8 bytes of the ip
    required uint64 low = 1;
    // lower value, last 8 bytes of the ip
    required uint64 high = 2;
}

// This is sent only from Sōzu to Sōzu
message WorkerRequest {
    required string id = 1;
    required Request content = 2;
}

// A response as sent by a worker
message WorkerResponse {
    required string id = 1;
    required ResponseStatus status = 2;
    // an associated message to detail failure, success or processing
    required string message = 3;
    optional ResponseContent content = 4;
}

// intended to workers
message ServerMetricsConfig {
    required string address = 1;
    required bool tagged_metrics = 2;
    optional string prefix = 3;
}

// Used by a worker to start its server loop.
// The defaults should match those of the config module
message ServerConfig {
    required uint64 max_connections = 1 [default = 10000];
    required uint32 front_timeout = 2 [default = 60];
    required uint32 back_timeout = 3 [default = 30];
    required uint32 connect_timeout = 4 [default = 3];
    required uint32 zombie_check_interval = 5 [default = 1800];
    required uint32 accept_queue_timeout = 6 [default = 60];
    required uint64 min_buffers = 7 [default = 1];
    required uint64 max_buffers = 8 [default = 1000];
    required uint64 buffer_size = 9 [default = 16393];
    required string log_level = 10 [default = "info"];
    required string log_target = 11 [default = "stdout"];
    optional string access_logs_target = 12;
    required uint64 command_buffer_size = 13 [default = 1000000];
    required uint64 max_command_buffer_size = 14 [default = 2000000];
    optional ServerMetricsConfig metrics = 15;
    required ProtobufAccessLogFormat access_log_format = 16;
    required bool log_colored = 17;
}

enum ProtobufAccessLogFormat {
    Ascii = 1;
    Protobuf = 2;
}

// Addresses of listeners, passed to new workers
message ListenersCount {
    // socket addresses of HTTP listeners
    repeated string http = 1;
    // socket addresses of HTTPS listeners
    repeated string tls = 2;
    // socket addresses of TCP listeners
    repeated string tcp = 3;
}

// the Sōzu state, passed to a new worker.
// Consists in a collection of worker requests
message InitialState {
    repeated WorkerRequest requests = 1;
}

message OpenTelemetry {
    required string trace_id = 1;
    required string span_id = 2;
    optional string parent_span_id = 3;
}

// An access log, meant to be passed to another agent
message ProtobufAccessLog {
    // error message if any
    optional string message = 1;
    // LogContext = request_id + cluster_id + backend_id
    required Uint128 request_id = 2;
    // id of the cluster (set of frontend, backend, routing rules)
    optional string cluster_id = 3;
    // id of the backend (the server to which the traffic is redirected)
    optional string backend_id = 4;
    // ip and port of the client
    optional SocketAddress session_address = 5;
    // socket address of the backend server
    optional SocketAddress backend_address = 6;
    // the protocol, with SSL/TLS version, for instance "HTTPS-TLS1.1"
    required string protocol = 7;
    // TCP or HTTP endpoint (method, path, context...)
    required ProtobufEndpoint endpoint = 8;
    // round trip time for the client (microseconds)
    optional uint64 client_rtt = 9;
    // round trip time for the backend (microseconds)
    optional uint64 server_rtt = 10;
    // time spent on a session (microseconds)
    required uint64 service_time = 13;
    // number of bytes received from the client
    required uint64 bytes_in = 14;
    // number of bytes written to the client
    required uint64 bytes_out = 15;
    // value of the User-Agent header, if any
    optional string user_agent = 16;
    // custom tags as key-values, for instance owner_id: MyOrganisation
    map<string, string> tags = 17;
    // short description of which process sends the log, for instance: "WRK-02"
    required string tag = 18;
    // POSIX timestamp, nanoseconds
    required Uint128 time = 19;
    // Entire time between first byte received and last byte of the response.
    // If a request ends abruptly before the last byte is transmitted,
    // the `request_time` produced is the time elapsed since the first byte received.
    optional uint64 request_time = 20;
    // time for the backend to respond (microseconds)
    optional uint64 response_time = 21;
    // OpenTelemetry tracing information
    optional OpenTelemetry otel = 22;
}

message ProtobufEndpoint {
    oneof inner {
        HttpEndpoint http = 1;
        TcpEndpoint tcp = 2;
    }
}

message HttpEndpoint {
    optional string method = 1;
    optional string authority = 2;
    optional string path = 3;
    // warning: this should be a u16 but protobuf only has uint32.
    // Make sure the value never exceeds u16 bounds.
    optional uint32 status = 4;
    optional string reason = 5;
}

message TcpEndpoint {}