OtlpMetrics exports unit "1" for metrics with no declared unit, so Prometheus backends rename gauges to *_ratio
Los mantenedores suelen responder en 1 día
@effect-bot ya está trabajando en esto.
Desde el 4/11/2026.
Evaluación
Este issue todavía no se ha evaluado.
Descripción
What version of Effect is running?
effect 4.1.2. We first hit this on 4.0.2.
What steps can reproduce the bug?
import { createServer } from 'node:http';
import { Effect, Layer, Metric } from 'effect';
import { OtlpMetrics, OtlpSerialization } from 'effect/observability';
import { FetchHttpClient } from 'effect/http';
const seen = new Map();
const server = createServer((req, res) => {
let body = '';
req.on('data', (chunk) => (body += chunk));
req.on('end', () => {
for (const rm of JSON.parse(body).resourceMetrics ?? [])
for (const sm of rm.scopeMetrics ?? [])
for (const m of sm.metrics ?? []) {
const dp = (m.gauge ?? m.sum ?? m.histogram)?.dataPoints?.[0];
seen.set(m.name, { unit: m.unit, attributes: dp?.attributes?.map((a) => a.key) });
}
res.setHeader('content-type', 'application/json');
res.end('{}');
});
});
await new Promise((r) => server.listen(4399, '127.0.0.1', r));
const telemetry = OtlpMetrics.layer({
url: 'http://127.0.0.1:4399/v1/metrics',
resource: { serviceName: 'probe' },
exportInterval: '200 millis',
}).pipe(Layer.provide(OtlpSerialization.layerJson), Layer.provide(FetchHttpClient.layer));
const program = Effect.gen(function* () {
yield* Metric.update(Metric.gauge('app_build_info'), 1);
yield* Metric.update(Metric.counter('app_events'), 1);
yield* Metric.update(Metric.gauge('app_workaround', { attributes: { unit: '' } }), 1);
yield* Effect.sleep('1 second');
});
await Effect.runPromise(program.pipe(Effect.provide(telemetry)));
console.log(Object.fromEntries(seen));
process.exit(0);
What is the expected behavior?
A metric with no declared unit is exported with an empty unit. unit is optional in the OpenTelemetry metrics API, and "1" is a claim the author never made: it means dimensionless.
What do you see instead?
app_build_info: { unit: '1', attributes: [] }
app_events: { unit: '1', attributes: [] }
app_workaround: { unit: '', attributes: [ 'unit' ] }
The default is in toUcumUnit, packages/effect/src/observability/OtlpMetrics.ts:533:
const toUcumUnit = (unit: string | undefined): string => unit === undefined ? "1" : ucumUnits.get(unit) ?? unit
Additional information
prometheus/otlptranslator appends _ratio to gauges whose unit is "1" (metric_namer.go). So app_build_info is stored as app_build_info_ratio. We found this in production on Mimir: alert rules written from the source name read an absent series, and no test in the emitting repo could see it.
The only workaround we found is attributes: { unit: '' }, as in app_workaround above. It also adds unit to the data point attributes.
Changing the default renames stored series for anyone already querying the _ratio names, so it may deserve a release note.
- Lenguaje dominante
- TypeScript
- Estrellas
- 16.7k
- Forks
- 808
- Merge medio
- 11 h 31 min
- PR fusionados (30 d)
- 834
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de Effect-TS/effect
-
Xml: `positions` decode option that puts `line` and `column` on `StartElement` eventsPosiblemente ocupada @effect-bot la tomó hoy. Abierto
Effect-TS/effect#10400 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
effect/ai: support the MCP Apps extension (`io.modelcontextprotocol/ui`)Posiblemente ocupada @effect-bot la tomó hoy. Abierto
Effect-TS/effect#10399 · 2 comentarios · 1 reacción · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
Flat RPC client and AtomRpc query/mutation: type-check cost grows with RPCs in the group × tags calledPosiblemente ocupada @effect-bot la tomó hoy. Abierto
Effect-TS/effect#10396 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
Support `format: "password"` as `Redacted` in JSON Schema import/export and the OpenAPI generatorPosiblemente ocupada @effect-bot la tomó hoy. Abiertoenhancement
Effect-TS/effect#10394 · 2 comentarios · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
Versioned schemas with version negotiation in HttpApi, Rpc and clusterPosiblemente ocupada @effect-bot la tomó hace 1 día. Abierto
Effect-TS/effect#10383 · 2 comentarios · 1 asignado ·
Los mantenedores suelen responder en 1 día
Todos los issues de Effect-TS/effect
Issues similares
-
area: web bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
kinqsradio/orbyn-engineering#227 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
joeldesante/TurfBuilder#258 ·
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
ncecere/open-mcp-portal#85 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 63/100
loathers/garbage-collector#2865 ·
Los mantenedores suelen responder en 1 día
-
test-reliability
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
Azure/azure-sdk-for-js#40672 · 1 reacción ·
Los mantenedores suelen responder en 1 día