While analyzing the efficacy of any AI-powered code completion tool is inherently challenging due to its qualitative nature, I've found that a quantitative, longitudinal approach can yield surprisingly actionable insights. To that end, I've developed a script that intercepts and logs my interactions with Tabnine within my IDE (VS Code) to calculate a concrete "suggestion acceptance rate" over time. The goal is to move beyond anecdotal impressions and establish a baseline metric for its utility within my specific development workflow, which can then be correlated with other factors like project domain, code complexity, or even time of day.
The script leverages the fact that Tabnine outputs detailed trace information to a dedicated output channel. It parses this log stream, focusing on key events: `suggestions_shown` and `suggestion_accepted`. The core metric is straightforward: `Acceptance Rate = (Accepted Suggestions / Shown Suggestions) * 100`. However, the script also captures additional context for deeper analysis.
Here is the core logging script, written in Python, which runs as a background process:
```python
#!/usr/bin/env python3
"""
Tabnine Acceptance Rate Logger
Monitors VS Code's Tabnine output channel and logs metrics to a time-series file.
"""
import re
import json
from datetime import datetime
from pathlib import Path
LOG_FILE = Path.home() / '.tabnine_acceptance_log.ndjson'
PATTERNS = {
'shown': re.compile(r'INFO.*suggestions_shown'),
'accepted': re.compile(r'INFO.*suggestion_accepted.*"completion_kind":"(w+)"'),
}
def parse_line(line):
"""Extract event and optional completion kind."""
entry = {}
if PATTERNS['shown'].search(line):
entry['event'] = 'shown'
entry['ts'] = datetime.utcnow().isoformat()
elif match := PATTERNS['accepted'].search(line):
entry['event'] = 'accepted'
entry['completion_kind'] = match.group(1)
entry['ts'] = datetime.utcnow().isoformat()
return entry
def main():
# Simulate tailing the Tabnine log.
# In practice, you'd pipe 'code --log extensionHost --level verbose' filtered for Tabnine.
import sys
for line in sys.stdin:
if 'Tabnine' not in line:
continue
parsed = parse_line(line)
if parsed:
with open(LOG_FILE, 'a') as f:
f.write(json.dumps(parsed) + 'n')
print(f"Logged: {parsed}")
if __name__ == '__main__':
main()
```
The script outputs structured log entries in NDJSON format for easy ingestion. A sample entry looks like:
```json
{"event": "accepted", "completion_kind": "inline", "ts": "2023-10-26T14:32:15.123456"}
```
To generate periodic reports, I use a simple aggregation script that reads the NDJSON log:
```bash
#!/bin/bash
LOG=~/.tabnine_acceptance_log.ndjson
echo "Tabnine Acceptance Report - $(date)"
echo "========================================="
TOTAL_SHOWN=$(grep -c '"event":"shown"' "$LOG")
TOTAL_ACCEPTED=$(grep -c '"event":"accepted"' "$LOG")
if [ "$TOTAL_SHOWN" -gt 0 ]; then
RATE=$(echo "scale=2; $TOTAL_ACCEPTED * 100 / $TOTAL_SHOWN" | bc)
echo "Total Suggestions Shown: $TOTAL_SHOWN"
echo "Total Suggestions Accepted: $TOTAL_ACCEPTED"
echo "Overall Acceptance Rate: ${RATE}%"
echo ""
echo "Breakdown by Completion Kind:"
grep '"event":"accepted"' "$LOG" | grep -o '"completion_kind":"[^"]*"' | sort | uniq -c
fi
```
Preliminary findings from a two-week data collection period on a mid-sized Kubernetes operator project:
* **Overall Acceptance Rate:** 34.7%
* **Breakdown by `completion_kind`:**
* `inline`: 42% acceptance (most useful for boilerplate and API calls)
* `snippet`: 28% acceptance (often too generic or requires heavy modification)
* `vanilla`: 31% acceptance (standard single-line completions)
* **Observations:** The acceptance rate dipped significantly during periods of writing novel business logic versus implementing common CRUD operations or configuration manifests. This suggests Tabnine's training data is more effective for certain coding patterns.
This data-driven approach allows for several optimizations:
* Identifying contexts where Tabnine is less effective and potentially disabling it to reduce cognitive load.
* Correlating acceptance rates with specific file extensions or project directories.
* Benchmarking acceptance rate changes across different Tabnine model versions or configuration tweaks (e.g., adjusting the `tabnine.experimental.autoImportCompletions` setting).
I am interested in hearing if others have attempted similar quantitative analyses and what other metadata (e.g., latency per suggestion, relevance score) might be worth capturing to build a more comprehensive model of tool efficiency. The raw log parsing approach, while rudimentary, provides a foundation for building a custom Grafana dashboard if one were to export these metrics to a Prometheus instance.
Interesting approach! I actually tried logging Tabnine interactions a few months back but ran into issues with their log format changes. Had to add some fallback regex patterns when the JSON structure shifted between versions. Have you noticed similar version stability problems?
The correlation with project domain sounds promising. I'd be curious if you're thinking of storing this data somewhere structured, maybe a small Postgres table or even a time-series database for the longitudinal analysis. Could pair nicely with some simple dashboards later.
ship it
Interesting methodology, but I'd question isolating acceptance rate as a primary metric. It ignores suggestion quality and latency impact on workflow.
Have you considered weighting the calculation by the time saved when a multi-line suggestion is accepted versus the distraction cost of a low-probability single-token completion? The log events don't capture that value differential.
For longitudinal storage, I'd avoid overengineering with a separate database. Append to a timestamped CSV and analyze in SQL later. Adding too much structure upfront biases what you measure.
EXPLAIN ANALYZE