diff --git a/cmd/modern/main.go b/cmd/modern/main.go
index 4b358b48..eeeadb9d 100644
--- a/cmd/modern/main.go
+++ b/cmd/modern/main.go
@@ -12,6 +12,8 @@
 package main
 
 import (
+	"path"
+
 	"github.com/microsoft/go-sqlcmd/internal"
 	"github.com/microsoft/go-sqlcmd/internal/cmdparser"
 	"github.com/microsoft/go-sqlcmd/internal/cmdparser/dependency"
@@ -20,9 +22,9 @@ import (
 	"github.com/microsoft/go-sqlcmd/internal/output"
 	"github.com/microsoft/go-sqlcmd/internal/output/verbosity"
 	"github.com/microsoft/go-sqlcmd/internal/pal"
+	"github.com/microsoft/go-sqlcmd/internal/telemetry"
 	"github.com/microsoft/go-sqlcmd/pkg/sqlcmd"
 	"github.com/spf13/cobra"
-	"path"
 
 	"os"
 
@@ -38,6 +40,8 @@ var version = "local-build" // overridden in pipeline builds with: -ldflags="-X
 // If the first argument is a modern CLI subcommand, the modern CLI is
 // executed. Otherwise, the legacy CLI is executed.
 func main() {
+	telemetry.InitializeAppInsights()
+
 	dependencies := dependency.Options{
 		Output: output.New(output.Options{
 			StandardWriter: os.Stdout,
diff --git a/cmd/modern/root.go b/cmd/modern/root.go
index 8a83f02b..26d78951 100644
--- a/cmd/modern/root.go
+++ b/cmd/modern/root.go
@@ -142,3 +142,7 @@ func (c *Root) addGlobalFlags() {
 		Usage:      localizer.Sprintf("log level, error=0, warn=1, info=2, debug=3, trace=4"),
 	})
 }
+
+func (c *Root) LogTelemtry() {
+	/* Dummy implementation for now */
+}
diff --git a/cmd/modern/root/config/add-context.go b/cmd/modern/root/config/add-context.go
index 351bb0c8..0ae101ea 100644
--- a/cmd/modern/root/config/add-context.go
+++ b/cmd/modern/root/config/add-context.go
@@ -10,6 +10,7 @@ import (
 	"github.com/microsoft/go-sqlcmd/internal/cmdparser"
 	"github.com/microsoft/go-sqlcmd/internal/config"
 	"github.com/microsoft/go-sqlcmd/internal/localizer"
+	"github.com/microsoft/go-sqlcmd/internal/telemetry"
 )
 
 // AddContext implements the `sqlcmd config add-context` command
@@ -93,4 +94,23 @@ func (c *AddContext) run() {
 		{localizer.Sprintf("To start interactive query session"), "sqlcmd query"},
 		{localizer.Sprintf("To run a query"), "sqlcmd query \"SELECT @@version\""},
 	}, localizer.Sprintf("Current Context '%v'", context.Name))
+	c.LogTelemtry()
+}
+
+func (c *AddContext) LogTelemtry() {
+	eventName := "config-add-context"
+	properties := map[string]string{}
+	properties["Command"] = "config"
+	properties["SubCommand"] = "add-context"
+	if c.name != "" {
+		properties["name"] = "set"
+	}
+	if c.endpointName != "" {
+		properties["endpoint"] = "set"
+	}
+	if c.userName != "" {
+		properties["user"] = "set"
+	}
+	telemetry.TrackEvent(eventName, properties)
+	telemetry.CloseTelemetry()
 }
diff --git a/cmd/modern/root/config/add-endpoint.go b/cmd/modern/root/config/add-endpoint.go
index e11126e8..96ab7614 100644
--- a/cmd/modern/root/config/add-endpoint.go
+++ b/cmd/modern/root/config/add-endpoint.go
@@ -11,6 +11,7 @@ import (
 	"github.com/microsoft/go-sqlcmd/internal/cmdparser"
 	"github.com/microsoft/go-sqlcmd/internal/config"
 	"github.com/microsoft/go-sqlcmd/internal/localizer"
+	"github.com/microsoft/go-sqlcmd/internal/telemetry"
 )
 
 // AddEndpoint implements the `sqlcmd config add-endpoint` command
@@ -82,4 +83,23 @@ func (c *AddEndpoint) run() {
 		{localizer.Sprintf("Delete this endpoint"), fmt.Sprintf("sqlcmd config delete-endpoint %v", uniqueEndpointName)},
 	},
 		localizer.Sprintf("Endpoint '%v' added (address: '%v', port: '%v')", uniqueEndpointName, c.address, c.port))
+	c.LogTelemtry()
+}
+
+func (c *AddEndpoint) LogTelemtry() {
+	eventName := "config-add-endpoint"
+	properties := map[string]string{}
+	properties["Command"] = "Config"
+	properties["SubCommand"] = "add-endpoint"
+	if c.name != "" {
+		properties["name"] = "set"
+	}
+	if c.address != "" {
+		properties["address"] = "set"
+	}
+	if c.port != 0 {
+		properties["port"] = "set"
+	}
+	telemetry.TrackEvent(eventName, properties)
+	telemetry.CloseTelemetry()
 }
