Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- uses: actions/checkout@v3
with:
fetch-depth: 1
- uses: WillAbides/setup-go-faster@v1.8.0
- uses: actions/setup-go@v6
with:
go-version: ${{ matrix.go }}
- run: "go test -race ./..."
Expand Down
3 changes: 2 additions & 1 deletion cmd/cli/ad_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import (
hh "github.com/microsoft/wmi/pkg/hardware/host"

"github.com/Control-D-Inc/ctrld"
"github.com/Control-D-Inc/ctrld/internal/system"
)

// addExtraSplitDnsRule adds split DNS rule for domain if it's part of active directory.
func addExtraSplitDnsRule(cfg *ctrld.Config) bool {
domain, err := getActiveDirectoryDomain()
domain, err := system.GetActiveDirectoryDomain()
if err != nil {
mainLog.Load().Debug().Msgf("unable to get active directory domain: %v", err)
return false
Expand Down
6 changes: 4 additions & 2 deletions cmd/cli/ad_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@ import (
"testing"
"time"

"github.com/stretchr/testify/assert"

"github.com/Control-D-Inc/ctrld"
"github.com/Control-D-Inc/ctrld/internal/system"
"github.com/Control-D-Inc/ctrld/testhelper"
"github.com/stretchr/testify/assert"
)

func Test_getActiveDirectoryDomain(t *testing.T) {
start := time.Now()
domain, err := getActiveDirectoryDomain()
domain, err := system.GetActiveDirectoryDomain()
if err != nil {
t.Fatal(err)
}
Expand Down
24 changes: 20 additions & 4 deletions cmd/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -642,13 +642,19 @@ func processCDFlags(cfg *ctrld.Config) (*controld.ResolverConfig, error) {
logger.Info().Msgf("fetching Controld D configuration from API: %s", cdUID)
bo := backoff.NewBackoff("processCDFlags", logf, 30*time.Second)
bo.LogLongerThan = 30 * time.Second

ctx := context.Background()
resolverConfig, err := controld.FetchResolverConfig(cdUID, rootCmd.Version, cdDev)
req := &controld.ResolverConfigRequest{
RawUID: cdUID,
Version: rootCmd.Version,
Metadata: ctrld.SystemMetadata(ctx),
}
resolverConfig, err := controld.FetchResolverConfig(req, cdDev)
for {
if errUrlNetworkError(err) {
bo.BackOff(ctx, err)
logger.Warn().Msg("could not fetch resolver using bootstrap DNS, retrying...")
resolverConfig, err = controld.FetchResolverConfig(cdUID, rootCmd.Version, cdDev)
resolverConfig, err = controld.FetchResolverConfig(req, cdDev)
continue
}
break
Expand Down Expand Up @@ -1516,7 +1522,12 @@ func cdUIDFromProvToken() string {
if customHostname != "" && !validHostname(customHostname) {
mainLog.Load().Fatal().Msgf("invalid custom hostname: %q", customHostname)
}
req := &controld.UtilityOrgRequest{ProvToken: cdOrg, Hostname: customHostname}

req := &controld.UtilityOrgRequest{
ProvToken: cdOrg,
Hostname: customHostname,
Metadata: ctrld.SystemMetadata(context.Background()),
}
// Process provision token if provided.
resolverConfig, err := controld.FetchResolverUID(req, rootCmd.Version, cdDev)
if err != nil {
Expand Down Expand Up @@ -1857,7 +1868,12 @@ func runningIface(s service.Service) *ifaceResponse {

// doValidateCdRemoteConfig fetches and validates custom config for cdUID.
func doValidateCdRemoteConfig(cdUID string, fatal bool) error {
rc, err := controld.FetchResolverConfig(cdUID, rootCmd.Version, cdDev)
req := &controld.ResolverConfigRequest{
RawUID: cdUID,
Version: rootCmd.Version,
Metadata: ctrld.SystemMetadata(context.Background()),
}
rc, err := controld.FetchResolverConfig(req, cdDev)
if err != nil {
logger := mainLog.Load().Fatal()
if !fatal {
Expand Down
7 changes: 6 additions & 1 deletion cmd/cli/control_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,12 @@ func (p *prog) registerControlServerHandler() {
}

// Re-fetch pin code from API.
if rc, err := controld.FetchResolverConfig(cdUID, rootCmd.Version, cdDev); rc != nil {
rcReq := &controld.ResolverConfigRequest{
RawUID: cdUID,
Version: rootCmd.Version,
Metadata: ctrld.SystemMetadata(context.Background()),
}
if rc, err := controld.FetchResolverConfig(rcReq, cdDev); rc != nil {
if rc.DeactivationPin != nil {
cdDeactivationPin.Store(*rc.DeactivationPin)
} else {
Expand Down
8 changes: 7 additions & 1 deletion cmd/cli/dns_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -954,7 +954,13 @@ func (p *prog) doSelfUninstall(answer *dns.Msg) {
logger := mainLog.Load().With().Str("mode", "self-uninstall").Logger()
if p.refusedQueryCount > selfUninstallMaxQueries {
p.checkingSelfUninstall = true
_, err := controld.FetchResolverConfig(cdUID, rootCmd.Version, cdDev)

req := &controld.ResolverConfigRequest{
RawUID: cdUID,
Version: rootCmd.Version,
Metadata: ctrld.SystemMetadata(context.Background()),
}
_, err := controld.FetchResolverConfig(req, cdDev)
logger.Debug().Msg("maximum number of refused queries reached, checking device status")
selfUninstallCheck(err, p, logger)

Expand Down
7 changes: 6 additions & 1 deletion cmd/cli/prog.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,12 @@ func (p *prog) apiConfigReload() {
}

doReloadApiConfig := func(forced bool, logger zerolog.Logger) {
resolverConfig, err := controld.FetchResolverConfig(cdUID, rootCmd.Version, cdDev)
req := &controld.ResolverConfigRequest{
RawUID: cdUID,
Version: rootCmd.Version,
Metadata: ctrld.SystemMetadata(context.Background()),
}
resolverConfig, err := controld.FetchResolverConfig(req, cdDev)
selfUninstallCheck(err, p, logger)
if err != nil {
logger.Warn().Err(err).Msg("could not fetch resolver config")
Expand Down
46 changes: 46 additions & 0 deletions docs/runtime-internal-logging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Runtime Internal Logging

When no logging is configured (i.e., `log_path` is not set), ctrld automatically enables an internal logging system. This system stores logs in memory to provide troubleshooting information when problems occur.

## Purpose

The runtime internal logging system is designed primarily for **ctrld developers**, not end users. It captures detailed diagnostic information that can be useful for troubleshooting issues when they arise, especially in production environments where explicit logging may not be configured.

## When It's Enabled

Internal logging is automatically enabled when:

- ctrld is running in Control D mode (i.e., `--cd` flag is provided)
- No log file is configured (i.e., `log_path` is empty or not set)

If a log file is explicitly configured via `log_path`, internal logging will **not** be enabled, as the configured log file serves the logging purpose.

## How It Works

The internal logging system:

- Stores logs in **in-memory buffers** (not written to disk)
- Captures logs at **debug level** for normal operations and **warn level** for warnings
- Maintains separate buffers for normal logs and warning logs
- Automatically manages buffer size to prevent unbounded memory growth
- Preserves initialization logs even when buffers overflow

## Configuration

**Important**: The `log_level` configuration option does **not** affect the internal logging system. Internal logging always operates at debug level for normal logs and warn level for warnings, regardless of the `log_level` setting in the configuration file.

The `log_level` setting only affects:
- Console output (when running interactively)
- File-based logging (when `log_path` is configured)

## Accessing Internal Logs

Internal logs can be accessed through the control server API endpoints. This functionality is intended for developers and support personnel who need to diagnose issues.

## Notes

- Internal logging is **not** a replacement for proper log file configuration in production environments
- For production deployments, it is recommended to configure `log_path` to enable persistent file-based logging
- Internal logs are stored in memory and will be lost if the process terminates unexpectedly
- The internal logging system is automatically disabled when explicit logging is configured

5 changes: 0 additions & 5 deletions doh.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,6 @@ func (r *dohResolver) Resolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, erro
}
if err != nil {
err = wrapUrlError(err)
if r.isDoH3 {
if closer, ok := c.Transport.(io.Closer); ok {
closer.Close()
}
}
return nil, fmt.Errorf("could not perform request: %w", err)
}
defer resp.Body.Close()
Expand Down
17 changes: 12 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.24
require (
github.com/Masterminds/semver/v3 v3.2.1
github.com/ameshkov/dnsstamps v1.0.3
github.com/brunogui0812/sysprofiler v0.5.0
github.com/coreos/go-systemd/v22 v22.5.0
github.com/cuonglm/osinfo v0.0.0-20230921071424-e0e1b1e0bbbf
github.com/docker/go-units v0.5.0
Expand All @@ -15,6 +16,7 @@ require (
github.com/hashicorp/golang-lru/v2 v2.0.1
github.com/illarion/gonotify/v2 v2.0.3
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2
github.com/jaypipes/ghw v0.21.0
github.com/jaytaylor/go-hostsfile v0.0.0-20220426042432-61485ac1fa6c
github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86
github.com/kardianos/service v1.2.1
Expand All @@ -27,12 +29,12 @@ require (
github.com/prometheus/client_golang v1.19.1
github.com/prometheus/client_model v0.5.0
github.com/prometheus/prom2json v1.3.3
github.com/quic-go/quic-go v0.56.0
github.com/quic-go/quic-go v0.57.1
github.com/rs/zerolog v1.28.0
github.com/spf13/cobra v1.8.1
github.com/spf13/pflag v1.0.5
github.com/spf13/cobra v1.9.1
github.com/spf13/pflag v1.0.6
github.com/spf13/viper v1.16.0
github.com/stretchr/testify v1.9.0
github.com/stretchr/testify v1.11.1
github.com/vishvananda/netlink v1.2.1-beta.2
golang.org/x/net v0.43.0
golang.org/x/sync v0.16.0
Expand All @@ -55,8 +57,10 @@ require (
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/groob/plist v0.0.0-20200425180238-0f631f258c01 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jaypipes/pcidb v1.1.1 // indirect
github.com/jsimonetti/rtnetlink v1.4.0 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
Expand All @@ -75,15 +79,17 @@ require (
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/common v0.48.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/qpack v0.6.0 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/spakin/awk v1.0.0 // indirect
github.com/spf13/afero v1.9.5 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
github.com/u-root/uio v0.0.0-20240118234441-a3c409a6018e // indirect
github.com/vishvananda/netns v0.0.4 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go4.org/mem v0.0.0-20220726221520-4f986261bf13 // indirect
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
golang.org/x/crypto v0.41.0 // indirect
Expand All @@ -94,6 +100,7 @@ require (
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
howett.net/plist v1.0.2-0.20250314012144-ee69052608d9 // indirect
)

replace github.com/mr-karan/doggo => github.com/Windscribe/doggo v0.0.0-20220919152748-2c118fc391f8
Expand Down
Loading