lightshuttle_otel/
config.rs1use std::collections::HashMap;
4
5use lightshuttle_runtime::{ContainerSpec, ImageSource, PortBinding};
6
7pub const SYNTHETIC_RESOURCE_NAME: &str = "lightshuttle_otel";
11
12const DEFAULT_OTLP_GRPC_PORT: u16 = 4317;
14
15const DEFAULT_OTLP_HTTP_PORT: u16 = 4318;
17
18const DEFAULT_IMAGE: &str = "otel/opentelemetry-collector:0.108.0";
20
21#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct CollectorConfig {
27 pub image: String,
29 pub otlp_grpc_port: u16,
31 pub otlp_http_port: u16,
33}
34
35impl CollectorConfig {
36 #[must_use]
39 pub fn defaults() -> Self {
40 Self {
41 image: DEFAULT_IMAGE.to_owned(),
42 otlp_grpc_port: DEFAULT_OTLP_GRPC_PORT,
43 otlp_http_port: DEFAULT_OTLP_HTTP_PORT,
44 }
45 }
46
47 #[must_use]
52 pub fn hostname(&self, project: &str) -> String {
53 format!("{project}_{SYNTHETIC_RESOURCE_NAME}")
54 }
55
56 #[must_use]
62 pub fn to_container_spec(&self, project: &str) -> ContainerSpec {
63 ContainerSpec {
64 name: format!("{project}_{SYNTHETIC_RESOURCE_NAME}"),
65 project: project.to_owned(),
66 resource: SYNTHETIC_RESOURCE_NAME.to_owned(),
67 image: ImageSource::Pull(self.image.clone()),
68 env: HashMap::new(),
69 ports: vec![
70 PortBinding {
71 container_port: DEFAULT_OTLP_GRPC_PORT,
72 host_address: Some("127.0.0.1".to_owned()),
73 host_port: self.otlp_grpc_port,
74 },
75 PortBinding {
76 container_port: DEFAULT_OTLP_HTTP_PORT,
77 host_address: Some("127.0.0.1".to_owned()),
78 host_port: self.otlp_http_port,
79 },
80 ],
81 volumes: Vec::new(),
82 command: None,
83 healthcheck: None,
92 working_dir: None,
93 }
94 }
95}
96
97impl Default for CollectorConfig {
98 fn default() -> Self {
99 Self::defaults()
100 }
101}
102
103#[cfg(test)]
104mod tests {
105 use super::*;
106
107 #[test]
108 fn defaults_match_otlp_standard_ports() {
109 let cfg = CollectorConfig::defaults();
110 assert_eq!(cfg.otlp_grpc_port, 4317);
111 assert_eq!(cfg.otlp_http_port, 4318);
112 assert!(cfg.image.starts_with("otel/opentelemetry-collector"));
113 }
114
115 #[test]
116 fn hostname_is_project_prefixed() {
117 let cfg = CollectorConfig::defaults();
118 assert_eq!(cfg.hostname("demo"), "demo_lightshuttle_otel");
119 }
120
121 #[test]
122 fn to_container_spec_publishes_both_otlp_ports() {
123 let cfg = CollectorConfig::defaults();
124 let spec = cfg.to_container_spec("demo");
125
126 assert_eq!(spec.name, "demo_lightshuttle_otel");
127 assert_eq!(spec.project, "demo");
128 assert_eq!(spec.resource, "lightshuttle_otel");
129 assert_eq!(spec.ports.len(), 2);
130 let host_ports: Vec<u16> = spec.ports.iter().map(|p| p.host_port).collect();
131 assert!(host_ports.contains(&4317));
132 assert!(host_ports.contains(&4318));
133 }
134}