2017-11-25 13:36:03 +01:00
package collector
import (
"bytes"
"encoding/base64"
"encoding/json"
"net"
"net/http"
"strconv"
"time"
"github.com/mitchellh/hashstructure"
2022-11-21 18:36:05 +01:00
"github.com/rs/zerolog/log"
2023-02-03 15:24:05 +01:00
"github.com/traefik/traefik/v3/pkg/config/static"
"github.com/traefik/traefik/v3/pkg/redactor"
"github.com/traefik/traefik/v3/pkg/version"
2017-11-25 13:36:03 +01:00
)
2022-05-03 15:54:08 +02:00
// collectorURL URL where the stats are sent.
2023-06-16 23:08:05 +02:00
const collectorURL = "https://collect.traefik.io/yYaUej3P42cziRVzv6T5w2aYy9po2Mrn"
2017-11-25 13:36:03 +01:00
2020-05-11 12:06:07 +02:00
// Collected data.
2017-11-25 13:36:03 +01:00
type data struct {
2024-08-28 15:00:06 +02:00
Version string ` json:"version" `
Codename string ` json:"codename" `
BuildDate string ` json:"buildDate" `
Configuration string ` json:"configuration" `
Hash string ` json:"hash" `
2017-11-25 13:36:03 +01:00
}
// Collect anonymous data.
2018-11-27 17:42:04 +01:00
func Collect ( staticConfiguration * static . Configuration ) error {
2022-05-03 15:54:08 +02:00
buf , err := createBody ( staticConfiguration )
2017-11-25 13:36:03 +01:00
if err != nil {
return err
}
2022-05-03 15:54:08 +02:00
resp , err := makeHTTPClient ( ) . Post ( collectorURL , "application/json; charset=utf-8" , buf )
if resp != nil {
_ = resp . Body . Close ( )
}
return err
}
func createBody ( staticConfiguration * static . Configuration ) ( * bytes . Buffer , error ) {
anonConfig , err := redactor . Anonymize ( staticConfiguration )
if err != nil {
return nil , err
}
2022-11-21 18:36:05 +01:00
log . Debug ( ) . Msgf ( "Anonymous stats sent to %s: %s" , collectorURL , anonConfig )
2017-11-25 13:36:03 +01:00
2018-11-27 17:42:04 +01:00
hashConf , err := hashstructure . Hash ( staticConfiguration , nil )
2017-11-25 13:36:03 +01:00
if err != nil {
2022-05-03 15:54:08 +02:00
return nil , err
2017-11-25 13:36:03 +01:00
}
data := & data {
Version : version . Version ,
Codename : version . Codename ,
BuildDate : version . BuildDate ,
Hash : strconv . FormatUint ( hashConf , 10 ) ,
Configuration : base64 . StdEncoding . EncodeToString ( [ ] byte ( anonConfig ) ) ,
}
buf := new ( bytes . Buffer )
2024-03-20 10:26:03 +01:00
err = json . NewEncoder ( buf ) . Encode ( data )
2017-11-25 13:36:03 +01:00
if err != nil {
2022-05-03 15:54:08 +02:00
return nil , err
2017-11-25 13:36:03 +01:00
}
2022-05-03 15:54:08 +02:00
return buf , err
2017-11-25 13:36:03 +01:00
}
func makeHTTPClient ( ) * http . Client {
dialer := & net . Dialer {
2019-03-18 11:30:07 +01:00
Timeout : 30 * time . Second ,
2017-11-25 13:36:03 +01:00
KeepAlive : 30 * time . Second ,
DualStack : true ,
}
transport := & http . Transport {
Proxy : http . ProxyFromEnvironment ,
DialContext : dialer . DialContext ,
IdleConnTimeout : 90 * time . Second ,
TLSHandshakeTimeout : 10 * time . Second ,
ExpectContinueTimeout : 1 * time . Second ,
}
return & http . Client { Transport : transport }
}