diff --git a/cmd/modern/root/config/add-user.go b/cmd/modern/root/config/add-user.go
index f0232670..3a9a43bb 100644
--- a/cmd/modern/root/config/add-user.go
+++ b/cmd/modern/root/config/add-user.go
@@ -11,6 +11,7 @@ import (
 	"github.com/microsoft/go-sqlcmd/cmd/modern/sqlconfig"
 	"github.com/microsoft/go-sqlcmd/internal/localizer"
 	"github.com/microsoft/go-sqlcmd/internal/pal"
+	"github.com/microsoft/go-sqlcmd/internal/telemetry"
 
 	"github.com/microsoft/go-sqlcmd/internal/cmdparser"
 	"github.com/microsoft/go-sqlcmd/internal/config"
@@ -170,3 +171,23 @@ func (c *AddUser) run() {
 	uniqueUserName := config.AddUser(user)
 	output.Info(localizer.Sprintf("User '%v' added", uniqueUserName))
 }
+
+func (c *AddUser) LogTelemtry() {
+	eventName := "config-add-user"
+	properties := map[string]string{}
+	if c.username != "" {
+		properties["username"] = "set"
+	}
+	if c.authType != "" {
+		properties["authtype"] = c.authType
+	}
+	if c.name != "" {
+		properties["name"] = "set"
+	}
+
+	if c.passwordEncryption != "" {
+		properties["passwordEncryption"] = "set"
+	}
+	telemetry.TrackEvent(eventName, properties)
+	telemetry.CloseTelemetry()
+}
diff --git a/cmd/modern/root/config/view.go b/cmd/modern/root/config/view.go
index a5a2c6e2..d7151235 100644
--- a/cmd/modern/root/config/view.go
+++ b/cmd/modern/root/config/view.go
@@ -4,9 +4,12 @@
 package config
 
 import (
+	"strconv"
+
 	"github.com/microsoft/go-sqlcmd/internal/cmdparser"
 	"github.com/microsoft/go-sqlcmd/internal/config"
 	"github.com/microsoft/go-sqlcmd/internal/localizer"
+	"github.com/microsoft/go-sqlcmd/internal/telemetry"
 )
 
 // View implements the `sqlcmd config view` command
@@ -48,4 +51,15 @@ func (c *View) run() {
 
 	contents := config.RedactedConfig(c.raw)
 	output.Struct(contents)
+	c.LogTelemtry()
+}
+
+func (c *View) LogTelemtry() {
+	eventName := "config-view"
+	properties := map[string]string{}
+	properties["Command"] = "Config"
+	properties["SubCommand"] = "View"
+	properties["Flag"] = strconv.FormatBool(c.raw)
+	telemetry.TrackEvent(eventName, properties)
+	telemetry.CloseTelemetry()
 }
diff --git a/cmd/sqlcmd/sqlcmd.go b/cmd/sqlcmd/sqlcmd.go
index 33c702b2..de15f9ef 100644
--- a/cmd/sqlcmd/sqlcmd.go
+++ b/cmd/sqlcmd/sqlcmd.go
@@ -19,6 +19,7 @@ import (
 	"github.com/microsoft/go-mssqldb/azuread"
 	"github.com/microsoft/go-mssqldb/msdsn"
 	"github.com/microsoft/go-sqlcmd/internal/localizer"
+	"github.com/microsoft/go-sqlcmd/internal/telemetry"
 	"github.com/microsoft/go-sqlcmd/pkg/console"
 	"github.com/microsoft/go-sqlcmd/pkg/sqlcmd"
 	"github.com/spf13/cobra"
@@ -221,11 +222,11 @@ func Execute(version string) {
 					fmt.Println(localizer.Sprintf("Servers:"))
 				}
 				listLocalServers()
-				os.Exit(0)
+				telemetry.CloseTelemetryAndExit(0)
 			}
 			if len(argss) > 0 {
 				fmt.Printf("%s'%s': Unknown command. Enter '--help' for command help.", sqlcmdErrorPrefix, argss[0])
-				os.Exit(1)
+				telemetry.CloseTelemetryAndExit(1)
 			}
 
 			vars := sqlcmd.InitializeVariables(args.useEnvVars())
@@ -238,16 +239,16 @@ func Execute(version string) {
 				fmt.Println()
 				fmt.Println(localizer.Sprintf("Legal docs and information: aka.ms/SqlcmdLegal"))
 				fmt.Println(localizer.Sprintf("Third party notices: aka.ms/SqlcmdNotices"))
-				os.Exit(0)
+				telemetry.CloseTelemetryAndExit(0)
 			}
 
 			if args.Help {
 				fmt.Print(cmd.UsageString())
-				os.Exit(0)
+				telemetry.CloseTelemetryAndExit(0)
 			}
 
 			exitCode, _ := run(vars, &args)
-			os.Exit(exitCode)
+			telemetry.CloseTelemetryAndExit(exitCode)
 
 		},
 	}
