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
use crate::campaign::Campaign;

use std::collections::HashMap;

use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct Configuration {

    /// The server URL should look like `https://myhost.example.com/ci/cleaninsights.php`.
    pub server: String,

    /// The Matomo site ID to record this data for.
    #[serde(rename = "siteId")]
    pub site_id: u32,

    /// Connection timeout. OPTIONAL, defaults to 5 seconds.
    #[serde(default = "Configuration::default_timeout")]
    pub timeout: u64,

    /// The SDK uses a truncated exponential backoff strategy on server failures. So the delay until
    /// it retries will rise exponentially, until it reaches `max_retry_delay` seconds.
    ///
    /// OPTIONAL, defaults to 3600 seconds. (1 hour)
    #[serde(rename = "maxRetryDelay", default = "Configuration::default_max_retry_delay")]
    pub max_retry_delay: i64,

    /// The number in days of how long the SDK will try to keep sending old measurements. If the
    /// measurements become older than that, they will be purged.
    ///
    /// OPTIONAL, defaults to 100 days.
    #[serde(rename = "maxAgeOfOldData", default = "Configuration::default_max_age_of_old_data")]
    pub max_age_of_old_data: i64,

    /// Regulates, how often data persistence is done. OPTIONAL. Defaults to 10.
    ///
    /// If set to 1, every time something is tracked, *ALL* data is stored to disk. The more you track,
    /// the higher you should set this to avoid heavy load due to disk I/O.
    #[serde(rename = "persistEveryNTimes", default = "Configuration::default_persist_every_n_times")]
    pub persist_every_n_times: u32,

    /// When set to true, assumes consent for all campaigns and none for features.
    /// Only use this, when you're running on the server and don't measure anything users
    /// might need to give consent to!
    #[serde(rename = "serverSideAnonymousUsage", default = "Configuration::default_server_side_anonymous_usage")]
    pub server_side_anonymous_usage: bool,

    /// When set, CleanInsights SDK will print some debug output to STDOUT. OPTIONAL. Defaults to false.
    #[serde(default = "Configuration::default_debug")]
    pub debug: bool,

    /// Campaign configuration.
    pub campaigns: HashMap<String, Campaign>,
}

impl Configuration {

    /// Returns a configuration with the given `server`, `site_id` and `campaigns` and sane
    /// defaults for the other properties.
    ///
    /// # Arguments
    /// * server: The server URL should look like `https://myhost.example.com/ci/cleaninsights.php`.
    /// * site_id: The Matomo site ID to record this data for.
    /// * campaigns: Campaign configuration.
    ///
    /// # Defaults:
    /// * timeout: 5 seconds.
    /// * max_retry_delay: 3600 seconds.
    /// * max_age_of_old_data: 100 days.
    /// * persist_every_n_times: 10
    /// * server_side_anonymous_usage: false
    /// * debug: false
    pub fn new(server: String, site_id: u32, campaigns: HashMap<String, Campaign>) -> Configuration
    {
        Configuration {
            server, site_id, campaigns,
            timeout: Configuration::default_timeout(),
            max_retry_delay: Configuration::default_max_retry_delay(),
            max_age_of_old_data: Configuration::default_max_age_of_old_data(),
            persist_every_n_times: Configuration::default_persist_every_n_times(),
            server_side_anonymous_usage: Configuration::default_server_side_anonymous_usage(),
            debug: Configuration::default_debug() }
    }

    pub fn default_timeout() -> u64 { 5 }

    pub fn default_max_retry_delay() -> i64 { 3600 }

    pub fn default_max_age_of_old_data() -> i64 { 100 }

    pub fn default_persist_every_n_times() -> u32 { 10 }

    pub fn default_server_side_anonymous_usage() -> bool { false }

    pub fn default_debug() -> bool { false }
}

#[cfg(test)]
mod tests {
    use super::*;
    use chrono::{Utc, TimeZone};
    use crate::campaign::EventAggregationRule;

    #[test]
    fn new_configuration() {
        let campaign = Campaign {
            start: Utc.with_ymd_and_hms(2021, 1, 1, 0, 0, 0).unwrap(),
            end: Utc.with_ymd_and_hms(2021, 12, 31, 23, 59, 59).unwrap(),
            aggregation_period_length: 1,
            number_of_periods: 100,
            only_record_once: true,
            event_aggregation_rule: EventAggregationRule::Avg,
            strengthen_anonymity: false };

        let mut campaigns = HashMap::new();
        campaigns.insert(String::from("test"), campaign);

        let configuration = Configuration {
            server: "https://example.org/cleaninsights.php".to_string(),
            site_id: 12345,
            timeout: 20,
            max_retry_delay: 18000,
            max_age_of_old_data: 365,
            persist_every_n_times: 1,
            server_side_anonymous_usage: true,
            debug: true,
            campaigns };

        let json = serde_json::to_string(&configuration);

        assert_eq!(json.unwrap(),
                   "{\"server\":\"https://example.org/cleaninsights.php\",\"siteId\":12345,\"timeout\":20,\
                   \"maxRetryDelay\":18000,\"maxAgeOfOldData\":365,\"persistEveryNTimes\":1,\
                   \"serverSideAnonymousUsage\":true,\"debug\":true,\"campaigns\":{\"test\":{\
                   \"start\":\"2021-01-01T00:00:00Z\",\"end\":\"2021-12-31T23:59:59Z\",\
                   \"aggregationPeriodLength\":1,\"numberOfPeriods\":100,\"onlyRecordOnce\":true,\
                   \"eventAggregationRule\":\"avg\",\"strengthenAnonymity\":false}}}")
    }

    #[test]
    fn new_configuration_with_defaults() {
        let campaign = Campaign::new(
            Utc.with_ymd_and_hms(2021, 1, 1, 0, 0, 0).unwrap(),
            Utc.with_ymd_and_hms(2021, 12, 31, 23, 59, 59).unwrap(),
            1);

        let mut campaigns = HashMap::new();
        campaigns.insert(String::from("test"), campaign);

        let configuration = Configuration::new(
            String::from("https://example.org/cleaninsights.php"),
            12345,
            campaigns);

        let json = serde_json::to_string(&configuration);

        assert_eq!(json.unwrap(),
                   "{\"server\":\"https://example.org/cleaninsights.php\",\"siteId\":12345,\"timeout\":5,\
                   \"maxRetryDelay\":3600,\"maxAgeOfOldData\":100,\"persistEveryNTimes\":10,\
                   \"serverSideAnonymousUsage\":false,\"debug\":false,\"campaigns\":{\"test\":{\
                   \"start\":\"2021-01-01T00:00:00Z\",\"end\":\"2021-12-31T23:59:59Z\",\
                   \"aggregationPeriodLength\":1,\"numberOfPeriods\":1,\"onlyRecordOnce\":false,\
                   \"eventAggregationRule\":\"sum\",\"strengthenAnonymity\":false}}}")
    }
}