forked from hashicorp/terraform-ls
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement opt-in telemetry (hashicorp#681)
* Implement opt-in telemetry events * Update README.md Co-authored-by: James Pogran <jpogran@outlook.com> * Update README.md Co-authored-by: James Pogran <jpogran@outlook.com> Co-authored-by: James Pogran <jpogran@outlook.com>
- Loading branch information
1 parent
a22e7e5
commit 130111e
Showing
20 changed files
with
582 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
# Telemetry | ||
|
||
The language server is capable of sending telemetry using the native LSP `telemetry/event` method. | ||
Telemetry is off by default and can enabled by passing a supported request format version | ||
as an experimental client capability. | ||
|
||
```json | ||
{ | ||
"capabilities": { | ||
"experimental": { | ||
"telemetryVersion": 1 | ||
} | ||
} | ||
} | ||
``` | ||
|
||
Clients then implement opt-in or opt-out in the UI and should reflect the user's choice. | ||
|
||
## Privacy | ||
|
||
Sensitive data, such as filesystem paths or addresses of providers sourced from outside the Terraform Registry | ||
are anonymized. Random UUID is generated in memory and tracked instead of a path or a private provider address. | ||
|
||
Mapping of such UUIDs is not persisted anywhere other than in memory during process lifetime. | ||
|
||
## Request Format | ||
|
||
The only supported version is currently `1`. Version negotiation allows the server | ||
to introduce breaking changes to the format and have clients adopt gradually. | ||
|
||
### `v1` | ||
|
||
[`telemetry/event`](https://microsoft.github.io/language-server-protocol/specifications/specification-3-16/#telemetry_event) structure | ||
|
||
```json | ||
{ | ||
"v": 1, | ||
"name": "eventName", | ||
"properties": {} | ||
} | ||
``` | ||
|
||
`properties` may contain **any (valid) JSON types** | ||
including arrays and arbitrarily nested objects. It is client's | ||
reponsibility to serialize these properties when and if necessary. | ||
|
||
Example events: | ||
|
||
```json | ||
{ | ||
"v": 1, | ||
"name": "initialize", | ||
"properties": { | ||
"experimentalCapabilities.referenceCountCodeLens": true, | ||
"lsVersion": "0.23.0", | ||
"options.commandPrefix": true, | ||
"options.excludeModulePaths": false, | ||
"options.experimentalFeatures.prefillRequiredFields": false, | ||
"options.experimentalFeatures.validateOnSave": false, | ||
"options.rootModulePaths": false, | ||
"options.terraformExecPath": false, | ||
"options.terraformExecTimeout": "", | ||
"options.terraformLogFilePath": false, | ||
"root_uri": "dir" | ||
} | ||
} | ||
``` | ||
```json | ||
{ | ||
"v": 1, | ||
"name": "moduleData", | ||
"properties": { | ||
"backend": "remote", | ||
"backend.remote.hostname": "app.terraform.io", | ||
"installedProviders": { | ||
"registry.terraform.io/hashicorp/aws": "3.57.0", | ||
"registry.terraform.io/hashicorp/null": "3.1.0" | ||
}, | ||
"moduleId": "8aa5a4dc-4780-2d90-b8fb-57de8288fb32", | ||
"providerRequirements": { | ||
"registry.terraform.io/hashicorp/aws": "", | ||
"registry.terraform.io/hashicorp/null": "~> 3.1" | ||
}, | ||
"tfRequirements": "~> 1.0", | ||
"tfVersion": "1.0.7" | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package handlers | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/hashicorp/terraform-ls/internal/state" | ||
"github.com/hashicorp/terraform-ls/internal/telemetry" | ||
"github.com/hashicorp/terraform-schema/backend" | ||
) | ||
|
||
func sendModuleTelemetry(ctx context.Context, store *state.StateStore, telemetrySender telemetry.Sender) state.ModuleChangeHook { | ||
return func(_, newMod *state.Module) { | ||
modId, err := store.GetModuleID(newMod.Path) | ||
if err != nil { | ||
return | ||
} | ||
|
||
properties := map[string]interface{}{ | ||
"moduleId": modId, | ||
} | ||
|
||
if len(newMod.Meta.CoreRequirements) > 0 { | ||
properties["tfRequirements"] = newMod.Meta.CoreRequirements.String() | ||
} | ||
if newMod.Meta.Backend != nil { | ||
properties["backend"] = newMod.Meta.Backend.Type | ||
if data, ok := newMod.Meta.Backend.Data.(*backend.Remote); ok { | ||
hostname := data.Hostname | ||
|
||
// anonymize any non-default hostnames | ||
if hostname != "" && hostname != "app.terraform.io" { | ||
hostname = "custom-hostname" | ||
} | ||
|
||
properties["backend.remote.hostname"] = hostname | ||
} | ||
} | ||
if len(newMod.Meta.ProviderRequirements) > 0 { | ||
reqs := make(map[string]string, 0) | ||
for pAddr, cons := range newMod.Meta.ProviderRequirements { | ||
if telemetry.IsPublicProvider(pAddr) { | ||
reqs[pAddr.String()] = cons.String() | ||
continue | ||
} | ||
|
||
// anonymize any unknown providers or the ones not publicly listed | ||
id, err := store.GetProviderID(pAddr) | ||
if err != nil { | ||
continue | ||
} | ||
addr := fmt.Sprintf("unlisted/%s", id) | ||
reqs[addr] = cons.String() | ||
} | ||
properties["providerRequirements"] = reqs | ||
} | ||
|
||
if newMod.TerraformVersion != nil { | ||
properties["tfVersion"] = newMod.TerraformVersion.String() | ||
} | ||
|
||
if len(newMod.InstalledProviders) > 0 { | ||
installedProviders := make(map[string]string, 0) | ||
for pAddr, pv := range newMod.InstalledProviders { | ||
if telemetry.IsPublicProvider(pAddr) { | ||
versionString := "" | ||
if pv != nil { | ||
versionString = pv.String() | ||
} | ||
installedProviders[pAddr.String()] = versionString | ||
continue | ||
} | ||
|
||
// anonymize any unknown providers or the ones not publicly listed | ||
id, err := store.GetProviderID(pAddr) | ||
if err != nil { | ||
continue | ||
} | ||
addr := fmt.Sprintf("unlisted/%s", id) | ||
installedProviders[addr] = "" | ||
} | ||
properties["installedProviders"] = installedProviders | ||
} | ||
|
||
telemetrySender.SendEvent(ctx, "moduleData", properties) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.