Skip to main content
What telemetry does: stores usage locally in telemetry.json, and can optionally batch or stream events to your server. ✅
Discover how telemetry helps you understand interactions and performance. It is not only about collecting data, it is about unlocking insights that improve the learning journey. Below you will find how to configure the path for telemetry.json and how to transmit events as they occur.

Configure in learn.json ⚙️

Each LearnPack course includes a learn.json file for exercise testing, compiler selection, and more. The telemetry key lets you streamline data tracking. Telemetry Key Example When registered users interact with a course, LearnPack can record and transmit events for key actions:
UI actionEvent name
Press the Next buttonopen_step
Click Runcompile
Click Run teststest
Ask the AI tutorai_interaction

How often telemetry is sent ⏱️

1

Batch

After executing learnpack start, telemetry is sent for the first time if it is configured.
When opening a new step, the next step is marked as started and the current copy of telemetry is sent to the configured batch URL.
2

Stream

For each new event, if the stream URL is configured, LearnPack sends a webhook with the event to the specified endpoint.
Reminder: configure both batch and stream URLs to ensure events are received as expected. Endpoints must accept POST requests.

What telemetry stores

Telemetry includes information about opened exercises and timestamps, compilation and test results, work sessions, the first start time, the environment where it runs, and identifiers for telemetry and the student if it is a 4Geeks student.
{
  "telemetry_id": "atlbmot8wvalltng",
  "slug": "prompt-engineering-for-beginners",
  "agent": "vscode",
  "tutorial_started_at": 1718211567826,
  "steps": [
    {
      "slug": "00-welcome",
      "position": 0,
      "files": [
        { "path": "exercises\\00-welcome/README.es.md", "name": "README.es.md", "hidden": true },
        { "path": "exercises\\00-welcome/README.md", "name": "README.md", "hidden": true },
        { "path": "exercises\\00-welcome/__pycache__", "name": "__pycache__", "hidden": true }
      ],
      "ai_interactions": [],
      "compilations": [],
      "tests": [],
      "is_testeable": false
    },
    {
      "slug": "01.1-obtain-api-key",
      "position": 3,
      "files": [
        { "path": "exercises\\01.1-obtain-api-key/app.py", "name": "app.py", "hidden": false },
        { "path": "exercises\\01.1-obtain-api-key/README.es.md", "name": "README.es.md", "hidden": true },
        { "path": "exercises\\01.1-obtain-api-key/README.md", "name": "README.md", "hidden": true },
        { "path": "exercises\\01.1-obtain-api-key/test.py", "name": "test.py", "hidden": true },
        { "path": "exercises\\01.1-obtain-api-key/__pycache__", "name": "__pycache__", "hidden": true }
      ],
      "ai_interactions": [],
      "compilations": [
        {
          "stderr": "DQpbbm90aWNlXSBBIG5ldyByZWxlYXNlIG9mIHBpcCBhdmFpbGFibGU6IDIyLjMuMSAtPiAyNC4wDQpbbm90aWNlXSBUbyB1cGRhdGUsIHJ1bjogcHl0aG9uLmV4ZSAtbSBwaXAgaW5zdGFsbCAtLXVwZ3JhZGUgcGlwDQo=",
          "stdout": "RW50ZXIgeW91ciBBUEkga2V5OiBSZXF1aXJlbWVudCBhbHJlYWR5IHNhdGlzZmllZDogcHl0aG9uLWRvdGVudiBpbiBjOlx1c2Vyc1xsZWdpb25cYXBwZGF0YVxsb2NhbFxwcm9ncmFtc1xweXRob25ccHl0aG9uMzExXGxpYlxzaXRlLXBhY2thZ2VzIChmcm9tIC1yIHJlcXVpcmVtZW50cy50eHQgKGxpbmUgMSkpICgxLjAuMSkNClJlcXVpcmVtZW50IGFscmVhZHkgc2F0aXNmaWVkOiBncm9xIGluIGM6XHVzZXJzXGxlZ2lvblxhcHBkYXRhXGxvY2FsXHByb2dyYW1zXHB5dGhvblxweXRob24zMTFcbGliXHNpdGUtcGFja2FnZXMgKGZyb20gLXIgcmVxdWlyZW1lbnRzLnR4dCAobGluZSAyKSkgKDAuOC4wKQ0KUmVxdWlyZW1lbnQgYWxyZWFkeSBzYXRpc2ZpZWQ6IGFueWlvPDUsPj0zLjUuMCBpbiBjOlx1c2Vyc1xsZWdpb25cYXBwZGF0YVxsb2NhbFxwcm9ncmFtc1xweXRob25ccHl0aG9uMzExXGxpYlxzaXRlLXBhY2thZ2VzIChmcm9tIGdyb3EtPi1yIHJlcXVpcmVtZW50cy50eHQgKGxpbmUgMikpICg0LjQuMCkNClJlcXVpcmVtZW50IGFscmVhZHkgc2F0aXNmaWVkOiBkaXN0cm88Miw+PTEuNy4wIGluIGM6XHVzZXJzXGxlZ2lvblxhcHBkYXRhXGxvY2FsXHByb2dyYW1zXHB5dGhvblxweXRob24zMTFcbGliXHNpdGUtcGFja2FnZXMgKGZyb20gZ3JvcS0+LXIgcmVxdWlyZW1lbnRzLnR4dCAobGluZSAyKSkgKDEuOS4wKQ0KUmVxdWlyZW1lbnQgYWxyZWFkeSBzYXRpc2ZpZWQ6IGh0dHB4PDEsPj0wLjIzLjAgaW4gYzpcdXNlcnNcbGVnaW9uXGFwcGRhdGFcbG9jYWxccHJvZ3JhbXNccHl0aG9uXHB5dGhvbjMxMVxsaWJcc2l0ZS1wYWNrYWdlcyAoZnJvbSBncm9xLT4tciByZXF1aXJlbWVudHMudHh0IChsaW5lIDIpKSAoMC4yNy4wKQ0KUmVxdWlyZW1lbnQgYWxyZWFkeSBzYXRpc2ZpZWQ6IHB5ZGFudGljPDMsPj0xLjkuMCBpbiBjOlx1c2Vyc1xsZWdpb25cYXBwZGF0YVxsb2NhbFxwcm9ncmFtc1xweXRob25ccHl0aG9uMzExXGxpYlxzaXRlLXBhY2thZ2VzIA==",
          "signal": "SIGTERM",
          "memoryUsage": 532480,
          "cpuUsage": 0,
          "errorType": "run-time",
          "starting_at": 1718211884140,
          "source_code": "aW1wb3J0IG9zDQojIERPIE5PVCBDSEFOR0UgVEhJUyBDT0RFDQoNCg0KQVBJX0tFWSA9IGlucHV0KCJFbnRlciB5b3VyIEFQSSBrZXk6ICIpDQoNCiMgU2F2ZSB0aGUgQVBJX0tFWSBpbiB0aGUgZG90ZW52IGZpbGUNCndpdGggb3BlbigiLmVudiIsICJ3IikgYXMgZjoNCiAgICBmLndyaXRlKGYiR1JPUV9BUElfS0VZPXtBUElfS0VZfVxuIikNCg0KIyBFeHBvcnQgdGhlIEFQSV9LRVkgYXMgYW4gZW52aXJvbm1lbnQgdmFyaWFibGUNCm9zLmVudmlyb25bIkdST1FfQVBJX0tFWSJdID0gQVBJX0tFWQ0KDQojIEluc3RhbGwgdGhlIGRlcGVuZGVuY2llcyBpbiB0aGUgcmVxdWlyZW1lbnRzLnR4dCBmaWxlDQpwcmludCgiSW5zdGFsbGluZyBkZXBlbmRlbmNpZXMuLi4iKQ0Kb3Muc3lzdGVtKCJwaXAgaW5zdGFsbCAtciByZXF1aXJlbWVudHMudHh0IikNCg==",
          "ended_at": 1718211886645,
          "exit_code": null
        }
      ],
      "tests": [
        {
          "starting_at": 1718211893013,
          "source_code": "aW1wb3J0IG9zDQojIERPIE5PVCBDSEFOR0UgVEhJUyBDT0RFDQoNCg0KQVBJX0tFWSA9IGlucHV0KCJFbnRlciB5b3VyIEFQSSBrZXk6ICIpDQoNCiMgU2F2ZSB0aGUgQVBJX0tFWSBpbiB0aGUgZG90ZW52IGZpbGUNCndpdGggb3BlbigiLmVudiIsICJ3IikgYXMgZjoNCiAgICBmLndyaXRlKGYiR1JPUV9BUElfS0VZPXtBUElfS0VZfVxuIikNCg0KIyBFeHBvcnQgdGhlIEFQSV9LRVkgYXMgYW4gZW52aXJvbm1lbnQgdmFyaWFibGUNCm9zLmVudmlyb25bIkdST1FfQVBJX0tFWSJdID0gQVBJX0tFWQ0KDQojIEluc3RhbGwgdGhlIGRlcGVuZGVuY2llcyBpbiB0aGUgcmVxdWlyZW1lbnRzLnR4dCBmaWxlDQpwcmludCgiSW5zdGFsbGluZyBkZXBlbmRlbmNpZXMuLi4iKQ0Kb3Muc3lzdGVtKCJwaXAgaW5zdGFsbCAtciByZXF1aXJlbWVudHMudHh0IikNCg==",
          "ended_at": 1718211893606,
          "stdout": "G1sxbT09PT09PT09PT09PT09PT09PT09PT09PT09PT09IHRlc3Qgc2Vzc2lvbiBzdGFydHMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT0bWzBtDQpwbGF0Zm9ybSB3aW4zMiAtLSBQeXRob24gMy4xMS4zLCBweXRlc3QtOC4yLjIsIHBsdWdneS0xLjUuMA0Kcm9vdGRpcjogQzpcVXNlcnNcTEVHSU9OXFByb2plY3RzXGpvYnNcNGdlZWtzXHR1dG9yaWFsc1xwcm9tcHQtZW5nDQpwbHVnaW5zOiBhbnlpby00LjQuMCwgdGVzdGRveC0zLjEuMA0KY29sbGVjdGVkIDEgaXRlbQ0KDQpleGVyY2lzZXNcMDEuMS1vYnRhaW4tYXBpLWtleVx0ZXN0LnB5IBtbMzJtLhtbMG0bWzMybSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbMTAwJV0bWzBtDQoNChtbMzJtPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09IBtbMzJtG1sxbTEgcGFzc2VkG1swbRtbMzJtIGluIDAuMDNzG1swbRtbMzJtID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PRtbMG0NCg==",
          "stderr": "",
          "exit_code": 0
        }
      ],
      "is_testeable": true,
      "opened_at": 1718211866688,
      "completed_at": 1718211893606
    }
    // ...rest of the file continues
  ],
  "workout_session": [
    { "started_at": 1718211567826, "ended_at": 1718211913735 },
    { "started_at": 1718211952333 }
  ],
  "last_interaction_at": 1718211913735
}
Privacy: only non-sensitive usage data is collected to enhance performance and user experience.

Next up

See also