Lyncea

Référence ingestion

Format du payload OTLP/JSON, codes d'erreur HTTP, comportement de retry attendu et limites de l'endpoint POST /v1/logs.

Cette page documente le contrat HTTP de https://api.monitoring.crahe-arthur.com/v1/logs en détail. Pour un guide pas-à-pas avec exemples par stack, voir Premiers pas.

Endpoint

POST https://api.monitoring.crahe-arthur.com/v1/logs — authentification par clé d'API (header Authorization: Bearer lyn_live_xxx, scope write:logs).

L'OTel Collector et la plupart des transports/appenders SDK pointent vers la racine https://api.lyncea.io et ajoutent eux-mêmes /v1/logs. Quand vous configurez un SDK OTel à la main (OTLPLogExporter côté Node ou Python par exemple), écrivez le chemin complet https://api.lyncea.io/v1/logs — ces exporters n'ajoutent pas le suffixe.

Format du payload

Deux content-types acceptés :

Content-TypeUsage
application/x-protobufFormat binaire ExportLogsServiceRequest. Par défaut pour les SDK OTel et Collector.
application/jsonVersion JSON du même schéma. Pratique pour les scripts et les bridges sans protobuf.

Content-Encoding: gzip et deflate sont décodés automatiquement. La limite de 16 MiB s'applique après décompression — un ratio extrême déclenche un 413 plutôt qu'une consommation mémoire incontrôlée.

Exemple minimal valide (JSON)

{
  "resourceLogs": [
    {
      "resource": {
        "attributes": [
          { "key": "service.name", "value": { "stringValue": "checkout-api" } },
          { "key": "deployment.environment", "value": { "stringValue": "prod" } }
        ]
      },
      "scopeLogs": [
        {
          "scope": { "name": "lyncea-quickstart" },
          "logRecords": [
            {
              "timeUnixNano": "1717171717000000000",
              "severityNumber": 9,
              "severityText": "INFO",
              "body": { "stringValue": "user logged in" },
              "attributes": [
                { "key": "user.id", "value": { "stringValue": "42" } }
              ]
            }
          ]
        }
      ]
    }
  ]
}

Contraintes :

  • resourceLogs[] ne peut pas être vide (400 sinon).
  • timeUnixNano est une chaîne de 19 chiffres (nanosecondes Unix) — ne pas l'envoyer en number, JavaScript perd la précision au-delà de 2^53.
  • Tout le reste est optionnel mais recommandé pour exploiter pleinement la recherche de logs.

Sévérité

OTel utilise severityNumber (entier 1–24). Mapping habituel à connaître si vous écrivez le payload à la main — les bridges officiels font ce mapping pour vous :

NiveauseverityNumberseverityText
TRACE1TRACE
DEBUG5DEBUG
INFO9INFO
WARN13WARN
ERROR17ERROR
FATAL21FATAL

Les valeurs intermédiaires (DEBUG2 = 6, INFO3 = 11, etc.) sont autorisées par la spec et passent sans transformation.

Attributs OTel exploités

Lyncea lit un seul attribut côté ingestion : deployment.environment (resource), pour appliquer l'allowlist du projet — voir Environnements de projet.

Tous les autres attributs (service.name, service.version, trace_id, attributs de logRecord custom…) sont conservés tels quels dans le payload et indexables côté recherche via GET /api/v1/logs. Aucun attribut n'est silencieusement supprimé.

Réponses HTTP

StatutQuandBodyRetry-After
200 OKLot accepté à l'edgeExportLogsServiceResponse (vide en v1)
400 Bad RequestJSON malformé, resourceLogs vide, Content-Type non géréStatus { code: 3, message }
401 UnauthorizedClé d'API absente ou invalideStatus { code: 16, message }
403 ForbiddenScope write:logs manquant, ou tenant suspenduStatus { code: 7, message }
413 Payload Too LargeBody brut > 4 MiB ou décompressé > 16 MiBStatus { code: 3, message }
429 Too Many RequestsQuota EPS dépassé (par clé ou par tenant — voir Plans)Status { code: 8, message }secondes
503 Service UnavailablePipeline Lyncea momentanément indisponible (incident côté ingestion)Status { code: 14, message }5

Le body d'erreur est toujours le proto gRPC Status { code, message }, encodé dans le même content-type que la requête (JSON ou protobuf).

Retry & backoff

Côté client, appliquer la convention OTel standard :

  • Retry exponentiel sur 429 et 503 uniquement, en respectant Retry-After quand il est présent.
  • Pas de retry sur les autres 4xx — ils signalent une erreur de configuration (clé invalide, scope manquant, payload trop gros, JSON malformé) qu'un retry ne corrigera pas.
  • Buffer en mémoire côté client pour absorber les coupures brèves.

Les SDK OTel officiels et l'OTel Collector implémentent ce comportement nativement (queue interne + retry + circuit breaker) — vous n'avez rien à coder. Si vous écrivez votre propre client, partez d'un backoff exponentiel 1s → 2s → 4s → 8s → 16s avec jitter et un cap raisonnable.

200 OK signifie « accepté pour traitement », pas « consultable dans l'interface ». La pipeline est asynchrone (Kafka → ClickHouse) — comptez quelques secondes en régime nominal avant qu'un log apparaisse dans GET /api/v1/logs ou dans le live tail.

Limites

ParamètreValeur par défaut
Body brut maximum4 MiB
Body après décompression maximum16 MiB
Quota d'événements par seconde (EPS)dépend du plan — voir Plans
Granularité du rate-limitpar clé d'API et par tenant agrégé

Le rate-limit est un token-bucket dont la capacité et la vitesse de refill suivent l'EPS du plan. Une rafale peut consommer jusqu'à la capacité complète avant de rate-limiter.

Voir aussi

  • Premiers pas — créer un projet, générer une clé et envoyer son premier log.
  • Environnements de projet — allowlist deployment.environment et préfixes de clé.
  • Plans — quotas EPS et rétention par offre.

On this page