forked from Silverfish/proton-bridge
feat(BRIDGE-266): heartbeat telemetry update; extra integration tests;
This commit is contained in:
@ -24,6 +24,7 @@ import (
|
||||
|
||||
"github.com/ProtonMail/gluon/async"
|
||||
"github.com/ProtonMail/go-proton-api"
|
||||
"github.com/ProtonMail/proton-bridge/v3/internal/plan"
|
||||
"github.com/ProtonMail/proton-bridge/v3/internal/updater"
|
||||
)
|
||||
|
||||
@ -62,7 +63,7 @@ func newDistinctionUtility(ctx context.Context, panicHandler async.PanicHandler,
|
||||
|
||||
observabilitySender: observabilitySender,
|
||||
|
||||
userPlanUnsafe: planUnknown,
|
||||
userPlanUnsafe: plan.Unknown,
|
||||
|
||||
heartbeatData: heartbeatData{},
|
||||
heartbeatTicker: time.NewTicker(updateInterval),
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
package observability
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/gluon/async"
|
||||
@ -87,10 +87,6 @@ func (d *distinctionUtility) sendHeartbeat() {
|
||||
})
|
||||
}
|
||||
|
||||
func formatBool(value bool) string {
|
||||
return fmt.Sprintf("%t", value)
|
||||
}
|
||||
|
||||
// generateHeartbeatUserMetric creates the heartbeat user metric and includes the relevant data.
|
||||
func (d *distinctionUtility) generateHeartbeatUserMetric() proton.ObservabilityMetric {
|
||||
return generateHeartbeatMetric(
|
||||
@ -98,10 +94,10 @@ func (d *distinctionUtility) generateHeartbeatUserMetric() proton.ObservabilityM
|
||||
d.getEmailClientUserAgent(),
|
||||
getEnabled(d.settingsGetter.GetProxyAllowed()),
|
||||
getEnabled(d.getBetaAccessEnabled()),
|
||||
formatBool(d.heartbeatData.receivedOtherError),
|
||||
formatBool(d.heartbeatData.receivedSyncError),
|
||||
formatBool(d.heartbeatData.receivedEventLoopError),
|
||||
formatBool(d.heartbeatData.receivedGluonError),
|
||||
strconv.FormatBool(d.heartbeatData.receivedOtherError),
|
||||
strconv.FormatBool(d.heartbeatData.receivedSyncError),
|
||||
strconv.FormatBool(d.heartbeatData.receivedEventLoopError),
|
||||
strconv.FormatBool(d.heartbeatData.receivedGluonError),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -18,76 +18,9 @@
|
||||
package observability
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/ProtonMail/gluon/async"
|
||||
"github.com/ProtonMail/go-proton-api"
|
||||
"github.com/ProtonMail/proton-bridge/v3/internal/plan"
|
||||
)
|
||||
|
||||
const (
|
||||
planUnknown = "unknown"
|
||||
planOther = "other"
|
||||
planBusiness = "business"
|
||||
planIndividual = "individual"
|
||||
planGroup = "group"
|
||||
)
|
||||
|
||||
var planHierarchy = map[string]int{ //nolint:gochecknoglobals
|
||||
planBusiness: 4,
|
||||
planGroup: 3,
|
||||
planIndividual: 2,
|
||||
planOther: 1,
|
||||
planUnknown: 0,
|
||||
}
|
||||
|
||||
type planGetter interface {
|
||||
GetOrganizationData(ctx context.Context) (proton.OrganizationResponse, error)
|
||||
}
|
||||
|
||||
func isHigherPriority(currentPlan, newPlan string) bool {
|
||||
newRank, ok := planHierarchy[newPlan]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
currentRank, ok2 := planHierarchy[currentPlan]
|
||||
if !ok2 {
|
||||
return true // we don't have a valid plan, might as well replace it
|
||||
}
|
||||
|
||||
return newRank > currentRank
|
||||
}
|
||||
|
||||
func mapUserPlan(planName string) string {
|
||||
if planName == "" {
|
||||
return planUnknown
|
||||
}
|
||||
switch strings.TrimSpace(strings.ToLower(planName)) {
|
||||
case "mail2022":
|
||||
return planIndividual
|
||||
case "bundle2022":
|
||||
return planIndividual
|
||||
case "family2022":
|
||||
return planGroup
|
||||
case "visionary2022":
|
||||
return planGroup
|
||||
case "mailpro2022":
|
||||
return planBusiness
|
||||
case "planbiz2024":
|
||||
return planBusiness
|
||||
case "bundlepro2022":
|
||||
return planBusiness
|
||||
case "bundlepro2024":
|
||||
return planBusiness
|
||||
case "duo2024":
|
||||
return planGroup
|
||||
|
||||
default:
|
||||
return planOther
|
||||
}
|
||||
}
|
||||
|
||||
func (d *distinctionUtility) setUserPlan(planName string) {
|
||||
if planName == "" {
|
||||
return
|
||||
@ -96,24 +29,12 @@ func (d *distinctionUtility) setUserPlan(planName string) {
|
||||
d.userPlanLock.Lock()
|
||||
defer d.userPlanLock.Unlock()
|
||||
|
||||
userPlanMapped := mapUserPlan(planName)
|
||||
if isHigherPriority(d.userPlanUnsafe, userPlanMapped) {
|
||||
userPlanMapped := plan.MapUserPlan(planName)
|
||||
if plan.IsHigherPriority(d.userPlanUnsafe, userPlanMapped) {
|
||||
d.userPlanUnsafe = userPlanMapped
|
||||
}
|
||||
}
|
||||
|
||||
func (d *distinctionUtility) registerUserPlan(ctx context.Context, getter planGetter, panicHandler async.PanicHandler) {
|
||||
go func() {
|
||||
defer async.HandlePanic(panicHandler)
|
||||
|
||||
orgRes, err := getter.GetOrganizationData(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
d.setUserPlan(orgRes.Organization.PlanName)
|
||||
}()
|
||||
}
|
||||
|
||||
func (d *distinctionUtility) getUserPlanSafe() string {
|
||||
d.userPlanLock.Lock()
|
||||
defer d.userPlanLock.Unlock()
|
||||
|
||||
@ -250,7 +250,7 @@ func (s *Service) addMetricsIfClients(metric ...proton.ObservabilityMetric) {
|
||||
s.addMetrics(metric...)
|
||||
}
|
||||
|
||||
func (s *Service) RegisterUserClient(userID string, protonClient *proton.Client, telemetryService *telemetry.Service) {
|
||||
func (s *Service) RegisterUserClient(userID string, protonClient *proton.Client, telemetryService *telemetry.Service, userPlan string) {
|
||||
s.log.Info("Registering user client, ID:", userID)
|
||||
|
||||
s.withUserClientStoreLock(func() {
|
||||
@ -260,7 +260,7 @@ func (s *Service) RegisterUserClient(userID string, protonClient *proton.Client,
|
||||
}
|
||||
})
|
||||
|
||||
s.distinctionUtility.registerUserPlan(s.ctx, protonClient, s.panicHandler)
|
||||
s.distinctionUtility.setUserPlan(userPlan)
|
||||
|
||||
// There may be a case where we already have metric updates stored, so try to flush;
|
||||
s.sendSignal(s.signalDataArrived)
|
||||
|
||||
@ -20,15 +20,16 @@ package observability
|
||||
import (
|
||||
gluonMetrics "github.com/ProtonMail/gluon/observability/metrics"
|
||||
"github.com/ProtonMail/go-proton-api"
|
||||
"github.com/ProtonMail/proton-bridge/v3/internal/plan"
|
||||
)
|
||||
|
||||
func GenerateAllUsedDistinctionMetricPermutations() []proton.ObservabilityMetric {
|
||||
planValues := []string{
|
||||
planUnknown,
|
||||
planOther,
|
||||
planBusiness,
|
||||
planIndividual,
|
||||
planGroup}
|
||||
plan.Unknown,
|
||||
plan.Other,
|
||||
plan.Business,
|
||||
plan.Individual,
|
||||
plan.Group}
|
||||
mailClientValues := []string{
|
||||
emailAgentAppleMail,
|
||||
emailAgentOutlook,
|
||||
@ -58,11 +59,11 @@ func GenerateAllUsedDistinctionMetricPermutations() []proton.ObservabilityMetric
|
||||
|
||||
func GenerateAllHeartbeatMetricPermutations() []proton.ObservabilityMetric {
|
||||
planValues := []string{
|
||||
planUnknown,
|
||||
planOther,
|
||||
planBusiness,
|
||||
planIndividual,
|
||||
planGroup}
|
||||
plan.Unknown,
|
||||
plan.Other,
|
||||
plan.Business,
|
||||
plan.Individual,
|
||||
plan.Group}
|
||||
mailClientValues := []string{
|
||||
emailAgentAppleMail,
|
||||
emailAgentOutlook,
|
||||
|
||||
@ -104,8 +104,3 @@ func TestMatchUserAgent(t *testing.T) {
|
||||
require.Equal(t, testCase.result, matchUserAgent(testCase.agent))
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatBool(t *testing.T) {
|
||||
require.Equal(t, "false", formatBool(false))
|
||||
require.Equal(t, "true", formatBool(true))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user