Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

[sdk/local-evaluation] getEnvironmentFlags() evaluations are not tracked for analytics

Aperta Adatta ai principianti
#304 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
Meno di un'ora
Idoneità per principianti
85/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
nodejs, typescript
Ambito
analytics

Direzione di ricerca

La segnalazione punta a getEnvironmentFlagsFromDocument in sdk/index.ts intorno alla riga 640, dove Flags.fromEvaluationResult viene chiamato senza l'analytics processor. Confrontalo con getIdentityFlagsFromDocument vicino alla riga 669, che passa già this.analyticsProcessor. Esegui lo script di riproduzione della issue: è completato quando l'esecuzione locale riporta {"my_feature":5}, come quella remota.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Problem

With enableLocalEvaluation: true, flag evaluations from getEnvironmentFlags() are never counted towards analytics. The same code against the same environment reports usage correctly when local evaluation is off, so flag analytics are effectively unavailable to anyone evaluating locally.

The cause looks like a missed argument in getEnvironmentFlagsFromDocument:

// sdk/index.ts:640
const flags = Flags.fromEvaluationResult(evaluationResult);

The other three evaluation paths all pass the processor through:

  • getIdentityFlagsFromDocument (local) -> sdk/index.ts:669, passes this.analyticsProcessor
  • getEnvironmentFlagsFromApi (remote) -> sdk/index.ts:689
  • getIdentityFlagsFromApi (remote) -> sdk/index.ts:710

Since the other local path already tracks, this doesn't look like a deliberate decision to skip analytics during local evaluation.

For what it's worth, the Python client passes it in the equivalent method, so the two SDKs behave differently here:

# flagsmith/flagsmith.py:535, _get_environment_flags_from_document
return Flags.from_evaluation_result(
    evaluation_result=evaluation_result,
    analytics_processor=self._analytics_processor,
    default_flag_handler=self.default_flag_handler,
)

Impact

getEnvironmentFlags() is the common path for server-side usage, and local evaluation is the recommended mode there, so this combination silently reports no usage at all. Nothing warns or errors, and the dashboard just shows the flag as unused. We ran into it while using analytics to decide which stale flags were safe to delete, where a flag wrongly showing zero evaluations is the dangerous direction to be wrong in.

Reproduction

Standalone script, no account needed; it stubs the API locally and compares the two modes.

const http = require('node:http');
const { Flagsmith } = require('flagsmith-nodejs');

const ENV_DOC = {
  api_key: 'ser.repro',
  project: { id: 1, name: 'repro', organisation: { id: 1, name: 'org', feature_analytics: true,
    stop_serving_flags: false, persist_trait_data: true }, hide_disabled_flags: false, segments: [] },
  feature_states: [{ feature: { id: 1, name: 'my_feature', type: 'STANDARD' },
    enabled: true, feature_state_value: null, featurestate_uuid: 'fs-1', multivariate_feature_state_values: [] }],
  identity_overrides: []
};
const API_FLAGS = [{ feature: { id: 1, name: 'my_feature', type: 'STANDARD' },
  enabled: true, feature_state_value: null }];

(async () => {
  const server = http.createServer((req, res) => {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    if (req.url.includes('environment-document')) return res.end(JSON.stringify(ENV_DOC));
    if (req.url.includes('/flags')) return res.end(JSON.stringify(API_FLAGS));
    res.end('{}');
  });
  await new Promise(r => server.listen(0, '127.0.0.1', r));
  const apiUrl = `http://127.0.0.1:${server.address().port}/api/v1/`;

  async function run(local) {
    const f = new Flagsmith({ environmentKey: 'ser.repro', apiUrl,
      enableLocalEvaluation: local, enableAnalytics: true });
    const flags = await f.getEnvironmentFlags();
    for (let i = 0; i < 5; i++) await flags.isFeatureEnabled('my_feature');
    const buf = { ...(f.analyticsProcessor?.analyticsData ?? {}) };
    f.environmentDataPollingManager?.stop();
    console.log(`${local ? 'LOCAL ' : 'REMOTE'} -> buffer ${JSON.stringify(buf)}`);
  }

  await run(true);
  await run(false);
  server.close();
})();

Observed:

LOCAL  -> buffer {}
REMOTE -> buffer {"my_feature":5}

Expected: both report {"my_feature":5}.

Version: [email protected] (current npm latest), Node 24.13.0. Line numbers above are from main as of today, which still has the same call.

Workaround

Calling trackFeature(name) on the processor after each evaluation restores the counts, which is what we're doing for now.

Lingua principale
TypeScript
Stelle
30
Fork
28
Merge medio
7g 23h
PR unite (30g)
3

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di Flagsmith/flagsmith-nodejs-client

Tutte le issue di Flagsmith/flagsmith-nodejs-client

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.