Skip to content

Commit

Permalink
feat: configure telemetry
Browse files Browse the repository at this point in the history
resolves #108
  • Loading branch information
PhearZero committed Feb 14, 2025
1 parent d8b44a6 commit dbeeb03
Show file tree
Hide file tree
Showing 23 changed files with 760 additions and 30 deletions.
1 change: 1 addition & 0 deletions cmd/configure/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ var Cmd = &cobra.Command{

func init() {
Cmd.AddCommand(serviceCmd)
Cmd.AddCommand(telemetryCmd)
}

const RunningErrorMsg = "algorand is currently running. Please stop the node with *node stop* before configuring"
Expand Down
16 changes: 0 additions & 16 deletions cmd/configure/network.go

This file was deleted.

17 changes: 5 additions & 12 deletions cmd/configure/service.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package configure

import (
"errors"
"github.com/algorandfoundation/nodekit/cmd/utils"
"github.com/algorandfoundation/nodekit/cmd/utils/explanations"
"github.com/algorandfoundation/nodekit/internal/algod"
"github.com/algorandfoundation/nodekit/internal/system"
"github.com/algorandfoundation/nodekit/ui/style"
"github.com/charmbracelet/lipgloss"
"github.com/spf13/cobra"
Expand All @@ -28,16 +27,10 @@ var serviceLong = lipgloss.JoinVertical(

// serviceCmd is a Cobra command for managing Algorand service files, requiring root privileges to ensure proper execution.
var serviceCmd = &cobra.Command{
Use: "service",
Short: serviceShort,
Long: serviceLong,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
if !system.IsSudo() {
return errors.New(
"you need to be root to run this command. Please run this command with sudo")
}
return nil
},
Use: "service",
Short: serviceShort,
Long: serviceLong,
PersistentPreRunE: utils.IsSudoCmd,
RunE: func(cmd *cobra.Command, args []string) error {
// TODO: Combine this with algod.UpdateService and algod.SetNetwork
return algod.EnsureService()
Expand Down
120 changes: 120 additions & 0 deletions cmd/configure/telemetry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package configure

import (
cmdutils "github.com/algorandfoundation/nodekit/cmd/utils"
"github.com/algorandfoundation/nodekit/cmd/utils/explanations"
"github.com/algorandfoundation/nodekit/internal/algod"
"github.com/algorandfoundation/nodekit/internal/algod/telemetry"
"github.com/algorandfoundation/nodekit/internal/algod/utils"
"github.com/algorandfoundation/nodekit/ui/style"
"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/log"
"github.com/spf13/cobra"
)

var dataDir = ""
var telemetryEndpoint string
var telemetryName string
var telemetryDisable bool
var telemetryEnable bool

var telemetryShort = "Configure telemetry for the Algorand daemon"
var NodelyTelemetryWarning = "The default telemetry provider is Nodely."
var telemetryLong = lipgloss.JoinVertical(
lipgloss.Left,
style.Purple(style.BANNER),
"",
style.Bold(telemetryShort),
"",
style.BoldUnderline("Overview:"),
"When a node is run using the algod command, before the script starts the server,",
"it configures its telemetry based on the appropriate logging.config file.",
"When a node’s telemetry is enabled, a telemetry state is added to the node’s logger",
"reflecting the fields contained within the appropriate config file",
"",
style.Yellow.Render(NodelyTelemetryWarning),
)

var telemetryCmd = cmdutils.WithAlgodFlags(&cobra.Command{
Use: "telemetry",
Short: telemetryShort,
Long: telemetryLong,
PersistentPreRunE: cmdutils.IsSudoCmd,
Run: func(cmd *cobra.Command, args []string) {
log.Warn(style.Yellow.Render(explanations.SudoWarningMsg))
resolvedDir, err := algod.GetDataDir(dataDir)
if err != nil {
log.Fatal(err)
}

// Current Log Configuration
logConfig, _ := utils.GetLogConfigFromDataDir(resolvedDir)

hasDisable := cmd.Flags().Lookup("disable").Changed
hasEnabled := cmd.Flags().Lookup("enable").Changed
hasEndpoint := cmd.Flags().Lookup("endpoint").Changed
hasName := cmd.Flags().Lookup("name").Changed

hasFlags := hasDisable || hasEndpoint || hasName || hasEnabled

if hasFlags {
newConfig := telemetry.Config{
SendToLog: logConfig.SendToLog,
GUID: logConfig.GUID,
FilePath: logConfig.FilePath,
UserName: logConfig.UserName,
Password: logConfig.Password,
MinLogLevel: logConfig.MinLogLevel,
ReportHistoryLevel: logConfig.ReportHistoryLevel,
}
if hasEndpoint {
newConfig.URI = telemetryEndpoint
} else {
newConfig.URI = logConfig.URI
}
if hasName {
newConfig.Name = telemetryName
} else {
newConfig.Name = logConfig.Name
}

if hasDisable {
newConfig.Enable = false
} else if hasEnabled {
newConfig.Enable = true
} else {
newConfig.Enable = logConfig.Enable
}
mergeConfig := telemetry.MergeLogConfigs(*logConfig, newConfig)
if logConfig.IsEqual(mergeConfig) {
log.Debug("Configuration up to date, nothing to do")
} else {
logConfig = &mergeConfig
err := utils.WriteLogConfigToDataDir(resolvedDir, logConfig)
if err != nil {
log.Fatal(err)
}
}
}

log.Debug("Restarting node...")
err = algod.Stop()
if err != nil {
log.Fatal(err)
}
err = algod.Start()
if err != nil {
log.Fatal(err)
}
log.Debug("Node restarted successfully.")
},
}, &dataDir)

func init() {
telemetryCmd.Flags().BoolVarP(&telemetryDisable, "disable", "", false, "Disables telemetry")
telemetryCmd.Flags().BoolVarP(&telemetryEnable, "enable", "", false, "Enables telemetry")
telemetryCmd.MarkFlagsOneRequired("disable", "enable")
telemetryCmd.MarkFlagsMutuallyExclusive("disable", "enable")
telemetryCmd.Flags().StringVarP(&telemetryEndpoint, "endpoint", "e", string(cmdutils.NodelyTelemetryProvider), "Sets the \"URI\" property")
telemetryCmd.Flags().StringVarP(&telemetryName, "name", "n", "anon", "Enable Algorand remote logging with specified node name")
}
14 changes: 14 additions & 0 deletions cmd/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import (
cmdutils "github.com/algorandfoundation/nodekit/cmd/utils"
"github.com/algorandfoundation/nodekit/cmd/utils/explanations"
"github.com/algorandfoundation/nodekit/internal/algod"
"github.com/algorandfoundation/nodekit/internal/algod/telemetry"
"github.com/algorandfoundation/nodekit/internal/algod/utils"
"github.com/algorandfoundation/nodekit/internal/system"
"github.com/algorandfoundation/nodekit/ui/style"
"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/log"
"github.com/spf13/cobra"
"os/exec"
"strings"
)

// DebugInfo represents diagnostic information about
Expand All @@ -35,6 +37,9 @@ type DebugInfo struct {
Algod string `json:"algod"`

DataFolder utils.DataFolderConfig `json:"data"`

// Telemetry holds the configuration settings for telemetry, such as enabling, logging, reporting URI, and user details.
Telemetry telemetry.Config `json:"telemetry"`
}

// debugCmdShort provides a brief description of the "debug" command, which displays debugging information.
Expand Down Expand Up @@ -71,6 +76,14 @@ var debugCmd = cmdutils.WithAlgodFlags(&cobra.Command{
if err != nil {
return err
}

// Get the log configuration
logConfig, _ := utils.GetLogConfigFromDataDir(dataDir)
lenPassword := len(logConfig.Password)
if lenPassword > 0 {
logConfig.Password = strings.Repeat("*", lenPassword)
}

folderDebug, err := utils.ToDataFolderConfig(dataDir)
folderDebug.Token = folderDebug.Token[:3] + "..."
if err != nil {
Expand All @@ -83,6 +96,7 @@ var debugCmd = cmdutils.WithAlgodFlags(&cobra.Command{
IsInstalled: algod.IsInstalled(),
Algod: path,
DataFolder: folderDebug,
Telemetry: *logConfig,
}
data, err := json.MarshalIndent(info, "", " ")
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/algorandfoundation/nodekit/api"
"github.com/algorandfoundation/nodekit/cmd/catchup"
"github.com/algorandfoundation/nodekit/cmd/configure"
"github.com/algorandfoundation/nodekit/cmd/telemetry"
"github.com/algorandfoundation/nodekit/cmd/utils"
"github.com/algorandfoundation/nodekit/cmd/utils/explanations"
"github.com/algorandfoundation/nodekit/internal/algod"
Expand Down Expand Up @@ -139,6 +140,7 @@ func init() {
RootCmd.AddCommand(upgradeCmd)
RootCmd.AddCommand(catchup.Cmd)
RootCmd.AddCommand(configure.Cmd)
RootCmd.AddCommand(telemetry.Cmd)
}
}

Expand Down
30 changes: 30 additions & 0 deletions cmd/telemetry/disable/disable.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package disable

import (
"github.com/algorandfoundation/nodekit/cmd/utils/explanations"
"github.com/algorandfoundation/nodekit/ui/style"
"github.com/charmbracelet/lipgloss"
"github.com/spf13/cobra"
)

var Short = "Disable Telemetry"
var Long = lipgloss.JoinVertical(
lipgloss.Left,
style.Purple(style.BANNER),
"",
style.Bold(Short),
"",
style.BoldUnderline("Overview:"),
"Configure telemetry for the Algorand daemon.",
"",
style.Yellow.Render(explanations.ExperimentalWarning),
)
var Cmd = &cobra.Command{
Use: "disable",
Short: Short,
Long: Long,
}

func init() {
Cmd.AddCommand(nodelyCmd)
}
91 changes: 91 additions & 0 deletions cmd/telemetry/disable/nodely.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package disable

import (
"errors"
cmdutils "github.com/algorandfoundation/nodekit/cmd/utils"
"github.com/algorandfoundation/nodekit/cmd/utils/explanations"
"github.com/algorandfoundation/nodekit/internal/algod"
"github.com/algorandfoundation/nodekit/internal/algod/utils"
"github.com/algorandfoundation/nodekit/internal/system"
"github.com/algorandfoundation/nodekit/ui/style"
"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/log"
"github.com/spf13/cobra"
"os"
)

var nodelyShort = "Disable Nodely"
var nodelyLong = lipgloss.JoinVertical(
lipgloss.Left,
style.Purple(style.BANNER),
"",
style.Bold(nodelyShort),
"",
style.BoldUnderline("Overview:"),
"Nodely Telemetry is a free telemetry service offered by a third party (Nodely)",
"Enabling telemetry will configure your node to send health metrics to Nodely",
"Privacy note: Information about your node (including participating accounts and approximate geographic location) will be associated with an anonymous user identifier (GUID.)",
"Tip: Keep this GUID identifier private if you do not want this information to be linked to your identity.",
"",
style.Yellow.Render(explanations.ExperimentalWarning),
)

var dataDir string

const (
NodelyNotConfiguredErrorMsg = "nodely is not configured"
NodelyDisabledErrorMsg = "nodely is already disabled"
)

var nodelyQuestion = `
# Overview
Nodely Telemetry is a free telemetry service offered by a third party (Nodely)
Enabling telemetry will configure your node to send health metrics to Nodely
> Privacy note: Information about your node (including participating accounts and approximate geographic location) will be associated with an anonymous user identifier (GUID.)
> Tip: Keep this GUID identifier private if you do not want this information to be linked to your identity.
**Do you want to disable telemetry with the nodely provider? (y/n)**
`

var nodelyCmd = cmdutils.WithAlgodFlags(&cobra.Command{
Use: "nodely",
Short: nodelyShort,
Long: nodelyLong,
Run: func(cmd *cobra.Command, args []string) {
log.Warn(explanations.SudoWarningMsg)

// Resolve Data Directory
dataDir, err := algod.GetDataDir(dataDir)
if err != nil {
log.Fatal(err)
}

// Fetch configuration
config, err := utils.GetLogConfigFromDataDir(dataDir)
cobra.CheckErr(err)

// Error if already disabled
if !config.Enable && config.URI == string(cmdutils.NodelyTelemetryProvider) {
log.Fatal(errors.New(NodelyDisabledErrorMsg))
}
cmd.Println(style.BANNER)

answer := cmdutils.Prompt(nodelyQuestion)
if answer {
// Get the path to nodekit
path, err := os.Executable()
if err != nil {
log.Fatal(err)
}

// Elevated Configuration
err = system.RunAll(system.CmdsList{{"sudo", path, "configure", "telemetry", "--disable"}})
if err != nil {
log.Fatal(err)
}
}
},
}, &dataDir)
30 changes: 30 additions & 0 deletions cmd/telemetry/enable/enable.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package enable

import (
"github.com/algorandfoundation/nodekit/cmd/utils/explanations"
"github.com/algorandfoundation/nodekit/ui/style"
"github.com/charmbracelet/lipgloss"
"github.com/spf13/cobra"
)

var Short = "Enable Telemetry"
var Long = lipgloss.JoinVertical(
lipgloss.Left,
style.Purple(style.BANNER),
"",
style.Bold(Short),
"",
style.BoldUnderline("Overview:"),
"Configure telemetry for the Algorand daemon.",
"",
style.Yellow.Render(explanations.ExperimentalWarning),
)
var Cmd = &cobra.Command{
Use: "enable",
Short: Short,
Long: Long,
}

func init() {
Cmd.AddCommand(nodelyCmd)
}
Loading

0 comments on commit dbeeb03

Please sign in to comment.