Skip to content

Commit

Permalink
Initial Python telemetry (#1972)
Browse files Browse the repository at this point in the history
Python feature usage telemetry.

---------

Co-authored-by: Alexander Hansen <[email protected]>
Co-authored-by: sezna <[email protected]>
  • Loading branch information
3 people authored Oct 30, 2024
1 parent bedd810 commit 07765a7
Show file tree
Hide file tree
Showing 6 changed files with 439 additions and 5 deletions.
7 changes: 7 additions & 0 deletions pip/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ operation BellState() : Unit {
BellState()
```

## Telemetry

This library sends telemetry. Minimal anonymous data is collected to help measure feature usage and performance.
All telemetry events can be seen in the source file [telemetry_events.py](https://github.com/microsoft/qsharp/tree/main/pip/qsharp/telemetry_events.py).

To disable sending telemetry from this package, set the environment variable `QSHARP_PYTHON_TELEMETRY=none`

## Support

For more information about the Azure Quantum Development Kit, visit [https://aka.ms/AQ/Documentation](https://aka.ms/AQ/Documentation).
Expand Down
3 changes: 3 additions & 0 deletions pip/qsharp/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

from . import telemetry_events
from ._qsharp import (
init,
eval,
Expand All @@ -20,6 +21,8 @@
PhaseFlipNoise,
)

telemetry_events.on_import()

from ._native import Result, Pauli, QSharpError, TargetProfile

# IPython notebook specific features
Expand Down
35 changes: 30 additions & 5 deletions pip/qsharp/_qsharp.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

from . import telemetry_events
from ._native import (
Interpreter,
TargetProfile,
Expand All @@ -23,8 +24,10 @@
from .estimator._estimator import EstimatorResult, EstimatorParams
import json
import os
from time import monotonic

_interpreter = None
_config = None

# Check if we are running in a Jupyter notebook to use the IPython display function
_in_jupyter = False
Expand Down Expand Up @@ -161,6 +164,7 @@ def init(
from ._http import fetch_github

global _interpreter
global _config

if isinstance(target_name, str):
target = target_name.split(".")[0].lower()
Expand Down Expand Up @@ -198,9 +202,10 @@ def init(
fetch_github,
)

_config = Config(target_profile, language_features, manifest_contents, project_root)
# Return the configuration information to provide a hint to the
# language service through the cell output.
return Config(target_profile, language_features, manifest_contents, project_root)
return _config


def get_interpreter() -> Interpreter:
Expand Down Expand Up @@ -286,6 +291,9 @@ def run(
if shots < 1:
raise QSharpError("The number of shots must be greater than 0.")

telemetry_events.on_run(shots)
start_time = monotonic()

results: List[ShotResult] = []

def print_output(output: Output) -> None:
Expand Down Expand Up @@ -317,6 +325,9 @@ def on_save_events(output: Output) -> None:
# compilation.
entry_expr = None

durationMs = (monotonic() - start_time) * 1000
telemetry_events.on_run_end(durationMs, shots)

if save_events:
return results
else:
Expand Down Expand Up @@ -366,10 +377,15 @@ def compile(entry_expr: str) -> QirInputData:
file.write(str(program))
"""
ipython_helper()

start = monotonic()
global _config
target_profile = _config._config.get("targetProfile", "unspecified")
telemetry_events.on_compile(target_profile)
ll_str = get_interpreter().qir(entry_expr)
return QirInputData("main", ll_str)

res = QirInputData("main", ll_str)
durationMs = (monotonic() - start) * 1000
telemetry_events.on_compile_end(durationMs, target_profile)
return res

def circuit(
entry_expr: Optional[str] = None, *, operation: Optional[str] = None
Expand Down Expand Up @@ -421,9 +437,18 @@ def _coerce_estimator_params(

params = _coerce_estimator_params(params)
param_str = json.dumps(params)

telemetry_events.on_estimate()
start = monotonic()
res_str = get_interpreter().estimate(entry_expr, param_str)
res = json.loads(res_str)

try:
qubits = res[0]["logicalCounts"]["numQubits"]
except (KeyError, IndexError):
qubits = "unknown"

durationMs = (monotonic() - start) * 1000
telemetry_events.on_estimate_end(durationMs, qubits)
return EstimatorResult(res)


Expand Down
Loading

0 comments on commit 07765a7

Please sign in to comment.