<commit_before>package ddevapp

import (
	"fmt"
	"github.com/denisbrodbeck/machineid"
	"github.com/drud/ddev/pkg/globalconfig"
	"github.com/drud/ddev/pkg/nodeps"
	"github.com/drud/ddev/pkg/output"
	"github.com/drud/ddev/pkg/version"
	"gopkg.in/segmentio/analytics-go.v3"
	"os"
	"runtime"
	"strconv"
	"time"
)

var hashedHostID string

// ReportableEvents is the list of events that we choose to report specifically.
// Excludes non-ddev custom commands.
var ReportableEvents = map[string]bool{"auth": true, "composer": true, "config": true, "debug": true, "delete": true, "describe": true, "exec": true, "export-db": true, "import-db": true, "import-files": true, "launch": true, "list": true, "logs": true, "mysql": true, "pause": true, "poweroff": true, "pull": true, "restart": true, "restore-snapshot": true, "sequelpro": true, "share": true, "snapshot": true, "ssh": true, "start": true, "stop": true, "xdebug": true}

// GetInstrumentationUser normally gets just the hashed hostID but if
// an explicit user is provided in global_config.yaml that will be prepended.
func GetInstrumentationUser() string {
	return hashedHostID
}

// SetInstrumentationBaseTags sets the basic always-used tags for Segment
func SetInstrumentationBaseTags() {
	if globalconfig.DdevGlobalConfig.InstrumentationOptIn {
		dockerVersion, _ := version.GetDockerVersion()
		composeVersion, _ := version.GetDockerComposeVersion()
		isToolbox := nodeps.IsDockerToolbox()

		nodeps.InstrumentationTags["OS"] = runtime.GOOS
		nodeps.InstrumentationTags["dockerVersion"] = dockerVersion
		nodeps.InstrumentationTags["dockerComposeVersion"] = composeVersion
		nodeps.InstrumentationTags["dockerToolbox"] = strconv.FormatBool(isToolbox)
		nodeps.InstrumentationTags["version"] = version.VERSION
		nodeps.InstrumentationTags["ServerHash"] = GetInstrumentationUser()
	}
}

// SetInstrumentationAppTags creates app-specific tags for Segment
func (app *DdevApp) SetInstrumentationAppTags() {
	ignoredProperties := []string{"approot", "hostname", "hostnames", "httpurl", "httpsurl", "httpURLs", "httpsURLs", "primary_url", "mailhog_url", "mailhog_https_url", "name", "phpmyadmin_url", "phpmyadmin_http_url", "router_status_log", "shortroot", "urls"}

	if globalconfig.DdevGlobalConfig.InstrumentationOptIn {
		describeTags, _ := app.Describe()
		for key, val := range describeTags {
			if !nodeps.ArrayContainsString(ignoredProperties, key) {
				nodeps.InstrumentationTags[key] = fmt.Sprintf("%v", val)
			}
		}
	}
}

// SegmentUser does the enqueue of the Identify action, identifying the user
// Here we just use the hashed hostid as the user id
func SegmentUser(client analytics.Client, hashedID string) error {
	timezone, _ := time.Now().In(time.Local).Zone()
	lang := os.Getenv("LANG")
	err := client.Enqueue(analytics.Identify{
		UserId:  hashedID,<commit_msg>Add ProjectHash to segment reporting, fixes #2193 (#2198)<commit_after>package ddevapp

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"github.com/denisbrodbeck/machineid"
	"github.com/drud/ddev/pkg/globalconfig"
	"github.com/drud/ddev/pkg/nodeps"
	"github.com/drud/ddev/pkg/output"
	"github.com/drud/ddev/pkg/version"
	"gopkg.in/segmentio/analytics-go.v3"
	"os"
	"runtime"
	"strconv"
	"time"
)

var hashedHostID string

// ReportableEvents is the list of events that we choose to report specifically.
// Excludes non-ddev custom commands.
var ReportableEvents = map[string]bool{"auth": true, "composer": true, "config": true, "debug": true, "delete": true, "describe": true, "exec": true, "export-db": true, "import-db": true, "import-files": true, "launch": true, "list": true, "logs": true, "mysql": true, "pause": true, "poweroff": true, "pull": true, "restart": true, "restore-snapshot": true, "sequelpro": true, "share": true, "snapshot": true, "ssh": true, "start": true, "stop": true, "xdebug": true}

// GetInstrumentationUser normally gets just the hashed hostID but if
// an explicit user is provided in global_config.yaml that will be prepended.
func GetInstrumentationUser() string {
	return hashedHostID
}

// SetInstrumentationBaseTags sets the basic always-used tags for Segment
func SetInstrumentationBaseTags() {
	if globalconfig.DdevGlobalConfig.InstrumentationOptIn {
		dockerVersion, _ := version.GetDockerVersion()
		composeVersion, _ := version.GetDockerComposeVersion()
		isToolbox := nodeps.IsDockerToolbox()

		nodeps.InstrumentationTags["OS"] = runtime.GOOS
		nodeps.InstrumentationTags["dockerVersion"] = dockerVersion
		nodeps.InstrumentationTags["dockerComposeVersion"] = composeVersion
		nodeps.InstrumentationTags["dockerToolbox"] = strconv.FormatBool(isToolbox)
		nodeps.InstrumentationTags["version"] = version.VERSION
		nodeps.InstrumentationTags["ServerHash"] = GetInstrumentationUser()
	}
}

// getProjectHash combines the machine ID and project name and then
// hashes the result, so we can end up with a unique project id
func getProjectHash(projectName string) string {
	ph := hmac.New(sha256.New, []byte(GetInstrumentationUser()+projectName))
	_, _ = ph.Write([]byte("phash"))
	return hex.EncodeToString(ph.Sum(nil))
}

// SetInstrumentationAppTags creates app-specific tags for Segment
func (app *DdevApp) SetInstrumentationAppTags() {
	ignoredProperties := []string{"approot", "hostname", "hostnames", "httpurl", "httpsurl", "httpURLs", "httpsURLs", "primary_url", "mailhog_url", "mailhog_https_url", "name", "phpmyadmin_url", "phpmyadmin_http_url", "router_status_log", "shortroot", "urls"}

	if globalconfig.DdevGlobalConfig.InstrumentationOptIn {
		describeTags, _ := app.Describe()
		for key, val := range describeTags {
			if !nodeps.ArrayContainsString(ignoredProperties, key) {
				nodeps.InstrumentationTags[key] = fmt.Sprintf("%v", val)
			}
		}
	}
	nodeps.InstrumentationTags["ProjectID"] = getProjectHash(app.Name)
}

// SegmentUser does the enqueue of the Identify action, identifying the user
// Here we just use the hashed hostid as the user id
func SegmentUser(client analytics.Client, hashedID string) error {
	timezone, _ := time.Now().In(time.Local).Zone()
	lang := os.Getenv("LANG")
	err := client.Enqueue(analytics.Identify{
		UserId:  hashedID,
{'fraction_non_alphanumeric': 0.13652597402597402, 'fraction_numerical': 0.0025974025974025974, 'mean_word_length': 5.807734806629834, 'pattern_counts': {'":': 52, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1982384', 'n_tokens_mistral': 2094, 'n_tokens_neox': 2021, 'n_words': 484}