@@ -271,7 +272,7 @@ func Execute(version string) {
 	})
 	rootCmd.SetArgs(convertOsArgs(os.Args[1:]))
 	if err := rootCmd.Execute(); err != nil {
-		os.Exit(1)
+		telemetry.CloseTelemetryAndExit(1)
 	}
 }
 
diff --git a/go.mod b/go.mod
index 0be1eaea..96a465ad 100644
--- a/go.mod
+++ b/go.mod
@@ -5,11 +5,13 @@ go 1.21
 require (
 	github.com/alecthomas/chroma/v2 v2.5.0
 	github.com/billgraziano/dpapi v0.4.0
+	github.com/denisbrodbeck/machineid v1.0.1
 	github.com/docker/distribution v2.8.2+incompatible
 	github.com/docker/docker v24.0.9+incompatible
 	github.com/docker/go-connections v0.4.0
 	github.com/golang-sql/sqlexp v0.1.0
 	github.com/google/uuid v1.3.0
+	github.com/microsoft/ApplicationInsights-Go v0.4.4
 	github.com/microsoft/go-mssqldb v1.6.0
 	github.com/opencontainers/image-spec v1.0.2
 	github.com/peterh/liner v1.2.2
@@ -25,6 +27,7 @@ require (
 )
 
 require (
+	code.cloudfoundry.org/clock v0.0.0-20180518195852-02e53af36e6c // indirect
 	github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1 // indirect
 	github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 // indirect
 	github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect
@@ -40,6 +43,7 @@ require (
 	github.com/docker/go-units v0.5.0 // indirect
 	github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
 	github.com/fsnotify/fsnotify v1.6.0 // indirect
+	github.com/gofrs/uuid v3.3.0+incompatible // indirect
 	github.com/gogo/protobuf v1.3.2 // indirect
 	github.com/golang-jwt/jwt/v5 v5.0.0 // indirect
 	github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
diff --git a/go.sum b/go.sum
index 7b539c9e..b51d56c7 100644
--- a/go.sum
+++ b/go.sum
@@ -35,6 +35,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
 cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
 cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
 cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
+code.cloudfoundry.org/clock v0.0.0-20180518195852-02e53af36e6c h1:5eeuG0BHx1+DHeT3AP+ISKZ2ht1UjGhm581ljqYpVeQ=
+code.cloudfoundry.org/clock v0.0.0-20180518195852-02e53af36e6c/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8=
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1 h1:/iHxaJhsFr0+xVFfbMr5vxz848jyiWuIEDhYq3y5odY=
 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
@@ -85,6 +87,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/denisbrodbeck/machineid v1.0.1 h1:geKr9qtkB876mXguW2X6TU4ZynleN6ezuMSRhl4D7AQ=
+github.com/denisbrodbeck/machineid v1.0.1/go.mod h1:dJUwb7PTidGDeYyUBmXZ2GphQBbjJCrnectwCyxcUSI=
 github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
 github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
 github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
@@ -110,6 +114,7 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
 github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
 github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
@@ -122,6 +127,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
 github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/gofrs/uuid v3.3.0+incompatible h1:8K4tyRfvU1CYPgJsveYFQMhpFd/wXNM7iK6rR7UHz84=
+github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
@@ -204,6 +211,7 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
 github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
 github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
@@ -238,6 +246,8 @@ github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8Bz
 github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
 github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/microsoft/ApplicationInsights-Go v0.4.4 h1:G4+H9WNs6ygSCe6sUyxRc2U81TI5Es90b2t/MwX5KqY=
+github.com/microsoft/ApplicationInsights-Go v0.4.4/go.mod h1:fKRUseBqkw6bDiXTs3ESTiU/4YTIHsQS4W3fP2ieF4U=
 github.com/microsoft/go-mssqldb v1.6.0 h1:mM3gYdVwEPFrlg/Dvr2DNVEgYFG7L42l+dGc67NNNpc=
 github.com/microsoft/go-mssqldb v1.6.0/go.mod h1:00mDtPbeQCRGC1HwOOR5K/gr30P1NcEG0vx6Kbv2aJU=
 github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
@@ -252,6 +262,9 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
 github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
 github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
@@ -328,6 +341,7 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU
 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
 github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
+github.com/tedsuo/ifrit v0.0.0-20180802180643-bea94bb476cc/go.mod h1:eyZnKCc955uh98WQvzOm0dgAeLnf2O0Rz0LPoC5ze+0=
 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -385,6 +399,7 @@ golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -441,6 +456,7 @@ golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -656,8 +672,10 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
 gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
 gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/internal/cmdparser/interface.go b/internal/cmdparser/interface.go
index 23793e79..6a408120 100644
--- a/internal/cmdparser/interface.go
+++ b/internal/cmdparser/interface.go
@@ -42,4 +42,8 @@ type Command interface {
 	// the Command object to have access to the dependencies it needs, without
 	// having to manage them directly.
 	SetCrossCuttingConcerns(dependency.Options)
+
+	// LogTelemtry is used to track the useful telemetry for the command
+	// To be enforced after the review
+	// LogTelemtry()
 }
diff --git a/internal/localizer/localizer.go b/internal/localizer/localizer.go
index ebd6fd68..0ffe3586 100644
--- a/internal/localizer/localizer.go
+++ b/internal/localizer/localizer.go
@@ -19,6 +19,7 @@ import (
 )
 
 var Translator *message.Printer
+var LocaleName = "en-us"
 
 var supportedLanguages = map[string]string{
 	"de-de":   "de-DE",
@@ -40,11 +41,11 @@ var supportedLanguages = map[string]string{
 // based on env var SQLCMD_LANG which expects language
 // tag such as en-us, de-de, fr-ch, etc.
 func init() {
-	localeName := strings.ToLower(os.Getenv("SQLCMD_LANG"))
-	if _, ok := supportedLanguages[localeName]; !ok {
-		localeName = "en-us"
+	LocaleName = strings.ToLower(os.Getenv("SQLCMD_LANG"))
+	if _, ok := supportedLanguages[LocaleName]; !ok {
+		LocaleName = "en-us"
 	}
-	Translator = message.NewPrinter(language.MustParse(supportedLanguages[localeName]))
+	Translator = message.NewPrinter(language.MustParse(supportedLanguages[LocaleName]))
 }
 
 // Errorf() is wrapper function to create localized errors
diff --git a/internal/telemetry/appinsights.go b/internal/telemetry/appinsights.go
new file mode 100644
index 00000000..9c14ad12
--- /dev/null
+++ b/internal/telemetry/appinsights.go
@@ -0,0 +1,302 @@
+package telemetry
+
+import (
+	"fmt"
+	"os"
+	"runtime"
+	"strings"
+	"time"
+
+	"github.com/google/uuid"
+	"github.com/microsoft/ApplicationInsights-Go/appinsights"
+	"github.com/microsoft/go-sqlcmd/internal/localizer"
+)
+
+var telemetryClient appinsights.TelemetryClient
+var isTelemetryEnabled string = "true"
+
+type TelemetrySqlcmd struct {
+	EventName  string
+	Properties map[string]string
+}
+
+// Event Names
+const (
+	Legacy                  = "sqlcmd/legacy"
+	Config                  = "sqlcmd/config"
+	ConfigAddContext        = "sqlcmd/config/addcontext"
+	ConfigAddEndpoint       = "sqlcmd/config/addendpoint"
+	ConfigAddUser           = "sqlcmd/config/adduser"
+	ConfigConnectionStrings = "sqlcmd/config/connectionstrings"
+	ConfigCurrentContexts   = "sqlcmd/config/currentcontexts"
+	ConfigDeleteContext     = "sqlcmd/config/deletecontext"
+	ConfigDeleteEndpoint    = "sqlcmd/config/deleteendpoint"
+	ConfigDeleteUser        = "sqlcmd/config/deleteuser"
+	ConfigGetContexts       = "sqlcmd/config/getcontexts"
+	ConfigGetEndpoints      = "sqlcmd/config/getendpoints"
+	ConfigGetUsers          = "sqlcmd/config/getusers"
+	ConfigUseContext        = "sqlcmd/config/usecontext"
+	ConfigView              = "sqlcmd/config/view"
+	Create                  = "sqlcmd/create"
+	CreateAzsqlEdge         = "sqlcmd/create/azsqledge"
+	CreateMssql             = "sqlcmd/create/mssql"
+	Delete                  = "sqlcmd/delete"
+	SqlcmdHelp              = "sqlcmd/help"
+	Open                    = "sqlcmd/open"
+	SqlcmdQuery             = "sqlcmd/query"
+	Start                   = "sqlcmd/start"
+	Stop                    = "sqlcmd/stop"
+)
+
+// Property Names
+var (
+	// Common Properties
+	userId    string
+	sessionId string
+	locLang   string
+	userOs    string
+)
+
+const (
+
+	//Common Properties
+	UserId    = "Sqlcmd.userId"
+	SessionId = "Sqlcmd.sessionId"
+	LocLang   = "Sqlcmd.locLang"
+	UserOs    = "Sqlcmd.userOs"
+
+	// Legacy Flags
+	HelpSymbol                  = "Sqlcmd.Legacy.?"
+	Helpflag                    = "Sqlcmd.Legacy.help.h"
+	Sqlconfig                   = "Sqlcmd.sqlconfig"
+	Verbosity                   = "Sqlcmd.verbosity"
+	Version                     = "Sqlcmd.version"
+	ApplicationIntent           = "Sqlcmd.Legacy.application-intent.K"
+	AuthenticationMethod        = "Sqlcmd.Legacy.authentication-method"
+	BatchTerminator             = "Sqlcmd.Legacy.batch-terminator.c"
+	ChangePassword              = "Sqlcmd.Legacy.change-password.z"
+	ChangePasswordExit          = "Sqlcmd.Legacy.change-password-exit.Z"
+	ClientRegionalSetting       = "Sqlcmd.Legacy.client-regional-setting.R"
+	ColumnSeparator             = "Sqlcmd.Legacy.column-separator.s"
+	DatabaseName                = "Sqlcmd.Legacy.database-name.d"
+	DedicatedAdminConnection    = "Sqlcmd.Legacy.dedicated-admin-connection.A"
+	DisableCmdAndWarn           = "Sqlcmd.Legacy.disable-cmd-and-warn.X"
+	DisableVariableSubstitution = "Sqlcmd.Legacy.disable-variable-substitution.x"
+	DriverLoggingLevel          = "Sqlcmd.Legacy.driver-logging-level"
+	EchoInput                   = "Sqlcmd.Legacy.echo-input.e"
+	EnableColumnEncryption      = "Sqlcmd.Legacy.enable-column-encryption.g"
+	EnableQuotedIdentifiers     = "Sqlcmd.Legacy.enable-quoted-identifiers.I"
+	EncryptConnection           = "Sqlcmd.Legacy.encrypt-connection.N"
+	ErrorLevel                  = "Sqlcmd.Legacy.error-level.m"
+	ErrorSeverityLevel          = "Sqlcmd.Legacy.error-severity-level.V"
+	ErrorsToStderr              = "Sqlcmd.Legacy.errors-to-stderr.r"
+	ExitOnError                 = "Sqlcmd.Legacy.exit-on-error.b"
+	FixedTypeWidth              = "Sqlcmd.Legacy.fixed-type-width.Y"
+	Format                      = "Sqlcmd.Legacy.format.F"
+	Headers                     = "Sqlcmd.Legacy.headers.h"
+	InitialQuery                = "Sqlcmd.Legacy.initial-query.q"
+	InputFile                   = "Sqlcmd.Legacy.input-file.i"
+	ListServers                 = "Sqlcmd.Legacy.list-servers.L"
+	LoginTimeOut                = "Sqlcmd.Legacy.login-timeOut.l"
+	MultiSubnetFailover         = "Sqlcmd.Legacy.multi-subnet-failover.M"
+	OutputFile                  = "Sqlcmd.Legacy.output-file.o"
+	PacketSize                  = "Sqlcmd.Legacy.packet-size.a"
+	Password                    = "Sqlcmd.Legacy.password.P"
+	Query                       = "Sqlcmd.Legacy.query.Q"
+	QueryTimeout                = "Sqlcmd.Legacy.query-timeout.t"
+	RemoveControlCharacters     = "Sqlcmd.Legacy.remove-control-characters.k"
+	ScreenWidth                 = "Sqlcmd.Legacy.screen-width.w"
+	Server                      = "Sqlcmd.Legacy.server.S"
+	TrimSpaces                  = "Sqlcmd.Legacy.trim-spaces.W"
+	TrustServerCertificate      = "Sqlcmd.Legacy.trust-server-certificate.C"
+	UnicodeOutputFile           = "Sqlcmd.Legacy.unicode-output-file.u"
+	UseAad                      = "Sqlcmd.Legacy.use-aad.G"
+	UseTrustedConnection        = "Sqlcmd.Legacy.use-trusted-connection.E"
+	UserName                    = "Sqlcmd.Legacy.user-name.U"
+	VariableTypeWidth           = "Sqlcmd.Legacy.variable-type-width.y"
+	Variables                   = "Sqlcmd.Legacy.variables.v"
+	WorkstationName             = "Sqlcmd.Legacy.workstation-name.H"
+
+	// Modern Flags
+	ConfigAddContextHelp            = "Sqlcmd.Config.AddContext.help"
+	ConfigAddContextEndpoint        = "Sqlcmd.Config.AddContext.Endpoint"
+	ConfigAddContextName            = "Sqlcmd.Config.AddContext.Name"
+	ConfigAddContextUser            = "Sqlcmd.Config.AddContext.User"
+	ConfigAddEndpointHelp           = "Sqlcmd.Config.AddEndpoint.help"
+	ConfigAddEndpointAddress        = "Sqlcmd.Config.AddEndpoint.Address"
+	ConfigAddEndpointName           = "Sqlcmd.Config.AddEndpoint.Name"
+	ConfigAddEndpointPort           = "Sqlcmd.Config.AddEndpoint.Port"
+	ConfigAddUserHelp               = "Sqlcmd.Config.AddUser.help"
+	ConfigAddUserAuthType           = "Sqlcmd.Config.AddUser.AuthType"
+	ConfigAddUserName               = "Sqlcmd.Config.AddUser.Name"
+	ConfigAddUserPasswordEncryption = "Sqlcmd.Config.AddUser.PasswordEncryption"
+	ConfigAddUserUsername           = "Sqlcmd.Config.AddUser.Username"
+	ConfigAddUserPassword           = "Sqlcmd.Config.AddUser.Password"
+	ConfigConnectionStringsHelp     = "Sqlcmd.Config.ConnectionStrings.help"
+	ConfigConnectionStringsDatabase = "Config.ConnectionStrings.database.d"
+	ConfigCurrentContextsHelp       = "Sqlcmd.Config.CurrentContexts.help"
+	ConfigDeleteContextHelp         = "Sqlcmd.Config.DeleteContext.help"
+	ConfigDeleteContextCascade      = "Sqlcmd.Config.DeleteContext.Cascade"
+	ConfigDeleteContextname         = "Sqlcmd.Config.DeleteContext.name"
+	ConfigDeleteEndpointHelp        = "Sqlcmd.Config.DeleteEndpoint.help"
+	ConfigDeleteEndpointName        = "Sqlcmd.Config.DeleteEndpoint.Name"
+	ConfigDeleteUserHelp            = "Sqlcmd.Config.DeleteUser.help"
+	ConfigDeleteUserName            = "Sqlcmd.Config.DeleteUser.Name"
+	ConfigGetContextsHelp           = "Sqlcmd.Config.GetContexts.help"
+	ConfigGetContextsDetailed       = "Sqlcmd.Config.GetContexts.Detailed"
+	ConfigGetContextsName           = "Sqlcmd.Config.GetContexts.Name"
+	ConfigGetEndpointsHelp          = "Sqlcmd.Config.GetEndpoints.help"
+	ConfigGetEndpointsDetailed      = "Sqlcmd.Config.GetEndpoints.Detailed"
+	ConfigGetEndpointsName          = "Sqlcmd.Config.GetEndpoints.Name"
+	ConfigGetUsersHelp              = "Sqlcmd.Config.GetUsers.help"
+	ConfigGetUsersDetailed          = "Sqlcmd.Config.GetUsers.Detailed"
+	ConfigGetUsersName              = "Sqlcmd.Config.GetUsers.Name"
+	ConfigUseContextHelp            = "Sqlcmd.Config.UseContext.help"
+	ConfigUseContextname            = "Sqlcmd.Config.UseContext.name"
+	ConfigViewHelp                  = "Sqlcmd.Config.View.help"
+	ConfigViewRaw                   = "Sqlcmd.Config.View.Raw"
+	ConfigHelp                      = "Sqlcmd.Config.help"
+
+	CreateHelp                          = "Sqlcmd.Create.help"
+	CreateAzsqlEdgeHelp                 = "Sqlcmd.Create.AzsqlEdge.help"
+	CreateAzsqlEdgeGetTagsHelp          = "Sqlcmd.Create.AzsqlEdge.GetTags.help"
+	CreateAzsqlEdgeAcceptEula           = "Sqlcmd.Create.AzsqlEdge.AcceptEula"
+	CreateAzsqlEdgeArchitecture         = "Sqlcmd.Create.AzsqlEdge.Architecture"
+	CreateAzsqlEdgeCached               = "Sqlcmd.Create.AzsqlEdge.Cached"
+	CreateAzsqlEdgeCollation            = "Sqlcmd.Create.AzsqlEdge.Collation"
+	CreateAzsqlEdgeContextName          = "Sqlcmd.Create.AzsqlEdge.ContextName.c"
+	CreateAzsqlEdgeErrorlogWaitLine     = "Sqlcmd.Create.AzsqlEdge.ErrorlogWaitLine"
+	CreateAzsqlEdgeHostname             = "Sqlcmd.Create.AzsqlEdge.Hostname"
+	CreateAzsqlEdgeName                 = "Sqlcmd.Create.AzsqlEdge.Name"
+	CreateAzsqlEdgeOs                   = "Sqlcmd.Create.AzsqlEdge.Os"
+	CreateAzsqlEdgePasswordEncryption   = "Sqlcmd.Create.AzsqlEdge.PasswordEncryption"
+	CreateAzsqlEdgePasswordLength       = "Sqlcmd.Create.AzsqlEdge.PasswordLength"
+	CreateAzsqlEdgePasswordMinNumber    = "Sqlcmd.Create.AzsqlEdge.PasswordMinNumber"
+	CreateAzsqlEdgePasswordMinSpecial   = "Sqlcmd.Create.AzsqlEdge.PasswordMinSpecial"
+	CreateAzsqlEdgePasswordMinUpper     = "Sqlcmd.Create.AzsqlEdge.PasswordMinUpper"
+	CreateAzsqlEdgePasswordSpecialChars = "Sqlcmd.Create.AzsqlEdge.PasswordSpecialChars"
+	CreateAzsqlEdgePort                 = "Sqlcmd.Create.AzsqlEdge.Port"
+	CreateAzsqlEdgeRegistry             = "Sqlcmd.Create.AzsqlEdge.Registry"
+	CreateAzsqlEdgeRepo                 = "Sqlcmd.Create.AzsqlEdge.Repo"
+	CreateAzsqlEdgeTag                  = "Sqlcmd.Create.AzsqlEdge.Tag"
+	CreateAzsqlEdgeUserDatabase         = "Sqlcmd.Create.AzsqlEdge.UserDatabase.u"
+	CreateAzsqlEdgeUsing                = "Sqlcmd.Create.AzsqlEdge.Using"
+
+	CreateMssqlHelp                 = "Sqlcmd.Create.Mssql.help"
+	CreateMssqlGetTagsHelp          = "Sqlcmd.Create.Mssql.GetTags.help"
+	CreateMssqlAcceptEula           = "Sqlcmd.Create.Mssql.AcceptEula"
+	CreateMssqlArchitecture         = "Sqlcmd.Create.Mssql.Architecture"
+	CreateMssqlCached               = "Sqlcmd.Create.Mssql.Cached"
+	CreateMssqlCollation            = "Sqlcmd.Create.Mssql.Collation"
+	CreateMssqlContextName          = "Sqlcmd.Create.Mssql.ContextName.c"
+	CreateMssqlErrorlogWaitLine     = "Sqlcmd.Create.Mssql.ErrorlogWaitLine"
+	CreateMssqlHostname             = "Sqlcmd.Create.Mssql.Hostname"
+	CreateMssqlName                 = "Sqlcmd.Create.Mssql.Name"
+	CreateMssqlOs                   = "Sqlcmd.Create.Mssql.Os"
+	CreateMssqlPasswordEncryption   = "Sqlcmd.Create.Mssql.PasswordEncryption"
+	CreateMssqlPasswordLength       = "Sqlcmd.Create.Mssql.PasswordLength"
+	CreateMssqlPasswordMinNumber    = "Sqlcmd.Create.Mssql.PasswordMinNumber"
+	CreateMssqlPasswordMinSpecial   = "Sqlcmd.Create.Mssql.PasswordMinSpecial"
+	CreateMssqlPasswordMinUpper     = "Sqlcmd.Create.Mssql.PasswordMinUpper"
+	CreateMssqlPasswordSpecialChars = "Sqlcmd.Create.Mssql.PasswordSpecialChars"
+	CreateMssqlPort                 = "Sqlcmd.Create.Mssql.Port"
+	CreateMssqlRegistry             = "Sqlcmd.Create.Mssql.Registry"
+	CreateMssqlRepo                 = "Sqlcmd.Create.Mssql.Repo"
+	CreateMssqlTag                  = "Sqlcmd.Create.Mssql.Tag"
+	CreateMssqlUserDatabase         = "Sqlcmd.Create.Mssql.UserDatabase.u"
+	CreateMssqlUsing                = "Sqlcmd.Create.Mssql.Using"
+
+	DeleteHelp  = "Sqlcmd.Delete.help"
+	DeleteForce = "Sqlcmd.Delete.Force"
+	DeleteYes   = "Sqlcmd.Delete.Yes"
+
+	Help = "Sqlcmd.help"
+
+	OpenHelp    = "Sqlcmd.Open.help"
+	OpenAdsHelp = "Sqlcmd.Open.Ads.help"
+
+	QueryHelp     = "Sqlcmd.Query.help"
+	QueryDatabase = "Sqlcmd.Query.database.d"
+	Queryquery    = "Sqlcmd.Query.query.q"
+	QueryText     = "Sqlcmd.Query.Text.t"
+	StartHelp     = "Sqlcmd.Start.help"
+	StopHelp      = "Sqlcmd.Stop.help"
+)
+
+func initCommonProps() {
+	if userId == "" {
+		userId = getOrCreateUserId()
+	}
+	if sessionId == "" {
+		sessionId = uuid.NewString()
+	}
+	locLang = localizer.LocaleName
+	userOs = runtime.GOOS
+}
+
+func init() {
+	telemetryEnabled := strings.ToLower(os.Getenv("SQLCMD_TELEMETRY"))
+	if telemetryEnabled == "false" {
+		isTelemetryEnabled = "false"
+	}
+	if isTelemetryEnabled == "true" {
+		InitializeAppInsights()
+		initCommonProps()
+	}
+}
+
+func InitializeTelemetryLogging() {
+	loggingEnabled := strings.ToLower(os.Getenv("SQLCMD_TELEMETRY_LOGGING"))
+	if isTelemetryEnabled == "true" && loggingEnabled == "true" {
+		// Add a diagnostics listener for printing telemetry messages
+		appinsights.NewDiagnosticsMessageListener(func(msg string) error {
+			fmt.Printf("[%s] %s\n", time.Now().Format(time.UnixDate), msg)
+			return nil
+		})
+	}
+}
+
+func InitializeAppInsights() {
+	instrumentationKey := "f305b208-557d-4fba-bf06-25345c4dfdbc"
+	config := appinsights.NewTelemetryConfiguration(instrumentationKey)
+	telemetryClient = appinsights.NewTelemetryClientFromConfig(config)
+	InitializeTelemetryLogging()
+}
+
+func TrackEvent(eventName string, properties map[string]string) {
+	if isTelemetryEnabled == "true" {
+		event := appinsights.NewEventTelemetry(eventName)
+		for key, value := range properties {
+			event.Properties[key] = value
+		}
+		telemetryClient.Track(event)
+	}
+}
+
+func CloseTelemetry() {
+	select {
+	case <-telemetryClient.Channel().Close(10 * time.Second):
+		// Ten second timeout for retries.
+
+		// If we got here, then all telemetry was submitted
+		// successfully, and we can proceed to exiting.
+	case <-time.After(30 * time.Second):
+		// Thirty second absolute timeout.  This covers any
+		// previous telemetry submission that may not have
+		// completed before Close was called.
+
+		// There are a number of reasons we could have
+		// reached here.  We gave it a go, but telemetry
+		// submission failed somewhere.  Perhaps old events
+		// were still retrying, or perhaps we're throttled.
+		// Either way, we don't want to wait around for it
+		// to complete, so let's just exit.
+	}
+}
+
+func CloseTelemetryAndExit(exitcode int) {
+	if isTelemetryEnabled == "true" {
+		CloseTelemetry()
+	}
+	os.Exit(exitcode)
+}
diff --git a/internal/telemetry/userid_darwin.go b/internal/telemetry/userid_darwin.go
new file mode 100644
index 00000000..ea2bd450
--- /dev/null
+++ b/internal/telemetry/userid_darwin.go
@@ -0,0 +1,13 @@
+package telemetry
+
+import (
+	"os/user"
+
+	"github.com/denisbrodbeck/machineid"
+)
+
+func getOrCreateUserId() string {
+	user, _ := user.Current()
+	id, _ := machineid.ProtectedID(user.Username)
+	return id
+}
diff --git a/internal/telemetry/userid_linux.go b/internal/telemetry/userid_linux.go
new file mode 100644
index 00000000..ea2bd450
--- /dev/null
+++ b/internal/telemetry/userid_linux.go
@@ -0,0 +1,13 @@
+package telemetry
+
+import (
+	"os/user"
+
+	"github.com/denisbrodbeck/machineid"
+)
+
+func getOrCreateUserId() string {
+	user, _ := user.Current()
+	id, _ := machineid.ProtectedID(user.Username)
+	return id
+}
diff --git a/internal/telemetry/userid_windows.go b/internal/telemetry/userid_windows.go
new file mode 100644
index 00000000..338dcc14
--- /dev/null
+++ b/internal/telemetry/userid_windows.go
@@ -0,0 +1,29 @@
+package telemetry
+
+import (
+	"log"
+	"strings"
+
+	"github.com/google/uuid"
+	"golang.org/x/sys/windows/registry"
+)
+
+func getOrCreateUserId() string {
+
+	k, err := registry.OpenKey(registry.CURRENT_USER, `Software\Microsoft\SQMClient`, registry.ALL_ACCESS)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer k.Close()
+
+	s, _, err := k.GetStringValue("UserId")
+	if err != nil && strings.Contains(err.Error(), "The system cannot find the file specified") {
+		id := uuid.New()
+		k.SetStringValue("UserId", "{"+strings.ToUpper(id.String()+"}"))
+		s, _, _ = k.GetStringValue("UserId")
+	}
+	if strings.Contains(s, "{") {
+		return s[1 : len(s)-1]
+	}
+	return s
+}
diff --git a/pkg/sqlcmd/sqlcmd.go b/pkg/sqlcmd/sqlcmd.go
index 4ee661dc..b241dd6e 100644
--- a/pkg/sqlcmd/sqlcmd.go
+++ b/pkg/sqlcmd/sqlcmd.go
@@ -27,6 +27,7 @@ import (
 	"github.com/microsoft/go-mssqldb/msdsn"
 	"github.com/microsoft/go-sqlcmd/internal/color"
 	"github.com/microsoft/go-sqlcmd/internal/localizer"
+	"github.com/microsoft/go-sqlcmd/internal/telemetry"
 	"golang.org/x/text/encoding/unicode"
 	"golang.org/x/text/transform"
 )
@@ -571,7 +572,7 @@ func (s *Sqlcmd) SetupCloseHandler() {
 		if s.lineIo != nil {
 			s.lineIo.Close()
 		}
-		os.Exit(0)
+		telemetry.CloseTelemetryAndExit(0)
 	}()
 }